pass layer2_API test, still need review

This commit is contained in:
Ziao 2023-11-28 14:35:55 -08:00
parent e56d304d2f
commit e69527a10b
6 changed files with 61 additions and 113 deletions

View File

@ -11,9 +11,10 @@ class FilesOperation {
public:
TreeNode *root_node;
FilesOperation(RawDisk&, Fs*);
int read_datablock(const INode_Data& inode, u_int64_t index, char* buffer);
int write_datablock(INode_Data& inode, u_int64_t index, char* buffer);
//int read_datablock(const INode_Data& inode, u_int64_t index, char* buffer);
//int write_datablock(INode_Data& inode, u_int64_t index, char* buffer);
void initialize_rootinode();
void printbuffer(const char*,int);
void printDirectory(u_int64_t);
INode_Data* create_new_inode(u_int64_t parent_inode_number, const char* name, mode_t mode);
void unlink_inode(u_int64_t inode_number);

View File

@ -101,15 +101,6 @@ TreeNode *find_parentPath(TreeNode *root, const char *path) {
void freeHashTable(HashTable *table) {
if (table == NULL) return;
for (int i = 0; i < table->size; ++i) {
FileNode *current = table->table[i];
while (current != NULL) {
FileNode *temp = current;
current = current->next;
// free(temp->name);
// free(temp);
}
}
free(table->table);
free(table);
}

View File

@ -23,71 +23,17 @@ struct DirectoryEntry {
}
};
void FilesOperation::printbuffer(const char* buff, int len) {
for(int i=0;i<len;i++){
printf("%x ",buff[i]);
}
printf("\n");
}
FilesOperation::FilesOperation(RawDisk& disk_, Fs* fs): disk(disk_) {
this->fs = fs;
}
u_int64_t index_to_offset(const INode_Data& inode, RawDisk& disk, u_int64_t index) {
u_int64_t ret;
u_int64_t offset;
if (index < 48) {
return inode.direct_blocks[index];
} else if (index < 48 + 512){
char indirect_buffer[IO_BLOCK_SIZE] = {0};
disk.read_block(inode.single_indirect_block/IO_BLOCK_SIZE, indirect_buffer);
read_u64(&ret, indirect_buffer+8*(index-48));
return ret;
} else if (index < 48 + 512 + 512*512) {
char indirect_buffer[IO_BLOCK_SIZE] = {0};
disk.read_block(inode.double_indirect_block/IO_BLOCK_SIZE, indirect_buffer);
read_u64(&offset, indirect_buffer+8*((index-48-512)/512));
disk.read_block(offset/IO_BLOCK_SIZE,indirect_buffer);
read_u64(&ret, indirect_buffer+8*((index-48-512)%512));
return ret;
} else if (index < 48 + 512 + 512*512 + 512*512*512){
char indirect_buffer[IO_BLOCK_SIZE] = {0};
disk.read_block(inode.triple_indirect_block/IO_BLOCK_SIZE, indirect_buffer);
read_u64(&offset, indirect_buffer+8*((index-48-512-512*512)/(512*512)));
disk.read_block(offset/IO_BLOCK_SIZE,indirect_buffer);
read_u64(&offset, indirect_buffer+8*(((index-48-512-512*512)%(512*512))/512));
disk.read_block(offset/IO_BLOCK_SIZE,indirect_buffer);
read_u64(&ret, indirect_buffer+8*((index-48-512-512*512)%512));
return ret;
} else {
printf("index out of range, tried to access index %llu, max index %llu\n", index, 48+512+512*512+512*512*512);
return -1;
}
}
int FilesOperation::read_datablock(const INode_Data& inode, u_int64_t index, char* buffer) {
if (index >= inode.metadata.size) {
printf("Read datablock out of range, inode number %llu", inode.inode_num);
return -1;
}
u_int64_t read_offset = index_to_offset(inode, disk, index);
if (read_offset == (u_int64_t)(-1)) {
return -1;
}
//printf("Read %llu\n", read_offset/IO_BLOCK_SIZE);
return disk.read_block(read_offset/IO_BLOCK_SIZE, buffer);
}
int FilesOperation::write_datablock(INode_Data& inode, u_int64_t index, char* buffer) {
while (index >= inode.metadata.size) {
u_int64_t alloc_num;
int ret = (fs->allocate_datablock(&inode, &alloc_num));
printf("allocate_datablock returned %d\n",ret);
if (ret!=0) assert(false);
inode.metadata.size += 1;
}
u_int64_t write_offset = index_to_offset(inode, disk, index);
if (write_offset == (u_int64_t)(-1)) {
return -1;
}
//printf("Write %llu\n", write_offset/IO_BLOCK_SIZE);
return disk.write_block(write_offset/IO_BLOCK_SIZE, buffer);
}
void FilesOperation::create_dot_dotdot(INode_Data* inode, u_int64_t parent_inode_number) {
char buffer[IO_BLOCK_SIZE] = {0};
DirectoryEntry dot;
@ -98,7 +44,8 @@ void FilesOperation::create_dot_dotdot(INode_Data* inode, u_int64_t parent_inode
dotdot.inode_number = parent_inode_number;
strcpy(dotdot.file_name, "..");
dotdot.serialize(buffer+264);
int ret = write_datablock(*inode, 0, buffer);
int ret = fs->write(inode, buffer, IO_BLOCK_SIZE, 0);
//printf("in create_dot_dotdot: fs->write returned %d\n",ret);
}
void FilesOperation::initialize_rootinode() {
@ -118,7 +65,7 @@ void FilesOperation::printDirectory(u_int64_t inode_number) {
inode.inode_num = inode_number;
fs->inode_manager->load_inode(&inode);
char buffer[IO_BLOCK_SIZE] = {0};
read_datablock(inode, 0, buffer);
fs->read(&inode, buffer, IO_BLOCK_SIZE, 0);
DirectoryEntry ent;
for(int i=0;i<=IO_BLOCK_SIZE-264;i+=264){
ent.deserialize(buffer+i);
@ -143,8 +90,8 @@ INode_Data* FilesOperation::create_new_inode(u_int64_t parent_inode_number, cons
// Check if file or directory already exists
char r_buffer[IO_BLOCK_SIZE] = {0};
for (u_int64_t idx=0; idx<inode.metadata.size; idx++) {
read_datablock(inode, idx, r_buffer);
for (u_int64_t idx=0; idx<inode.metadata.size/IO_BLOCK_SIZE; idx++) {
fs->read(&inode, r_buffer, IO_BLOCK_SIZE, idx*IO_BLOCK_SIZE);
DirectoryEntry ent;
for(int i=0;i<=IO_BLOCK_SIZE-264;i+=264){
ent.deserialize(r_buffer+i);
@ -164,11 +111,12 @@ INode_Data* FilesOperation::create_new_inode(u_int64_t parent_inode_number, cons
fs->inode_manager->new_inode(0, 0, mode, new_inode);
if ((mode & S_IFMT) == S_IFDIR) {
create_dot_dotdot(new_inode, parent_inode_number);
fs->inode_manager->save_inode(new_inode);
}
char rw_buffer[IO_BLOCK_SIZE] = {0};
for (u_int64_t idx=0; idx<inode.metadata.size; idx++) {
read_datablock(inode, idx, rw_buffer);
for (u_int64_t idx=0; idx<inode.metadata.size/IO_BLOCK_SIZE; idx++) {
fs->read(&inode, rw_buffer, IO_BLOCK_SIZE, idx*IO_BLOCK_SIZE);
DirectoryEntry ent;
for(int i=0;i<=IO_BLOCK_SIZE-264;i+=264){
ent.deserialize(rw_buffer+i);
@ -181,7 +129,7 @@ INode_Data* FilesOperation::create_new_inode(u_int64_t parent_inode_number, cons
}
}
if (allocated) {
write_datablock(inode, idx, rw_buffer);
fs->write(&inode, rw_buffer, IO_BLOCK_SIZE, idx*IO_BLOCK_SIZE);
break;
}
}
@ -192,7 +140,7 @@ INode_Data* FilesOperation::create_new_inode(u_int64_t parent_inode_number, cons
ent.inode_number = new_inode->inode_num;
strcpy(ent.file_name, name);
ent.serialize(write_buffer);
write_datablock(inode, inode.metadata.size, write_buffer);
fs->write(&inode, write_buffer, IO_BLOCK_SIZE, (inode.metadata.size/IO_BLOCK_SIZE)*IO_BLOCK_SIZE);
fs->inode_manager->save_inode(&inode);
}
@ -221,8 +169,8 @@ u_int64_t FilesOperation::disk_namei(const char* path) {
u_int64_t new_inode_number = 0;
char buffer[IO_BLOCK_SIZE] = {0};
for(u_int64_t idx=0; idx<inode.metadata.size; idx++) {
read_datablock(inode, idx, buffer);
for(u_int64_t idx=0; idx<inode.metadata.size/IO_BLOCK_SIZE; idx++) {
fs->read(&inode, buffer, IO_BLOCK_SIZE, idx*IO_BLOCK_SIZE);
DirectoryEntry ent;
for(int i=0;i<=IO_BLOCK_SIZE-264;i+=264){
ent.deserialize(buffer+i);
@ -265,7 +213,7 @@ int FilesOperation::fischl_mkdir(const char* path, mode_t mode) {
FileNode *parent_filenode = strlen(ParentPath)? fischl_find_entry(root_node, ParentPath): root_node->self_info;
if (parent_filenode == NULL) {
fprintf(stderr,"[%s ,%d] ParentPath:{%s} not found\n",__func__,__LINE__, ParentPath);
delete pathdup;
free(pathdup);
return -ENOENT;//parentpath directory does not exist
}
u_int64_t parent_inode_number = parent_filenode->inode_number;
@ -274,7 +222,7 @@ int FilesOperation::fischl_mkdir(const char* path, mode_t mode) {
INode_Data* ret = create_new_inode(parent_inode_number, newDirname, mode|S_IFDIR);//specify S_IFDIR as directory
if (ret == NULL) return -1;//ENOSPC but create_new_inode handle ENAMETOOLONG EEXIST
fischl_add_entry(parent_filenode->subdirectory, ret->inode_num, newDirname, ret);
delete pathdup;
free(pathdup);
return 0;//SUCCESS
}
/*
@ -291,7 +239,7 @@ int FilesOperation::fischl_mknod(const char* path, mode_t mode, dev_t dev) {
FileNode *parent_filenode = strlen(ParentPath)? fischl_find_entry(root_node, ParentPath): root_node->self_info;
if (parent_filenode == NULL) {
fprintf(stderr,"[%s ,%d] ParentPath:{%s} not found\n",__func__,__LINE__, ParentPath);
delete pathdup;
free(pathdup);
return -1;
}
u_int64_t parent_inode_number = parent_filenode->inode_number;
@ -300,7 +248,7 @@ int FilesOperation::fischl_mknod(const char* path, mode_t mode, dev_t dev) {
if (ret == NULL) return -1;//ENOSPC but create_new_inode handle ENAMETOOLONG EEXIST
//make new node
fischl_add_entry(parent_filenode->subdirectory, ret->inode_num, newFilename, ret);
delete pathdup;
free(pathdup);
return 0;//SUCESS
}
/*
@ -317,7 +265,7 @@ int FilesOperation::fischl_create(const char* path, mode_t mode, struct fuse_fil
FileNode *parent_filenode = strlen(ParentPath)? fischl_find_entry(root_node, ParentPath): root_node->self_info;
if (parent_filenode == NULL) {
fprintf(stderr,"[%s ,%d] ParentPath:{%s} not found\n",__func__,__LINE__, ParentPath);
delete pathdup;
free(pathdup);
return -1;
}
u_int64_t parent_inode_number = parent_filenode->inode_number;
@ -328,7 +276,7 @@ int FilesOperation::fischl_create(const char* path, mode_t mode, struct fuse_fil
fischl_add_entry(parent_filenode->subdirectory, ret->inode_num, newFilename, ret);
//directly give inode number rather than create file descriptor table
fi->fh = ret->inode_num;//assign file descriptor as inode number to fuse system
delete pathdup;
free(pathdup);
return 0;//SUCESS
}
@ -338,8 +286,8 @@ void FilesOperation::unlink_inode(u_int64_t inode_number) {
fs->inode_manager->load_inode(&inode);
if ((inode.metadata.permissions & S_IFMT) == S_IFDIR) {
char buffer[IO_BLOCK_SIZE] = {0};
for(u_int64_t idx=0; idx<inode.metadata.size; idx++) {
read_datablock(inode, idx, buffer);
for(u_int64_t idx=0; idx<inode.metadata.size/IO_BLOCK_SIZE; idx++) {
fs->read(&inode, buffer, IO_BLOCK_SIZE, idx*IO_BLOCK_SIZE);
DirectoryEntry ent;
for(int i=0;i<=IO_BLOCK_SIZE-264;i+=264){
if(ent.inode_number && strcmp(ent.file_name,".") && strcmp(ent.file_name,"..")){
@ -348,10 +296,11 @@ void FilesOperation::unlink_inode(u_int64_t inode_number) {
}
}
}
// TODO: This is probably incorrect
while(inode.metadata.size != 0) {
u_int64_t dummy;
fs->deallocate_datablock(&inode, &dummy);
inode.metadata.size--;
inode.metadata.size-=IO_BLOCK_SIZE;
}
fs->inode_manager->free_inode(&inode);
}
@ -369,7 +318,7 @@ int FilesOperation::fischl_unlink(const char* path) {
FileNode *parent_filenode = fischl_find_entry(root_node, ParentPath);
if (parent_filenode == NULL) {
printf("parent %s not found by fischl_find_entry\n", ParentPath);
delete pathdup;
free(pathdup);
return -1;
}
u_int64_t parent_inode_number = parent_filenode->inode_number;
@ -380,8 +329,8 @@ int FilesOperation::fischl_unlink(const char* path) {
parent_INode.inode_num = parent_inode_number;
fs->inode_manager->load_inode(&parent_INode);
char rw_buffer[IO_BLOCK_SIZE] = {0};
for (u_int64_t idx=0; idx<parent_INode.metadata.size; idx++) {
read_datablock(parent_INode, idx, rw_buffer);
for (u_int64_t idx=0; idx<parent_INode.metadata.size/IO_BLOCK_SIZE; idx++) {
fs->read(&parent_INode, rw_buffer, IO_BLOCK_SIZE, idx*IO_BLOCK_SIZE);
DirectoryEntry ent;
for(int i=0;i<=IO_BLOCK_SIZE-264;i+=264){
ent.deserialize(rw_buffer+i);
@ -393,7 +342,7 @@ int FilesOperation::fischl_unlink(const char* path) {
}
}
if (target_inode) {
write_datablock(parent_INode, idx, rw_buffer);
fs->write(&parent_INode, rw_buffer, IO_BLOCK_SIZE, idx*IO_BLOCK_SIZE);
break;
}
}
@ -403,11 +352,11 @@ int FilesOperation::fischl_unlink(const char* path) {
unlink_inode(target_inode);
// remove node itself and from parent hash
fischl_rm_entry(parent_filenode->subdirectory, filename);
delete pathdup;
free(pathdup);
return 0;
} else {
printf("cannot find %s in %s", filename, ParentPath);
delete pathdup;
free(pathdup);
return -1;
}
}
@ -457,7 +406,7 @@ int FilesOperation::fischl_write(const char *path, const char *buf, size_t size,
// Assuming inode is correctly initialized here based on 'path'
inode.inode_num = fi->fh;
fs->inode_manager->load_inode(&inode);
size_t len = inode.metadata.size * IO_BLOCK_SIZE; // Assuming each block is 4096 bytes
size_t len = (inode.metadata.size/IO_BLOCK_SIZE) * IO_BLOCK_SIZE; // Assuming each block is 4096 bytes
size_t bytes_write = 0;
size_t block_index = offset / IO_BLOCK_SIZE; // Starting block index
@ -466,7 +415,7 @@ int FilesOperation::fischl_write(const char *path, const char *buf, size_t size,
char block_buffer[IO_BLOCK_SIZE]; // Temporary buffer for each block
size_t copy_size = std::min(size - bytes_write, IO_BLOCK_SIZE - block_offset);
memcpy(block_buffer + block_offset, buf + bytes_write, copy_size);
write_datablock(inode, block_index, block_buffer);
fs->write(&inode, block_buffer, IO_BLOCK_SIZE, block_index*IO_BLOCK_SIZE);
// fprintf(stderr,"[%s ,%d] inode.size %d, block_index %d, block_buffer %s\n",__func__,__LINE__, inode.size, block_index, block_buffer);
bytes_write += copy_size;
block_index++;
@ -492,7 +441,7 @@ int FilesOperation::fischl_read(const char *path, char *buf, size_t size, off_t
// Assuming inode is correctly initialized here based on 'path'
inode.inode_num = fi->fh;
fs->inode_manager->load_inode(&inode);
size_t len = inode.metadata.size * IO_BLOCK_SIZE; // Assuming each block is 4096 bytes
size_t len = (inode.metadata.size/IO_BLOCK_SIZE) * IO_BLOCK_SIZE; // Assuming each block is 4096 bytes
if (offset >= len) return 0; // Offset is beyond the end of the file
if (offset + size > len) size = len - offset; // Adjust size if it goes beyond EOF
@ -501,9 +450,9 @@ int FilesOperation::fischl_read(const char *path, char *buf, size_t size, off_t
size_t block_index = offset / IO_BLOCK_SIZE; // Starting block index
size_t block_offset = offset % IO_BLOCK_SIZE; // Offset within the first block
// fprintf(stderr,"[%s ,%d] inode.metadata.size %d\n",__func__,__LINE__, inode.metadata.size);
while (bytes_read < size && block_index < inode.metadata.size) {
while (bytes_read < size && block_index < inode.metadata.size/IO_BLOCK_SIZE) {
char block_buffer[IO_BLOCK_SIZE]; // Temporary buffer for each block
read_datablock(inode, block_index, block_buffer);
fs->read(&inode, block_buffer, IO_BLOCK_SIZE, block_index*IO_BLOCK_SIZE);
// fprintf(stderr,"[%s ,%d] block_index %d\n",__func__,__LINE__, block_index);
size_t copy_size = std::min(size - bytes_read, IO_BLOCK_SIZE - block_offset);
memcpy(buf + bytes_read, block_buffer + block_offset, copy_size);

View File

@ -3,6 +3,7 @@ set(TARGET_LAYER1_API test_layer1_API)
set(TARGET_LAYER2_API test_layer2_API)
set(TARGET_DIR_API test_dir_API)
set(DIR_PLACE /dev/vdb)
# set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -fsanitize=address")
# add test sources here ...
add_executable(${TARGET_LAYER0}
@ -21,6 +22,7 @@ add_executable(${TARGET_LAYER1_API}
../lib/fs/datablock_manager.cpp
../lib/fs/fs_data_types.cpp
../lib/fs/fs_resize.cpp
../lib/fs/fs_read_write.cpp
../lib/fs/fs.cpp
../lib/fs/inode_manager.cpp
)
@ -30,6 +32,7 @@ add_executable(${TARGET_LAYER2_API}
../lib/fs/datablock_manager.cpp
../lib/fs/fs_data_types.cpp
../lib/fs/fs_resize.cpp
../lib/fs/fs_read_write.cpp
../lib/fs/fs.cpp
../lib/fs/inode_manager.cpp
../lib/files.cpp
@ -41,6 +44,7 @@ add_executable(${TARGET_DIR_API}
../lib/fs/datablock_manager.cpp
../lib/fs/fs_data_types.cpp
../lib/fs/fs_resize.cpp
../lib/fs/fs_read_write.cpp
../lib/fs/fs.cpp
../lib/fs/inode_manager.cpp
dir_API.cpp

View File

@ -133,7 +133,7 @@ int main(int argc, char *argv[]) {
for (int j = 0; j < 3; j++) {
fs->allocate_datablock(&inode_list[i], &temp_block_num);
//assert(temp_block_num == rec_datablock_free[i][j]);
printf("%llu," ,itemp_block_num);
printf("%llu," ,temp_block_num);
}
printf("\n");
}

View File

@ -27,7 +27,7 @@ void traverseDirHierarchy(const dir_test* dir, int depth);
//global can be taken
std::string target_filepath;
dir_test* mock_root = nullptr;
RawDisk *H;
RawDisk *H; // Use FakeRawDisk here if memory sanitizer complains
Fs *fs;
FilesOperation *fsop;
@ -45,15 +45,11 @@ TEST(FileOperationTest, MkdirnodTest) {
mode = S_IRWXU | S_IRWXG | S_IRWXO;//future should test permission
//S_IRWXU(S_IRUSR | S_IWUSR | S_IXUSR) (owner), S_IRWXG(S_IRGRP | S_IWGRP | S_IXGRP) (group), S_IRWXO(S_IROTH | S_IWOTH | S_IXOTH)
EXPECT_EQ(fsop->fischl_create("/test", mode, &fi), 0);
printf("point 1:");
fsop->printDirectory(1);
EXPECT_EQ(fsop->fischl_mkdir("/foo", mode), 0);
printf("point 2:");
fsop->printDirectory(1);
EXPECT_EQ(fsop->fischl_mkdir("/foo/bar", mode),0);
printf("point 3:");
fsop->printDirectory(1);
EXPECT_EQ(fsop->fischl_create("/foo/bar/baz", mode, &fi), 0);
fsop->printDirectory(4);
// the following three testcases will fail
printf("Failing cases\n");
EXPECT_TRUE(fsop->fischl_mkdir("foo/bar", mode) < 0);
@ -74,11 +70,14 @@ TEST(FileOperationTest, WriteTest) {
struct fuse_file_info fi;
//file test
printf("point 0\n");
get_disk_inum = fsop->disk_namei("/test");
printf("point 1\n");
fsop->fischl_open("/test", &fi);
EXPECT_EQ(fi.fh, get_disk_inum);
buffer[0] = '1';
fsop->fischl_write("/test", buffer, sizeof(buffer), 0, &fi);
printf("point 2\n");
//other file baz
get_disk_inum = fsop->disk_namei("/foo/bar/baz");
buffer[0] = '4';
@ -134,8 +133,8 @@ TEST(FileOperationTest, ReadTest) {
get_file_inum = fsop->namei("/test");
inode.inode_num = get_file_inum;
fs->inode_manager->load_inode(&inode);
fsop->read_datablock(inode, 0, read_buffer);
EXPECT_EQ(read_buffer[0], '1');
//fsop->read_datablock(inode, 0, read_buffer);
//EXPECT_EQ(read_buffer[0], '1');
//read test file again with fischl_read API
struct fuse_file_info fi;
@ -165,12 +164,14 @@ TEST(FileOperationTest, PressureTest) {
mode_t mode;//set mode
mode = S_IRWXU | S_IRWXG | S_IRWXO;//future should test permission
EXPECT_EQ(fsop->fischl_mkdir("/pressure", mode), 0);
fsop->printDirectory(1);
u_int64_t inode_numbers[700];
std::string prefix = "/pressure/No_";
for(int i=0;i<700;i++){
EXPECT_EQ(fsop->fischl_mkdir((prefix+std::to_string(i)).c_str(), mode), 0);
}
fsop->printDirectory(6);
for(int i=0;i<700;i++){
EXPECT_EQ(fsop->namei((prefix+std::to_string(i)).c_str()),fsop->disk_namei((prefix+std::to_string(i)).c_str()));
}
@ -211,7 +212,7 @@ int main(int argc, char **argv) {
const char* d = (argc < 2) ? "/dev/vdc" : argv[1];
setupTestDirectory(&mock_root);
H = new FakeRawDisk(2048);
H = new FakeRawDisk(21504);
fs = new Fs(H);
fs->format();
fsop = new FilesOperation(*H, fs);
@ -299,7 +300,9 @@ dir_test* createDirHierarchy(int level, int maxLevel) {
void setupTestDirectory(dir_test** root) {
// Allocate memory for root
*root = new dir_test;
(*root)->name = strdup("/"); // use / as begin
char* root_name = new char[2];
strcpy(root_name, "/");
(*root)->name = root_name; // use / as begin
(*root)->inFile = nullptr; // Initialize file list to nullptr
(*root)->subdir = createDirHierarchy(0, 1);
(*root)->next = nullptr;