diff --git a/include/files.h b/include/files.h index 1f8d010..9035eec 100644 --- a/include/files.h +++ b/include/files.h @@ -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); diff --git a/lib/direntry.cpp b/lib/direntry.cpp index 4810ab3..2366dde 100644 --- a/lib/direntry.cpp +++ b/lib/direntry.cpp @@ -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); } diff --git a/lib/files.cpp b/lib/files.cpp index 8438fb9..b030d46 100644 --- a/lib/files.cpp +++ b/lib/files.cpp @@ -23,71 +23,17 @@ struct DirectoryEntry { } }; +void FilesOperation::printbuffer(const char* buff, int len) { + for(int i=0;ifs = 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; idxread(&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; idxread(&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; idxread(&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; idxread(&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; idxread(&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); diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 61a3a06..71919cf 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -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 diff --git a/test/layer1_API.cpp b/test/layer1_API.cpp index df41f7f..a1a3a87 100644 --- a/test/layer1_API.cpp +++ b/test/layer1_API.cpp @@ -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"); } diff --git a/test/layer2_API_dir.cpp b/test/layer2_API_dir.cpp index 3275691..3b88561 100644 --- a/test/layer2_API_dir.cpp +++ b/test/layer2_API_dir.cpp @@ -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;