From 47927b0a8a6fc2577f6b87ae44a2bafa6bd8a022 Mon Sep 17 00:00:00 2001 From: wangziao <1575538687@qq.com> Date: Sun, 12 Nov 2023 03:22:24 -0800 Subject: [PATCH 01/13] modify layer 1 for pressure testing on a small fs --- include/fs.h | 32 +++++++++--- test/CMakeLists.txt | 8 ++- test/layer1_test1.cpp | 110 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 141 insertions(+), 9 deletions(-) create mode 100644 test/layer1_test1.cpp diff --git a/include/fs.h b/include/fs.h index 067d595..4e989e2 100644 --- a/include/fs.h +++ b/include/fs.h @@ -9,8 +9,10 @@ one inode equipped with one 512 bytes block *****************************************************/ #define SECTOR_SIZE 512 #define IO_BLOCK_SIZE 4096 -#define MAX_INODE 524288 -#define MAX_BLOCKNUM MAX_INODE*2 //62914560 +#define MAX_INODE 2048 +// 524288 +#define MAX_BLOCKNUM 51200 +// 1GB Disk: 2097152 = 196512 IO_BLOCK's. MAX_INODE*2 //62914560 class SuperBlock{ @@ -159,6 +161,7 @@ public: } } } + // we can assert here that freeBlockNum is nonzero here, since we always change head when a block is full (see below) disk.rawdisk_write(freeListHead, buffer, sizeof(buffer)); bool notFull = false; for (int i = 8; i < 264; i++){ @@ -168,8 +171,8 @@ public: } } if (!notFull){ - printf("HEADER REMOVAL DETECTED %llu %llu\n", freeListHead, freeBlockNum); u_int64_t next_header = read_byte_at(0, buffer); + printf("HEADER MOVE (Cause: Alloc) %llu -> %llu (%llu)\n", freeListHead, next_header, freeBlockNum); SuperBlock::writeFreeListHead(disk, next_header); } return freeBlockNum; @@ -178,6 +181,9 @@ public: bool allo_single_indirect(RawDisk &disk, u_int64_t &single_i, u_int64_t freeBlockNum) { if (single_i == 0){ single_i = datablock_allocate_in_list(disk); + char init_buffer[IO_BLOCK_SIZE] = {0}; + disk.rawdisk_write(single_i, init_buffer, sizeof(init_buffer)); + // I think the same should be done to alloc double, triple indirect } bool inSingle = false; char buffer[IO_BLOCK_SIZE] = {0}; @@ -197,6 +203,8 @@ public: bool allo_double_indirect(RawDisk &disk, u_int64_t &double_i, u_int64_t freeBlockNum) { if (double_i == 0){ double_i = datablock_allocate_in_list(disk); + char init_buffer[IO_BLOCK_SIZE] = {0}; + disk.rawdisk_write(double_i, init_buffer, sizeof(init_buffer)); } bool inDouble = false; char buffer[IO_BLOCK_SIZE] = {0}; @@ -217,6 +225,8 @@ public: bool allo_triple_indirect(RawDisk &disk, u_int64_t &triple_i, u_int64_t freeBlockNum) { if (triple_i == 0){ triple_i = datablock_allocate_in_list(disk); + char init_buffer[IO_BLOCK_SIZE] = {0}; + disk.rawdisk_write(triple_i, init_buffer, sizeof(init_buffer)); } bool inTriple = false; char buffer[IO_BLOCK_SIZE] = {0}; @@ -268,22 +278,25 @@ public: // find the related 2048block head u_int64_t freeBlockHead = ((freeBlockNum/SECTOR_SIZE-MAX_INODE)/(8*2048)*(8*2048)+MAX_INODE)*SECTOR_SIZE; - // mark it alive in its bitmap char buffer[IO_BLOCK_SIZE] = {0}; - bool notEmpty = false; disk.rawdisk_read(freeBlockHead, buffer, sizeof(buffer)); + + // mark it alive in its bitmap + u_int64_t inBlockPos = (freeBlockNum-freeBlockHead)/IO_BLOCK_SIZE-1; + buffer[8+inBlockPos/8] &= (-1)^(1<<(inBlockPos%8)); + + bool notEmpty = false; for (int i = 8; i < 264; i++){ if(buffer[i] != 0){ notEmpty = true; } } - u_int64_t inBlockPos = (freeBlockNum-freeBlockHead)/IO_BLOCK_SIZE-1; - buffer[8+inBlockPos/8] &= (-1)^(1<<(inBlockPos%8)); // if its bitmap was 0, add it back to the list head if(!notEmpty){ u_int64_t freeListHead = SuperBlock::getFreeListHead(disk); write_byte_at(freeListHead, 0, buffer); + printf("HEADER MOVE (Cause: Dealloc) %llu -> %llu\n", freeListHead, freeBlockHead); SuperBlock::writeFreeListHead(disk, freeBlockHead); } disk.rawdisk_write(freeBlockHead, buffer, sizeof(buffer)); @@ -297,13 +310,14 @@ public: char buffer[IO_BLOCK_SIZE] = {0}; int delpoint = -1; disk.rawdisk_read(single_i, buffer, sizeof(buffer)); - for (int i=4088; i >= 0; i--){ + for (int i=4088; i >= 0; i-=8){ u_int64_t addr = read_byte_at(i, buffer); if(addr != 0){ freeBlockNum = addr; addr = 0; write_byte_at(addr, i, buffer); delpoint = i; + //printf("delpoint: %d\n", delpoint); break; } } @@ -377,8 +391,10 @@ public: freeBlockNum = deallo_triple_indirect(disk, triple_indirect); if(!freeBlockNum){ freeBlockNum = deallo_double_indirect(disk, double_indirect); + //printf("In fs.h, Inode::datablock_deallocate: finished dealloc double indirect, got %lld\n", freeBlockNum); if(!freeBlockNum){ freeBlockNum = deallo_single_indirect(disk, single_indirect); + //printf("In fs.h, Inode::datablock_deallocate: finished dealloc single indirect, got %lld\n", freeBlockNum); if(!freeBlockNum){ for(int i = 47; i>=0; i--) if(blocks[i] != 0){ diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index b946592..41d7049 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,5 +1,6 @@ set(TARGET_LAYER0 test_layer0) set(TARGET_LAYER1_API test_layer1_API) +set(TARGET_LAYER1_TEST1 test_layer1_test1) set(DIR_PLACE /dev/vdb) # add test sources here ... @@ -11,7 +12,12 @@ add_executable(${TARGET_LAYER1_API} # add need lib and source code here layer1_API.cpp ) +add_executable(${TARGET_LAYER1_TEST1} + # add need lib and source code here + layer1_test1.cpp +) # add test to activate ctest -VV add_test(NAME ${TARGET_LAYER0} COMMAND sudo ./${TARGET_LAYER0} ${DIR_PLACE}) -add_test(NAME ${TARGET_LAYER1_API} COMMAND sudo ./${TARGET_LAYER1_API} ${DIR_PLACE}) \ No newline at end of file +add_test(NAME ${TARGET_LAYER1_API} COMMAND sudo ./${TARGET_LAYER1_API} ${DIR_PLACE}) +add_test(NAME ${TARGET_LAYER1_TEST1} COMMAND sudo ./${TARGET_LAYER1_TEST1} ${DIR_PLACE}) \ No newline at end of file diff --git a/test/layer1_test1.cpp b/test/layer1_test1.cpp new file mode 100644 index 0000000..27fa971 --- /dev/null +++ b/test/layer1_test1.cpp @@ -0,0 +1,110 @@ +#include +#include +#include +#include "fs.h" +#include + +// in fs.h: +// #define MAX_INODE 2048 +// #define MAX_BLOCKNUM 51200 +// 51200 Sectors = 2048 * 25 Sectors = 25MB +// Free List Heads: 2048*512, 2048*9*512, 2048*17*512 +// Available INodes: 2047 (-1 because superblock) +// Available DataBlocks (including Indirect Blocks): 2047 * 3 = 6141 + +int main(int argc, char *argv[]) { + const char* d = (argc < 2) ? "/dev/vdc" : argv[1]; + + RawDisk *H = new RawDisk(d); + + printf("=== INode Alloc/Dealloc Test ===\n"); + INodeOperation inop; + inop.initialize(*H); + + // Test INode alloc and dealloc + int inode_list[2046] = {0}; // if we allocate 2047 inodes head will be 0 (faulty) + printf("freeInodeHead: %d \n", SuperBlock::getFreeINodeHead(*H)); // this impl should give 1 + for(int i=0;i<2046;i++){ + inode_list[i] = inop.inode_allocate(*H); + if (SuperBlock::getFreeINodeHead(*H) == 0) { + printf("%d\n",i); + assert(false); + } + } + printf("freeInodeHead: %d \n", SuperBlock::getFreeINodeHead(*H)); // this impl should give 2047 + for(int i=0;i<1024;i++){ + inop.inode_free(*H,inode_list[i]); + } + for(int i=0;i<1022;i++){ + inode_list[i] = inop.inode_allocate(*H); + assert(SuperBlock::getFreeINodeHead(*H) != 0); + } + printf("freeInodeHead: %d \n", SuperBlock::getFreeINodeHead(*H)); // this impl should give 2 + inode_list[1022] = inop.inode_allocate(*H); + printf("freeInodeHead: %d \n", SuperBlock::getFreeINodeHead(*H)); // this impl should give 1 + inode_list[1023] = inop.inode_allocate(*H); + printf("freeInodeHead: %d \n", SuperBlock::getFreeINodeHead(*H)); // this impl should give 2047 + + // Test Many Files + printf("=== Many Files Test ===\n"); + INode inode_inside[100]; + for(int i=0;i<100;i++){ + inode_inside[i].inode_construct(inode_list[i],*H); + for(int j=0;j<60;j++) { // Note that 1 indirect block is used for each file + u_int64_t allcBlockNum = inode_inside[i].datablock_allocate(*H); + if (SuperBlock::getFreeListHead(*H) >= (u_int64_t) 51200*512) { + printf("Bad FreeListHead: %d, %d, %llu\n", i, j, SuperBlock::getFreeListHead(*H)); + assert(false); + } + if (allcBlockNum % 2048 != 0 || allcBlockNum < 2048*512 || allcBlockNum >= 25*2048*512) { + printf("Bad Allocated Block Number: %d, %d, %llu\n", i, j, allcBlockNum); + assert(false); + } + } + } + printf("Finished Allocating\n"); + // in this impl should give 17*2048*512 = 17825792 + printf("freeListHead: %llu \n", SuperBlock::getFreeListHead(*H)); // if all 6141 blocks allocated, would give 51200*512 (faulty) + for(int i=0;i<100;i++){ + for(int j=0;j<59;j++){ + u_int64_t freedBlkNum = inode_inside[i].datablock_deallocate(*H); + u_int64_t fh = SuperBlock::getFreeListHead(*H); + if (freedBlkNum % 2048 != 0 || freedBlkNum < 2048*512 || freedBlkNum >= 25*2048*512 || fh >= 51200*512) { + printf("%d, %d, Freed Block Number: %llu\n", i, j, freedBlkNum); + printf("FreeListHead is %llu\n", fh); + assert(false); + } + } + } + printf("Finished Deallocating\n"); + printf("freeListHead: %d \n", SuperBlock::getFreeListHead(*H)); + + // Test Big File (Use direct, single indirect, double indirect) + printf("=== Big File Test ===\n"); + for(int j=0;j<5000;j++){ + u_int64_t allcBlockNum = inode_inside[0].datablock_allocate(*H); + u_int64_t fh = SuperBlock::getFreeListHead(*H); + if (allcBlockNum % 2048 != 0 || allcBlockNum < 2048*512 || allcBlockNum >= 25*2048*512 || fh >= 51200*512) { + printf("%d, Alloc Block Number: %llu\n", j, allcBlockNum); + printf("FreeListHead is %llu\n", fh); + assert(false); + } + } + printf("Finished Allocating\n"); + printf("freeListHead: %d \n", SuperBlock::getFreeListHead(*H)); + for(int j=0;j<5000;j++){ + u_int64_t freedBlkNum = inode_inside[0].datablock_deallocate(*H); + u_int64_t fh = SuperBlock::getFreeListHead(*H); + if (freedBlkNum % 2048 != 0 || freedBlkNum < 2048*512 || freedBlkNum >= 25*2048*512 || fh >= 51200*512) { + printf("%d, Freed Block Number: %llu\n", j, freedBlkNum); + printf("FreeListHead is %llu\n", fh); + assert(false); + } + } + printf("Finished Deallocating\n"); + printf("freeListHead: %d \n", SuperBlock::getFreeListHead(*H)); + + delete H; // Delete the RawDisk object + + return 0; +} From da703c02f0d4a4b1bb6b1a1243df5d564b2e0927 Mon Sep 17 00:00:00 2001 From: WangZiao Date: Sun, 12 Nov 2023 13:55:12 -0800 Subject: [PATCH 02/13] use GuangZhe's version of fs.h --- include/fs.h | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/include/fs.h b/include/fs.h index 962ae26..92542af 100644 --- a/include/fs.h +++ b/include/fs.h @@ -9,10 +9,8 @@ one inode equipped with one 512 bytes block *****************************************************/ #define SECTOR_SIZE 512 #define IO_BLOCK_SIZE 4096 -#define MAX_INODE 2048 -// 524288 -#define MAX_BLOCKNUM 51200 -// 1GB Disk: 2097152 = 196512 IO_BLOCK's. MAX_INODE*2 //62914560 +#define MAX_INODE 524288 +#define MAX_BLOCKNUM MAX_INODE*2 //62914560 class SuperBlock{ @@ -172,8 +170,8 @@ public: } } if (!notFull){ + printf("HEADER REMOVAL DETECTED %llu %llu\n", freeListHead, freeBlockNum); u_int64_t next_header = read_byte_at(0, buffer); - printf("HEADER MOVE (Cause: Alloc) %llu -> %llu (%llu)\n", freeListHead, next_header, freeBlockNum); SuperBlock::writeFreeListHead(disk, next_header); } return freeBlockNum; @@ -278,26 +276,22 @@ public: // find the related 2048block head u_int64_t freeBlockHead = ((freeBlockNum/SECTOR_SIZE-MAX_INODE)/(8*2048)*(8*2048)+MAX_INODE)*SECTOR_SIZE; + // mark it alive in its bitmap char buffer[IO_BLOCK_SIZE] = {0}; bool nowInList = false; disk.rawdisk_read(freeBlockHead, buffer, sizeof(buffer)); - - // mark it alive in its bitmap - u_int64_t inBlockPos = (freeBlockNum-freeBlockHead)/IO_BLOCK_SIZE-1; - buffer[8+inBlockPos/8] &= (-1)^(1<<(inBlockPos%8)); - - bool notEmpty = false; for (int i = 8; i < 264; i++){ if((i < 263 && buffer[i] != -1) || (i == 263 && buffer[i] != 127)){ nowInList = true; } } + u_int64_t inBlockPos = (freeBlockNum-freeBlockHead)/IO_BLOCK_SIZE-1; + buffer[8+inBlockPos/8] &= (-1)^(1<<(inBlockPos%8)); // if its bitmap was 0, add it back to the list head if(!nowInList){ u_int64_t freeListHead = SuperBlock::getFreeListHead(disk); write_byte_at(freeListHead, 0, buffer); - printf("HEADER MOVE (Cause: Dealloc) %llu -> %llu\n", freeListHead, freeBlockHead); SuperBlock::writeFreeListHead(disk, freeBlockHead); } disk.rawdisk_write(freeBlockHead, buffer, sizeof(buffer)); @@ -318,7 +312,6 @@ public: addr = 0; write_byte_at(addr, i, buffer); delpoint = i; - //printf("delpoint: %d\n", delpoint); break; } } @@ -392,10 +385,8 @@ public: freeBlockNum = deallo_triple_indirect(disk, triple_indirect); if(!freeBlockNum){ freeBlockNum = deallo_double_indirect(disk, double_indirect); - //printf("In fs.h, Inode::datablock_deallocate: finished dealloc double indirect, got %lld\n", freeBlockNum); if(!freeBlockNum){ freeBlockNum = deallo_single_indirect(disk, single_indirect); - //printf("In fs.h, Inode::datablock_deallocate: finished dealloc single indirect, got %lld\n", freeBlockNum); if(!freeBlockNum){ for(int i = 47; i>=0; i--) if(blocks[i] != 0){ From 3814ee040908edfe102033e2912eff054c4b17a3 Mon Sep 17 00:00:00 2001 From: WangZiao Date: Sun, 12 Nov 2023 14:38:37 -0800 Subject: [PATCH 03/13] test on top of GuangZhe's fix on layer1 --- include/fs.h | 7 ++++--- test/layer1_test1.cpp | 3 +++ 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/include/fs.h b/include/fs.h index 128e738..c162e30 100644 --- a/include/fs.h +++ b/include/fs.h @@ -9,8 +9,8 @@ one inode equipped with one 512 bytes block *****************************************************/ #define SECTOR_SIZE 512 #define IO_BLOCK_SIZE 4096 -#define MAX_INODE 524288 -#define MAX_BLOCKNUM MAX_INODE*2 //62914560 +#define MAX_INODE 2048 +#define MAX_BLOCKNUM 51200 //62914560 class SuperBlock{ @@ -169,8 +169,8 @@ public: } } if (!notFull){ - printf("HEADER REMOVAL DETECTED %llu %llu\n", freeListHead, freeBlockNum); u_int64_t next_header = read_byte_at(0, buffer); + printf("HEADER MOVE (Cause: Alloc) %llu -> %llu (%llu)\n", freeListHead, next_header, freeBlockNum); SuperBlock::writeFreeListHead(disk, next_header); } return freeBlockNum; @@ -291,6 +291,7 @@ public: if(!nowInList){ u_int64_t freeListHead = SuperBlock::getFreeListHead(disk); write_byte_at(freeListHead, 0, buffer); + printf("HEADER MOVE (Cause: Dealloc) %llu -> %llu\n", freeListHead, freeBlockHead); SuperBlock::writeFreeListHead(disk, freeBlockHead); } disk.rawdisk_write(freeBlockHead, buffer, sizeof(buffer)); diff --git a/test/layer1_test1.cpp b/test/layer1_test1.cpp index 27fa971..2943ecd 100644 --- a/test/layer1_test1.cpp +++ b/test/layer1_test1.cpp @@ -81,8 +81,10 @@ int main(int argc, char *argv[]) { // Test Big File (Use direct, single indirect, double indirect) printf("=== Big File Test ===\n"); + u_int64_t lastAllc = 0; for(int j=0;j<5000;j++){ u_int64_t allcBlockNum = inode_inside[0].datablock_allocate(*H); + lastAllc = allcBlockNum; u_int64_t fh = SuperBlock::getFreeListHead(*H); if (allcBlockNum % 2048 != 0 || allcBlockNum < 2048*512 || allcBlockNum >= 25*2048*512 || fh >= 51200*512) { printf("%d, Alloc Block Number: %llu\n", j, allcBlockNum); @@ -90,6 +92,7 @@ int main(int argc, char *argv[]) { assert(false); } } + printf("last allocate for big file: %llu\n", lastAllc); printf("Finished Allocating\n"); printf("freeListHead: %d \n", SuperBlock::getFreeListHead(*H)); for(int j=0;j<5000;j++){ From 85bf159ee0360f9e2283585252757eff96be76ff Mon Sep 17 00:00:00 2001 From: Connor Date: Tue, 14 Nov 2023 00:15:03 -0800 Subject: [PATCH 04/13] temporary addition of new header structure --- .gitignore | 16 +- .vscode/settings.json | 6 + CMakeLists.txt | 3 + Issues.txt | 63 +++ include/fs.h | 806 +++++++++++++++-------------- include/fs.hpp | 33 ++ include/fs/datablock_allocator.hpp | 32 ++ include/fs/fs_data_types.hpp | 45 ++ include/fs/inode_allocator.hpp | 40 ++ include/rawdisk.h | 82 --- include/rawdisk.hpp | 95 ++++ lib/fs/datablock_allocator.cpp | 75 +++ lib/fs/fs.cpp | 78 +++ lib/fs/fs_data_types.cpp | 89 ++++ lib/fs/fs_resize.cpp | 0 lib/fs/inode_allocator.cpp | 29 ++ 16 files changed, 1007 insertions(+), 485 deletions(-) create mode 100644 .vscode/settings.json create mode 100644 Issues.txt create mode 100644 include/fs.hpp create mode 100644 include/fs/datablock_allocator.hpp create mode 100644 include/fs/fs_data_types.hpp create mode 100644 include/fs/inode_allocator.hpp delete mode 100644 include/rawdisk.h create mode 100644 include/rawdisk.hpp create mode 100644 lib/fs/datablock_allocator.cpp create mode 100644 lib/fs/fs.cpp create mode 100644 lib/fs/fs_data_types.cpp create mode 100644 lib/fs/fs_resize.cpp create mode 100644 lib/fs/inode_allocator.cpp diff --git a/.gitignore b/.gitignore index 07ed706..48dd518 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,15 @@ -build/* \ No newline at end of file +build/* + +# vscode gitignore +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +!.vscode/*.code-snippets + +# Local History for Visual Studio Code +.history/ + +# Built Visual Studio Code Extensions +*.vsix \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..d6ef3d1 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,6 @@ +{ + "cmake.configureOnOpen": false, + "cSpell.words": [ + "unneccary" + ] +} \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index f0c5624..b660f23 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,6 +13,9 @@ add_executable(fischl # Header files lib/fischl.cpp lib/main.cpp + lib/fs/fs_data_types.cpp + lib/fs/fs_resize.cpp + lib/fs/fs.cpp ) diff --git a/Issues.txt b/Issues.txt new file mode 100644 index 0000000..c3ee9ec --- /dev/null +++ b/Issues.txt @@ -0,0 +1,63 @@ +Problem - no header guards +Problem - code in header file +Problem - inconisitent use of SECTOR_SIZE IO_BLOCK_SIZE + + +?18: what is directory + +22: read of less than sector-size unpermitted + +?25: does the casting here work as expected, would a bitmask be better + +Question: why are we passing a disk every time to superblock functions, shouldn't that be associated with the superblock (i.e. the file system object) + +37: same issues with this function + +Superblock should be read and written to all at once to avoid unneccary io reads and should be stateful regarding the fs data (also it maybe good to rename superblock to fs and make it in charge of formatting the fs) + +57: magic num + +?69: strange reference pattern with current_pos - usually handled by func returning num bytes read + +?69: should these helper functions be in the inode at all + +?76: these two funcs could be combined together + +?83: inode_construct may want to be named inode_load to fit pattern + +inode objs (block_number) should likely be able to be made with out the use of inode_construct when they are first created + + +132: + +?142: odd use of block nums - byte addresses and io_block addresses + +143: magic num 32? + +?144: possibly make this a continue also use 0b11111111 and 0b01111111 + +?145: j = 0 twice + +?76: why is this function read_byte_at if it reads 8 bytes + +?144: why is the last bit of the bitmask unused + +?171: returned free must be zeroed before use + +177: no error handling for cannot allocate block (free list empty) + +?215: should this be made into a recursive func + +241: no error checking + +278: the empty checking and adding to free list head seems busted + +303: -- + +?315: && addr == 0 does nothing + +398: can try to deallocate the super block so // deal with empty needs implementation + +?433: why even mix sector size into free list + +428: no limit checking \ No newline at end of file diff --git a/include/fs.h b/include/fs.h index 067d595..2b7d143 100644 --- a/include/fs.h +++ b/include/fs.h @@ -1,8 +1,8 @@ #include "rawdisk.h" /***************************************************** -30GB Disk low-level operation and data structure: spuerblock, inode, and buffer cache -512 bytes sector for 1 block, 62914560 block(sector) -4K bytes sector for 1 block, 7864320 block(sector) +30GB Disk low-level operation and data structure: spuerblock, inode, and buffer +cache 512 bytes sector for 1 block, 62914560 block(sector) 4K bytes sector for 1 +block, 7864320 block(sector) one inode equipped with one 512 bytes block @@ -10,455 +10,457 @@ one inode equipped with one 512 bytes block #define SECTOR_SIZE 512 #define IO_BLOCK_SIZE 4096 #define MAX_INODE 524288 -#define MAX_BLOCKNUM MAX_INODE*2 //62914560 +#define MAX_BLOCKNUM MAX_INODE * 2 // 62914560 -class SuperBlock{ +class SuperBlock { public: - SuperBlock(const char *directory){ + SuperBlock(const char *directory) {} + ~SuperBlock() {} + static u_int64_t getFreeListHead(RawDisk &disk) { + char buffer[8] = {0}; + disk.rawdisk_read(0, buffer, sizeof(buffer)); + u_int64_t t = 0; + for (int j = 0; j < 8; j++) + t = t | (((u_int64_t)(unsigned char)buffer[j]) << (8 * j)); + return t; + } + static void writeFreeListHead(RawDisk &disk, u_int64_t t) { + char buffer[8] = {0}; + for (int j = 0; j < 8; j++) { + buffer[j] = (t >> (8 * j)) & 0xFF; } - ~SuperBlock(){ + disk.rawdisk_write(0, buffer, sizeof(buffer)); + } - } - static u_int64_t getFreeListHead(RawDisk &disk){ - char buffer[8] = {0}; - disk.rawdisk_read(0, buffer, sizeof(buffer)); - u_int64_t t = 0; - for (int j = 0; j < 8; j++) - t = t | (((u_int64_t)(unsigned char)buffer[j])<<(8*j)); - return t; - } + static u_int64_t getFreeINodeHead(RawDisk &disk) { + char buffer[8] = {0}; + disk.rawdisk_read(8, buffer, sizeof(buffer)); + u_int64_t t = 0; + for (int j = 0; j < 8; j++) + t = t | (((u_int64_t)(unsigned char)buffer[j]) << (8 * j)); + return t; + } - static void writeFreeListHead(RawDisk &disk, u_int64_t t){ - char buffer[8] = {0}; - for (int j = 0; j < 8; j++){ - buffer[j] = (t >> (8 * j)) & 0xFF; - } - disk.rawdisk_write(0, buffer, sizeof(buffer)); - } - - static u_int64_t getFreeINodeHead(RawDisk &disk){ - char buffer[8] = {0}; - disk.rawdisk_read(8, buffer, sizeof(buffer)); - u_int64_t t = 0; - for (int j = 0; j < 8; j++) - t = t | (((u_int64_t)(unsigned char)buffer[j])<<(8*j)); - return t; - } - - static void writeFreeINodeHead(RawDisk &disk, u_int64_t t){ - char buffer[8] = {0}; - for (int j = 0; j < 8; j++){ - buffer[j] = (t >> (8 * j)) & 0xFF; - } - disk.rawdisk_write(8, buffer, sizeof(buffer)); + static void writeFreeINodeHead(RawDisk &disk, u_int64_t t) { + char buffer[8] = {0}; + for (int j = 0; j < 8; j++) { + buffer[j] = (t >> (8 * j)) & 0xFF; } + disk.rawdisk_write(8, buffer, sizeof(buffer)); + } }; -class INode{ - // direct datablocks - u_int64_t blocks[48]; - // indirect address - u_int64_t single_indirect, double_indirect, triple_indirect; - // other +class INode { + // direct datablocks + u_int64_t blocks[48]; + // indirect address + u_int64_t single_indirect, double_indirect, triple_indirect; + // other - u_int64_t uid; - u_int64_t gid; - u_int64_t permissions; - u_int64_t size; - u_int64_t block_number; + u_int64_t uid; + u_int64_t gid; + u_int64_t permissions; + u_int64_t size; + u_int64_t block_number; public: - void read_get_byte(u_int64_t &t, int ¤t_pos, char *buffer){ - t = 0; - for (int j = 0; j < 8; j++) - t = t | (((u_int64_t)(unsigned char)buffer[j+current_pos])<<(8*j)); - current_pos += 8; + void read_get_byte(u_int64_t &t, int ¤t_pos, char *buffer) { + t = 0; + for (int j = 0; j < 8; j++) + t = t | (((u_int64_t)(unsigned char)buffer[j + current_pos]) << (8 * j)); + current_pos += 8; + } + + static u_int64_t read_byte_at(int current_pos, char *buffer) { + u_int64_t t = 0; + for (int j = 0; j < 8; j++) + t = t | (((u_int64_t)(unsigned char)buffer[j + current_pos]) << (8 * j)); + return t; + } + + void inode_construct(u_int64_t blockNumber, RawDisk &disk) { + char buffer[SECTOR_SIZE] = {0}; + disk.rawdisk_read(blockNumber * SECTOR_SIZE, buffer, sizeof(buffer)); + block_number = blockNumber; + int current_pos = 0; + // initialize blocks + for (int i = 0; i < 48; i++) { + read_get_byte(blocks[i], current_pos, buffer); } + read_get_byte(single_indirect, current_pos, buffer); + read_get_byte(double_indirect, current_pos, buffer); + read_get_byte(triple_indirect, current_pos, buffer); + read_get_byte(uid, current_pos, buffer); + read_get_byte(gid, current_pos, buffer); + read_get_byte(permissions, current_pos, buffer); + read_get_byte(size, current_pos, buffer); + } - static u_int64_t read_byte_at(int current_pos, char *buffer){ - u_int64_t t = 0; - for (int j = 0; j < 8; j++) - t = t | (((u_int64_t)(unsigned char)buffer[j+current_pos])<<(8*j)); - return t; + void write_get_byte(u_int64_t t, int ¤t_pos, char *buffer) { + for (int j = 0; j < 8; j++) { + buffer[j + current_pos] = t & (((u_int64_t)1 << (8)) - 1); + t >>= 8; } + current_pos += 8; + } - void inode_construct(u_int64_t blockNumber, RawDisk &disk){ - char buffer[SECTOR_SIZE] = {0}; - disk.rawdisk_read(blockNumber*SECTOR_SIZE, buffer, sizeof(buffer)); - block_number = blockNumber; - int current_pos = 0; - // initialize blocks - for (int i = 0; i < 48; i++){ - read_get_byte(blocks[i], current_pos, buffer); - } - read_get_byte(single_indirect, current_pos, buffer); - read_get_byte(double_indirect, current_pos, buffer); - read_get_byte(triple_indirect, current_pos, buffer); - read_get_byte(uid, current_pos, buffer); - read_get_byte(gid, current_pos, buffer); - read_get_byte(permissions, current_pos, buffer); - read_get_byte(size, current_pos, buffer); + static void write_byte_at(u_int64_t t, int current_pos, char *buffer) { + for (int j = 0; j < 8; j++) { + buffer[j + current_pos] = t & (((u_int64_t)1 << (8)) - 1); + t >>= 8; } + } - void write_get_byte(u_int64_t t, int ¤t_pos, char *buffer){ - for (int j = 0; j < 8; j++){ - buffer[j+current_pos] = t & (((u_int64_t)1<<(8))-1); - t >>= 8; - } - current_pos += 8; + void inode_save(RawDisk &disk) { + char buffer[SECTOR_SIZE] = {0}; + int current_pos = 0; + for (int i = 0; i < 48; i++) { + write_get_byte(blocks[i], current_pos, buffer); } + write_get_byte(single_indirect, current_pos, buffer); + write_get_byte(double_indirect, current_pos, buffer); + write_get_byte(triple_indirect, current_pos, buffer); + write_get_byte(uid, current_pos, buffer); + write_get_byte(gid, current_pos, buffer); + write_get_byte(permissions, current_pos, buffer); + write_get_byte(size, current_pos, buffer); + disk.rawdisk_write(block_number * SECTOR_SIZE, buffer, sizeof(buffer)); + } - static void write_byte_at(u_int64_t t, int current_pos, char *buffer){ - for (int j = 0; j < 8; j++){ - buffer[j+current_pos] = t & (((u_int64_t)1<<(8))-1); - t >>= 8; + u_int64_t datablock_allocate_in_list(RawDisk &disk) { + // find a free data block + u_int64_t freeListHead = SuperBlock::getFreeListHead(disk); + /* + 1. initialization + 2. data block starting position + 3. r/w between storage and rawdisk to maintain + */ + char buffer[IO_BLOCK_SIZE] = {0}; + u_int64_t freeBlockNum = 0; + disk.rawdisk_read(freeListHead, buffer, sizeof(buffer)); + for (int i = 8; i < 264; i++) { + if ((i < 263 && buffer[i] != -1) || (i == 263 && buffer[i] != 127)) { + int j = 0; + for (j = 0; j < 8; j++) { + if ((buffer[i] & (1 << j)) == 0) { + buffer[i] |= (1 << j); + break; + } } + if (j < 8) { + freeBlockNum = freeListHead + ((i - 8) * 8 + j + 1) * IO_BLOCK_SIZE; + break; + } + } } - - void inode_save(RawDisk &disk){ - char buffer[SECTOR_SIZE] = {0}; - int current_pos = 0; - for (int i = 0; i < 48; i++){ - write_get_byte(blocks[i], current_pos, buffer); - } - write_get_byte(single_indirect, current_pos, buffer); - write_get_byte(double_indirect, current_pos, buffer); - write_get_byte(triple_indirect, current_pos, buffer); - write_get_byte(uid, current_pos, buffer); - write_get_byte(gid, current_pos, buffer); - write_get_byte(permissions, current_pos, buffer); - write_get_byte(size, current_pos, buffer); - disk.rawdisk_write(block_number*SECTOR_SIZE, buffer, sizeof(buffer)); + disk.rawdisk_write(freeListHead, buffer, sizeof(buffer)); + bool notFull = false; + for (int i = 8; i < 264; i++) { + if ((i < 263 && buffer[i] != -1) || (i == 263 && buffer[i] != 127)) { + notFull = true; + break; + } } - - u_int64_t datablock_allocate_in_list(RawDisk &disk){ - //find a free data block - u_int64_t freeListHead = SuperBlock::getFreeListHead(disk); - /* - 1. initialization - 2. data block starting position - 3. r/w between storage and rawdisk to maintain - */ - char buffer[IO_BLOCK_SIZE] = {0}; - u_int64_t freeBlockNum = 0; - disk.rawdisk_read(freeListHead, buffer, sizeof(buffer)); - for (int i = 8; i < 264; i++){ - if((i < 263 && buffer[i] != -1) || (i == 263 && buffer[i] != 127)){ - int j = 0; - for (j = 0; j < 8; j++){ - if ((buffer[i]&(1<= 0; i--){ - u_int64_t addr = read_byte_at(i, buffer); - if(addr != 0){ - freeBlockNum = addr; - addr = 0; - write_byte_at(addr, i, buffer); - delpoint = i; - break; - } - } + bool inSingle = false; + char buffer[IO_BLOCK_SIZE] = {0}; + disk.rawdisk_read(single_i, buffer, sizeof(buffer)); + for (int i = 0; i < IO_BLOCK_SIZE; i += 8) { + u_int64_t addr = read_byte_at(i, buffer); + if (addr == 0) { + inSingle = true; + write_byte_at(freeBlockNum, i, buffer); disk.rawdisk_write(single_i, buffer, sizeof(buffer)); - u_int64_t addr = read_byte_at(0, buffer); - if (delpoint == 0 && addr == 0){ - datablock_deallocate_in_list(single_i, disk); - single_i = 0; - } - return freeBlockNum; + break; + } } + return inSingle; + } - bool deallo_double_indirect(RawDisk &disk, u_int64_t &double_i){ - if (double_i == 0){ - return false; - } - u_int64_t freeBlockNum = 0; - char buffer[IO_BLOCK_SIZE] = {0}; - int delpoint = -1; - disk.rawdisk_read(double_i, buffer, sizeof(buffer)); - for (int i=4088; i >= 0; i-=8){ - u_int64_t addr = read_byte_at(i, buffer); - u_int64_t inSingle = deallo_single_indirect(disk, addr); - if (inSingle){ - freeBlockNum = inSingle; - write_byte_at(addr, i, buffer); - delpoint = i; - break; - } - } + bool allo_double_indirect(RawDisk &disk, u_int64_t &double_i, + u_int64_t freeBlockNum) { + if (double_i == 0) { + double_i = datablock_allocate_in_list(disk); + } + bool inDouble = false; + char buffer[IO_BLOCK_SIZE] = {0}; + disk.rawdisk_read(double_i, buffer, sizeof(buffer)); + for (int i = 0; i < IO_BLOCK_SIZE; i += 8) { + u_int64_t addr = read_byte_at(i, buffer); + bool flag = allo_single_indirect(disk, addr, freeBlockNum); + if (flag) { + write_byte_at(addr, i, buffer); disk.rawdisk_write(double_i, buffer, sizeof(buffer)); - u_int64_t addr = read_byte_at(0, buffer); - if (delpoint == 0 && addr == 0){ - datablock_deallocate_in_list(double_i, disk); - double_i = 0; - } - return freeBlockNum; + inDouble = true; + break; + } } + return inDouble; + } - bool deallo_triple_indirect(RawDisk &disk, u_int64_t &triple_i){ - if (triple_i == 0){ - return false; - } - u_int64_t freeBlockNum = 0; - char buffer[IO_BLOCK_SIZE] = {0}; - int delpoint = -1; - disk.rawdisk_read(triple_i, buffer, sizeof(buffer)); - for (int i=4088; i >= 0; i-=8){ - u_int64_t addr = read_byte_at(i, buffer); - u_int64_t inDouble = deallo_double_indirect(disk, addr); - if (inDouble){ - freeBlockNum = inDouble; - write_byte_at(addr, i, buffer); - delpoint = i; - break; - } - } + bool allo_triple_indirect(RawDisk &disk, u_int64_t &triple_i, + u_int64_t freeBlockNum) { + if (triple_i == 0) { + triple_i = datablock_allocate_in_list(disk); + } + bool inTriple = false; + char buffer[IO_BLOCK_SIZE] = {0}; + disk.rawdisk_read(triple_i, buffer, sizeof(buffer)); + for (int i = 0; i < IO_BLOCK_SIZE; i += 8) { + u_int64_t addr = read_byte_at(i, buffer); + bool flag = allo_double_indirect(disk, addr, freeBlockNum); + if (flag) { + write_byte_at(addr, i, buffer); disk.rawdisk_write(triple_i, buffer, sizeof(buffer)); - u_int64_t addr = read_byte_at(0, buffer); - if (delpoint == 0 && addr == 0){ - datablock_deallocate_in_list(triple_i, disk); - triple_i = 0; + inTriple = true; + break; + } + } + return inTriple; + } + + // allowcate 1 datablock and add to the end of the file + u_int64_t datablock_allocate(RawDisk &disk) { + // do we need to check dynamic? + + // add the data block to blocks, single, double, triple + u_int64_t freeBlockNum = datablock_allocate_in_list(disk); + bool inBlocks = false; + for (int i = 0; i < 48; i++) + if (blocks[i] == 0) { + inBlocks = true; + blocks[i] = freeBlockNum; + break; + } + if (!inBlocks) { + bool inSingle = allo_single_indirect(disk, single_indirect, freeBlockNum); + if (!inSingle) { + bool inDouble = + allo_double_indirect(disk, double_indirect, freeBlockNum); + if (!inDouble) { + bool inTriple = + allo_triple_indirect(disk, triple_indirect, freeBlockNum); + // wait to deal with too big files } - return freeBlockNum; + } } - // deallocate 1 datablock from the end of the file - u_int64_t datablock_deallocate(RawDisk &disk){ - // find the last datablock and remove it from inode (triple->direct) - u_int64_t freeBlockNum = 0; - freeBlockNum = deallo_triple_indirect(disk, triple_indirect); - if(!freeBlockNum){ - freeBlockNum = deallo_double_indirect(disk, double_indirect); - if(!freeBlockNum){ - freeBlockNum = deallo_single_indirect(disk, single_indirect); - if(!freeBlockNum){ - for(int i = 47; i>=0; i--) - if(blocks[i] != 0){ - freeBlockNum = blocks[i]; - blocks[i] = 0; - break; - } - // deal with empty - } + // return the block number + inode_save(disk); + return freeBlockNum; + } + + void datablock_deallocate_in_list(u_int64_t freeBlockNum, RawDisk &disk) { + // find the related 2048block head + u_int64_t freeBlockHead = + ((freeBlockNum / SECTOR_SIZE - MAX_INODE) / (8 * 2048) * (8 * 2048) + + MAX_INODE) * + SECTOR_SIZE; + + // mark it alive in its bitmap + char buffer[IO_BLOCK_SIZE] = {0}; + bool notEmpty = false; + disk.rawdisk_read(freeBlockHead, buffer, sizeof(buffer)); + for (int i = 8; i < 264; i++) { + if (buffer[i] != 0) { + notEmpty = true; + } + } + u_int64_t inBlockPos = (freeBlockNum - freeBlockHead) / IO_BLOCK_SIZE - 1; + buffer[8 + inBlockPos / 8] &= (-1) ^ (1 << (inBlockPos % 8)); + + // if its bitmap was 0, add it back to the list head + if (!notEmpty) { + u_int64_t freeListHead = SuperBlock::getFreeListHead(disk); + write_byte_at(freeListHead, 0, buffer); + SuperBlock::writeFreeListHead(disk, freeBlockHead); + } + disk.rawdisk_write(freeBlockHead, buffer, sizeof(buffer)); + } + + u_int64_t deallo_single_indirect(RawDisk &disk, u_int64_t &single_i) { + if (single_i == 0) { + return 0; + } + u_int64_t freeBlockNum = 0; + char buffer[IO_BLOCK_SIZE] = {0}; + int delpoint = -1; + disk.rawdisk_read(single_i, buffer, sizeof(buffer)); + for (int i = 4088; i >= 0; i--) { + u_int64_t addr = read_byte_at(i, buffer); + if (addr != 0) { + freeBlockNum = addr; + addr = 0; + write_byte_at(addr, i, buffer); + delpoint = i; + break; + } + } + disk.rawdisk_write(single_i, buffer, sizeof(buffer)); + u_int64_t addr = read_byte_at(0, buffer); + if (delpoint == 0 && addr == 0) { + datablock_deallocate_in_list(single_i, disk); + single_i = 0; + } + return freeBlockNum; + } + + bool deallo_double_indirect(RawDisk &disk, u_int64_t &double_i) { + if (double_i == 0) { + return false; + } + u_int64_t freeBlockNum = 0; + char buffer[IO_BLOCK_SIZE] = {0}; + int delpoint = -1; + disk.rawdisk_read(double_i, buffer, sizeof(buffer)); + for (int i = 4088; i >= 0; i -= 8) { + u_int64_t addr = read_byte_at(i, buffer); + u_int64_t inSingle = deallo_single_indirect(disk, addr); + if (inSingle) { + freeBlockNum = inSingle; + write_byte_at(addr, i, buffer); + delpoint = i; + break; + } + } + disk.rawdisk_write(double_i, buffer, sizeof(buffer)); + u_int64_t addr = read_byte_at(0, buffer); + if (delpoint == 0 && addr == 0) { + datablock_deallocate_in_list(double_i, disk); + double_i = 0; + } + return freeBlockNum; + } + + bool deallo_triple_indirect(RawDisk &disk, u_int64_t &triple_i) { + if (triple_i == 0) { + return false; + } + u_int64_t freeBlockNum = 0; + char buffer[IO_BLOCK_SIZE] = {0}; + int delpoint = -1; + disk.rawdisk_read(triple_i, buffer, sizeof(buffer)); + for (int i = 4088; i >= 0; i -= 8) { + u_int64_t addr = read_byte_at(i, buffer); + u_int64_t inDouble = deallo_double_indirect(disk, addr); + if (inDouble) { + freeBlockNum = inDouble; + write_byte_at(addr, i, buffer); + delpoint = i; + break; + } + } + disk.rawdisk_write(triple_i, buffer, sizeof(buffer)); + u_int64_t addr = read_byte_at(0, buffer); + if (delpoint == 0 && addr == 0) { + datablock_deallocate_in_list(triple_i, disk); + triple_i = 0; + } + return freeBlockNum; + } + + // deallocate 1 datablock from the end of the file + u_int64_t datablock_deallocate(RawDisk &disk) { + // find the last datablock and remove it from inode (triple->direct) + u_int64_t freeBlockNum = 0; + freeBlockNum = deallo_triple_indirect(disk, triple_indirect); + if (!freeBlockNum) { + freeBlockNum = deallo_double_indirect(disk, double_indirect); + if (!freeBlockNum) { + freeBlockNum = deallo_single_indirect(disk, single_indirect); + if (!freeBlockNum) { + for (int i = 47; i >= 0; i--) + if (blocks[i] != 0) { + freeBlockNum = blocks[i]; + blocks[i] = 0; + break; } + // deal with empty } - - // add it back to freeBlocklist - datablock_deallocate_in_list(freeBlockNum, disk); - inode_save(disk); - return freeBlockNum; + } } + + // add it back to freeBlocklist + datablock_deallocate_in_list(freeBlockNum, disk); + inode_save(disk); + return freeBlockNum; + } }; -class INodeOperation{ -// free list head is at super block (0): first 8 bytes +class INodeOperation { + // free list head is at super block (0): first 8 bytes public: - //initialization of the rawdisk - void initialize(RawDisk &disk){ - // initialize Inode list head - SuperBlock::writeFreeINodeHead(disk, 1); - for (u_int64_t i = 1; i < MAX_INODE; i++){ - char buffer[SECTOR_SIZE] = {0}; - u_int64_t t = i + 1; - if (t < MAX_INODE){ - for (int j = 0; j < 8; j++){ - buffer[j] = (t >> (8 * j)) & 0xFF; - } - } - disk.rawdisk_write(i*SECTOR_SIZE, buffer, sizeof(buffer)); - } - SuperBlock::writeFreeListHead(disk, MAX_INODE*SECTOR_SIZE); // maximum inode number 2^19 0x80000 - //Have tested this initialize function but MAX_BLOCK too much, MAX_INODE*2 works - for (u_int64_t i = MAX_INODE; i < MAX_BLOCKNUM-4096; i += 2048*8){ - char buffer[IO_BLOCK_SIZE] = {0}; - u_int64_t t = (i + 2048*8)*SECTOR_SIZE; - //t is address, storing in to buffer - for (int j = 0; j < 8; j++){ - buffer[j] = (t >> (8 * j)) & 0xFF; - } - disk.rawdisk_write(i*SECTOR_SIZE, buffer, sizeof(buffer)); + // initialization of the rawdisk + void initialize(RawDisk &disk) { + // initialize Inode list head + SuperBlock::writeFreeINodeHead(disk, 1); + for (u_int64_t i = 1; i < MAX_INODE; i++) { + char buffer[SECTOR_SIZE] = {0}; + u_int64_t t = i + 1; + if (t < MAX_INODE) { + for (int j = 0; j < 8; j++) { + buffer[j] = (t >> (8 * j)) & 0xFF; } + } + disk.rawdisk_write(i * SECTOR_SIZE, buffer, sizeof(buffer)); } - - // allocate an inode from free inode list head and return the number of the inode - // the i-th inode is in the i-th block - u_int64_t inode_allocate(RawDisk &disk){ - u_int64_t freeINodeHead = SuperBlock::getFreeINodeHead(disk); - char buffer[SECTOR_SIZE] = {0}; - disk.rawdisk_read(freeINodeHead*SECTOR_SIZE, buffer, sizeof(buffer)); - u_int64_t newINodeHead = INode::read_byte_at(0, buffer); - // deal with no more INode - SuperBlock::writeFreeINodeHead(disk, newINodeHead); - //to do: initialize the INode on disk at freeINodeHead - - //return inode number - return freeINodeHead; + SuperBlock::writeFreeListHead( + disk, MAX_INODE * SECTOR_SIZE); // maximum inode number 2^19 0x80000 + // Have tested this initialize function but MAX_BLOCK too much, MAX_INODE*2 + // works + for (u_int64_t i = MAX_INODE; i < MAX_BLOCKNUM - 4096; i += 2048 * 8) { + char buffer[IO_BLOCK_SIZE] = {0}; + u_int64_t t = (i + 2048 * 8) * SECTOR_SIZE; + // t is address, storing in to buffer + for (int j = 0; j < 8; j++) { + buffer[j] = (t >> (8 * j)) & 0xFF; + } + disk.rawdisk_write(i * SECTOR_SIZE, buffer, sizeof(buffer)); } + } - // free the inode and add it to the free inode list head - void inode_free(RawDisk &disk, u_int64_t INodeNumber){ - u_int64_t freeINodeHead = SuperBlock::getFreeINodeHead(disk); - char buffer[SECTOR_SIZE] = {0}; - INode::write_byte_at(freeINodeHead, 0, buffer); - disk.rawdisk_write(INodeNumber*SECTOR_SIZE, buffer, sizeof(buffer)); - SuperBlock::writeFreeINodeHead(disk, INodeNumber); - } + // allocate an inode from free inode list head and return the number of the + // inode the i-th inode is in the i-th block + u_int64_t inode_allocate(RawDisk &disk) { + u_int64_t freeINodeHead = SuperBlock::getFreeINodeHead(disk); + char buffer[SECTOR_SIZE] = {0}; + disk.rawdisk_read(freeINodeHead * SECTOR_SIZE, buffer, sizeof(buffer)); + u_int64_t newINodeHead = INode::read_byte_at(0, buffer); + // deal with no more INode + SuperBlock::writeFreeINodeHead(disk, newINodeHead); + // to do: initialize the INode on disk at freeINodeHead - //ignore for now - void inode_read(){ + // return inode number + return freeINodeHead; + } - } + // free the inode and add it to the free inode list head + void inode_free(RawDisk &disk, u_int64_t INodeNumber) { + u_int64_t freeINodeHead = SuperBlock::getFreeINodeHead(disk); + char buffer[SECTOR_SIZE] = {0}; + INode::write_byte_at(freeINodeHead, 0, buffer); + disk.rawdisk_write(INodeNumber * SECTOR_SIZE, buffer, sizeof(buffer)); + SuperBlock::writeFreeINodeHead(disk, INodeNumber); + } - void inode_write(){ + // ignore for now + void inode_read() {} - } + void inode_write() {} }; \ No newline at end of file diff --git a/include/fs.hpp b/include/fs.hpp new file mode 100644 index 0000000..5063c5c --- /dev/null +++ b/include/fs.hpp @@ -0,0 +1,33 @@ +#ifndef FS_HPP +#define FS_HPP + +#include "fs/datablock_allocator.hpp" +#include "fs/fs_data_types.hpp" +#include "fs/inode_allocator.hpp" +#include "rawdisk.hpp" + +#define NUM_INODE_BLOCKS 1023 +#define NUM_BLOCKS 2048 + +class Fs { +public: + Fs(RawDisk *disk); + + int resize(INode_Data *inode_data, u_int64_t size, bool absolute); + + int format(); + + // should probably be private but is not for testing + RawDisk *disk; + SuperBlock_Data superblock; + INode_Allocator inode_allocator; + DataBlock_Allocator datablock_allocator; + + int load_superblock(); + int store_superblock(); + + int load_inode(INode_Data *inode_data); + int store_inode(INode_Data *inode_data); +}; + +#endif \ No newline at end of file diff --git a/include/fs/datablock_allocator.hpp b/include/fs/datablock_allocator.hpp new file mode 100644 index 0000000..764ab72 --- /dev/null +++ b/include/fs/datablock_allocator.hpp @@ -0,0 +1,32 @@ +#ifndef DATABLOCK_ALLOCATOR_HPP +#define DATABLOCK_ALLOCATOR_HPP + +class Fs; + +class DataBlock_Allocator { +public: + DataBlock_Allocator(Fs *fs, u_int64_t block_segment_start, + u_int64_t block_segment_end); + + virtual int new_datablock(u_int64_t *block_num) = 0; + virtual int free_datablock(u_int64_t block_num) = 0; + + virtual int format() = 0; + +protected: + Fs *fs; + u_int64_t block_segment_start, block_segment_end; +}; + +class DataBlock_Allocator_Bitmap : DataBlock_Allocator { + using DataBlock_Allocator::DataBlock_Allocator; + + const int DATABLOCKS_PER_BITMAP_BLOCK = 255; + + int new_datablock(u_int64_t *block_num) override; + int free_datablock(u_int64_t block_num) override; + + int format() override; +}; + +#endif \ No newline at end of file diff --git a/include/fs/fs_data_types.hpp b/include/fs/fs_data_types.hpp new file mode 100644 index 0000000..f3958ea --- /dev/null +++ b/include/fs/fs_data_types.hpp @@ -0,0 +1,45 @@ +#ifndef FS_DATA_TYPES_HPP +#define FS_DATA_TYPES_HPP + +#include "rawdisk.hpp" + +#define INODE_SIZE 512 + +size_t write_u64(u_int64_t num, char buf[]); + +size_t read_u64(u_int64_t *num, char buf[]); + +class SuperBlock_Data { + u_int64_t free_list_head; + u_int64_t inode_list_head; + SuperBlock_Data(); + void serialize(char buf[]); + void deserialize(char buf[]); +}; + +class INode_Data { + u_int64_t inode_num; + +#define NUMBER_OF_METADATA_BYTES (4 * sizeof(u_int64_t) + sizeof(u_int32_t)) + struct INode_MetaData { + u_int64_t uid; + u_int64_t gid; + u_int64_t permissions; + u_int64_t size; // not yet implemented + u_int32_t reference_count; + } metadata; + size_t serialize_metadata(char buf[]); + size_t deserialize_metadata(char buf[]); + + const size_t NUMBER_OF_DIRECT_BLOCKS = + ((INODE_SIZE - NUMBER_OF_METADATA_BYTES) / sizeof(u_int64_t)) - 3; + + u_int64_t single_indirect_block, double_indirect_block, triple_indirect_block; + u_int64_t direct_blocks[NUMBER_OF_DIRECT_BLOCKS]; + + INode_Data(u_int64_t inode_num); + void serialize(char buf[]); + void deserialize(char buf[]); +}; + +#endif \ No newline at end of file diff --git a/include/fs/inode_allocator.hpp b/include/fs/inode_allocator.hpp new file mode 100644 index 0000000..fca64f0 --- /dev/null +++ b/include/fs/inode_allocator.hpp @@ -0,0 +1,40 @@ +#ifndef INODE_ALLOCATOR_HPP +#define INODE_ALLOCATOR_HPP + +#include "fs_data_types.hpp" +#include "rawdisk.hpp" + +class Fs; + +class INode_Allocator { +public: + const int INODES_PER_BLOCK = BLOCK_SIZE / INODE_SIZE; + + INode_Allocator(Fs *fs, u_int64_t block_segment_start, + u_int64_t block_segment_end); + + virtual int new_inode(u_int64_t uid, u_int64_t gid, u_int64_t permissions, + INode_Data *inode_data) = 0; + virtual int free_inode(INode_Data *inode_data) = 0; + + virtual int format() = 0; + + u_int64_t get_block_num(INode_Data *inode_data); + u_int64_t get_block_offset(INode_Data *inode_data); + +protected: + Fs *fs; + u_int64_t block_segment_start, block_segment_end; +}; + +class INode_Allocator_Freelist : INode_Allocator { + using INode_Allocator::INode_Allocator; + + int new_inode(u_int64_t uid, u_int64_t gid, u_int64_t permissions, + INode_Data *inode_data) override; + int free_inode(INode_Data *inode_data) override; + + int format() override; +}; + +#endif \ No newline at end of file diff --git a/include/rawdisk.h b/include/rawdisk.h deleted file mode 100644 index 4cccf70..0000000 --- a/include/rawdisk.h +++ /dev/null @@ -1,82 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -class RawDisk{ - - int fd; - const char* dir; - u_int64_t numSectors; - u_int64_t diskSize; - -public: - RawDisk(const char *directory) : fd(-1), dir(nullptr), numSectors(0), diskSize(0) { - dir = directory; - /*dir = strdup("/dev/vdc"); - numSectors = 62914560; - diskSize = 32212254720;*/ - - // Open the block device (replace /dev/sdX with the actual device) - fd = open(dir, O_RDWR); // Allow read and write - if (fd == -1) { - perror("Error opening device"); - exit(1); - } - - // Use ioctl with BLKGETSIZE to get the number of sectors - if (ioctl(fd, BLKGETSIZE64, &diskSize) == -1) { - perror("Error getting disk size"); - close(fd); - exit(1); - } - - // Calculate the size in bytes - numSectors = diskSize / 512; // Assuming a sector size of 512 bytes - - printf("====Initializing RawDisk====\n"); - printf("Number of sectors: %llu\n", numSectors); - printf("Disk size (in bytes): %llu\n", diskSize); - } - - ~RawDisk() { - if (fd != -1) { - close(fd); - } - } - - int rawdisk_read(u_int64_t offset, char *buffer, size_t length) { - if (lseek(fd, offset, SEEK_SET) == (u_int64_t)-1) { - perror("Error seeking to offset"); - return -1; - } - - ssize_t bytesRead = read(fd, buffer, length); - if (bytesRead == -1) { - perror("Error reading from device"); - return -1; - } - - return 0; - } - - // Write a specified number of bytes at a given byte offset - int rawdisk_write(u_int64_t offset, char *buffer, size_t length) { - if (lseek(fd, offset, SEEK_SET) == (u_int64_t)-1) { - perror("Error seeking to offset"); - return -1; - } - - ssize_t bytesWritten = write(fd, buffer, length); - if (bytesWritten == -1) { - perror("Error writing to device"); - return -1; - } - - return 0; - } - -}; \ No newline at end of file diff --git a/include/rawdisk.hpp b/include/rawdisk.hpp new file mode 100644 index 0000000..9922e81 --- /dev/null +++ b/include/rawdisk.hpp @@ -0,0 +1,95 @@ +#ifndef RAWDISK_HPP +#define RAWDISK_HPP + +#include +#include +#include +#include +#include +#include +#include + +#define BLOCK_SIZE 4096 + +class RawDisk { + + int fd; + const char *dir; + u_int64_t numSectors; + u_int64_t diskSize; + +public: + RawDisk(const char *directory) + : fd(-1), dir(nullptr), numSectors(0), diskSize(0) { + dir = directory; + /*dir = strdup("/dev/vdc"); + numSectors = 62914560; + diskSize = 32212254720;*/ + + // Open the block device (replace /dev/sdX with the actual device) + fd = open(dir, O_RDWR); // Allow read and write + if (fd == -1) { + perror("Error opening device"); + exit(1); + } + + // Use ioctl with BLKGETSIZE to get the number of sectors + if (ioctl(fd, BLKGETSIZE64, &diskSize) == -1) { + perror("Error getting disk size"); + close(fd); + exit(1); + } + + // Calculate the size in bytes + numSectors = diskSize / 512; // Assuming a sector size of 512 bytes + + printf("====Initializing RawDisk====\n"); + printf("Number of sectors: %llu\n", numSectors); + printf("Disk size (in bytes): %llu\n", diskSize); + } + + ~RawDisk() { + if (fd != -1) { + close(fd); + } + } + + int read_block(u_int64_t block_number, char *buffer) { + u_int64_t offset = block_number * BLOCK_SIZE; + + if (lseek(fd, offset, SEEK_SET) == (u_int64_t)-1) { + perror("Error seeking to offset"); + return -1; + } + + // TODO: this is incorrect + ssize_t bytesRead = read(fd, buffer, BLOCK_SIZE); + if (bytesRead < BLOCK_SIZE) { + perror("Error reading from device"); + return -1; + } + + return 0; + } + + // Write a specified number of bytes at a given byte offset + int write_block(u_int64_t block_number, char *buffer) { + u_int64_t offset = block_number * BLOCK_SIZE; + + if (lseek(fd, offset, SEEK_SET) == (u_int64_t)-1) { + perror("Error seeking to offset"); + return -1; + } + + // TODO: this is incorrect + ssize_t bytesWritten = write(fd, buffer, BLOCK_SIZE); + if (bytesWritten < BLOCK_SIZE) { + perror("Error writing to device"); + return -1; + } + + return 0; + } +}; + +#endif \ No newline at end of file diff --git a/lib/fs/datablock_allocator.cpp b/lib/fs/datablock_allocator.cpp new file mode 100644 index 0000000..da778a7 --- /dev/null +++ b/lib/fs/datablock_allocator.cpp @@ -0,0 +1,75 @@ +#include "fs.hpp" + +DataBlock_Allocator::DataBlock_Allocator(Fs *fs, u_int64_t block_segment_start, + u_int64_t block_segment_end) { + fs = fs; + block_segment_start = block_segment_start; + block_segment_end = block_segment_end; +} + +class BitmapBlock_Data { + char buf[BLOCK_SIZE]; + + u_int64_t get_next_node() { + u_int64_t block_num; + read_u64(&block_num, buf) return block_num; + } + void set_next_node(u_int64_t block_num) { write_u64(block_num, buf); } + + u_int64_t claim_relative_block() { + // This type u_int64_t is important + u_int64_t *data = &buf[8]; + u_int64_t relative_block_num = 0; + + for (size_t i = 0; i < (BLOCK_SIZE / 8) - 1; ++i) + if (data[i] != (~0)) + for (size_t j = 0; j < 64; ++j) + if (data[i] & (1 << j)) { + data[i] |= (1 << j); + return (i * 64) + j + 1; + } + + perror("Error claiming block from bitmap"); + return 0; + } + void release_relative_block(u_int64_t relative_block_num) { + relative_block_num -= 1; + size_t index = (relative_block_num / 8) + 8; + int offset = relative_block_num % 8; + buf[index] &= ~(1 << offset); + } +} + +int DataBlock_Allocator_Bitmap::new_datablock(u_int64_t *block_num) { + int err; + BitmapBlock_Data bitmap = BitmapBlock_Data(); + u_int64_t bitmap_block_num = fs->superblock.free_list_head; + + if ((err = disk->read_block(bitmap_block_num, bitmap.buf)) < 0) + return err; + + u_int64_t relative_block_num = bitmap.claim_relative_block(); + + if (relative_block_num == DATABLOCKS_PER_BITMAP_BLOCK) { + fs->superblock.free_list_head = bitmap.get_next_node(); + if ((err = fs->store_superblock()) < 0) + return err; + } + + bitmap.set_next_node(0); + + if ((err = disk->write_block(bitmap_block_num, bitmap.buf)) < 0) + return err; + + (*block_num) = relative_block_num + bitmap_block_num; + return 0; +} + +int DataBlock_Allocator_Bitmap::free_datablock(u_int64_t block_num) { + return -1; + + // sticing almost full bitmaps back at start of freelist os slow + // also potentially like 256 times slower +} + +int DataBlock_Allocator_Bitmap::format() { return -1; } \ No newline at end of file diff --git a/lib/fs/fs.cpp b/lib/fs/fs.cpp new file mode 100644 index 0000000..52e8a4d --- /dev/null +++ b/lib/fs/fs.cpp @@ -0,0 +1,78 @@ +#include "fs.hpp" + +Fs::Fs(RawDisk *disk) { + disk = disk; + superblock = SuperBlock_Data(); + inode_allocator = INode_Allocator_Freelist(this, 1, 1 + NUM_INODE_BLOCKS); + datablock_allocator = + DataBlock_Allocator_Bitmap(this, 1 + NUM_INODE_BLOCKS, NUM_BLOCKS); +}; + +int Fs::format() { + int err; + if ((err = store_superblock()) < 0) + return err; + if ((err = inode_allocator.format()) < 0) + return err; + if ((err = datablock_allocator.format()) < 0) + return err; + return 0; +} + +int Fs::load_superblock() { + char buf[BLOCK_SIZE]; + int err; + + if ((err = disk->read_block(0, buf)) < 0) + return err; + + superblock.deserialize(buf); + + return 0; +} +int Fs::store_superblock() { + char buf[BLOCK_SIZE] = {0}; + int err; + + superblock.serialize(buf); + + if ((err = disk->write_block(0, buf)) < 0) + return err; + + return 0; +} + +int Fs::load_inode(INode_Data *inode_data) { + char buf[BLOCK_SIZE]; + int err; + + u_int64_t block_num = inode_allocator.get_block_num(inode_data); + if (block_num == 0) + return -1; + u_int64_t block_offset = inode_allocator.get_block_offset(inode_data); + + if ((err = disk->read_block(block_num, buf)) < 0) + return err; + + inode_data->deserialize(&buf[block_offset]) + + return 0; +} +int Fs::store_inode(INode_Data *inode_data) { + char buf[BLOCK_SIZE]; + int err; + + u_int64_t block_num = inode_allocator.get_block_num(inode_data); + if (block_num == 0) + return -1; + u_int64_t block_offset = inode_allocator.get_block_offset(inode_data); + + if ((err = disk->read_block(block_num, buf)) < 0) + return err; + + inode_data->serialize(&buf[block_offset]) + + if ((err = disk->write_block(block_num, buf)) < 0) return err; + + return 0; +} \ No newline at end of file diff --git a/lib/fs/fs_data_types.cpp b/lib/fs/fs_data_types.cpp new file mode 100644 index 0000000..dac0536 --- /dev/null +++ b/lib/fs/fs_data_types.cpp @@ -0,0 +1,89 @@ +#include "fs.hpp" + +size_t write_u64(u_int64_t num, char buf[]) { + size_t i = 0; + for (; i < 8; ++i) + buf[i] = (char)(num >> (i * 8)); + return i; +} + +size_t read_u64(u_int64_t *num, char buf[]) { + size_t i = 0; + (*num) = 0; + for (; i < 8; ++i) { + (*num) <<= 8; + (*num) |= ((u_int64_t)buf[i]) & 0xFF; + } + return i; +} + +SuperBlock_Data::SuperBlock_Data() { + free_list_head = 0; + inode_list_head = 0; +} + +SuperBlock_Data::serialize(char buf[]) { + size_t i = 0; + i += write_u64(free_list_head, &buf[i]); + i += write_u64(inode_list_head, &buf[i]); +} + +SuperBlock_Data::deserialize(char buf[]) { + size_t i = 0; + i += read_u64(&free_list_head, &buf[i]); + i += read_u64(&inode_list_head, &buf[i]); +} + +INode_Data::INode_Data(u_int64_t inode_num) { + inode_num = inode_num; + + metadata.uid = -1; + metadata.gid = -1; + metadata.permissions = -1; + metadata.size = 0; + metadata.reference_count = 0; + + single_indirect_block = double_indirect_block = triple_indirect_block = 0; + + for (size_t i = 0; i < NUMBER_OF_DIRECT_BLOCKS; ++i) + direct_blocks[i] = 0; +} + +size_t INode_Data::serialize_metadata(char buf[]) { + size_t i = 0; + i += write_u64(metadata.uid, &buf[i]); + i += write_u64(metadata.gid, &buf[i]); + i += write_u64(metadata.permissions, &buf[i]); + i += write_u64(metadata.size, &buf[i]); + i += write_u64(metadata.reference_count, &buf[i]); + return i; +} + +size_t INode_Data::deserialize_metadata(char buf[]) { + size_t i = 0; + i += read_u64(&metadata.uid, &buf[i]); + i += read_u64(&metadata.gid, &buf[i]); + i += read_u64(&metadata.permissions, &buf[i]); + i += read_u64(&metadata.size, &buf[i]); + i += read_u64(&metadata.reference_count, &buf[i]); + return i; +} + +void INode_Data::serialize(char buf[]) { + size_t i = 0; + i += serialize_metadata(&buf[i]); + i += write_u64(triple_indirect_block, &buf[i]); + i += write_u64(double_indirect_block, &buf[i]); + i += write_u64(single_indirect_block, &buf[i]); + for (size_t j = 0; j < NUMBER_OF_DIRECT_BLOCKS; ++j) + i += write_u64(direct_blocks[j], &buf[i]); +} +void INode_Data::deserialize(char buf[]) { + size_t i = 0; + i += deserialize_metadata(&buf[i]); + i += read_u64(&triple_indirect_block, &buf[i]); + i += read_u64(&double_indirect_block, &buf[i]); + i += read_u64(&single_indirect_block, &buf[i]); + for (size_t j = 0; j < NUMBER_OF_DIRECT_BLOCKS; ++j) + i += read_u64(&direct_blocks[j], &buf[i]); +} \ No newline at end of file diff --git a/lib/fs/fs_resize.cpp b/lib/fs/fs_resize.cpp new file mode 100644 index 0000000..e69de29 diff --git a/lib/fs/inode_allocator.cpp b/lib/fs/inode_allocator.cpp new file mode 100644 index 0000000..9ba3fa3 --- /dev/null +++ b/lib/fs/inode_allocator.cpp @@ -0,0 +1,29 @@ +#include "fs.hpp" + +INode_Allocator::INode_Allocator(Fs *fs, u_int64_t block_segment_start, + u_int64_t block_segment_end) { + fs = fs; + block_segment_start = block_segment_start; + block_segment_end = block_segment_end; +} + +u_int64_t INode_Allocator::get_block_num(INode_Data *inode_data) { + u_int64_t block_num = + block_segment_start + (inode_data->inode_num / INODES_PER_BLOCK); + if (block_num >= block_segment_end) + return 0; + return block_num; +} +u_int64_t INode_Allocator::get_block_offset(INode_Data *inode_data) { + return (inode_data->inode_num % INODES_PER_BLOCK) * INODE_SIZE; +} + +int INode_Allocator_Freelist::new_inode(u_int64_t uid, u_int64_t gid, + u_int64_t permissions, + INode_Data *inode_data) { + (*inode_data) = nullptr; + return -1; +} +int INode_Allocator_Freelist::free_inode(INode_Data *inode_data) { return -1; } + +int INode_Allocator_Freelist::format() { return -1; } From 8c263f02b1f979d0c38bb1e364296ea030c1c7d7 Mon Sep 17 00:00:00 2001 From: Connor Date: Tue, 14 Nov 2023 22:24:00 -0800 Subject: [PATCH 05/13] temporary addition of inode/datablock allocation --- include/fs.hpp | 7 ++- include/fs/fs_data_types.hpp | 8 ++- include/fs/inode_allocator.hpp | 1 + lib/fs/datablock_allocator.cpp | 112 +++++++++++++++++++++++++-------- lib/fs/fs.cpp | 35 ++++++++--- lib/fs/fs_data_types.cpp | 39 +++++++++--- lib/fs/inode_allocator.cpp | 84 ++++++++++++++++++++++--- 7 files changed, 233 insertions(+), 53 deletions(-) diff --git a/include/fs.hpp b/include/fs.hpp index 5063c5c..36eeac2 100644 --- a/include/fs.hpp +++ b/include/fs.hpp @@ -24,10 +24,13 @@ public: DataBlock_Allocator datablock_allocator; int load_superblock(); - int store_superblock(); + int save_superblock(); + + int save_free_list_head(u_int64_t new_free_list_head); + int save_inode_list_head(u_int64_t new_inode_list_head); int load_inode(INode_Data *inode_data); - int store_inode(INode_Data *inode_data); + int save_inode(INode_Data *inode_data); }; #endif \ No newline at end of file diff --git a/include/fs/fs_data_types.hpp b/include/fs/fs_data_types.hpp index f3958ea..5fed834 100644 --- a/include/fs/fs_data_types.hpp +++ b/include/fs/fs_data_types.hpp @@ -9,6 +9,10 @@ size_t write_u64(u_int64_t num, char buf[]); size_t read_u64(u_int64_t *num, char buf[]); +size_t write_u32(u_int32_t num, char buf[]); + +size_t read_u32(u_int32_t *num, char buf[]); + class SuperBlock_Data { u_int64_t free_list_head; u_int64_t inode_list_head; @@ -20,13 +24,15 @@ class SuperBlock_Data { class INode_Data { u_int64_t inode_num; -#define NUMBER_OF_METADATA_BYTES (4 * sizeof(u_int64_t) + sizeof(u_int32_t)) +#define NUMBER_OF_METADATA_BYTES \ + (4 * sizeof(u_int64_t) + (2 * sizeof(u_int32_t))) struct INode_MetaData { u_int64_t uid; u_int64_t gid; u_int64_t permissions; u_int64_t size; // not yet implemented u_int32_t reference_count; + u_int32_t flags; } metadata; size_t serialize_metadata(char buf[]); size_t deserialize_metadata(char buf[]); diff --git a/include/fs/inode_allocator.hpp b/include/fs/inode_allocator.hpp index fca64f0..1d856bb 100644 --- a/include/fs/inode_allocator.hpp +++ b/include/fs/inode_allocator.hpp @@ -25,6 +25,7 @@ public: protected: Fs *fs; u_int64_t block_segment_start, block_segment_end; + u_int64_t max_num_inodes; }; class INode_Allocator_Freelist : INode_Allocator { diff --git a/lib/fs/datablock_allocator.cpp b/lib/fs/datablock_allocator.cpp index da778a7..d8ea8a8 100644 --- a/lib/fs/datablock_allocator.cpp +++ b/lib/fs/datablock_allocator.cpp @@ -9,29 +9,35 @@ DataBlock_Allocator::DataBlock_Allocator(Fs *fs, u_int64_t block_segment_start, class BitmapBlock_Data { char buf[BLOCK_SIZE]; + u_int64_t datablocks_per_bitmap; + + BitmapBlock_Data(u_int64_t datablocks_per_bitmap_) + : datablocks_per_bitmap(datablocks_per_bitmap_) {} u_int64_t get_next_node() { u_int64_t block_num; - read_u64(&block_num, buf) return block_num; + read_u64(&block_num, buf); + return block_num; } void set_next_node(u_int64_t block_num) { write_u64(block_num, buf); } - u_int64_t claim_relative_block() { - // This type u_int64_t is important - u_int64_t *data = &buf[8]; - u_int64_t relative_block_num = 0; + u_int64_t find_unfilled() { + const char *data = &buf[8]; + u_int64_t i = 0; - for (size_t i = 0; i < (BLOCK_SIZE / 8) - 1; ++i) - if (data[i] != (~0)) - for (size_t j = 0; j < 64; ++j) - if (data[i] & (1 << j)) { - data[i] |= (1 << j); - return (i * 64) + j + 1; - } + for (; i < datablocks_per_bitmap; ++i) + if (data[i / 8] & (1 << (i % 8)) == 0) + return i + 1; - perror("Error claiming block from bitmap"); return 0; } + u_int64_t claim_relative_block() { + u_int64_t unfilled = find_unfilled(); + if (unfilled) + buf[((unfilled - 1) / 8) + 8] |= (1 << ((unfilled - 1) % 8)); + return unfilled; + } + void release_relative_block(u_int64_t relative_block_num) { relative_block_num -= 1; size_t index = (relative_block_num / 8) + 8; @@ -42,34 +48,90 @@ class BitmapBlock_Data { int DataBlock_Allocator_Bitmap::new_datablock(u_int64_t *block_num) { int err; - BitmapBlock_Data bitmap = BitmapBlock_Data(); + BitmapBlock_Data bitmap = BitmapBlock_Data(DATABLOCKS_PER_BITMAP_BLOCK); u_int64_t bitmap_block_num = fs->superblock.free_list_head; + const char zero_buf[BLOCK_SIZE] = {0}; + + if (bitmap_block_num < block_segment_start || + bitmap_block_num >= block_segment_end) + return -1; if ((err = disk->read_block(bitmap_block_num, bitmap.buf)) < 0) return err; u_int64_t relative_block_num = bitmap.claim_relative_block(); - if (relative_block_num == DATABLOCKS_PER_BITMAP_BLOCK) { - fs->superblock.free_list_head = bitmap.get_next_node(); - if ((err = fs->store_superblock()) < 0) - return err; - } + if (relative_block_num == 0) + return -1; - bitmap.set_next_node(0); + u_int64_t block_num = relative_block_num + bitmap_block; + + // NOTE: this could be removed for speed + if ((err = disk->write_block(block_num, zero_buf)) < 0) + return err; + + if (relative_block_num == DATABLOCKS_PER_BITMAP_BLOCK) { + if ((err = fs->save_free_list_head(bitmap.get_next_node())) < 0) + return err; + bitmap.set_next_node(0); + } if ((err = disk->write_block(bitmap_block_num, bitmap.buf)) < 0) return err; - (*block_num) = relative_block_num + bitmap_block_num; + (*block_num) = block_num; return 0; } int DataBlock_Allocator_Bitmap::free_datablock(u_int64_t block_num) { - return -1; + int err; + BitmapBlock_Data bitmap = BitmapBlock_Data(DATABLOCKS_PER_BITMAP_BLOCK); + const u_int64_t bitmap_region_size = DATABLOCKS_PER_BITMAP_BLOCK + 1; + bool update_freelist = false; - // sticing almost full bitmaps back at start of freelist os slow - // also potentially like 256 times slower + u_int64_t bitmap_block_num = + (((block_num - block_segment_start) / bitmap_region_size) * + bitmap_region_size) + + block_segment_start; + + if ((err = disk->read_block(bitmap_block_num, bitmap.buf)) < 0) + return err; + + bitmap.release_relative_block(block_num - bitmap_block_num); + + if (bitmap.find_unfilled() == 0) { + update_freelist = true; + bitmap.set_next_node(fs->superblock.free_list_head); + } + + if ((err = disk->write_block(bitmap_block_num, bitmap.buf)) < 0) + return err; + + if (update_freelist) { + if ((err = fs->save_free_list_head(bitmap_block_num)) < 0) + return err; + } + + return 0; + + // placing almost full bitmaps back at start of freelist is slow + // potentially like 256 times slower throughput } -int DataBlock_Allocator_Bitmap::format() { return -1; } \ No newline at end of file +int DataBlock_Allocator_Bitmap::format() { + const u_int64_t bitmap_region_size = DATABLOCKS_PER_BITMAP_BLOCK + 1; + char buf[BLOCK_SIZE] = {0}; + int err; + u_int64_t i = block_segment_start; + for (; i <= block_segment_end - (2 * bitmap_region_size); + i += bitmap_region_size) { + write_u64(i + bitmap_region_size, buf); + if ((err = disk->write_block(i, buf)) < 0) + return err; + } + if ((err = disk->write_block(i, buf)) < 0) + return err; + if ((err = fs->save_free_list_head(block_segment_start)) < 0) + return err; + return 0; +} \ No newline at end of file diff --git a/lib/fs/fs.cpp b/lib/fs/fs.cpp index 52e8a4d..9beb2df 100644 --- a/lib/fs/fs.cpp +++ b/lib/fs/fs.cpp @@ -42,35 +42,56 @@ int Fs::store_superblock() { return 0; } +int Fs::save_free_list_head(u_int64_t new_free_list_head) { + u_int64_t temp = superblock.free_list_head; + int err; + superblock.free_list_head = new_free_list_head; + if ((err = fs->store_superblock()) < 0) { + superblock.free_list_head = temp; + return err; + } + return 0; +} +int Fs::save_inode_list_head(u_int64_t new_inode_list_head) { + u_int64_t temp = superblock.inode_list_head; + int err; + superblock.inode_list_head = new_inode_list_head; + if ((err = fs->store_superblock()) < 0) { + superblock.inode_list_head = temp; + return err; + } + return 0; +} + int Fs::load_inode(INode_Data *inode_data) { char buf[BLOCK_SIZE]; int err; - u_int64_t block_num = inode_allocator.get_block_num(inode_data); + u_int64_t block_num = inode_allocator.get_block_num(inode_data->inode_num); if (block_num == 0) return -1; - u_int64_t block_offset = inode_allocator.get_block_offset(inode_data); + u_int64_t block_offset = inode_allocator.get_block_offset(inode_data->inode_num); if ((err = disk->read_block(block_num, buf)) < 0) return err; - inode_data->deserialize(&buf[block_offset]) + inode_data->deserialize(&buf[block_offset]); return 0; } -int Fs::store_inode(INode_Data *inode_data) { +int Fs::save_inode(INode_Data *inode_data) { char buf[BLOCK_SIZE]; int err; - u_int64_t block_num = inode_allocator.get_block_num(inode_data); + u_int64_t block_num = inode_allocator.get_block_num(inode_data->inode_num); if (block_num == 0) return -1; - u_int64_t block_offset = inode_allocator.get_block_offset(inode_data); + u_int64_t block_offset = inode_allocator.get_block_offset(inode_data->inode_num); if ((err = disk->read_block(block_num, buf)) < 0) return err; - inode_data->serialize(&buf[block_offset]) + inode_data->serialize(&buf[block_offset]); if ((err = disk->write_block(block_num, buf)) < 0) return err; diff --git a/lib/fs/fs_data_types.cpp b/lib/fs/fs_data_types.cpp index dac0536..9fa5794 100644 --- a/lib/fs/fs_data_types.cpp +++ b/lib/fs/fs_data_types.cpp @@ -1,22 +1,41 @@ #include "fs.hpp" -size_t write_u64(u_int64_t num, char buf[]) { +template T write_int(T num, char buf[]) +{ size_t i = 0; - for (; i < 8; ++i) + for (; i < sizeof(T); ++i) buf[i] = (char)(num >> (i * 8)); return i; } -size_t read_u64(u_int64_t *num, char buf[]) { +template T read_int(T *num, char buf[]) +{ size_t i = 0; - (*num) = 0; - for (; i < 8; ++i) { - (*num) <<= 8; - (*num) |= ((u_int64_t)buf[i]) & 0xFF; + T temp = 0; + for (; i < sizeof(T); ++i) { + temp <<= 8; + temp |= ((T)buf[i]) & 0xFF; } + (*num) = temp; return i; } +size_t write_u64(u_int64_t num, char buf[]) { + return write_int(num, buf); +} + +size_t read_u64(u_int64_t *num, char buf[]) { + return read_int(num, buf); +} + +size_t write_u32(u_int32_t num, char buf[]) { + return write_int(num, buf); +} + +size_t read_u32(u_int32_t *num, char buf[]) { + return read_int(num, buf); +} + SuperBlock_Data::SuperBlock_Data() { free_list_head = 0; inode_list_head = 0; @@ -55,7 +74,8 @@ size_t INode_Data::serialize_metadata(char buf[]) { i += write_u64(metadata.gid, &buf[i]); i += write_u64(metadata.permissions, &buf[i]); i += write_u64(metadata.size, &buf[i]); - i += write_u64(metadata.reference_count, &buf[i]); + i += write_u32(metadata.reference_count, &buf[i]); + i += write_u32(metadata.flags, &buf[i]); return i; } @@ -65,7 +85,8 @@ size_t INode_Data::deserialize_metadata(char buf[]) { i += read_u64(&metadata.gid, &buf[i]); i += read_u64(&metadata.permissions, &buf[i]); i += read_u64(&metadata.size, &buf[i]); - i += read_u64(&metadata.reference_count, &buf[i]); + i += read_u32(&metadata.reference_count, &buf[i]); + i += read_u32(&metadata.flags, &buf[i]); return i; } diff --git a/lib/fs/inode_allocator.cpp b/lib/fs/inode_allocator.cpp index 9ba3fa3..36b8475 100644 --- a/lib/fs/inode_allocator.cpp +++ b/lib/fs/inode_allocator.cpp @@ -5,25 +5,91 @@ INode_Allocator::INode_Allocator(Fs *fs, u_int64_t block_segment_start, fs = fs; block_segment_start = block_segment_start; block_segment_end = block_segment_end; + max_num_inodes = (block_segment_end - block_segment_start) * INODES_PER_BLOCK; } -u_int64_t INode_Allocator::get_block_num(INode_Data *inode_data) { +u_int64_t INode_Allocator::get_block_num(u_int64_t inode_num) { u_int64_t block_num = - block_segment_start + (inode_data->inode_num / INODES_PER_BLOCK); + block_segment_start + (inode_num / INODES_PER_BLOCK); if (block_num >= block_segment_end) return 0; return block_num; } -u_int64_t INode_Allocator::get_block_offset(INode_Data *inode_data) { - return (inode_data->inode_num % INODES_PER_BLOCK) * INODE_SIZE; +u_int64_t INode_Allocator::get_block_offset(u_int64_t inode_num) { + return (inode_num % INODES_PER_BLOCK) * INODE_SIZE; } int INode_Allocator_Freelist::new_inode(u_int64_t uid, u_int64_t gid, u_int64_t permissions, INode_Data *inode_data) { - (*inode_data) = nullptr; - return -1; -} -int INode_Allocator_Freelist::free_inode(INode_Data *inode_data) { return -1; } + char buf[BLOCK_SIZE]; + int err; + u_int64_t inode_num = fs->superblock.inode_list_head; + if(inode_num > max_num_inodes) + return -1; + + u_int64_t block_num = get_block_num(inode_num); -int INode_Allocator_Freelist::format() { return -1; } + if(block_num == 0) + return -1; + + if ((err = disk->read_block(block_num, buf)) < 0) + return err; + + u_int64_t new_inode_list_head = 0; + read_u64(&new_inode_list_head, buf); + if ((err = fs->save_inode_list_head(new_inode_list_head)) < 0) + return err; + + (*inode_data) = INode_Data(inode_num); + + metadata.uid = uid; + metadata.gid = gid; + metadata.permissions = permissions; + + // It is debatable if this function should do this: + if ((err = fs->save_inode(inode_data)) < 0) { + inode_data->inode_num = 0xFFFFFFFFFFFFFFFF; + return err; + } + + return 0; +} +int INode_Allocator_Freelist::free_inode(INode_Data *inode_data) { + char buf[BLOCK_SIZE]; + int err; + + u_int64_t block_num = get_block_num(inode_data->inode_num); + u_int64_t block_offset = get_block_offset(inode_data->inode_num); + + if(block_num == 0) + return -1; + + if ((err = disk->read_block(block_num, buf)) < 0) + return err; + + write_u64(fs->superblock.inode_list_head, &buf[block_offset]); + + if ((err = disk->write_block(block_num, buf)) < 0) + return err; + + if ((err = fs->save_inode_list_head(inode_data->inode_num)) < 0) + return err; + + return 0; +} + +int INode_Allocator_Freelist::format() { + char buf[BLOCK_SIZE]; + int err; + u_int64_t next_inode_num = 1; + for(u_int64_t i = block_segment_start; i < block_segment_end; ++i) { + for(int j = 0; j < INODES_PER_BLOCK; ++next_inode_num, ++j) + write_u64(next_inode_num, &buf[j*INODE_SIZE]); + if ((err = disk->write_block(i, buf)) < 0) + return err; + } + if ((err = fs->save_inode_list_head(0)) < 0) + return err; + return 0; + } From 3ee1647e00808de76e033985fd498602abadb9d6 Mon Sep 17 00:00:00 2001 From: Connor Date: Tue, 14 Nov 2023 22:55:09 -0800 Subject: [PATCH 06/13] added in core fake rawdisk --- include/rawdisk.hpp | 79 +-------------------- lib/fs/datablock_allocator.cpp | 5 +- lib/fs/fs.cpp | 19 ++--- lib/fs/fs_data_types.cpp | 6 +- lib/fs/inode_allocator.cpp | 73 ++++++++++--------- lib/rawdisk.cpp | 124 +++++++++++++++++++++++++++++++++ 6 files changed, 178 insertions(+), 128 deletions(-) create mode 100644 lib/rawdisk.cpp diff --git a/include/rawdisk.hpp b/include/rawdisk.hpp index 9922e81..01c5a33 100644 --- a/include/rawdisk.hpp +++ b/include/rawdisk.hpp @@ -12,84 +12,11 @@ #define BLOCK_SIZE 4096 class RawDisk { - - int fd; - const char *dir; - u_int64_t numSectors; +public: u_int64_t diskSize; -public: - RawDisk(const char *directory) - : fd(-1), dir(nullptr), numSectors(0), diskSize(0) { - dir = directory; - /*dir = strdup("/dev/vdc"); - numSectors = 62914560; - diskSize = 32212254720;*/ - - // Open the block device (replace /dev/sdX with the actual device) - fd = open(dir, O_RDWR); // Allow read and write - if (fd == -1) { - perror("Error opening device"); - exit(1); - } - - // Use ioctl with BLKGETSIZE to get the number of sectors - if (ioctl(fd, BLKGETSIZE64, &diskSize) == -1) { - perror("Error getting disk size"); - close(fd); - exit(1); - } - - // Calculate the size in bytes - numSectors = diskSize / 512; // Assuming a sector size of 512 bytes - - printf("====Initializing RawDisk====\n"); - printf("Number of sectors: %llu\n", numSectors); - printf("Disk size (in bytes): %llu\n", diskSize); - } - - ~RawDisk() { - if (fd != -1) { - close(fd); - } - } - - int read_block(u_int64_t block_number, char *buffer) { - u_int64_t offset = block_number * BLOCK_SIZE; - - if (lseek(fd, offset, SEEK_SET) == (u_int64_t)-1) { - perror("Error seeking to offset"); - return -1; - } - - // TODO: this is incorrect - ssize_t bytesRead = read(fd, buffer, BLOCK_SIZE); - if (bytesRead < BLOCK_SIZE) { - perror("Error reading from device"); - return -1; - } - - return 0; - } - - // Write a specified number of bytes at a given byte offset - int write_block(u_int64_t block_number, char *buffer) { - u_int64_t offset = block_number * BLOCK_SIZE; - - if (lseek(fd, offset, SEEK_SET) == (u_int64_t)-1) { - perror("Error seeking to offset"); - return -1; - } - - // TODO: this is incorrect - ssize_t bytesWritten = write(fd, buffer, BLOCK_SIZE); - if (bytesWritten < BLOCK_SIZE) { - perror("Error writing to device"); - return -1; - } - - return 0; - } + virtual int read_block(u_int64_t block_number, char *buffer) = 0; + virtual int write_block(u_int64_t block_number, char *buffer) = 0; }; #endif \ No newline at end of file diff --git a/lib/fs/datablock_allocator.cpp b/lib/fs/datablock_allocator.cpp index d8ea8a8..022f97b 100644 --- a/lib/fs/datablock_allocator.cpp +++ b/lib/fs/datablock_allocator.cpp @@ -107,10 +107,9 @@ int DataBlock_Allocator_Bitmap::free_datablock(u_int64_t block_num) { if ((err = disk->write_block(bitmap_block_num, bitmap.buf)) < 0) return err; - if (update_freelist) { + if (update_freelist) if ((err = fs->save_free_list_head(bitmap_block_num)) < 0) return err; - } return 0; @@ -132,6 +131,6 @@ int DataBlock_Allocator_Bitmap::format() { if ((err = disk->write_block(i, buf)) < 0) return err; if ((err = fs->save_free_list_head(block_segment_start)) < 0) - return err; + return err; return 0; } \ No newline at end of file diff --git a/lib/fs/fs.cpp b/lib/fs/fs.cpp index 9beb2df..8e9d642 100644 --- a/lib/fs/fs.cpp +++ b/lib/fs/fs.cpp @@ -47,8 +47,8 @@ int Fs::save_free_list_head(u_int64_t new_free_list_head) { int err; superblock.free_list_head = new_free_list_head; if ((err = fs->store_superblock()) < 0) { - superblock.free_list_head = temp; - return err; + superblock.free_list_head = temp; + return err; } return 0; } @@ -57,8 +57,8 @@ int Fs::save_inode_list_head(u_int64_t new_inode_list_head) { int err; superblock.inode_list_head = new_inode_list_head; if ((err = fs->store_superblock()) < 0) { - superblock.inode_list_head = temp; - return err; + superblock.inode_list_head = temp; + return err; } return 0; } @@ -70,14 +70,15 @@ int Fs::load_inode(INode_Data *inode_data) { u_int64_t block_num = inode_allocator.get_block_num(inode_data->inode_num); if (block_num == 0) return -1; - u_int64_t block_offset = inode_allocator.get_block_offset(inode_data->inode_num); + u_int64_t block_offset = + inode_allocator.get_block_offset(inode_data->inode_num); if ((err = disk->read_block(block_num, buf)) < 0) return err; inode_data->deserialize(&buf[block_offset]); - return 0; + return 0; } int Fs::save_inode(INode_Data *inode_data) { char buf[BLOCK_SIZE]; @@ -86,14 +87,16 @@ int Fs::save_inode(INode_Data *inode_data) { u_int64_t block_num = inode_allocator.get_block_num(inode_data->inode_num); if (block_num == 0) return -1; - u_int64_t block_offset = inode_allocator.get_block_offset(inode_data->inode_num); + u_int64_t block_offset = + inode_allocator.get_block_offset(inode_data->inode_num); if ((err = disk->read_block(block_num, buf)) < 0) return err; inode_data->serialize(&buf[block_offset]); - if ((err = disk->write_block(block_num, buf)) < 0) return err; + if ((err = disk->write_block(block_num, buf)) < 0) + return err; return 0; } \ No newline at end of file diff --git a/lib/fs/fs_data_types.cpp b/lib/fs/fs_data_types.cpp index 9fa5794..32004f2 100644 --- a/lib/fs/fs_data_types.cpp +++ b/lib/fs/fs_data_types.cpp @@ -1,15 +1,13 @@ #include "fs.hpp" -template T write_int(T num, char buf[]) -{ +template T write_int(T num, char buf[]) { size_t i = 0; for (; i < sizeof(T); ++i) buf[i] = (char)(num >> (i * 8)); return i; } -template T read_int(T *num, char buf[]) -{ +template T read_int(T *num, char buf[]) { size_t i = 0; T temp = 0; for (; i < sizeof(T); ++i) { diff --git a/lib/fs/inode_allocator.cpp b/lib/fs/inode_allocator.cpp index 36b8475..df02930 100644 --- a/lib/fs/inode_allocator.cpp +++ b/lib/fs/inode_allocator.cpp @@ -9,8 +9,7 @@ INode_Allocator::INode_Allocator(Fs *fs, u_int64_t block_segment_start, } u_int64_t INode_Allocator::get_block_num(u_int64_t inode_num) { - u_int64_t block_num = - block_segment_start + (inode_num / INODES_PER_BLOCK); + u_int64_t block_num = block_segment_start + (inode_num / INODES_PER_BLOCK); if (block_num >= block_segment_end) return 0; return block_num; @@ -25,21 +24,21 @@ int INode_Allocator_Freelist::new_inode(u_int64_t uid, u_int64_t gid, char buf[BLOCK_SIZE]; int err; u_int64_t inode_num = fs->superblock.inode_list_head; - if(inode_num > max_num_inodes) + if (inode_num > max_num_inodes) return -1; - + u_int64_t block_num = get_block_num(inode_num); - if(block_num == 0) + if (block_num == 0) return -1; if ((err = disk->read_block(block_num, buf)) < 0) - return err; - + return err; + u_int64_t new_inode_list_head = 0; read_u64(&new_inode_list_head, buf); if ((err = fs->save_inode_list_head(new_inode_list_head)) < 0) - return err; + return err; (*inode_data) = INode_Data(inode_num); @@ -49,47 +48,47 @@ int INode_Allocator_Freelist::new_inode(u_int64_t uid, u_int64_t gid, // It is debatable if this function should do this: if ((err = fs->save_inode(inode_data)) < 0) { - inode_data->inode_num = 0xFFFFFFFFFFFFFFFF; - return err; + inode_data->inode_num = 0xFFFFFFFFFFFFFFFF; + return err; } return 0; } -int INode_Allocator_Freelist::free_inode(INode_Data *inode_data) { - char buf[BLOCK_SIZE]; - int err; +int INode_Allocator_Freelist::free_inode(INode_Data *inode_data) { + char buf[BLOCK_SIZE]; + int err; - u_int64_t block_num = get_block_num(inode_data->inode_num); - u_int64_t block_offset = get_block_offset(inode_data->inode_num); + u_int64_t block_num = get_block_num(inode_data->inode_num); + u_int64_t block_offset = get_block_offset(inode_data->inode_num); - if(block_num == 0) - return -1; + if (block_num == 0) + return -1; - if ((err = disk->read_block(block_num, buf)) < 0) - return err; + if ((err = disk->read_block(block_num, buf)) < 0) + return err; - write_u64(fs->superblock.inode_list_head, &buf[block_offset]); + write_u64(fs->superblock.inode_list_head, &buf[block_offset]); - if ((err = disk->write_block(block_num, buf)) < 0) - return err; + if ((err = disk->write_block(block_num, buf)) < 0) + return err; - if ((err = fs->save_inode_list_head(inode_data->inode_num)) < 0) - return err; + if ((err = fs->save_inode_list_head(inode_data->inode_num)) < 0) + return err; - return 0; + return 0; } int INode_Allocator_Freelist::format() { - char buf[BLOCK_SIZE]; - int err; - u_int64_t next_inode_num = 1; - for(u_int64_t i = block_segment_start; i < block_segment_end; ++i) { - for(int j = 0; j < INODES_PER_BLOCK; ++next_inode_num, ++j) - write_u64(next_inode_num, &buf[j*INODE_SIZE]); - if ((err = disk->write_block(i, buf)) < 0) - return err; - } - if ((err = fs->save_inode_list_head(0)) < 0) + char buf[BLOCK_SIZE]; + int err; + u_int64_t next_inode_num = 1; + for (u_int64_t i = block_segment_start; i < block_segment_end; ++i) { + for (int j = 0; j < INODES_PER_BLOCK; ++next_inode_num, ++j) + write_u64(next_inode_num, &buf[j * INODE_SIZE]); + if ((err = disk->write_block(i, buf)) < 0) return err; - return 0; - } + } + if ((err = fs->save_inode_list_head(0)) < 0) + return err; + return 0; +} diff --git a/lib/rawdisk.cpp b/lib/rawdisk.cpp new file mode 100644 index 0000000..cff45f3 --- /dev/null +++ b/lib/rawdisk.cpp @@ -0,0 +1,124 @@ +#include "rawdisk.hpp" + +class RealRawDisk : RawDisk { +public: + int fd; + const char *dir; + u_int64_t numSectors; + + RealRawDisk(const char *directory) + : fd(-1), dir(nullptr), numSectors(0), diskSize(0) { + dir = directory; + /*dir = strdup("/dev/vdc"); + numSectors = 62914560; + diskSize = 32212254720;*/ + + // Open the block device (replace /dev/sdX with the actual device) + fd = open(dir, O_RDWR); // Allow read and write + if (fd == -1) { + perror("Error opening device"); + exit(1); + } + + // Use ioctl with BLKGETSIZE to get the number of sectors + if (ioctl(fd, BLKGETSIZE64, &diskSize) == -1) { + perror("Error getting disk size"); + close(fd); + exit(1); + } + + // Calculate the size in bytes + numSectors = diskSize / 512; // Assuming a sector size of 512 bytes + + printf("====Initializing RawDisk====\n"); + printf("Number of sectors: %llu\n", numSectors); + printf("Disk size (in bytes): %llu\n", diskSize); + } + + ~RealRawDisk() { + if (fd != -1) { + close(fd); + } + } + + int read_block(u_int64_t block_number, char *buffer) { + u_int64_t offset = block_number * BLOCK_SIZE; + + if (lseek(fd, offset, SEEK_SET) == (u_int64_t)-1) { + perror("Error seeking to offset"); + return -1; + } + + // TODO: this is incorrect + ssize_t bytesRead = read(fd, buffer, BLOCK_SIZE); + if (bytesRead < BLOCK_SIZE) { + perror("Error reading from device"); + return -1; + } + + return 0; + } + + int write_block(u_int64_t block_number, char *buffer) { + u_int64_t offset = block_number * BLOCK_SIZE; + + if (lseek(fd, offset, SEEK_SET) == (u_int64_t)-1) { + perror("Error seeking to offset"); + return -1; + } + + // TODO: this is incorrect + ssize_t bytesWritten = write(fd, buffer, BLOCK_SIZE); + if (bytesWritten < BLOCK_SIZE) { + perror("Error writing to device"); + return -1; + } + + return 0; + } +}; + +class FakeRawDisk : RawDisk { +public: + char *disk; + + FakeRawDisk(u_int64_t num_blocks) { + disksize = num_blocks * BLOCK_SIZE; + disk = new char[disksize]; + if (disk == nullptr) { + perror("Error allocating fake disk"); + exit(1); + } + printf("====Initializing FAKE RawDisk====\n"); + printf("FAKE Disk size (in bytes): %llu\n", diskSize); + perror("!!! USING FAKE RawDisk - THIS IS FOR TESTING ONLY !!!"); + } + + ~FakeRawDisk() { delete[] disk; } + + int read_block(u_int64_t block_number, char *buffer) { + u_int64_t offset = block_number * BLOCK_SIZE; + + if (offset + BLOCK_SIZE > diskSize) { + perror("Error reading past fake disk size"); + return -1; + } + + memcpy(buffer, &disk[offset], BLOCK_SIZE); + + return 0; + } + + int write_block(u_int64_t block_number, char *buffer) { + u_int64_t offset = block_number * BLOCK_SIZE; + + if (offset + BLOCK_SIZE > diskSize) { + perror("Error writing past fake disk size"); + return -1; + } + + memcpy(&disk[offset], buffer, BLOCK_SIZE); + + return 0; + } +}; \ No newline at end of file From 6edece492c8531052079a8553d9284a16b3dc2c8 Mon Sep 17 00:00:00 2001 From: Connor Date: Wed, 15 Nov 2023 03:10:12 -0800 Subject: [PATCH 07/13] added de/alloc inode datablock s --- .gitignore | 28 +- .vscode/settings.json | 10 +- CMakeLists.txt | 48 +-- Issues.txt | 124 ++++---- README.md | 160 +++++----- include/fischl.h | 12 +- include/fs.h | 466 ----------------------------- include/fs.hpp | 73 ++--- include/fs/datablock_allocator.hpp | 65 ++-- include/fs/fs_data_types.hpp | 100 +++---- include/fs/inode_allocator.hpp | 83 ++--- include/fs_constants.hpp | 23 ++ include/rawdisk.hpp | 60 ++-- lib/fischl.cpp | 14 +- lib/fs/datablock_allocator.cpp | 270 ++++++++--------- lib/fs/fs.cpp | 206 ++++++------- lib/fs/fs_data_types.cpp | 210 +++++++------ lib/fs/fs_resize.cpp | 133 ++++++++ lib/fs/inode_allocator.cpp | 188 ++++++------ lib/main.cpp | 44 ++- lib/rawdisk.cpp | 256 ++++++++-------- test/CMakeLists.txt | 32 +- test/layer0.cpp | 58 ++-- test/layer1_API.cpp | 236 +++++++-------- test/testfischl.cpp | 24 +- 25 files changed, 1338 insertions(+), 1585 deletions(-) delete mode 100644 include/fs.h create mode 100644 include/fs_constants.hpp diff --git a/.gitignore b/.gitignore index 48dd518..9ed9097 100644 --- a/.gitignore +++ b/.gitignore @@ -1,15 +1,15 @@ -build/* - -# vscode gitignore -.vscode/* -!.vscode/settings.json -!.vscode/tasks.json -!.vscode/launch.json -!.vscode/extensions.json -!.vscode/*.code-snippets - -# Local History for Visual Studio Code -.history/ - -# Built Visual Studio Code Extensions +build/* + +# vscode gitignore +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +!.vscode/*.code-snippets + +# Local History for Visual Studio Code +.history/ + +# Built Visual Studio Code Extensions *.vsix \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json index d6ef3d1..c95263a 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,6 +1,6 @@ -{ - "cmake.configureOnOpen": false, - "cSpell.words": [ - "unneccary" - ] +{ + "cmake.configureOnOpen": false, + "cSpell.words": [ + "unneccary" + ] } \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index b660f23..877d0d2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,23 +1,25 @@ -cmake_minimum_required (VERSION 3.1.0) -project(fischl) - -set(CMAKE_CXX_STANDARD 14) - -include_directories( - # fischl include files - ${CMAKE_CURRENT_SOURCE_DIR}/include -) - -add_executable(fischl - - # Header files - lib/fischl.cpp - lib/main.cpp - lib/fs/fs_data_types.cpp - lib/fs/fs_resize.cpp - lib/fs/fs.cpp - -) - -enable_testing() -add_subdirectory(test) \ No newline at end of file +cmake_minimum_required (VERSION 3.1.0) +project(fischl) + +set(CMAKE_CXX_STANDARD 14) + +include_directories( + # fischl include files + ${CMAKE_CURRENT_SOURCE_DIR}/include +) + +add_executable(fischl + + lib/fischl.cpp + lib/main.cpp + lib/rawdisk.cpp + lib/fs/datablock_allocator.cpp + lib/fs/fs_data_types.cpp + lib/fs/fs_resize.cpp + lib/fs/fs.cpp + lib/fs/inode_allocator.cpp + +) + +#enable_testing() +#add_subdirectory(test) \ No newline at end of file diff --git a/Issues.txt b/Issues.txt index c3ee9ec..1677dff 100644 --- a/Issues.txt +++ b/Issues.txt @@ -1,63 +1,63 @@ -Problem - no header guards -Problem - code in header file -Problem - inconisitent use of SECTOR_SIZE IO_BLOCK_SIZE - - -?18: what is directory - -22: read of less than sector-size unpermitted - -?25: does the casting here work as expected, would a bitmask be better - -Question: why are we passing a disk every time to superblock functions, shouldn't that be associated with the superblock (i.e. the file system object) - -37: same issues with this function - -Superblock should be read and written to all at once to avoid unneccary io reads and should be stateful regarding the fs data (also it maybe good to rename superblock to fs and make it in charge of formatting the fs) - -57: magic num - -?69: strange reference pattern with current_pos - usually handled by func returning num bytes read - -?69: should these helper functions be in the inode at all - -?76: these two funcs could be combined together - -?83: inode_construct may want to be named inode_load to fit pattern - -inode objs (block_number) should likely be able to be made with out the use of inode_construct when they are first created - - -132: - -?142: odd use of block nums - byte addresses and io_block addresses - -143: magic num 32? - -?144: possibly make this a continue also use 0b11111111 and 0b01111111 - -?145: j = 0 twice - -?76: why is this function read_byte_at if it reads 8 bytes - -?144: why is the last bit of the bitmask unused - -?171: returned free must be zeroed before use - -177: no error handling for cannot allocate block (free list empty) - -?215: should this be made into a recursive func - -241: no error checking - -278: the empty checking and adding to free list head seems busted - -303: -- - -?315: && addr == 0 does nothing - -398: can try to deallocate the super block so // deal with empty needs implementation - -?433: why even mix sector size into free list - +Problem - no header guards +Problem - code in header file +Problem - inconisitent use of SECTOR_SIZE IO_BLOCK_SIZE + + +?18: what is directory + +22: read of less than sector-size unpermitted + +?25: does the casting here work as expected, would a bitmask be better + +Question: why are we passing a disk every time to superblock functions, shouldn't that be associated with the superblock (i.e. the file system object) + +37: same issues with this function + +Superblock should be read and written to all at once to avoid unneccary io reads and should be stateful regarding the fs data (also it maybe good to rename superblock to fs and make it in charge of formatting the fs) + +57: magic num + +?69: strange reference pattern with current_pos - usually handled by func returning num bytes read + +?69: should these helper functions be in the inode at all + +?76: these two funcs could be combined together + +?83: inode_construct may want to be named inode_load to fit pattern + +inode objs (block_number) should likely be able to be made with out the use of inode_construct when they are first created + + +132: + +?142: odd use of block nums - byte addresses and io_block addresses + +143: magic num 32? + +?144: possibly make this a continue also use 0b11111111 and 0b01111111 + +?145: j = 0 twice + +?76: why is this function read_byte_at if it reads 8 bytes + +?144: why is the last bit of the bitmask unused + +?171: returned free must be zeroed before use + +177: no error handling for cannot allocate block (free list empty) + +?215: should this be made into a recursive func + +241: no error checking + +278: the empty checking and adding to free list head seems busted + +303: -- + +?315: && addr == 0 does nothing + +398: can try to deallocate the super block so // deal with empty needs implementation + +?433: why even mix sector size into free list + 428: no limit checking \ No newline at end of file diff --git a/README.md b/README.md index 2dc19bb..43d625f 100644 --- a/README.md +++ b/README.md @@ -1,80 +1,80 @@ -# iloveos - -Simply copying libfuse. - - -## Branching Rules - -1. Fork the main branch and work on your own branch. -2. Test before initiating a Pull Request. -3. Get approved to get merged. - -# Quick Start - -## configure and build code -make build directory -```bash -mkdir -p build && cd build -cmake .. -make # cmake --build . is same -``` - -## run test -### add your own test file on test/CMakeList.txt -``` -set(TARGET_NAME run_tests) -set(TEST_NAME test_test) - -# add test sources here ... -add_executable(${TARGET_NAME} - - ../lib/fischl.cpp - testfischl.cpp - -) -add_executable(${TEST_NAME} - - ../lib/fischl.cpp - testtest.cpp - -) -add_test(NAME ${TARGET_NAME} COMMAND ${TARGET_NAME}) -add_test(NAME ${TEST_NAME} COMMAND ${TEST_NAME}) -``` - -### ctest -```bash -ctest -VVV -ctest -VV #Displays the output from the tests (e.g., stdout or stderr) in addition to the test information. -``` -Test Result will be like this -```bash -[cloud-user@ip-172-31-22-147 build]$ ctest -VVV -Test project /home/cloud-user/iloveos/build - Start 1: run_tests -1/1 Test #1: run_tests ........................ Passed 0.00 sec - -100% tests passed, 0 tests failed out of 1 - -Total Test time (real) = 0.01 sec -``` - -Failed demonstration -```bash -[cloud-user@ip-172-31-22-147 build]$ ctest -VVV -Test project /home/cloud-user/iloveos/build - Start 1: run_tests -1/2 Test #1: run_tests ........................ Passed 0.00 sec - Start 2: test_test -2/2 Test #2: test_test ........................Subprocess aborted***Exception: 0.26 sec - -50% tests passed, 1 tests failed out of 2 - -Total Test time (real) = 0.27 sec - -The following tests FAILED: - 2 - test_test (Subprocess aborted) -Errors while running CTest -Output from these tests are in: /home/cloud-user/iloveos/build/Testing/Temporary/LastTest.log -Use "--rerun-failed --output-on-failure" to re-run the failed cases verbosely. -``` +# iloveos + +Simply copying libfuse. + + +## Branching Rules + +1. Fork the main branch and work on your own branch. +2. Test before initiating a Pull Request. +3. Get approved to get merged. + +# Quick Start + +## configure and build code +make build directory +```bash +mkdir -p build && cd build +cmake .. +make # cmake --build . is same +``` + +## run test +### add your own test file on test/CMakeList.txt +``` +set(TARGET_NAME run_tests) +set(TEST_NAME test_test) + +# add test sources here ... +add_executable(${TARGET_NAME} + + ../lib/fischl.cpp + testfischl.cpp + +) +add_executable(${TEST_NAME} + + ../lib/fischl.cpp + testtest.cpp + +) +add_test(NAME ${TARGET_NAME} COMMAND ${TARGET_NAME}) +add_test(NAME ${TEST_NAME} COMMAND ${TEST_NAME}) +``` + +### ctest +```bash +ctest -VVV +ctest -VV #Displays the output from the tests (e.g., stdout or stderr) in addition to the test information. +``` +Test Result will be like this +```bash +[cloud-user@ip-172-31-22-147 build]$ ctest -VVV +Test project /home/cloud-user/iloveos/build + Start 1: run_tests +1/1 Test #1: run_tests ........................ Passed 0.00 sec + +100% tests passed, 0 tests failed out of 1 + +Total Test time (real) = 0.01 sec +``` + +Failed demonstration +```bash +[cloud-user@ip-172-31-22-147 build]$ ctest -VVV +Test project /home/cloud-user/iloveos/build + Start 1: run_tests +1/2 Test #1: run_tests ........................ Passed 0.00 sec + Start 2: test_test +2/2 Test #2: test_test ........................Subprocess aborted***Exception: 0.26 sec + +50% tests passed, 1 tests failed out of 2 + +Total Test time (real) = 0.27 sec + +The following tests FAILED: + 2 - test_test (Subprocess aborted) +Errors while running CTest +Output from these tests are in: /home/cloud-user/iloveos/build/Testing/Temporary/LastTest.log +Use "--rerun-failed --output-on-failure" to re-run the failed cases verbosely. +``` diff --git a/include/fischl.h b/include/fischl.h index 7226576..94113c2 100644 --- a/include/fischl.h +++ b/include/fischl.h @@ -1,7 +1,7 @@ -class fischl{ - - // declare - public: - int init(); - +class fischl{ + + // declare + public: + int init(); + }; \ No newline at end of file diff --git a/include/fs.h b/include/fs.h deleted file mode 100644 index 2b7d143..0000000 --- a/include/fs.h +++ /dev/null @@ -1,466 +0,0 @@ -#include "rawdisk.h" -/***************************************************** -30GB Disk low-level operation and data structure: spuerblock, inode, and buffer -cache 512 bytes sector for 1 block, 62914560 block(sector) 4K bytes sector for 1 -block, 7864320 block(sector) - -one inode equipped with one 512 bytes block - -*****************************************************/ -#define SECTOR_SIZE 512 -#define IO_BLOCK_SIZE 4096 -#define MAX_INODE 524288 -#define MAX_BLOCKNUM MAX_INODE * 2 // 62914560 - -class SuperBlock { - -public: - SuperBlock(const char *directory) {} - ~SuperBlock() {} - static u_int64_t getFreeListHead(RawDisk &disk) { - char buffer[8] = {0}; - disk.rawdisk_read(0, buffer, sizeof(buffer)); - u_int64_t t = 0; - for (int j = 0; j < 8; j++) - t = t | (((u_int64_t)(unsigned char)buffer[j]) << (8 * j)); - return t; - } - - static void writeFreeListHead(RawDisk &disk, u_int64_t t) { - char buffer[8] = {0}; - for (int j = 0; j < 8; j++) { - buffer[j] = (t >> (8 * j)) & 0xFF; - } - disk.rawdisk_write(0, buffer, sizeof(buffer)); - } - - static u_int64_t getFreeINodeHead(RawDisk &disk) { - char buffer[8] = {0}; - disk.rawdisk_read(8, buffer, sizeof(buffer)); - u_int64_t t = 0; - for (int j = 0; j < 8; j++) - t = t | (((u_int64_t)(unsigned char)buffer[j]) << (8 * j)); - return t; - } - - static void writeFreeINodeHead(RawDisk &disk, u_int64_t t) { - char buffer[8] = {0}; - for (int j = 0; j < 8; j++) { - buffer[j] = (t >> (8 * j)) & 0xFF; - } - disk.rawdisk_write(8, buffer, sizeof(buffer)); - } -}; - -class INode { - // direct datablocks - u_int64_t blocks[48]; - // indirect address - u_int64_t single_indirect, double_indirect, triple_indirect; - // other - - u_int64_t uid; - u_int64_t gid; - u_int64_t permissions; - u_int64_t size; - u_int64_t block_number; - -public: - void read_get_byte(u_int64_t &t, int ¤t_pos, char *buffer) { - t = 0; - for (int j = 0; j < 8; j++) - t = t | (((u_int64_t)(unsigned char)buffer[j + current_pos]) << (8 * j)); - current_pos += 8; - } - - static u_int64_t read_byte_at(int current_pos, char *buffer) { - u_int64_t t = 0; - for (int j = 0; j < 8; j++) - t = t | (((u_int64_t)(unsigned char)buffer[j + current_pos]) << (8 * j)); - return t; - } - - void inode_construct(u_int64_t blockNumber, RawDisk &disk) { - char buffer[SECTOR_SIZE] = {0}; - disk.rawdisk_read(blockNumber * SECTOR_SIZE, buffer, sizeof(buffer)); - block_number = blockNumber; - int current_pos = 0; - // initialize blocks - for (int i = 0; i < 48; i++) { - read_get_byte(blocks[i], current_pos, buffer); - } - read_get_byte(single_indirect, current_pos, buffer); - read_get_byte(double_indirect, current_pos, buffer); - read_get_byte(triple_indirect, current_pos, buffer); - read_get_byte(uid, current_pos, buffer); - read_get_byte(gid, current_pos, buffer); - read_get_byte(permissions, current_pos, buffer); - read_get_byte(size, current_pos, buffer); - } - - void write_get_byte(u_int64_t t, int ¤t_pos, char *buffer) { - for (int j = 0; j < 8; j++) { - buffer[j + current_pos] = t & (((u_int64_t)1 << (8)) - 1); - t >>= 8; - } - current_pos += 8; - } - - static void write_byte_at(u_int64_t t, int current_pos, char *buffer) { - for (int j = 0; j < 8; j++) { - buffer[j + current_pos] = t & (((u_int64_t)1 << (8)) - 1); - t >>= 8; - } - } - - void inode_save(RawDisk &disk) { - char buffer[SECTOR_SIZE] = {0}; - int current_pos = 0; - for (int i = 0; i < 48; i++) { - write_get_byte(blocks[i], current_pos, buffer); - } - write_get_byte(single_indirect, current_pos, buffer); - write_get_byte(double_indirect, current_pos, buffer); - write_get_byte(triple_indirect, current_pos, buffer); - write_get_byte(uid, current_pos, buffer); - write_get_byte(gid, current_pos, buffer); - write_get_byte(permissions, current_pos, buffer); - write_get_byte(size, current_pos, buffer); - disk.rawdisk_write(block_number * SECTOR_SIZE, buffer, sizeof(buffer)); - } - - u_int64_t datablock_allocate_in_list(RawDisk &disk) { - // find a free data block - u_int64_t freeListHead = SuperBlock::getFreeListHead(disk); - /* - 1. initialization - 2. data block starting position - 3. r/w between storage and rawdisk to maintain - */ - char buffer[IO_BLOCK_SIZE] = {0}; - u_int64_t freeBlockNum = 0; - disk.rawdisk_read(freeListHead, buffer, sizeof(buffer)); - for (int i = 8; i < 264; i++) { - if ((i < 263 && buffer[i] != -1) || (i == 263 && buffer[i] != 127)) { - int j = 0; - for (j = 0; j < 8; j++) { - if ((buffer[i] & (1 << j)) == 0) { - buffer[i] |= (1 << j); - break; - } - } - if (j < 8) { - freeBlockNum = freeListHead + ((i - 8) * 8 + j + 1) * IO_BLOCK_SIZE; - break; - } - } - } - disk.rawdisk_write(freeListHead, buffer, sizeof(buffer)); - bool notFull = false; - for (int i = 8; i < 264; i++) { - if ((i < 263 && buffer[i] != -1) || (i == 263 && buffer[i] != 127)) { - notFull = true; - break; - } - } - if (!notFull) { - printf("HEADER REMOVAL DETECTED %llu %llu\n", freeListHead, freeBlockNum); - u_int64_t next_header = read_byte_at(0, buffer); - SuperBlock::writeFreeListHead(disk, next_header); - } - return freeBlockNum; - } - - bool allo_single_indirect(RawDisk &disk, u_int64_t &single_i, - u_int64_t freeBlockNum) { - if (single_i == 0) { - - single_i = datablock_allocate_in_list(disk); - } - bool inSingle = false; - char buffer[IO_BLOCK_SIZE] = {0}; - disk.rawdisk_read(single_i, buffer, sizeof(buffer)); - for (int i = 0; i < IO_BLOCK_SIZE; i += 8) { - u_int64_t addr = read_byte_at(i, buffer); - if (addr == 0) { - inSingle = true; - write_byte_at(freeBlockNum, i, buffer); - disk.rawdisk_write(single_i, buffer, sizeof(buffer)); - break; - } - } - return inSingle; - } - - bool allo_double_indirect(RawDisk &disk, u_int64_t &double_i, - u_int64_t freeBlockNum) { - if (double_i == 0) { - double_i = datablock_allocate_in_list(disk); - } - bool inDouble = false; - char buffer[IO_BLOCK_SIZE] = {0}; - disk.rawdisk_read(double_i, buffer, sizeof(buffer)); - for (int i = 0; i < IO_BLOCK_SIZE; i += 8) { - u_int64_t addr = read_byte_at(i, buffer); - bool flag = allo_single_indirect(disk, addr, freeBlockNum); - if (flag) { - write_byte_at(addr, i, buffer); - disk.rawdisk_write(double_i, buffer, sizeof(buffer)); - inDouble = true; - break; - } - } - return inDouble; - } - - bool allo_triple_indirect(RawDisk &disk, u_int64_t &triple_i, - u_int64_t freeBlockNum) { - if (triple_i == 0) { - triple_i = datablock_allocate_in_list(disk); - } - bool inTriple = false; - char buffer[IO_BLOCK_SIZE] = {0}; - disk.rawdisk_read(triple_i, buffer, sizeof(buffer)); - for (int i = 0; i < IO_BLOCK_SIZE; i += 8) { - u_int64_t addr = read_byte_at(i, buffer); - bool flag = allo_double_indirect(disk, addr, freeBlockNum); - if (flag) { - write_byte_at(addr, i, buffer); - disk.rawdisk_write(triple_i, buffer, sizeof(buffer)); - inTriple = true; - break; - } - } - return inTriple; - } - - // allowcate 1 datablock and add to the end of the file - u_int64_t datablock_allocate(RawDisk &disk) { - // do we need to check dynamic? - - // add the data block to blocks, single, double, triple - u_int64_t freeBlockNum = datablock_allocate_in_list(disk); - bool inBlocks = false; - for (int i = 0; i < 48; i++) - if (blocks[i] == 0) { - inBlocks = true; - blocks[i] = freeBlockNum; - break; - } - if (!inBlocks) { - bool inSingle = allo_single_indirect(disk, single_indirect, freeBlockNum); - if (!inSingle) { - bool inDouble = - allo_double_indirect(disk, double_indirect, freeBlockNum); - if (!inDouble) { - bool inTriple = - allo_triple_indirect(disk, triple_indirect, freeBlockNum); - // wait to deal with too big files - } - } - } - - // return the block number - inode_save(disk); - return freeBlockNum; - } - - void datablock_deallocate_in_list(u_int64_t freeBlockNum, RawDisk &disk) { - // find the related 2048block head - u_int64_t freeBlockHead = - ((freeBlockNum / SECTOR_SIZE - MAX_INODE) / (8 * 2048) * (8 * 2048) + - MAX_INODE) * - SECTOR_SIZE; - - // mark it alive in its bitmap - char buffer[IO_BLOCK_SIZE] = {0}; - bool notEmpty = false; - disk.rawdisk_read(freeBlockHead, buffer, sizeof(buffer)); - for (int i = 8; i < 264; i++) { - if (buffer[i] != 0) { - notEmpty = true; - } - } - u_int64_t inBlockPos = (freeBlockNum - freeBlockHead) / IO_BLOCK_SIZE - 1; - buffer[8 + inBlockPos / 8] &= (-1) ^ (1 << (inBlockPos % 8)); - - // if its bitmap was 0, add it back to the list head - if (!notEmpty) { - u_int64_t freeListHead = SuperBlock::getFreeListHead(disk); - write_byte_at(freeListHead, 0, buffer); - SuperBlock::writeFreeListHead(disk, freeBlockHead); - } - disk.rawdisk_write(freeBlockHead, buffer, sizeof(buffer)); - } - - u_int64_t deallo_single_indirect(RawDisk &disk, u_int64_t &single_i) { - if (single_i == 0) { - return 0; - } - u_int64_t freeBlockNum = 0; - char buffer[IO_BLOCK_SIZE] = {0}; - int delpoint = -1; - disk.rawdisk_read(single_i, buffer, sizeof(buffer)); - for (int i = 4088; i >= 0; i--) { - u_int64_t addr = read_byte_at(i, buffer); - if (addr != 0) { - freeBlockNum = addr; - addr = 0; - write_byte_at(addr, i, buffer); - delpoint = i; - break; - } - } - disk.rawdisk_write(single_i, buffer, sizeof(buffer)); - u_int64_t addr = read_byte_at(0, buffer); - if (delpoint == 0 && addr == 0) { - datablock_deallocate_in_list(single_i, disk); - single_i = 0; - } - return freeBlockNum; - } - - bool deallo_double_indirect(RawDisk &disk, u_int64_t &double_i) { - if (double_i == 0) { - return false; - } - u_int64_t freeBlockNum = 0; - char buffer[IO_BLOCK_SIZE] = {0}; - int delpoint = -1; - disk.rawdisk_read(double_i, buffer, sizeof(buffer)); - for (int i = 4088; i >= 0; i -= 8) { - u_int64_t addr = read_byte_at(i, buffer); - u_int64_t inSingle = deallo_single_indirect(disk, addr); - if (inSingle) { - freeBlockNum = inSingle; - write_byte_at(addr, i, buffer); - delpoint = i; - break; - } - } - disk.rawdisk_write(double_i, buffer, sizeof(buffer)); - u_int64_t addr = read_byte_at(0, buffer); - if (delpoint == 0 && addr == 0) { - datablock_deallocate_in_list(double_i, disk); - double_i = 0; - } - return freeBlockNum; - } - - bool deallo_triple_indirect(RawDisk &disk, u_int64_t &triple_i) { - if (triple_i == 0) { - return false; - } - u_int64_t freeBlockNum = 0; - char buffer[IO_BLOCK_SIZE] = {0}; - int delpoint = -1; - disk.rawdisk_read(triple_i, buffer, sizeof(buffer)); - for (int i = 4088; i >= 0; i -= 8) { - u_int64_t addr = read_byte_at(i, buffer); - u_int64_t inDouble = deallo_double_indirect(disk, addr); - if (inDouble) { - freeBlockNum = inDouble; - write_byte_at(addr, i, buffer); - delpoint = i; - break; - } - } - disk.rawdisk_write(triple_i, buffer, sizeof(buffer)); - u_int64_t addr = read_byte_at(0, buffer); - if (delpoint == 0 && addr == 0) { - datablock_deallocate_in_list(triple_i, disk); - triple_i = 0; - } - return freeBlockNum; - } - - // deallocate 1 datablock from the end of the file - u_int64_t datablock_deallocate(RawDisk &disk) { - // find the last datablock and remove it from inode (triple->direct) - u_int64_t freeBlockNum = 0; - freeBlockNum = deallo_triple_indirect(disk, triple_indirect); - if (!freeBlockNum) { - freeBlockNum = deallo_double_indirect(disk, double_indirect); - if (!freeBlockNum) { - freeBlockNum = deallo_single_indirect(disk, single_indirect); - if (!freeBlockNum) { - for (int i = 47; i >= 0; i--) - if (blocks[i] != 0) { - freeBlockNum = blocks[i]; - blocks[i] = 0; - break; - } - // deal with empty - } - } - } - - // add it back to freeBlocklist - datablock_deallocate_in_list(freeBlockNum, disk); - inode_save(disk); - return freeBlockNum; - } -}; - -class INodeOperation { - // free list head is at super block (0): first 8 bytes - -public: - // initialization of the rawdisk - void initialize(RawDisk &disk) { - // initialize Inode list head - SuperBlock::writeFreeINodeHead(disk, 1); - for (u_int64_t i = 1; i < MAX_INODE; i++) { - char buffer[SECTOR_SIZE] = {0}; - u_int64_t t = i + 1; - if (t < MAX_INODE) { - for (int j = 0; j < 8; j++) { - buffer[j] = (t >> (8 * j)) & 0xFF; - } - } - disk.rawdisk_write(i * SECTOR_SIZE, buffer, sizeof(buffer)); - } - SuperBlock::writeFreeListHead( - disk, MAX_INODE * SECTOR_SIZE); // maximum inode number 2^19 0x80000 - // Have tested this initialize function but MAX_BLOCK too much, MAX_INODE*2 - // works - for (u_int64_t i = MAX_INODE; i < MAX_BLOCKNUM - 4096; i += 2048 * 8) { - char buffer[IO_BLOCK_SIZE] = {0}; - u_int64_t t = (i + 2048 * 8) * SECTOR_SIZE; - // t is address, storing in to buffer - for (int j = 0; j < 8; j++) { - buffer[j] = (t >> (8 * j)) & 0xFF; - } - disk.rawdisk_write(i * SECTOR_SIZE, buffer, sizeof(buffer)); - } - } - - // allocate an inode from free inode list head and return the number of the - // inode the i-th inode is in the i-th block - u_int64_t inode_allocate(RawDisk &disk) { - u_int64_t freeINodeHead = SuperBlock::getFreeINodeHead(disk); - char buffer[SECTOR_SIZE] = {0}; - disk.rawdisk_read(freeINodeHead * SECTOR_SIZE, buffer, sizeof(buffer)); - u_int64_t newINodeHead = INode::read_byte_at(0, buffer); - // deal with no more INode - SuperBlock::writeFreeINodeHead(disk, newINodeHead); - // to do: initialize the INode on disk at freeINodeHead - - // return inode number - return freeINodeHead; - } - - // free the inode and add it to the free inode list head - void inode_free(RawDisk &disk, u_int64_t INodeNumber) { - u_int64_t freeINodeHead = SuperBlock::getFreeINodeHead(disk); - char buffer[SECTOR_SIZE] = {0}; - INode::write_byte_at(freeINodeHead, 0, buffer); - disk.rawdisk_write(INodeNumber * SECTOR_SIZE, buffer, sizeof(buffer)); - SuperBlock::writeFreeINodeHead(disk, INodeNumber); - } - - // ignore for now - void inode_read() {} - - void inode_write() {} -}; \ No newline at end of file diff --git a/include/fs.hpp b/include/fs.hpp index 36eeac2..8be4ef6 100644 --- a/include/fs.hpp +++ b/include/fs.hpp @@ -1,36 +1,39 @@ -#ifndef FS_HPP -#define FS_HPP - -#include "fs/datablock_allocator.hpp" -#include "fs/fs_data_types.hpp" -#include "fs/inode_allocator.hpp" -#include "rawdisk.hpp" - -#define NUM_INODE_BLOCKS 1023 -#define NUM_BLOCKS 2048 - -class Fs { -public: - Fs(RawDisk *disk); - - int resize(INode_Data *inode_data, u_int64_t size, bool absolute); - - int format(); - - // should probably be private but is not for testing - RawDisk *disk; - SuperBlock_Data superblock; - INode_Allocator inode_allocator; - DataBlock_Allocator datablock_allocator; - - int load_superblock(); - int save_superblock(); - - int save_free_list_head(u_int64_t new_free_list_head); - int save_inode_list_head(u_int64_t new_inode_list_head); - - int load_inode(INode_Data *inode_data); - int save_inode(INode_Data *inode_data); -}; - +#ifndef FS_HPP +#define FS_HPP + +#include "fs/datablock_allocator.hpp" +#include "fs/fs_data_types.hpp" +#include "fs/inode_allocator.hpp" +#include "fs_constants.hpp" +#include "rawdisk.hpp" + +class Fs { +public: + Fs(RawDisk *disk); + ~Fs(); + + int allocate_datablock(INode_Data *inode_data); + int deallocate_datablock(INode_Data *inode_data); + + int format(); + + // should probably be private but is not for testing + RawDisk *disk; + SuperBlock_Data superblock; + INode_Allocator *inode_allocator; + DataBlock_Allocator *datablock_allocator; + + int load_superblock(); + int save_superblock(); + + int save_free_list_head(u_int64_t new_free_list_head); + int save_inode_list_head(u_int64_t new_inode_list_head); + + int load_inode(INode_Data *inode_data); + int save_inode(INode_Data *inode_data); + + int allocate_indirect(u_int64_t *storage, int n); + int deallocate_indirect(u_int64_t *storage, int n); +}; + #endif \ No newline at end of file diff --git a/include/fs/datablock_allocator.hpp b/include/fs/datablock_allocator.hpp index 764ab72..df01087 100644 --- a/include/fs/datablock_allocator.hpp +++ b/include/fs/datablock_allocator.hpp @@ -1,32 +1,35 @@ -#ifndef DATABLOCK_ALLOCATOR_HPP -#define DATABLOCK_ALLOCATOR_HPP - -class Fs; - -class DataBlock_Allocator { -public: - DataBlock_Allocator(Fs *fs, u_int64_t block_segment_start, - u_int64_t block_segment_end); - - virtual int new_datablock(u_int64_t *block_num) = 0; - virtual int free_datablock(u_int64_t block_num) = 0; - - virtual int format() = 0; - -protected: - Fs *fs; - u_int64_t block_segment_start, block_segment_end; -}; - -class DataBlock_Allocator_Bitmap : DataBlock_Allocator { - using DataBlock_Allocator::DataBlock_Allocator; - - const int DATABLOCKS_PER_BITMAP_BLOCK = 255; - - int new_datablock(u_int64_t *block_num) override; - int free_datablock(u_int64_t block_num) override; - - int format() override; -}; - +#ifndef DATABLOCK_ALLOCATOR_HPP +#define DATABLOCK_ALLOCATOR_HPP + +#include "fs_constants.hpp" + +class Fs; + +class DataBlock_Allocator { +public: + DataBlock_Allocator(Fs *fs, u_int64_t block_segment_start, + u_int64_t block_segment_end); + + virtual int new_datablock(u_int64_t *block_num) = 0; + virtual int free_datablock(u_int64_t block_num) = 0; + + virtual int format() = 0; + +protected: + Fs *fs; + u_int64_t block_segment_start, block_segment_end; +}; + +class DataBlock_Allocator_Bitmap : public DataBlock_Allocator { +public: + DataBlock_Allocator_Bitmap(Fs *fs, u_int64_t block_segment_start, + u_int64_t block_segment_end) + : DataBlock_Allocator(fs, block_segment_start, block_segment_end) {} + + int new_datablock(u_int64_t *block_num) override; + int free_datablock(u_int64_t block_num) override; + + int format() override; +}; + #endif \ No newline at end of file diff --git a/include/fs/fs_data_types.hpp b/include/fs/fs_data_types.hpp index 5fed834..cb64dc1 100644 --- a/include/fs/fs_data_types.hpp +++ b/include/fs/fs_data_types.hpp @@ -1,51 +1,51 @@ -#ifndef FS_DATA_TYPES_HPP -#define FS_DATA_TYPES_HPP - -#include "rawdisk.hpp" - -#define INODE_SIZE 512 - -size_t write_u64(u_int64_t num, char buf[]); - -size_t read_u64(u_int64_t *num, char buf[]); - -size_t write_u32(u_int32_t num, char buf[]); - -size_t read_u32(u_int32_t *num, char buf[]); - -class SuperBlock_Data { - u_int64_t free_list_head; - u_int64_t inode_list_head; - SuperBlock_Data(); - void serialize(char buf[]); - void deserialize(char buf[]); -}; - -class INode_Data { - u_int64_t inode_num; - -#define NUMBER_OF_METADATA_BYTES \ - (4 * sizeof(u_int64_t) + (2 * sizeof(u_int32_t))) - struct INode_MetaData { - u_int64_t uid; - u_int64_t gid; - u_int64_t permissions; - u_int64_t size; // not yet implemented - u_int32_t reference_count; - u_int32_t flags; - } metadata; - size_t serialize_metadata(char buf[]); - size_t deserialize_metadata(char buf[]); - - const size_t NUMBER_OF_DIRECT_BLOCKS = - ((INODE_SIZE - NUMBER_OF_METADATA_BYTES) / sizeof(u_int64_t)) - 3; - - u_int64_t single_indirect_block, double_indirect_block, triple_indirect_block; - u_int64_t direct_blocks[NUMBER_OF_DIRECT_BLOCKS]; - - INode_Data(u_int64_t inode_num); - void serialize(char buf[]); - void deserialize(char buf[]); -}; - +#ifndef FS_DATA_TYPES_HPP +#define FS_DATA_TYPES_HPP + +#include "fs_constants.hpp" + +size_t write_u64(u_int64_t num, char buf[]); + +size_t read_u64(u_int64_t *num, char buf[]); + +size_t write_u32(u_int32_t num, char buf[]); + +size_t read_u32(u_int32_t *num, char buf[]); + +class SuperBlock_Data { +public: + u_int64_t free_list_head; + u_int64_t inode_list_head; + SuperBlock_Data(); + void serialize(char buf[]); + void deserialize(char buf[]); +}; + +class INode_Data { +public: + u_int64_t inode_num; + +#define NUMBER_OF_METADATA_BYTES \ + (4 * sizeof(u_int64_t) + (2 * sizeof(u_int32_t))) + struct INode_MetaData { + u_int64_t uid; + u_int64_t gid; + u_int64_t permissions; + u_int64_t size; // not yet implemented + u_int32_t reference_count; + u_int32_t flags; + } metadata; + size_t serialize_metadata(char buf[]); + size_t deserialize_metadata(char buf[]); + +#define NUMBER_OF_DIRECT_BLOCKS \ + (((INODE_SIZE - NUMBER_OF_METADATA_BYTES) / sizeof(u_int64_t)) - 3) + + u_int64_t single_indirect_block, double_indirect_block, triple_indirect_block; + u_int64_t direct_blocks[NUMBER_OF_DIRECT_BLOCKS]; + + INode_Data(u_int64_t inode_num = 0xFFFFFFFFFFFFFFFF); + void serialize(char buf[]); + void deserialize(char buf[]); +}; + #endif \ No newline at end of file diff --git a/include/fs/inode_allocator.hpp b/include/fs/inode_allocator.hpp index 1d856bb..116474d 100644 --- a/include/fs/inode_allocator.hpp +++ b/include/fs/inode_allocator.hpp @@ -1,41 +1,44 @@ -#ifndef INODE_ALLOCATOR_HPP -#define INODE_ALLOCATOR_HPP - -#include "fs_data_types.hpp" -#include "rawdisk.hpp" - -class Fs; - -class INode_Allocator { -public: - const int INODES_PER_BLOCK = BLOCK_SIZE / INODE_SIZE; - - INode_Allocator(Fs *fs, u_int64_t block_segment_start, - u_int64_t block_segment_end); - - virtual int new_inode(u_int64_t uid, u_int64_t gid, u_int64_t permissions, - INode_Data *inode_data) = 0; - virtual int free_inode(INode_Data *inode_data) = 0; - - virtual int format() = 0; - - u_int64_t get_block_num(INode_Data *inode_data); - u_int64_t get_block_offset(INode_Data *inode_data); - -protected: - Fs *fs; - u_int64_t block_segment_start, block_segment_end; - u_int64_t max_num_inodes; -}; - -class INode_Allocator_Freelist : INode_Allocator { - using INode_Allocator::INode_Allocator; - - int new_inode(u_int64_t uid, u_int64_t gid, u_int64_t permissions, - INode_Data *inode_data) override; - int free_inode(INode_Data *inode_data) override; - - int format() override; -}; - +#ifndef INODE_ALLOCATOR_HPP +#define INODE_ALLOCATOR_HPP + +#include "fs_constants.hpp" +#include "fs_data_types.hpp" + +class Fs; + +class INode_Allocator { +public: + const int INODES_PER_BLOCK = IO_BLOCK_SIZE / INODE_SIZE; + + INode_Allocator(Fs *fs, u_int64_t block_segment_start, + u_int64_t block_segment_end); + + virtual int new_inode(u_int64_t uid, u_int64_t gid, u_int64_t permissions, + INode_Data *inode_data) = 0; + virtual int free_inode(INode_Data *inode_data) = 0; + + virtual int format() = 0; + + u_int64_t get_block_num(u_int64_t inode_data); + u_int64_t get_block_offset(u_int64_t inode_data); + +protected: + Fs *fs; + u_int64_t block_segment_start, block_segment_end; + u_int64_t max_num_inodes; +}; + +class INode_Allocator_Freelist : public INode_Allocator { +public: + INode_Allocator_Freelist(Fs *fs, u_int64_t block_segment_start, + u_int64_t block_segment_end) + : INode_Allocator(fs, block_segment_start, block_segment_end) {} + + int new_inode(u_int64_t uid, u_int64_t gid, u_int64_t permissions, + INode_Data *inode_data) override; + int free_inode(INode_Data *inode_data) override; + + int format() override; +}; + #endif \ No newline at end of file diff --git a/include/fs_constants.hpp b/include/fs_constants.hpp new file mode 100644 index 0000000..806aaed --- /dev/null +++ b/include/fs_constants.hpp @@ -0,0 +1,23 @@ +#ifndef FS_CONSTANTS_HPP +#define FS_CONSTANTS_HPP + +#include +#include +#include +#include +#include +#include +#include +#include + + +#define IO_BLOCK_SIZE 4096 + +#define NUM_INODE_BLOCKS 1023 +#define NUM_BLOCKS 2048 + +#define INODE_SIZE 512 + +#define DATABLOCKS_PER_BITMAP_BLOCK 255 + +#endif \ No newline at end of file diff --git a/include/rawdisk.hpp b/include/rawdisk.hpp index 01c5a33..ebbea1a 100644 --- a/include/rawdisk.hpp +++ b/include/rawdisk.hpp @@ -1,22 +1,40 @@ -#ifndef RAWDISK_HPP -#define RAWDISK_HPP - -#include -#include -#include -#include -#include -#include -#include - -#define BLOCK_SIZE 4096 - -class RawDisk { -public: - u_int64_t diskSize; - - virtual int read_block(u_int64_t block_number, char *buffer) = 0; - virtual int write_block(u_int64_t block_number, char *buffer) = 0; -}; - +#ifndef RAWDISK_HPP +#define RAWDISK_HPP + +#include "fs_constants.hpp" + +class RawDisk { +public: + u_int64_t diskSize; + + virtual int read_block(u_int64_t block_number, char *buffer) = 0; + virtual int write_block(u_int64_t block_number, char *buffer) = 0; + + void print_block(u_int64_t block_number); +}; + +class RealRawDisk : public RawDisk { +public: + int fd; + const char *dir; + u_int64_t numSectors; + + RealRawDisk(const char *directory); + ~RealRawDisk(); + + int read_block(u_int64_t block_number, char *buffer) override; + int write_block(u_int64_t block_number, char *buffer) override; +}; + +class FakeRawDisk : public RawDisk { +public: + char *disk; + + FakeRawDisk(u_int64_t num_blocks); + ~FakeRawDisk(); + + int read_block(u_int64_t block_number, char *buffer) override; + int write_block(u_int64_t block_number, char *buffer) override; +}; + #endif \ No newline at end of file diff --git a/lib/fischl.cpp b/lib/fischl.cpp index 3cc7ad7..2246652 100644 --- a/lib/fischl.cpp +++ b/lib/fischl.cpp @@ -1,8 +1,8 @@ -#include "fischl.h" - -#include - -int fischl::init(){ - printf("Hello Fischl!"); - return 3; +#include "fischl.h" + +#include + +int fischl::init(){ + printf("Hello Fischl!"); + return 3; } \ No newline at end of file diff --git a/lib/fs/datablock_allocator.cpp b/lib/fs/datablock_allocator.cpp index 022f97b..531b993 100644 --- a/lib/fs/datablock_allocator.cpp +++ b/lib/fs/datablock_allocator.cpp @@ -1,136 +1,136 @@ -#include "fs.hpp" - -DataBlock_Allocator::DataBlock_Allocator(Fs *fs, u_int64_t block_segment_start, - u_int64_t block_segment_end) { - fs = fs; - block_segment_start = block_segment_start; - block_segment_end = block_segment_end; -} - -class BitmapBlock_Data { - char buf[BLOCK_SIZE]; - u_int64_t datablocks_per_bitmap; - - BitmapBlock_Data(u_int64_t datablocks_per_bitmap_) - : datablocks_per_bitmap(datablocks_per_bitmap_) {} - - u_int64_t get_next_node() { - u_int64_t block_num; - read_u64(&block_num, buf); - return block_num; - } - void set_next_node(u_int64_t block_num) { write_u64(block_num, buf); } - - u_int64_t find_unfilled() { - const char *data = &buf[8]; - u_int64_t i = 0; - - for (; i < datablocks_per_bitmap; ++i) - if (data[i / 8] & (1 << (i % 8)) == 0) - return i + 1; - - return 0; - } - u_int64_t claim_relative_block() { - u_int64_t unfilled = find_unfilled(); - if (unfilled) - buf[((unfilled - 1) / 8) + 8] |= (1 << ((unfilled - 1) % 8)); - return unfilled; - } - - void release_relative_block(u_int64_t relative_block_num) { - relative_block_num -= 1; - size_t index = (relative_block_num / 8) + 8; - int offset = relative_block_num % 8; - buf[index] &= ~(1 << offset); - } -} - -int DataBlock_Allocator_Bitmap::new_datablock(u_int64_t *block_num) { - int err; - BitmapBlock_Data bitmap = BitmapBlock_Data(DATABLOCKS_PER_BITMAP_BLOCK); - u_int64_t bitmap_block_num = fs->superblock.free_list_head; - const char zero_buf[BLOCK_SIZE] = {0}; - - if (bitmap_block_num < block_segment_start || - bitmap_block_num >= block_segment_end) - return -1; - - if ((err = disk->read_block(bitmap_block_num, bitmap.buf)) < 0) - return err; - - u_int64_t relative_block_num = bitmap.claim_relative_block(); - - if (relative_block_num == 0) - return -1; - - u_int64_t block_num = relative_block_num + bitmap_block; - - // NOTE: this could be removed for speed - if ((err = disk->write_block(block_num, zero_buf)) < 0) - return err; - - if (relative_block_num == DATABLOCKS_PER_BITMAP_BLOCK) { - if ((err = fs->save_free_list_head(bitmap.get_next_node())) < 0) - return err; - bitmap.set_next_node(0); - } - - if ((err = disk->write_block(bitmap_block_num, bitmap.buf)) < 0) - return err; - - (*block_num) = block_num; - return 0; -} - -int DataBlock_Allocator_Bitmap::free_datablock(u_int64_t block_num) { - int err; - BitmapBlock_Data bitmap = BitmapBlock_Data(DATABLOCKS_PER_BITMAP_BLOCK); - const u_int64_t bitmap_region_size = DATABLOCKS_PER_BITMAP_BLOCK + 1; - bool update_freelist = false; - - u_int64_t bitmap_block_num = - (((block_num - block_segment_start) / bitmap_region_size) * - bitmap_region_size) + - block_segment_start; - - if ((err = disk->read_block(bitmap_block_num, bitmap.buf)) < 0) - return err; - - bitmap.release_relative_block(block_num - bitmap_block_num); - - if (bitmap.find_unfilled() == 0) { - update_freelist = true; - bitmap.set_next_node(fs->superblock.free_list_head); - } - - if ((err = disk->write_block(bitmap_block_num, bitmap.buf)) < 0) - return err; - - if (update_freelist) - if ((err = fs->save_free_list_head(bitmap_block_num)) < 0) - return err; - - return 0; - - // placing almost full bitmaps back at start of freelist is slow - // potentially like 256 times slower throughput -} - -int DataBlock_Allocator_Bitmap::format() { - const u_int64_t bitmap_region_size = DATABLOCKS_PER_BITMAP_BLOCK + 1; - char buf[BLOCK_SIZE] = {0}; - int err; - u_int64_t i = block_segment_start; - for (; i <= block_segment_end - (2 * bitmap_region_size); - i += bitmap_region_size) { - write_u64(i + bitmap_region_size, buf); - if ((err = disk->write_block(i, buf)) < 0) - return err; - } - if ((err = disk->write_block(i, buf)) < 0) - return err; - if ((err = fs->save_free_list_head(block_segment_start)) < 0) - return err; - return 0; +#include "fs.hpp" + +DataBlock_Allocator::DataBlock_Allocator(Fs *fs, u_int64_t block_segment_start, + u_int64_t block_segment_end) + : fs(fs), block_segment_start(block_segment_start), + block_segment_end(block_segment_end) {} + +class BitmapBlock_Data { +public: + char buf[IO_BLOCK_SIZE]; + u_int64_t datablocks_per_bitmap; + + BitmapBlock_Data(u_int64_t datablocks_per_bitmap_) + : datablocks_per_bitmap(datablocks_per_bitmap_) {} + + u_int64_t get_next_node() { + u_int64_t block_num; + read_u64(&block_num, buf); + return block_num; + } + void set_next_node(u_int64_t block_num) { write_u64(block_num, buf); } + + u_int64_t find_unfilled() { + const char *data = &buf[8]; + u_int64_t i = 0; + + for (; i < datablocks_per_bitmap; ++i) + if ((data[i / 8] & (1 << (i % 8))) == 0) + return i + 1; + + return 0; + } + u_int64_t claim_relative_block() { + u_int64_t unfilled = find_unfilled(); + if (unfilled) + buf[((unfilled - 1) / 8) + 8] |= (1 << ((unfilled - 1) % 8)); + return unfilled; + } + + void release_relative_block(u_int64_t relative_block_num) { + relative_block_num -= 1; + size_t index = (relative_block_num / 8) + 8; + int offset = relative_block_num % 8; + buf[index] &= ~(1 << offset); + } +}; + +int DataBlock_Allocator_Bitmap::new_datablock(u_int64_t *block_num) { + int err; + BitmapBlock_Data bitmap = BitmapBlock_Data(DATABLOCKS_PER_BITMAP_BLOCK); + u_int64_t bitmap_block_num = fs->superblock.free_list_head; + char zero_buf[IO_BLOCK_SIZE] = {0}; + + if (bitmap_block_num < block_segment_start || + bitmap_block_num >= block_segment_end) + return -1; + + if ((err = fs->disk->read_block(bitmap_block_num, bitmap.buf)) < 0) + return err; + + u_int64_t relative_block_num = bitmap.claim_relative_block(); + + if (relative_block_num == 0) + return -1; + + u_int64_t block_num_ = relative_block_num + bitmap_block_num; + + // NOTE: this could be removed for speed + if ((err = fs->disk->write_block(block_num_, zero_buf)) < 0) + return err; + + // Could be optimized + if (bitmap.find_unfilled() == 0) { + if ((err = fs->save_free_list_head(bitmap.get_next_node())) < 0) + return err; + bitmap.set_next_node(0); + } + + if ((err = fs->disk->write_block(bitmap_block_num, bitmap.buf)) < 0) + return err; + + (*block_num) = block_num_; + return 0; +} + +int DataBlock_Allocator_Bitmap::free_datablock(u_int64_t block_num) { + int err; + BitmapBlock_Data bitmap = BitmapBlock_Data(DATABLOCKS_PER_BITMAP_BLOCK); + const u_int64_t bitmap_region_size = DATABLOCKS_PER_BITMAP_BLOCK + 1; + bool update_freelist = false; + + u_int64_t bitmap_block_num = + (((block_num - block_segment_start) / bitmap_region_size) * + bitmap_region_size) + + block_segment_start; + + if ((err = fs->disk->read_block(bitmap_block_num, bitmap.buf)) < 0) + return err; + + if (bitmap.find_unfilled() == 0) { + update_freelist = true; + bitmap.set_next_node(fs->superblock.free_list_head); + } + + bitmap.release_relative_block(block_num - bitmap_block_num); + + if ((err = fs->disk->write_block(bitmap_block_num, bitmap.buf)) < 0) + return err; + + if (update_freelist) + if ((err = fs->save_free_list_head(bitmap_block_num)) < 0) + return err; + + return 0; + + // placing almost full bitmaps back at start of freelist is slow + // potentially like 256 times slower throughput +} + +int DataBlock_Allocator_Bitmap::format() { + const u_int64_t bitmap_region_size = DATABLOCKS_PER_BITMAP_BLOCK + 1; + char buf[IO_BLOCK_SIZE] = {0}; + int err; + u_int64_t i = block_segment_start; + for (; i <= block_segment_end - (2 * bitmap_region_size); + i += bitmap_region_size) { + write_u64(i + bitmap_region_size, buf); + if ((err = fs->disk->write_block(i, buf)) < 0) + return err; + } + if ((err = fs->disk->write_block(i, buf)) < 0) + return err; + if ((err = fs->save_free_list_head(block_segment_start)) < 0) + return err; + return 0; } \ No newline at end of file diff --git a/lib/fs/fs.cpp b/lib/fs/fs.cpp index 8e9d642..98d8f9d 100644 --- a/lib/fs/fs.cpp +++ b/lib/fs/fs.cpp @@ -1,102 +1,106 @@ -#include "fs.hpp" - -Fs::Fs(RawDisk *disk) { - disk = disk; - superblock = SuperBlock_Data(); - inode_allocator = INode_Allocator_Freelist(this, 1, 1 + NUM_INODE_BLOCKS); - datablock_allocator = - DataBlock_Allocator_Bitmap(this, 1 + NUM_INODE_BLOCKS, NUM_BLOCKS); -}; - -int Fs::format() { - int err; - if ((err = store_superblock()) < 0) - return err; - if ((err = inode_allocator.format()) < 0) - return err; - if ((err = datablock_allocator.format()) < 0) - return err; - return 0; -} - -int Fs::load_superblock() { - char buf[BLOCK_SIZE]; - int err; - - if ((err = disk->read_block(0, buf)) < 0) - return err; - - superblock.deserialize(buf); - - return 0; -} -int Fs::store_superblock() { - char buf[BLOCK_SIZE] = {0}; - int err; - - superblock.serialize(buf); - - if ((err = disk->write_block(0, buf)) < 0) - return err; - - return 0; -} - -int Fs::save_free_list_head(u_int64_t new_free_list_head) { - u_int64_t temp = superblock.free_list_head; - int err; - superblock.free_list_head = new_free_list_head; - if ((err = fs->store_superblock()) < 0) { - superblock.free_list_head = temp; - return err; - } - return 0; -} -int Fs::save_inode_list_head(u_int64_t new_inode_list_head) { - u_int64_t temp = superblock.inode_list_head; - int err; - superblock.inode_list_head = new_inode_list_head; - if ((err = fs->store_superblock()) < 0) { - superblock.inode_list_head = temp; - return err; - } - return 0; -} - -int Fs::load_inode(INode_Data *inode_data) { - char buf[BLOCK_SIZE]; - int err; - - u_int64_t block_num = inode_allocator.get_block_num(inode_data->inode_num); - if (block_num == 0) - return -1; - u_int64_t block_offset = - inode_allocator.get_block_offset(inode_data->inode_num); - - if ((err = disk->read_block(block_num, buf)) < 0) - return err; - - inode_data->deserialize(&buf[block_offset]); - - return 0; -} -int Fs::save_inode(INode_Data *inode_data) { - char buf[BLOCK_SIZE]; - int err; - - u_int64_t block_num = inode_allocator.get_block_num(inode_data->inode_num); - if (block_num == 0) - return -1; - u_int64_t block_offset = - inode_allocator.get_block_offset(inode_data->inode_num); - - if ((err = disk->read_block(block_num, buf)) < 0) - return err; - - inode_data->serialize(&buf[block_offset]); - - if ((err = disk->write_block(block_num, buf)) < 0) - return err; - - return 0; +#include "fs.hpp" + +Fs::Fs(RawDisk *disk) : disk(disk) { + superblock = SuperBlock_Data(); + inode_allocator = new INode_Allocator_Freelist(this, 1, 1 + NUM_INODE_BLOCKS); + datablock_allocator = + new DataBlock_Allocator_Bitmap(this, 1 + NUM_INODE_BLOCKS, NUM_BLOCKS); +}; + +Fs::~Fs() { + delete inode_allocator; + delete datablock_allocator; +}; + +int Fs::format() { + int err; + if ((err = save_superblock()) < 0) + return err; + if ((err = inode_allocator->format()) < 0) + return err; + if ((err = datablock_allocator->format()) < 0) + return err; + return 0; +} + +int Fs::load_superblock() { + char buf[IO_BLOCK_SIZE]; + int err; + + if ((err = disk->read_block(0, buf)) < 0) + return err; + + superblock.deserialize(buf); + + return 0; +} +int Fs::save_superblock() { + char buf[IO_BLOCK_SIZE] = {0}; + int err; + + superblock.serialize(buf); + + if ((err = disk->write_block(0, buf)) < 0) + return err; + + return 0; +} + +int Fs::save_free_list_head(u_int64_t new_free_list_head) { + u_int64_t temp = superblock.free_list_head; + int err; + superblock.free_list_head = new_free_list_head; + if ((err = save_superblock()) < 0) { + superblock.free_list_head = temp; + return err; + } + return 0; +} +int Fs::save_inode_list_head(u_int64_t new_inode_list_head) { + u_int64_t temp = superblock.inode_list_head; + int err; + superblock.inode_list_head = new_inode_list_head; + if ((err = save_superblock()) < 0) { + superblock.inode_list_head = temp; + return err; + } + return 0; +} + +int Fs::load_inode(INode_Data *inode_data) { + char buf[IO_BLOCK_SIZE]; + int err; + + u_int64_t block_num = inode_allocator->get_block_num(inode_data->inode_num); + if (block_num == 0) + return -1; + u_int64_t block_offset = + inode_allocator->get_block_offset(inode_data->inode_num); + + if ((err = disk->read_block(block_num, buf)) < 0) + return err; + + inode_data->deserialize(&buf[block_offset]); + + return 0; +} +int Fs::save_inode(INode_Data *inode_data) { + char buf[IO_BLOCK_SIZE]; + int err; + + u_int64_t block_num = inode_allocator->get_block_num(inode_data->inode_num); + if (block_num == 0) + return -1; + u_int64_t block_offset = + inode_allocator->get_block_offset(inode_data->inode_num); + + if ((err = disk->read_block(block_num, buf)) < 0) + return err; + + inode_data->serialize(&buf[block_offset]); + + if ((err = disk->write_block(block_num, buf)) < 0) + return err; + + return 0; } \ No newline at end of file diff --git a/lib/fs/fs_data_types.cpp b/lib/fs/fs_data_types.cpp index 32004f2..ee8b8d1 100644 --- a/lib/fs/fs_data_types.cpp +++ b/lib/fs/fs_data_types.cpp @@ -1,108 +1,104 @@ -#include "fs.hpp" - -template T write_int(T num, char buf[]) { - size_t i = 0; - for (; i < sizeof(T); ++i) - buf[i] = (char)(num >> (i * 8)); - return i; -} - -template T read_int(T *num, char buf[]) { - size_t i = 0; - T temp = 0; - for (; i < sizeof(T); ++i) { - temp <<= 8; - temp |= ((T)buf[i]) & 0xFF; - } - (*num) = temp; - return i; -} - -size_t write_u64(u_int64_t num, char buf[]) { - return write_int(num, buf); -} - -size_t read_u64(u_int64_t *num, char buf[]) { - return read_int(num, buf); -} - -size_t write_u32(u_int32_t num, char buf[]) { - return write_int(num, buf); -} - -size_t read_u32(u_int32_t *num, char buf[]) { - return read_int(num, buf); -} - -SuperBlock_Data::SuperBlock_Data() { - free_list_head = 0; - inode_list_head = 0; -} - -SuperBlock_Data::serialize(char buf[]) { - size_t i = 0; - i += write_u64(free_list_head, &buf[i]); - i += write_u64(inode_list_head, &buf[i]); -} - -SuperBlock_Data::deserialize(char buf[]) { - size_t i = 0; - i += read_u64(&free_list_head, &buf[i]); - i += read_u64(&inode_list_head, &buf[i]); -} - -INode_Data::INode_Data(u_int64_t inode_num) { - inode_num = inode_num; - - metadata.uid = -1; - metadata.gid = -1; - metadata.permissions = -1; - metadata.size = 0; - metadata.reference_count = 0; - - single_indirect_block = double_indirect_block = triple_indirect_block = 0; - - for (size_t i = 0; i < NUMBER_OF_DIRECT_BLOCKS; ++i) - direct_blocks[i] = 0; -} - -size_t INode_Data::serialize_metadata(char buf[]) { - size_t i = 0; - i += write_u64(metadata.uid, &buf[i]); - i += write_u64(metadata.gid, &buf[i]); - i += write_u64(metadata.permissions, &buf[i]); - i += write_u64(metadata.size, &buf[i]); - i += write_u32(metadata.reference_count, &buf[i]); - i += write_u32(metadata.flags, &buf[i]); - return i; -} - -size_t INode_Data::deserialize_metadata(char buf[]) { - size_t i = 0; - i += read_u64(&metadata.uid, &buf[i]); - i += read_u64(&metadata.gid, &buf[i]); - i += read_u64(&metadata.permissions, &buf[i]); - i += read_u64(&metadata.size, &buf[i]); - i += read_u32(&metadata.reference_count, &buf[i]); - i += read_u32(&metadata.flags, &buf[i]); - return i; -} - -void INode_Data::serialize(char buf[]) { - size_t i = 0; - i += serialize_metadata(&buf[i]); - i += write_u64(triple_indirect_block, &buf[i]); - i += write_u64(double_indirect_block, &buf[i]); - i += write_u64(single_indirect_block, &buf[i]); - for (size_t j = 0; j < NUMBER_OF_DIRECT_BLOCKS; ++j) - i += write_u64(direct_blocks[j], &buf[i]); -} -void INode_Data::deserialize(char buf[]) { - size_t i = 0; - i += deserialize_metadata(&buf[i]); - i += read_u64(&triple_indirect_block, &buf[i]); - i += read_u64(&double_indirect_block, &buf[i]); - i += read_u64(&single_indirect_block, &buf[i]); - for (size_t j = 0; j < NUMBER_OF_DIRECT_BLOCKS; ++j) - i += read_u64(&direct_blocks[j], &buf[i]); +#include "fs.hpp" + +template T write_int(T num, char buf[]) { + size_t i = 0; + for (; i < sizeof(T); ++i) + buf[i] = (char)(num >> (i * 8)); + return i; +} + +template T read_int(T *num, char buf[]) { + size_t i = 0; + T temp = 0; + for (; i < sizeof(T); ++i) + temp |= (((T)buf[i]) & 0xFF) << (8 * i); + (*num) = temp; + return i; +} + +size_t write_u64(u_int64_t num, char buf[]) { + return write_int(num, buf); +} + +size_t read_u64(u_int64_t *num, char buf[]) { + return read_int(num, buf); +} + +size_t write_u32(u_int32_t num, char buf[]) { + return write_int(num, buf); +} + +size_t read_u32(u_int32_t *num, char buf[]) { + return read_int(num, buf); +} + +SuperBlock_Data::SuperBlock_Data() { + free_list_head = 0; + inode_list_head = 0; +} + +void SuperBlock_Data::serialize(char buf[]) { + size_t i = 0; + i += write_u64(free_list_head, &buf[i]); + i += write_u64(inode_list_head, &buf[i]); +} + +void SuperBlock_Data::deserialize(char buf[]) { + size_t i = 0; + i += read_u64(&free_list_head, &buf[i]); + i += read_u64(&inode_list_head, &buf[i]); +} + +INode_Data::INode_Data(u_int64_t inode_num) : inode_num(inode_num) { + metadata.uid = -1; + metadata.gid = -1; + metadata.permissions = -1; + metadata.size = 0; + metadata.reference_count = 0; + + single_indirect_block = double_indirect_block = triple_indirect_block = 0; + + for (size_t i = 0; i < NUMBER_OF_DIRECT_BLOCKS; ++i) + direct_blocks[i] = 0; +} + +size_t INode_Data::serialize_metadata(char buf[]) { + size_t i = 0; + i += write_u64(metadata.uid, &buf[i]); + i += write_u64(metadata.gid, &buf[i]); + i += write_u64(metadata.permissions, &buf[i]); + i += write_u64(metadata.size, &buf[i]); + i += write_u32(metadata.reference_count, &buf[i]); + i += write_u32(metadata.flags, &buf[i]); + return i; +} + +size_t INode_Data::deserialize_metadata(char buf[]) { + size_t i = 0; + i += read_u64(&metadata.uid, &buf[i]); + i += read_u64(&metadata.gid, &buf[i]); + i += read_u64(&metadata.permissions, &buf[i]); + i += read_u64(&metadata.size, &buf[i]); + i += read_u32(&metadata.reference_count, &buf[i]); + i += read_u32(&metadata.flags, &buf[i]); + return i; +} + +void INode_Data::serialize(char buf[]) { + size_t i = 0; + i += serialize_metadata(&buf[i]); + i += write_u64(triple_indirect_block, &buf[i]); + i += write_u64(double_indirect_block, &buf[i]); + i += write_u64(single_indirect_block, &buf[i]); + for (size_t j = 0; j < NUMBER_OF_DIRECT_BLOCKS; ++j) + i += write_u64(direct_blocks[j], &buf[i]); +} +void INode_Data::deserialize(char buf[]) { + size_t i = 0; + i += deserialize_metadata(&buf[i]); + i += read_u64(&triple_indirect_block, &buf[i]); + i += read_u64(&double_indirect_block, &buf[i]); + i += read_u64(&single_indirect_block, &buf[i]); + for (size_t j = 0; j < NUMBER_OF_DIRECT_BLOCKS; ++j) + i += read_u64(&direct_blocks[j], &buf[i]); } \ No newline at end of file diff --git a/lib/fs/fs_resize.cpp b/lib/fs/fs_resize.cpp index e69de29..aa86465 100644 --- a/lib/fs/fs_resize.cpp +++ b/lib/fs/fs_resize.cpp @@ -0,0 +1,133 @@ +#include "fs.hpp" + +int Fs::allocate_datablock(INode_Data *inode_data) { + int result; + + for (size_t i = 0; i < NUMBER_OF_DIRECT_BLOCKS; ++i) + if (inode_data->direct_blocks[i] == 0) { + if ((result = datablock_allocator->new_datablock( + &(inode_data->direct_blocks[i]))) < 0) + return result; + return 0; + } + + result = allocate_indirect(&(inode_data->single_indirect_block), 1); + if (result <= 0) + return result; + + result = allocate_indirect(&(inode_data->double_indirect_block), 2); + if (result <= 0) + return result; + + result = allocate_indirect(&(inode_data->triple_indirect_block), 3); + if (result <= 0) + return result; + + return -1; +} + +// This can simply be made non recursive by copy pasting - it is just written +// this way as a proof of concept +int Fs::allocate_indirect(u_int64_t *storage, int n) { + char buf[IO_BLOCK_SIZE]; + int result; + + if ((*storage) == 0) { + if ((result = datablock_allocator->new_datablock(storage)) < 0) + return result; + if (n == 0) + return 0; + } + + if (n == 0) + return 1; + + u_int64_t temp; + + if ((result = disk->read_block(*storage, buf)) < 0) + return result; + + for (size_t i = 0; i < IO_BLOCK_SIZE; i += sizeof(u_int64_t)) { + read_u64(&temp, &buf[i]); + result = allocate_indirect(&temp, n - 1); + if (result < 0) + return result; + if (result == 0) { + write_u64(temp, &buf[i]); + if ((result = disk->write_block(*storage, buf)) < 0) + return result; + return 0; + } + } + + return 1; +} + +int Fs::deallocate_datablock(INode_Data *inode_data) { + int result; + + result = deallocate_indirect(&(inode_data->triple_indirect_block), 3); + if (result <= 0) + return result; + + result = deallocate_indirect(&(inode_data->double_indirect_block), 2); + if (result <= 0) + return result; + + result = deallocate_indirect(&(inode_data->single_indirect_block), 1); + if (result <= 0) + return result; + + for (size_t i = NUMBER_OF_DIRECT_BLOCKS - 1; i >= 0; --i) + if (inode_data->direct_blocks[i] != 0) { + if ((result = datablock_allocator->free_datablock( + inode_data->direct_blocks[i])) < 0) + return result; + inode_data->direct_blocks[i] = 0; + return 0; + } + + return -1; +} + +int Fs::deallocate_indirect(u_int64_t *storage, int n) { + char buf[IO_BLOCK_SIZE]; + int result; + + if (*storage == 0) + return 1; + + if (n == 0) { + if ((result = datablock_allocator->free_datablock(*storage)) < 0) + return result; + (*storage) = 0; + return 0; + } + + u_int64_t temp; + + if ((result = disk->read_block(*storage, buf)) < 0) + return result; + + for (size_t i = IO_BLOCK_SIZE - sizeof(u_int64_t); i >= 0; + i -= sizeof(u_int64_t)) { + read_u64(&temp, &buf[i]); + result = deallocate_indirect(&temp, n - 1); + if (result < 0) + return result; + if (result == 0) { + if (i == 0 && temp == 0) { + if ((result = datablock_allocator->free_datablock(*storage)) < 0) + return result; + (*storage) = 0; + } else { + write_u64(temp, &buf[i]); + if ((result = disk->write_block(*storage, buf)) < 0) + return result; + } + return 0; + } + } + + return 1; +} \ No newline at end of file diff --git a/lib/fs/inode_allocator.cpp b/lib/fs/inode_allocator.cpp index df02930..0d0ab85 100644 --- a/lib/fs/inode_allocator.cpp +++ b/lib/fs/inode_allocator.cpp @@ -1,94 +1,94 @@ -#include "fs.hpp" - -INode_Allocator::INode_Allocator(Fs *fs, u_int64_t block_segment_start, - u_int64_t block_segment_end) { - fs = fs; - block_segment_start = block_segment_start; - block_segment_end = block_segment_end; - max_num_inodes = (block_segment_end - block_segment_start) * INODES_PER_BLOCK; -} - -u_int64_t INode_Allocator::get_block_num(u_int64_t inode_num) { - u_int64_t block_num = block_segment_start + (inode_num / INODES_PER_BLOCK); - if (block_num >= block_segment_end) - return 0; - return block_num; -} -u_int64_t INode_Allocator::get_block_offset(u_int64_t inode_num) { - return (inode_num % INODES_PER_BLOCK) * INODE_SIZE; -} - -int INode_Allocator_Freelist::new_inode(u_int64_t uid, u_int64_t gid, - u_int64_t permissions, - INode_Data *inode_data) { - char buf[BLOCK_SIZE]; - int err; - u_int64_t inode_num = fs->superblock.inode_list_head; - if (inode_num > max_num_inodes) - return -1; - - u_int64_t block_num = get_block_num(inode_num); - - if (block_num == 0) - return -1; - - if ((err = disk->read_block(block_num, buf)) < 0) - return err; - - u_int64_t new_inode_list_head = 0; - read_u64(&new_inode_list_head, buf); - if ((err = fs->save_inode_list_head(new_inode_list_head)) < 0) - return err; - - (*inode_data) = INode_Data(inode_num); - - metadata.uid = uid; - metadata.gid = gid; - metadata.permissions = permissions; - - // It is debatable if this function should do this: - if ((err = fs->save_inode(inode_data)) < 0) { - inode_data->inode_num = 0xFFFFFFFFFFFFFFFF; - return err; - } - - return 0; -} -int INode_Allocator_Freelist::free_inode(INode_Data *inode_data) { - char buf[BLOCK_SIZE]; - int err; - - u_int64_t block_num = get_block_num(inode_data->inode_num); - u_int64_t block_offset = get_block_offset(inode_data->inode_num); - - if (block_num == 0) - return -1; - - if ((err = disk->read_block(block_num, buf)) < 0) - return err; - - write_u64(fs->superblock.inode_list_head, &buf[block_offset]); - - if ((err = disk->write_block(block_num, buf)) < 0) - return err; - - if ((err = fs->save_inode_list_head(inode_data->inode_num)) < 0) - return err; - - return 0; -} - -int INode_Allocator_Freelist::format() { - char buf[BLOCK_SIZE]; - int err; - u_int64_t next_inode_num = 1; - for (u_int64_t i = block_segment_start; i < block_segment_end; ++i) { - for (int j = 0; j < INODES_PER_BLOCK; ++next_inode_num, ++j) - write_u64(next_inode_num, &buf[j * INODE_SIZE]); - if ((err = disk->write_block(i, buf)) < 0) - return err; - } - if ((err = fs->save_inode_list_head(0)) < 0) - return err; - return 0; -} +#include "fs.hpp" + +INode_Allocator::INode_Allocator(Fs *fs, u_int64_t block_segment_start, + u_int64_t block_segment_end) + : fs(fs), block_segment_start(block_segment_start), + block_segment_end(block_segment_end) { + max_num_inodes = (block_segment_end - block_segment_start) * INODES_PER_BLOCK; +} + +u_int64_t INode_Allocator::get_block_num(u_int64_t inode_num) { + u_int64_t block_num = block_segment_start + (inode_num / INODES_PER_BLOCK); + if (block_num >= block_segment_end) + return 0; + return block_num; +} +u_int64_t INode_Allocator::get_block_offset(u_int64_t inode_num) { + return (inode_num % INODES_PER_BLOCK) * INODE_SIZE; +} + +int INode_Allocator_Freelist::new_inode(u_int64_t uid, u_int64_t gid, + u_int64_t permissions, + INode_Data *inode_data) { + char buf[IO_BLOCK_SIZE]; + int err; + u_int64_t inode_num = fs->superblock.inode_list_head; + if (inode_num > max_num_inodes) + return -1; + + u_int64_t block_num = get_block_num(inode_num); + u_int64_t block_offset = get_block_offset(inode_num); + + if (block_num == 0) + return -1; + + if ((err = fs->disk->read_block(block_num, buf)) < 0) + return err; + + u_int64_t new_inode_list_head = 0; + read_u64(&new_inode_list_head, &buf[block_offset]); + if ((err = fs->save_inode_list_head(new_inode_list_head)) < 0) + return err; + + (*inode_data) = INode_Data(inode_num); + + inode_data->metadata.uid = uid; + inode_data->metadata.gid = gid; + inode_data->metadata.permissions = permissions; + + // It is debatable if this function should do this: + if ((err = fs->save_inode(inode_data)) < 0) { + inode_data->inode_num = 0xFFFFFFFFFFFFFFFF; + return err; + } + + return 0; +} +int INode_Allocator_Freelist::free_inode(INode_Data *inode_data) { + char buf[IO_BLOCK_SIZE]; + int err; + + u_int64_t block_num = get_block_num(inode_data->inode_num); + u_int64_t block_offset = get_block_offset(inode_data->inode_num); + + if (block_num == 0) + return -1; + + if ((err = fs->disk->read_block(block_num, buf)) < 0) + return err; + + write_u64(fs->superblock.inode_list_head, &buf[block_offset]); + + if ((err = fs->disk->write_block(block_num, buf)) < 0) + return err; + + if ((err = fs->save_inode_list_head(inode_data->inode_num)) < 0) + return err; + + return 0; +} + +int INode_Allocator_Freelist::format() { + char buf[IO_BLOCK_SIZE]; + int err; + u_int64_t next_inode_num = 1; + for (u_int64_t i = block_segment_start; i < block_segment_end; ++i) { + for (int j = 0; j < INODES_PER_BLOCK; ++next_inode_num, ++j) + write_u64(next_inode_num, &buf[j * INODE_SIZE]); + if ((err = fs->disk->write_block(i, buf)) < 0) + return err; + } + if ((err = fs->save_inode_list_head(0)) < 0) + return err; + return 0; +} diff --git a/lib/main.cpp b/lib/main.cpp index 396b885..7ce392a 100644 --- a/lib/main.cpp +++ b/lib/main.cpp @@ -1,10 +1,36 @@ -#include "fischl.h" -#include "rawdisk.h" - -int main(){ - fischl *F = new fischl; - F->init(); - char *d = strdup("/dev/vdc"); - RawDisk *H = new RawDisk(d); - return 0; +#include "fischl.h" +#include "fs.hpp" +#include + +int main() { + // printf("hello word!"); + // fischl *F = new fischl; + // F->init(); + // char *d = strdup("/dev/vdc"); + RawDisk *disk = new FakeRawDisk(2048); + Fs *fs = new Fs(disk); + fs->format(); + disk->print_block(0); + disk->print_block(1); + INode_Data inode_data = INode_Data(); + fs->inode_allocator->new_inode(1, 2, 3, &inode_data); + int err; + for (int i = 0; i < 56 + 512 + 4; ++i) + err = fs->allocate_datablock(&inode_data); + + for (int i = 0; i < 3; ++i) + printf("%d\n", err = fs->deallocate_datablock(&inode_data)); + + fs->save_inode(&inode_data); + + disk->print_block(0); + disk->print_block(1); + + disk->print_block(1081); + + disk->print_block(1596); + + disk->print_block(1597); + + return 0; } \ No newline at end of file diff --git a/lib/rawdisk.cpp b/lib/rawdisk.cpp index cff45f3..c033bc2 100644 --- a/lib/rawdisk.cpp +++ b/lib/rawdisk.cpp @@ -1,124 +1,132 @@ -#include "rawdisk.hpp" - -class RealRawDisk : RawDisk { -public: - int fd; - const char *dir; - u_int64_t numSectors; - - RealRawDisk(const char *directory) - : fd(-1), dir(nullptr), numSectors(0), diskSize(0) { - dir = directory; - /*dir = strdup("/dev/vdc"); - numSectors = 62914560; - diskSize = 32212254720;*/ - - // Open the block device (replace /dev/sdX with the actual device) - fd = open(dir, O_RDWR); // Allow read and write - if (fd == -1) { - perror("Error opening device"); - exit(1); - } - - // Use ioctl with BLKGETSIZE to get the number of sectors - if (ioctl(fd, BLKGETSIZE64, &diskSize) == -1) { - perror("Error getting disk size"); - close(fd); - exit(1); - } - - // Calculate the size in bytes - numSectors = diskSize / 512; // Assuming a sector size of 512 bytes - - printf("====Initializing RawDisk====\n"); - printf("Number of sectors: %llu\n", numSectors); - printf("Disk size (in bytes): %llu\n", diskSize); - } - - ~RealRawDisk() { - if (fd != -1) { - close(fd); - } - } - - int read_block(u_int64_t block_number, char *buffer) { - u_int64_t offset = block_number * BLOCK_SIZE; - - if (lseek(fd, offset, SEEK_SET) == (u_int64_t)-1) { - perror("Error seeking to offset"); - return -1; - } - - // TODO: this is incorrect - ssize_t bytesRead = read(fd, buffer, BLOCK_SIZE); - if (bytesRead < BLOCK_SIZE) { - perror("Error reading from device"); - return -1; - } - - return 0; - } - - int write_block(u_int64_t block_number, char *buffer) { - u_int64_t offset = block_number * BLOCK_SIZE; - - if (lseek(fd, offset, SEEK_SET) == (u_int64_t)-1) { - perror("Error seeking to offset"); - return -1; - } - - // TODO: this is incorrect - ssize_t bytesWritten = write(fd, buffer, BLOCK_SIZE); - if (bytesWritten < BLOCK_SIZE) { - perror("Error writing to device"); - return -1; - } - - return 0; - } -}; - -class FakeRawDisk : RawDisk { -public: - char *disk; - - FakeRawDisk(u_int64_t num_blocks) { - disksize = num_blocks * BLOCK_SIZE; - disk = new char[disksize]; - if (disk == nullptr) { - perror("Error allocating fake disk"); - exit(1); - } - printf("====Initializing FAKE RawDisk====\n"); - printf("FAKE Disk size (in bytes): %llu\n", diskSize); - perror("!!! USING FAKE RawDisk - THIS IS FOR TESTING ONLY !!!"); - } - - ~FakeRawDisk() { delete[] disk; } - - int read_block(u_int64_t block_number, char *buffer) { - u_int64_t offset = block_number * BLOCK_SIZE; - - if (offset + BLOCK_SIZE > diskSize) { - perror("Error reading past fake disk size"); - return -1; - } - - memcpy(buffer, &disk[offset], BLOCK_SIZE); - - return 0; - } - - int write_block(u_int64_t block_number, char *buffer) { - u_int64_t offset = block_number * BLOCK_SIZE; - - if (offset + BLOCK_SIZE > diskSize) { - perror("Error writing past fake disk size"); - return -1; - } - - memcpy(&disk[offset], buffer, BLOCK_SIZE); - - return 0; - } -}; \ No newline at end of file +#include "fs.hpp" + +void RawDisk::print_block(u_int64_t block_number) { + const int nums_per_line = 64; + char buf[IO_BLOCK_SIZE]; + u_int64_t num; + + if (read_block(block_number, buf) < 0) { + perror("Error printing datablock"); + return; + } + + printf("\nBlock %llu:\n", block_number); + for (int i = 0; i < IO_BLOCK_SIZE; i += sizeof(u_int64_t)) { + read_u64(&num, &buf[i]); + printf("%llu ", num); + if ((i / sizeof(u_int64_t)) % nums_per_line == nums_per_line - 1) + printf("\n"); + } +} + +RealRawDisk::RealRawDisk(const char *directory) + : fd(-1), dir(nullptr), numSectors(0) { + dir = directory; + diskSize = 0; + /*dir = strdup("/dev/vdc"); + numSectors = 62914560; + diskSize = 32212254720;*/ + + // Open the block device (replace /dev/sdX with the actual device) + fd = open(dir, O_RDWR); // Allow read and write + if (fd == -1) { + perror("Error opening device"); + exit(1); + } + + // Use ioctl with BLKGETSIZE to get the number of sectors + if (ioctl(fd, BLKGETSIZE64, &diskSize) == -1) { + perror("Error getting disk size"); + close(fd); + exit(1); + } + + // Calculate the size in bytes + numSectors = diskSize / 512; // Assuming a sector size of 512 bytes + + printf("====Initializing RawDisk====\n"); + printf("Number of sectors: %llu\n", numSectors); + printf("Disk size (in bytes): %llu\n", diskSize); +} + +RealRawDisk::~RealRawDisk() { + if (fd != -1) { + close(fd); + } +} + +int RealRawDisk::read_block(u_int64_t block_number, char *buffer) { + u_int64_t offset = block_number * IO_BLOCK_SIZE; + + if (lseek(fd, offset, SEEK_SET) == (u_int64_t)-1) { + perror("Error seeking to offset"); + return -1; + } + + // TODO: this is incorrect + ssize_t bytesRead = read(fd, buffer, IO_BLOCK_SIZE); + if (bytesRead < IO_BLOCK_SIZE) { + perror("Error reading from device"); + return -1; + } + + return 0; +} + +int RealRawDisk::write_block(u_int64_t block_number, char *buffer) { + u_int64_t offset = block_number * IO_BLOCK_SIZE; + + if (lseek(fd, offset, SEEK_SET) == (u_int64_t)-1) { + perror("Error seeking to offset"); + return -1; + } + + // TODO: this is incorrect + ssize_t bytesWritten = write(fd, buffer, IO_BLOCK_SIZE); + if (bytesWritten < IO_BLOCK_SIZE) { + perror("Error writing to device"); + return -1; + } + + return 0; +} + +FakeRawDisk::FakeRawDisk(u_int64_t num_blocks) { + diskSize = num_blocks * IO_BLOCK_SIZE; + disk = new char[diskSize]; + if (disk == nullptr) { + perror("Error allocating fake disk"); + exit(1); + } + printf("====Initializing FAKE RawDisk====\n"); + printf("FAKE Disk size (in bytes): %llu\n", diskSize); + perror("!!! USING FAKE RawDisk - THIS IS FOR TESTING ONLY !!!"); +} + +FakeRawDisk::~FakeRawDisk() { delete[] disk; } + +int FakeRawDisk::read_block(u_int64_t block_number, char *buffer) { + u_int64_t offset = block_number * IO_BLOCK_SIZE; + + if (offset + IO_BLOCK_SIZE > diskSize) { + perror("Error reading past fake disk size"); + return -1; + } + + memcpy(buffer, &disk[offset], IO_BLOCK_SIZE); + + return 0; +} + +int FakeRawDisk::write_block(u_int64_t block_number, char *buffer) { + u_int64_t offset = block_number * IO_BLOCK_SIZE; + + if (offset + IO_BLOCK_SIZE > diskSize) { + perror("Error writing past fake disk size"); + return -1; + } + + memcpy(&disk[offset], buffer, IO_BLOCK_SIZE); + + return 0; +} \ No newline at end of file diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index b946592..a47d2a7 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,17 +1,17 @@ -set(TARGET_LAYER0 test_layer0) -set(TARGET_LAYER1_API test_layer1_API) -set(DIR_PLACE /dev/vdb) - -# add test sources here ... -add_executable(${TARGET_LAYER0} - # add need lib and source code here - layer0.cpp -) -add_executable(${TARGET_LAYER1_API} - # add need lib and source code here - layer1_API.cpp -) - -# add test to activate ctest -VV -add_test(NAME ${TARGET_LAYER0} COMMAND sudo ./${TARGET_LAYER0} ${DIR_PLACE}) +set(TARGET_LAYER0 test_layer0) +set(TARGET_LAYER1_API test_layer1_API) +set(DIR_PLACE /dev/vdb) + +# add test sources here ... +add_executable(${TARGET_LAYER0} + # add need lib and source code here + layer0.cpp +) +add_executable(${TARGET_LAYER1_API} + # add need lib and source code here + layer1_API.cpp +) + +# add test to activate ctest -VV +add_test(NAME ${TARGET_LAYER0} COMMAND sudo ./${TARGET_LAYER0} ${DIR_PLACE}) add_test(NAME ${TARGET_LAYER1_API} COMMAND sudo ./${TARGET_LAYER1_API} ${DIR_PLACE}) \ No newline at end of file diff --git a/test/layer0.cpp b/test/layer0.cpp index 8cc358a..122f066 100644 --- a/test/layer0.cpp +++ b/test/layer0.cpp @@ -1,29 +1,29 @@ -#include -#include -#include -#include "rawdisk.h" - -int main(int argc, char *argv[]) { - const char* d = (argc < 2) ? "/dev/vdc" : argv[1]; - - RawDisk *H = new RawDisk(d); - - char *buf = "iloveosdfjlseirfnerig"; - char readBuffer[512] = {0}; // Initialize to zeros - - //printf("dir %s, numSectors %lld, diskSize %lld \n", H->dir, H->numSectors, H->diskSize); - - //use number to substitute H->getnumSector(), getnumSectors() are not yest implemented - for(u_int64_t i = 0; i < 10; i++) { - H->rawdisk_write(i*512, buf, strlen(buf));//Change write_API - } - //use number to substitute H->getnumSector(), getnumSectors() are not yest implemented - for(u_int64_t i = 0; i < 10; i++) { - H->rawdisk_read(i*512, readBuffer, sizeof(readBuffer));//Change read_API - assert(strncmp(readBuffer, buf, strlen(buf)) == 0); - } - - delete H; // Delete the RawDisk object - - return 0; -} +#include +#include +#include +#include "rawdisk.h" + +int main(int argc, char *argv[]) { + const char* d = (argc < 2) ? "/dev/vdc" : argv[1]; + + RawDisk *H = new RawDisk(d); + + char *buf = "iloveosdfjlseirfnerig"; + char readBuffer[512] = {0}; // Initialize to zeros + + //printf("dir %s, numSectors %lld, diskSize %lld \n", H->dir, H->numSectors, H->diskSize); + + //use number to substitute H->getnumSector(), getnumSectors() are not yest implemented + for(u_int64_t i = 0; i < 10; i++) { + H->rawdisk_write(i*512, buf, strlen(buf));//Change write_API + } + //use number to substitute H->getnumSector(), getnumSectors() are not yest implemented + for(u_int64_t i = 0; i < 10; i++) { + H->rawdisk_read(i*512, readBuffer, sizeof(readBuffer));//Change read_API + assert(strncmp(readBuffer, buf, strlen(buf)) == 0); + } + + delete H; // Delete the RawDisk object + + return 0; +} diff --git a/test/layer1_API.cpp b/test/layer1_API.cpp index 0c63001..e898231 100644 --- a/test/layer1_API.cpp +++ b/test/layer1_API.cpp @@ -1,118 +1,118 @@ -#include -#include -#include -#include "fs.h" -#include - -int main(int argc, char *argv[]) { - const char* d = (argc < 2) ? "/dev/vdc" : argv[1]; - - RawDisk *H = new RawDisk(d); - - printf("test inode\n"); - INodeOperation inop; - inop.initialize(*H);//for inode initialization and datablock initialization - char buffer[8] = {0}; - /**************************test inode Initialization***************************/ - //test the begining of inode 1th - H->rawdisk_read((1) * SECTOR_SIZE, buffer, sizeof(buffer)); - u_int64_t t = 0; - for (int j = 0; j < 8; j++) - t |= ((u_int64_t)(unsigned char)buffer[j]) << (8 * j); - - assert(t == 2);//the first 1th unused inode will store the next unused inode 2th - //test the number before end of inode 524286th - H->rawdisk_read((MAX_INODE - 2) * SECTOR_SIZE, buffer, sizeof(buffer)); - t = 0; - for (int j = 0; j < 8; j++) - t |= ((u_int64_t)(unsigned char)buffer[j]) << (8 * j); - - assert(t == MAX_INODE - 1);//store the maximun th inode - //test the end of inode 524287th - H->rawdisk_read((MAX_INODE - 1) * SECTOR_SIZE, buffer, sizeof(buffer)); - t = 0; - for (int j = 0; j < 8; j++) - t |= ((u_int64_t)(unsigned char)buffer[j]) << (8 * j); - - assert(t == 0);//the end of inode(524287th inode) do not have the next inode address - /**************************test datablock Initialization***************************/ - //we separate 2048 4kB I/O block(1+2047) as a group and the first I/O block will manage the following 2047 I/O block usage. - //the first 8 bytes(0~7) in first I/O block store the address of next first I/O block, the following 256(8~263) bytes record 2047 I/O block usage. - //test the begining of free datablock - H->rawdisk_read((MAX_INODE) * SECTOR_SIZE, buffer, sizeof(buffer));//the begining of free datablock will store from address (MAX_INODE) * SECTOR_SIZE - t = 0; - for (int j = 0; j < 8; j++) - t |= ((u_int64_t)(unsigned char)buffer[j]) << (8 * j); - - assert(t == (MAX_INODE+2048*8)*SECTOR_SIZE);//the first 8 bytes of 4k I/O block will store the next address(after 2048*4k I/O block) - //test the end of the datablock - H->rawdisk_read((MAX_BLOCKNUM - 2048*8) * SECTOR_SIZE, buffer, sizeof(buffer)); - t = 0; - for (int j = 0; j < 8; j++) - t |= ((u_int64_t)(unsigned char)buffer[j]) << (8 * j); - - assert(t == (MAX_BLOCKNUM)*SECTOR_SIZE); - - /***************************test inode de/allocation**********************************/ - //when requesting an inode, the inode_allocation will give you the inode number, we use inode_list to store the sequence allocate inode - //arrary version - int inode_list[20] = {0}; - int record_free[10] = {0};//should do a pop up structure to record the free inode - int rec = 9; - //printf("Allocate 20 inode num:{"); - for(int i=0;i<20;i++){ - inode_list[i] = inop.inode_allocate(*H); - assert(inode_list[i] == i+1); - //printf(" %d", inode_list[i]); - } - //printf("}\n"); - for(int i=10;i<20;i++){ - inop.inode_free(*H,inode_list[i]);//free the 10 element from inode_list[10] - record_free[i-10] = inode_list[i]; - } - //allocate again the last 10 - printf("Allocate again: inode num:{"); - for(int i=10;i<20;i++){ - inode_list[i] = inop.inode_allocate(*H); - //printf("inode %d, rec_f %d\n,", inode_list[i],record_free[rec]); - assert(inode_list[i] == record_free[rec]); - rec--; - } - printf("}\n"); - /***************************test direct blocks[48] de/allocation**********************************/ - //after free the datablock, the program will find the first smallest address of datablock to give to the inode - //should test random resize each node, but should use datablock_free data structure to record - INode inode_inside[10]; - u_int64_t rec_datablock_free[10][3] = {0};//array version - for(int i=0;i<10;i++){ - inode_inside[i].inode_construct(inode_list[i],*H); - //printf("%dth data block starting addres: ", i); - for(int j=0;j<6;j++){ - inode_inside[i].datablock_allocate(*H); - //printf("%d," ,inode_inside[i].datablock_allocate(*H)); - } - //printf("\n"); - } - for(int i=0;i<10;i++){ - //printf("%dth data block free addres: ", i); - for(int j = 2;j >=0;j--){ - rec_datablock_free[i][j] = inode_inside[i].datablock_deallocate(*H); - //printf("", rec_datablock_free[i][j]); - } - //printf("\n"); - } - - for(int i=0;i<10;i++){ - //printf("%dth data block allocate again addres: ", i); - for(int j=0;j<3;j++){ - assert(inode_inside[i].datablock_allocate(*H) == rec_datablock_free[i][j]); - //printf("%d," ,inode_inside[i].datablock_allocate(*H)); - } - //printf("\n"); - } - - //printf("}\n"); - delete H; // Delete the RawDisk object - - return 0; -} +#include +#include +#include +#include "fs.h" +#include + +int main(int argc, char *argv[]) { + const char* d = (argc < 2) ? "/dev/vdc" : argv[1]; + + RawDisk *H = new RawDisk(d); + + printf("test inode\n"); + INodeOperation inop; + inop.initialize(*H);//for inode initialization and datablock initialization + char buffer[8] = {0}; + /**************************test inode Initialization***************************/ + //test the begining of inode 1th + H->rawdisk_read((1) * SECTOR_SIZE, buffer, sizeof(buffer)); + u_int64_t t = 0; + for (int j = 0; j < 8; j++) + t |= ((u_int64_t)(unsigned char)buffer[j]) << (8 * j); + + assert(t == 2);//the first 1th unused inode will store the next unused inode 2th + //test the number before end of inode 524286th + H->rawdisk_read((MAX_INODE - 2) * SECTOR_SIZE, buffer, sizeof(buffer)); + t = 0; + for (int j = 0; j < 8; j++) + t |= ((u_int64_t)(unsigned char)buffer[j]) << (8 * j); + + assert(t == MAX_INODE - 1);//store the maximun th inode + //test the end of inode 524287th + H->rawdisk_read((MAX_INODE - 1) * SECTOR_SIZE, buffer, sizeof(buffer)); + t = 0; + for (int j = 0; j < 8; j++) + t |= ((u_int64_t)(unsigned char)buffer[j]) << (8 * j); + + assert(t == 0);//the end of inode(524287th inode) do not have the next inode address + /**************************test datablock Initialization***************************/ + //we separate 2048 4kB I/O block(1+2047) as a group and the first I/O block will manage the following 2047 I/O block usage. + //the first 8 bytes(0~7) in first I/O block store the address of next first I/O block, the following 256(8~263) bytes record 2047 I/O block usage. + //test the begining of free datablock + H->rawdisk_read((MAX_INODE) * SECTOR_SIZE, buffer, sizeof(buffer));//the begining of free datablock will store from address (MAX_INODE) * SECTOR_SIZE + t = 0; + for (int j = 0; j < 8; j++) + t |= ((u_int64_t)(unsigned char)buffer[j]) << (8 * j); + + assert(t == (MAX_INODE+2048*8)*SECTOR_SIZE);//the first 8 bytes of 4k I/O block will store the next address(after 2048*4k I/O block) + //test the end of the datablock + H->rawdisk_read((MAX_BLOCKNUM - 2048*8) * SECTOR_SIZE, buffer, sizeof(buffer)); + t = 0; + for (int j = 0; j < 8; j++) + t |= ((u_int64_t)(unsigned char)buffer[j]) << (8 * j); + + assert(t == (MAX_BLOCKNUM)*SECTOR_SIZE); + + /***************************test inode de/allocation**********************************/ + //when requesting an inode, the inode_allocation will give you the inode number, we use inode_list to store the sequence allocate inode + //arrary version + int inode_list[20] = {0}; + int record_free[10] = {0};//should do a pop up structure to record the free inode + int rec = 9; + //printf("Allocate 20 inode num:{"); + for(int i=0;i<20;i++){ + inode_list[i] = inop.inode_allocate(*H); + assert(inode_list[i] == i+1); + //printf(" %d", inode_list[i]); + } + //printf("}\n"); + for(int i=10;i<20;i++){ + inop.inode_free(*H,inode_list[i]);//free the 10 element from inode_list[10] + record_free[i-10] = inode_list[i]; + } + //allocate again the last 10 + printf("Allocate again: inode num:{"); + for(int i=10;i<20;i++){ + inode_list[i] = inop.inode_allocate(*H); + //printf("inode %d, rec_f %d\n,", inode_list[i],record_free[rec]); + assert(inode_list[i] == record_free[rec]); + rec--; + } + printf("}\n"); + /***************************test direct blocks[48] de/allocation**********************************/ + //after free the datablock, the program will find the first smallest address of datablock to give to the inode + //should test random resize each node, but should use datablock_free data structure to record + INode inode_inside[10]; + u_int64_t rec_datablock_free[10][3] = {0};//array version + for(int i=0;i<10;i++){ + inode_inside[i].inode_construct(inode_list[i],*H); + //printf("%dth data block starting addres: ", i); + for(int j=0;j<6;j++){ + inode_inside[i].datablock_allocate(*H); + //printf("%d," ,inode_inside[i].datablock_allocate(*H)); + } + //printf("\n"); + } + for(int i=0;i<10;i++){ + //printf("%dth data block free addres: ", i); + for(int j = 2;j >=0;j--){ + rec_datablock_free[i][j] = inode_inside[i].datablock_deallocate(*H); + //printf("", rec_datablock_free[i][j]); + } + //printf("\n"); + } + + for(int i=0;i<10;i++){ + //printf("%dth data block allocate again addres: ", i); + for(int j=0;j<3;j++){ + assert(inode_inside[i].datablock_allocate(*H) == rec_datablock_free[i][j]); + //printf("%d," ,inode_inside[i].datablock_allocate(*H)); + } + //printf("\n"); + } + + //printf("}\n"); + delete H; // Delete the RawDisk object + + return 0; +} diff --git a/test/testfischl.cpp b/test/testfischl.cpp index 541aa97..1c83f3a 100644 --- a/test/testfischl.cpp +++ b/test/testfischl.cpp @@ -1,13 +1,13 @@ -#include "fischl.h" -#include - -void testFischlInit(){ - fischl *F = new fischl; - assert(F->init()==3); - delete F; -} - -int main(){ - testFischlInit(); - return 0; +#include "fischl.h" +#include + +void testFischlInit(){ + fischl *F = new fischl; + assert(F->init()==3); + delete F; +} + +int main(){ + testFischlInit(); + return 0; } \ No newline at end of file From 634180c3ce66ad98ff407bc93b6e1d161224a535 Mon Sep 17 00:00:00 2001 From: Connor Date: Wed, 15 Nov 2023 22:56:48 -0800 Subject: [PATCH 08/13] changed name of inode manager --- include/fs.hpp | 11 ++-- ...ck_allocator.hpp => datablock_manager.hpp} | 14 ++--- ...{inode_allocator.hpp => inode_manager.hpp} | 17 +++--- lib/fs/datablock_allocator.cpp | 8 +-- lib/fs/fs.cpp | 52 +++---------------- lib/fs/fs_resize.cpp | 10 ++-- lib/fs/inode_allocator.cpp | 52 ++++++++++++++++--- lib/main.cpp | 6 +-- 8 files changed, 85 insertions(+), 85 deletions(-) rename include/fs/{datablock_allocator.hpp => datablock_manager.hpp} (57%) rename include/fs/{inode_allocator.hpp => inode_manager.hpp} (66%) diff --git a/include/fs.hpp b/include/fs.hpp index 8be4ef6..0a372bc 100644 --- a/include/fs.hpp +++ b/include/fs.hpp @@ -1,9 +1,9 @@ #ifndef FS_HPP #define FS_HPP -#include "fs/datablock_allocator.hpp" +#include "fs/datablock_manager.hpp" #include "fs/fs_data_types.hpp" -#include "fs/inode_allocator.hpp" +#include "fs/inode_manager.hpp" #include "fs_constants.hpp" #include "rawdisk.hpp" @@ -20,8 +20,8 @@ public: // should probably be private but is not for testing RawDisk *disk; SuperBlock_Data superblock; - INode_Allocator *inode_allocator; - DataBlock_Allocator *datablock_allocator; + INode_Manager *inode_manager; + DataBlock_Manager *datablock_manager; int load_superblock(); int save_superblock(); @@ -29,9 +29,6 @@ public: int save_free_list_head(u_int64_t new_free_list_head); int save_inode_list_head(u_int64_t new_inode_list_head); - int load_inode(INode_Data *inode_data); - int save_inode(INode_Data *inode_data); - int allocate_indirect(u_int64_t *storage, int n); int deallocate_indirect(u_int64_t *storage, int n); }; diff --git a/include/fs/datablock_allocator.hpp b/include/fs/datablock_manager.hpp similarity index 57% rename from include/fs/datablock_allocator.hpp rename to include/fs/datablock_manager.hpp index df01087..17df611 100644 --- a/include/fs/datablock_allocator.hpp +++ b/include/fs/datablock_manager.hpp @@ -1,13 +1,13 @@ -#ifndef DATABLOCK_ALLOCATOR_HPP -#define DATABLOCK_ALLOCATOR_HPP +#ifndef DATABLOCK_MANAGER_HPP +#define DATABLOCK_MANAGER_HPP #include "fs_constants.hpp" class Fs; -class DataBlock_Allocator { +class DataBlock_Manager { public: - DataBlock_Allocator(Fs *fs, u_int64_t block_segment_start, + DataBlock_Manager(Fs *fs, u_int64_t block_segment_start, u_int64_t block_segment_end); virtual int new_datablock(u_int64_t *block_num) = 0; @@ -20,11 +20,11 @@ protected: u_int64_t block_segment_start, block_segment_end; }; -class DataBlock_Allocator_Bitmap : public DataBlock_Allocator { +class DataBlock_Manager_Bitmap : public DataBlock_Manager { public: - DataBlock_Allocator_Bitmap(Fs *fs, u_int64_t block_segment_start, + DataBlock_Manager_Bitmap(Fs *fs, u_int64_t block_segment_start, u_int64_t block_segment_end) - : DataBlock_Allocator(fs, block_segment_start, block_segment_end) {} + : DataBlock_Manager(fs, block_segment_start, block_segment_end) {} int new_datablock(u_int64_t *block_num) override; int free_datablock(u_int64_t block_num) override; diff --git a/include/fs/inode_allocator.hpp b/include/fs/inode_manager.hpp similarity index 66% rename from include/fs/inode_allocator.hpp rename to include/fs/inode_manager.hpp index 116474d..9ef860d 100644 --- a/include/fs/inode_allocator.hpp +++ b/include/fs/inode_manager.hpp @@ -1,16 +1,16 @@ -#ifndef INODE_ALLOCATOR_HPP -#define INODE_ALLOCATOR_HPP +#ifndef INODE_MANAGER_HPP +#define INODE_MANAGER_HPP #include "fs_constants.hpp" #include "fs_data_types.hpp" class Fs; -class INode_Allocator { +class INode_Manager { public: const int INODES_PER_BLOCK = IO_BLOCK_SIZE / INODE_SIZE; - INode_Allocator(Fs *fs, u_int64_t block_segment_start, + INode_Manager(Fs *fs, u_int64_t block_segment_start, u_int64_t block_segment_end); virtual int new_inode(u_int64_t uid, u_int64_t gid, u_int64_t permissions, @@ -22,17 +22,20 @@ public: u_int64_t get_block_num(u_int64_t inode_data); u_int64_t get_block_offset(u_int64_t inode_data); + int load_inode(INode_Data *inode_data); + int save_inode(INode_Data *inode_data); + protected: Fs *fs; u_int64_t block_segment_start, block_segment_end; u_int64_t max_num_inodes; }; -class INode_Allocator_Freelist : public INode_Allocator { +class INode_Manager_Freelist : public INode_Manager { public: - INode_Allocator_Freelist(Fs *fs, u_int64_t block_segment_start, + INode_Manager_Freelist(Fs *fs, u_int64_t block_segment_start, u_int64_t block_segment_end) - : INode_Allocator(fs, block_segment_start, block_segment_end) {} + : INode_Manager(fs, block_segment_start, block_segment_end) {} int new_inode(u_int64_t uid, u_int64_t gid, u_int64_t permissions, INode_Data *inode_data) override; diff --git a/lib/fs/datablock_allocator.cpp b/lib/fs/datablock_allocator.cpp index 531b993..e6737d7 100644 --- a/lib/fs/datablock_allocator.cpp +++ b/lib/fs/datablock_allocator.cpp @@ -1,6 +1,6 @@ #include "fs.hpp" -DataBlock_Allocator::DataBlock_Allocator(Fs *fs, u_int64_t block_segment_start, +DataBlock_Manager::DataBlock_Manager(Fs *fs, u_int64_t block_segment_start, u_int64_t block_segment_end) : fs(fs), block_segment_start(block_segment_start), block_segment_end(block_segment_end) {} @@ -45,7 +45,7 @@ public: } }; -int DataBlock_Allocator_Bitmap::new_datablock(u_int64_t *block_num) { +int DataBlock_Manager_Bitmap::new_datablock(u_int64_t *block_num) { int err; BitmapBlock_Data bitmap = BitmapBlock_Data(DATABLOCKS_PER_BITMAP_BLOCK); u_int64_t bitmap_block_num = fs->superblock.free_list_head; @@ -83,7 +83,7 @@ int DataBlock_Allocator_Bitmap::new_datablock(u_int64_t *block_num) { return 0; } -int DataBlock_Allocator_Bitmap::free_datablock(u_int64_t block_num) { +int DataBlock_Manager_Bitmap::free_datablock(u_int64_t block_num) { int err; BitmapBlock_Data bitmap = BitmapBlock_Data(DATABLOCKS_PER_BITMAP_BLOCK); const u_int64_t bitmap_region_size = DATABLOCKS_PER_BITMAP_BLOCK + 1; @@ -117,7 +117,7 @@ int DataBlock_Allocator_Bitmap::free_datablock(u_int64_t block_num) { // potentially like 256 times slower throughput } -int DataBlock_Allocator_Bitmap::format() { +int DataBlock_Manager_Bitmap::format() { const u_int64_t bitmap_region_size = DATABLOCKS_PER_BITMAP_BLOCK + 1; char buf[IO_BLOCK_SIZE] = {0}; int err; diff --git a/lib/fs/fs.cpp b/lib/fs/fs.cpp index 98d8f9d..c87ced9 100644 --- a/lib/fs/fs.cpp +++ b/lib/fs/fs.cpp @@ -2,23 +2,23 @@ Fs::Fs(RawDisk *disk) : disk(disk) { superblock = SuperBlock_Data(); - inode_allocator = new INode_Allocator_Freelist(this, 1, 1 + NUM_INODE_BLOCKS); - datablock_allocator = - new DataBlock_Allocator_Bitmap(this, 1 + NUM_INODE_BLOCKS, NUM_BLOCKS); + inode_manager = new INode_Manager_Freelist(this, 1, 1 + NUM_INODE_BLOCKS); + datablock_manager = + new DataBlock_Manager_Bitmap(this, 1 + NUM_INODE_BLOCKS, NUM_BLOCKS); }; Fs::~Fs() { - delete inode_allocator; - delete datablock_allocator; + delete inode_manager; + delete datablock_manager; }; int Fs::format() { int err; if ((err = save_superblock()) < 0) return err; - if ((err = inode_allocator->format()) < 0) + if ((err = inode_manager->format()) < 0) return err; - if ((err = datablock_allocator->format()) < 0) + if ((err = datablock_manager->format()) < 0) return err; return 0; } @@ -65,42 +65,4 @@ int Fs::save_inode_list_head(u_int64_t new_inode_list_head) { return err; } return 0; -} - -int Fs::load_inode(INode_Data *inode_data) { - char buf[IO_BLOCK_SIZE]; - int err; - - u_int64_t block_num = inode_allocator->get_block_num(inode_data->inode_num); - if (block_num == 0) - return -1; - u_int64_t block_offset = - inode_allocator->get_block_offset(inode_data->inode_num); - - if ((err = disk->read_block(block_num, buf)) < 0) - return err; - - inode_data->deserialize(&buf[block_offset]); - - return 0; -} -int Fs::save_inode(INode_Data *inode_data) { - char buf[IO_BLOCK_SIZE]; - int err; - - u_int64_t block_num = inode_allocator->get_block_num(inode_data->inode_num); - if (block_num == 0) - return -1; - u_int64_t block_offset = - inode_allocator->get_block_offset(inode_data->inode_num); - - if ((err = disk->read_block(block_num, buf)) < 0) - return err; - - inode_data->serialize(&buf[block_offset]); - - if ((err = disk->write_block(block_num, buf)) < 0) - return err; - - return 0; } \ No newline at end of file diff --git a/lib/fs/fs_resize.cpp b/lib/fs/fs_resize.cpp index aa86465..c700828 100644 --- a/lib/fs/fs_resize.cpp +++ b/lib/fs/fs_resize.cpp @@ -5,7 +5,7 @@ int Fs::allocate_datablock(INode_Data *inode_data) { for (size_t i = 0; i < NUMBER_OF_DIRECT_BLOCKS; ++i) if (inode_data->direct_blocks[i] == 0) { - if ((result = datablock_allocator->new_datablock( + if ((result = datablock_manager->new_datablock( &(inode_data->direct_blocks[i]))) < 0) return result; return 0; @@ -33,7 +33,7 @@ int Fs::allocate_indirect(u_int64_t *storage, int n) { int result; if ((*storage) == 0) { - if ((result = datablock_allocator->new_datablock(storage)) < 0) + if ((result = datablock_manager->new_datablock(storage)) < 0) return result; if (n == 0) return 0; @@ -80,7 +80,7 @@ int Fs::deallocate_datablock(INode_Data *inode_data) { for (size_t i = NUMBER_OF_DIRECT_BLOCKS - 1; i >= 0; --i) if (inode_data->direct_blocks[i] != 0) { - if ((result = datablock_allocator->free_datablock( + if ((result = datablock_manager->free_datablock( inode_data->direct_blocks[i])) < 0) return result; inode_data->direct_blocks[i] = 0; @@ -98,7 +98,7 @@ int Fs::deallocate_indirect(u_int64_t *storage, int n) { return 1; if (n == 0) { - if ((result = datablock_allocator->free_datablock(*storage)) < 0) + if ((result = datablock_manager->free_datablock(*storage)) < 0) return result; (*storage) = 0; return 0; @@ -117,7 +117,7 @@ int Fs::deallocate_indirect(u_int64_t *storage, int n) { return result; if (result == 0) { if (i == 0 && temp == 0) { - if ((result = datablock_allocator->free_datablock(*storage)) < 0) + if ((result = datablock_manager->free_datablock(*storage)) < 0) return result; (*storage) = 0; } else { diff --git a/lib/fs/inode_allocator.cpp b/lib/fs/inode_allocator.cpp index 0d0ab85..c61b015 100644 --- a/lib/fs/inode_allocator.cpp +++ b/lib/fs/inode_allocator.cpp @@ -1,23 +1,59 @@ #include "fs.hpp" -INode_Allocator::INode_Allocator(Fs *fs, u_int64_t block_segment_start, +INode_Manager::INode_Manager(Fs *fs, u_int64_t block_segment_start, u_int64_t block_segment_end) : fs(fs), block_segment_start(block_segment_start), block_segment_end(block_segment_end) { max_num_inodes = (block_segment_end - block_segment_start) * INODES_PER_BLOCK; } -u_int64_t INode_Allocator::get_block_num(u_int64_t inode_num) { +u_int64_t INode_Manager::get_block_num(u_int64_t inode_num) { u_int64_t block_num = block_segment_start + (inode_num / INODES_PER_BLOCK); if (block_num >= block_segment_end) return 0; return block_num; } -u_int64_t INode_Allocator::get_block_offset(u_int64_t inode_num) { +u_int64_t INode_Manager::get_block_offset(u_int64_t inode_num) { return (inode_num % INODES_PER_BLOCK) * INODE_SIZE; } -int INode_Allocator_Freelist::new_inode(u_int64_t uid, u_int64_t gid, +int INode_Manager::load_inode(INode_Data *inode_data) { + char buf[IO_BLOCK_SIZE]; + int err; + + u_int64_t block_num = get_block_num(inode_data->inode_num); + if (block_num == 0) + return -1; + u_int64_t block_offset = get_block_offset(inode_data->inode_num); + + if ((err = fs->disk->read_block(block_num, buf)) < 0) + return err; + + inode_data->deserialize(&buf[block_offset]); + + return 0; +} +int INode_Manager::save_inode(INode_Data *inode_data) { + char buf[IO_BLOCK_SIZE]; + int err; + + u_int64_t block_num = get_block_num(inode_data->inode_num); + if (block_num == 0) + return -1; + u_int64_t block_offset = get_block_offset(inode_data->inode_num); + + if ((err = fs->disk->read_block(block_num, buf)) < 0) + return err; + + inode_data->serialize(&buf[block_offset]); + + if ((err = fs->disk->write_block(block_num, buf)) < 0) + return err; + + return 0; +} + +int INode_Manager_Freelist::new_inode(u_int64_t uid, u_int64_t gid, u_int64_t permissions, INode_Data *inode_data) { char buf[IO_BLOCK_SIZE]; @@ -47,14 +83,14 @@ int INode_Allocator_Freelist::new_inode(u_int64_t uid, u_int64_t gid, inode_data->metadata.permissions = permissions; // It is debatable if this function should do this: - if ((err = fs->save_inode(inode_data)) < 0) { + if ((err = save_inode(inode_data)) < 0) { inode_data->inode_num = 0xFFFFFFFFFFFFFFFF; return err; } return 0; } -int INode_Allocator_Freelist::free_inode(INode_Data *inode_data) { +int INode_Manager_Freelist::free_inode(INode_Data *inode_data) { char buf[IO_BLOCK_SIZE]; int err; @@ -78,7 +114,7 @@ int INode_Allocator_Freelist::free_inode(INode_Data *inode_data) { return 0; } -int INode_Allocator_Freelist::format() { +int INode_Manager_Freelist::format() { char buf[IO_BLOCK_SIZE]; int err; u_int64_t next_inode_num = 1; @@ -92,3 +128,5 @@ int INode_Allocator_Freelist::format() { return err; return 0; } + + diff --git a/lib/main.cpp b/lib/main.cpp index 7ce392a..8aed40b 100644 --- a/lib/main.cpp +++ b/lib/main.cpp @@ -13,15 +13,15 @@ int main() { disk->print_block(0); disk->print_block(1); INode_Data inode_data = INode_Data(); - fs->inode_allocator->new_inode(1, 2, 3, &inode_data); + fs->inode_manager->new_inode(1, 2, 3, &inode_data); int err; for (int i = 0; i < 56 + 512 + 4; ++i) err = fs->allocate_datablock(&inode_data); - for (int i = 0; i < 3; ++i) + for (int i = 0; i < 5; ++i) printf("%d\n", err = fs->deallocate_datablock(&inode_data)); - fs->save_inode(&inode_data); + fs->inode_manager->save_inode(&inode_data); disk->print_block(0); disk->print_block(1); From 49c1643ab9be54d5a8525e07e8329633328754a6 Mon Sep 17 00:00:00 2001 From: Connor Date: Wed, 15 Nov 2023 23:14:06 -0800 Subject: [PATCH 09/13] changed manager file nemes --- CMakeLists.txt | 4 +- ...ck_allocator.cpp => datablock_manager.cpp} | 270 +++++++++--------- ...{inode_allocator.cpp => inode_manager.cpp} | 264 ++++++++--------- 3 files changed, 269 insertions(+), 269 deletions(-) rename lib/fs/{datablock_allocator.cpp => datablock_manager.cpp} (96%) rename lib/fs/{inode_allocator.cpp => inode_manager.cpp} (96%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 877d0d2..f7455c4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,11 +13,11 @@ add_executable(fischl lib/fischl.cpp lib/main.cpp lib/rawdisk.cpp - lib/fs/datablock_allocator.cpp + lib/fs/datablock_manager.cpp lib/fs/fs_data_types.cpp lib/fs/fs_resize.cpp lib/fs/fs.cpp - lib/fs/inode_allocator.cpp + lib/fs/inode_manager.cpp ) diff --git a/lib/fs/datablock_allocator.cpp b/lib/fs/datablock_manager.cpp similarity index 96% rename from lib/fs/datablock_allocator.cpp rename to lib/fs/datablock_manager.cpp index e6737d7..c5f5054 100644 --- a/lib/fs/datablock_allocator.cpp +++ b/lib/fs/datablock_manager.cpp @@ -1,136 +1,136 @@ -#include "fs.hpp" - -DataBlock_Manager::DataBlock_Manager(Fs *fs, u_int64_t block_segment_start, - u_int64_t block_segment_end) - : fs(fs), block_segment_start(block_segment_start), - block_segment_end(block_segment_end) {} - -class BitmapBlock_Data { -public: - char buf[IO_BLOCK_SIZE]; - u_int64_t datablocks_per_bitmap; - - BitmapBlock_Data(u_int64_t datablocks_per_bitmap_) - : datablocks_per_bitmap(datablocks_per_bitmap_) {} - - u_int64_t get_next_node() { - u_int64_t block_num; - read_u64(&block_num, buf); - return block_num; - } - void set_next_node(u_int64_t block_num) { write_u64(block_num, buf); } - - u_int64_t find_unfilled() { - const char *data = &buf[8]; - u_int64_t i = 0; - - for (; i < datablocks_per_bitmap; ++i) - if ((data[i / 8] & (1 << (i % 8))) == 0) - return i + 1; - - return 0; - } - u_int64_t claim_relative_block() { - u_int64_t unfilled = find_unfilled(); - if (unfilled) - buf[((unfilled - 1) / 8) + 8] |= (1 << ((unfilled - 1) % 8)); - return unfilled; - } - - void release_relative_block(u_int64_t relative_block_num) { - relative_block_num -= 1; - size_t index = (relative_block_num / 8) + 8; - int offset = relative_block_num % 8; - buf[index] &= ~(1 << offset); - } -}; - -int DataBlock_Manager_Bitmap::new_datablock(u_int64_t *block_num) { - int err; - BitmapBlock_Data bitmap = BitmapBlock_Data(DATABLOCKS_PER_BITMAP_BLOCK); - u_int64_t bitmap_block_num = fs->superblock.free_list_head; - char zero_buf[IO_BLOCK_SIZE] = {0}; - - if (bitmap_block_num < block_segment_start || - bitmap_block_num >= block_segment_end) - return -1; - - if ((err = fs->disk->read_block(bitmap_block_num, bitmap.buf)) < 0) - return err; - - u_int64_t relative_block_num = bitmap.claim_relative_block(); - - if (relative_block_num == 0) - return -1; - - u_int64_t block_num_ = relative_block_num + bitmap_block_num; - - // NOTE: this could be removed for speed - if ((err = fs->disk->write_block(block_num_, zero_buf)) < 0) - return err; - - // Could be optimized - if (bitmap.find_unfilled() == 0) { - if ((err = fs->save_free_list_head(bitmap.get_next_node())) < 0) - return err; - bitmap.set_next_node(0); - } - - if ((err = fs->disk->write_block(bitmap_block_num, bitmap.buf)) < 0) - return err; - - (*block_num) = block_num_; - return 0; -} - -int DataBlock_Manager_Bitmap::free_datablock(u_int64_t block_num) { - int err; - BitmapBlock_Data bitmap = BitmapBlock_Data(DATABLOCKS_PER_BITMAP_BLOCK); - const u_int64_t bitmap_region_size = DATABLOCKS_PER_BITMAP_BLOCK + 1; - bool update_freelist = false; - - u_int64_t bitmap_block_num = - (((block_num - block_segment_start) / bitmap_region_size) * - bitmap_region_size) + - block_segment_start; - - if ((err = fs->disk->read_block(bitmap_block_num, bitmap.buf)) < 0) - return err; - - if (bitmap.find_unfilled() == 0) { - update_freelist = true; - bitmap.set_next_node(fs->superblock.free_list_head); - } - - bitmap.release_relative_block(block_num - bitmap_block_num); - - if ((err = fs->disk->write_block(bitmap_block_num, bitmap.buf)) < 0) - return err; - - if (update_freelist) - if ((err = fs->save_free_list_head(bitmap_block_num)) < 0) - return err; - - return 0; - - // placing almost full bitmaps back at start of freelist is slow - // potentially like 256 times slower throughput -} - -int DataBlock_Manager_Bitmap::format() { - const u_int64_t bitmap_region_size = DATABLOCKS_PER_BITMAP_BLOCK + 1; - char buf[IO_BLOCK_SIZE] = {0}; - int err; - u_int64_t i = block_segment_start; - for (; i <= block_segment_end - (2 * bitmap_region_size); - i += bitmap_region_size) { - write_u64(i + bitmap_region_size, buf); - if ((err = fs->disk->write_block(i, buf)) < 0) - return err; - } - if ((err = fs->disk->write_block(i, buf)) < 0) - return err; - if ((err = fs->save_free_list_head(block_segment_start)) < 0) - return err; - return 0; +#include "fs.hpp" + +DataBlock_Manager::DataBlock_Manager(Fs *fs, u_int64_t block_segment_start, + u_int64_t block_segment_end) + : fs(fs), block_segment_start(block_segment_start), + block_segment_end(block_segment_end) {} + +class BitmapBlock_Data { +public: + char buf[IO_BLOCK_SIZE]; + u_int64_t datablocks_per_bitmap; + + BitmapBlock_Data(u_int64_t datablocks_per_bitmap_) + : datablocks_per_bitmap(datablocks_per_bitmap_) {} + + u_int64_t get_next_node() { + u_int64_t block_num; + read_u64(&block_num, buf); + return block_num; + } + void set_next_node(u_int64_t block_num) { write_u64(block_num, buf); } + + u_int64_t find_unfilled() { + const char *data = &buf[8]; + u_int64_t i = 0; + + for (; i < datablocks_per_bitmap; ++i) + if ((data[i / 8] & (1 << (i % 8))) == 0) + return i + 1; + + return 0; + } + u_int64_t claim_relative_block() { + u_int64_t unfilled = find_unfilled(); + if (unfilled) + buf[((unfilled - 1) / 8) + 8] |= (1 << ((unfilled - 1) % 8)); + return unfilled; + } + + void release_relative_block(u_int64_t relative_block_num) { + relative_block_num -= 1; + size_t index = (relative_block_num / 8) + 8; + int offset = relative_block_num % 8; + buf[index] &= ~(1 << offset); + } +}; + +int DataBlock_Manager_Bitmap::new_datablock(u_int64_t *block_num) { + int err; + BitmapBlock_Data bitmap = BitmapBlock_Data(DATABLOCKS_PER_BITMAP_BLOCK); + u_int64_t bitmap_block_num = fs->superblock.free_list_head; + char zero_buf[IO_BLOCK_SIZE] = {0}; + + if (bitmap_block_num < block_segment_start || + bitmap_block_num >= block_segment_end) + return -1; + + if ((err = fs->disk->read_block(bitmap_block_num, bitmap.buf)) < 0) + return err; + + u_int64_t relative_block_num = bitmap.claim_relative_block(); + + if (relative_block_num == 0) + return -1; + + u_int64_t block_num_ = relative_block_num + bitmap_block_num; + + // NOTE: this could be removed for speed + if ((err = fs->disk->write_block(block_num_, zero_buf)) < 0) + return err; + + // Could be optimized + if (bitmap.find_unfilled() == 0) { + if ((err = fs->save_free_list_head(bitmap.get_next_node())) < 0) + return err; + bitmap.set_next_node(0); + } + + if ((err = fs->disk->write_block(bitmap_block_num, bitmap.buf)) < 0) + return err; + + (*block_num) = block_num_; + return 0; +} + +int DataBlock_Manager_Bitmap::free_datablock(u_int64_t block_num) { + int err; + BitmapBlock_Data bitmap = BitmapBlock_Data(DATABLOCKS_PER_BITMAP_BLOCK); + const u_int64_t bitmap_region_size = DATABLOCKS_PER_BITMAP_BLOCK + 1; + bool update_freelist = false; + + u_int64_t bitmap_block_num = + (((block_num - block_segment_start) / bitmap_region_size) * + bitmap_region_size) + + block_segment_start; + + if ((err = fs->disk->read_block(bitmap_block_num, bitmap.buf)) < 0) + return err; + + if (bitmap.find_unfilled() == 0) { + update_freelist = true; + bitmap.set_next_node(fs->superblock.free_list_head); + } + + bitmap.release_relative_block(block_num - bitmap_block_num); + + if ((err = fs->disk->write_block(bitmap_block_num, bitmap.buf)) < 0) + return err; + + if (update_freelist) + if ((err = fs->save_free_list_head(bitmap_block_num)) < 0) + return err; + + return 0; + + // placing almost full bitmaps back at start of freelist is slow + // potentially like 256 times slower throughput +} + +int DataBlock_Manager_Bitmap::format() { + const u_int64_t bitmap_region_size = DATABLOCKS_PER_BITMAP_BLOCK + 1; + char buf[IO_BLOCK_SIZE] = {0}; + int err; + u_int64_t i = block_segment_start; + for (; i <= block_segment_end - (2 * bitmap_region_size); + i += bitmap_region_size) { + write_u64(i + bitmap_region_size, buf); + if ((err = fs->disk->write_block(i, buf)) < 0) + return err; + } + if ((err = fs->disk->write_block(i, buf)) < 0) + return err; + if ((err = fs->save_free_list_head(block_segment_start)) < 0) + return err; + return 0; } \ No newline at end of file diff --git a/lib/fs/inode_allocator.cpp b/lib/fs/inode_manager.cpp similarity index 96% rename from lib/fs/inode_allocator.cpp rename to lib/fs/inode_manager.cpp index c61b015..c9d2599 100644 --- a/lib/fs/inode_allocator.cpp +++ b/lib/fs/inode_manager.cpp @@ -1,132 +1,132 @@ -#include "fs.hpp" - -INode_Manager::INode_Manager(Fs *fs, u_int64_t block_segment_start, - u_int64_t block_segment_end) - : fs(fs), block_segment_start(block_segment_start), - block_segment_end(block_segment_end) { - max_num_inodes = (block_segment_end - block_segment_start) * INODES_PER_BLOCK; -} - -u_int64_t INode_Manager::get_block_num(u_int64_t inode_num) { - u_int64_t block_num = block_segment_start + (inode_num / INODES_PER_BLOCK); - if (block_num >= block_segment_end) - return 0; - return block_num; -} -u_int64_t INode_Manager::get_block_offset(u_int64_t inode_num) { - return (inode_num % INODES_PER_BLOCK) * INODE_SIZE; -} - -int INode_Manager::load_inode(INode_Data *inode_data) { - char buf[IO_BLOCK_SIZE]; - int err; - - u_int64_t block_num = get_block_num(inode_data->inode_num); - if (block_num == 0) - return -1; - u_int64_t block_offset = get_block_offset(inode_data->inode_num); - - if ((err = fs->disk->read_block(block_num, buf)) < 0) - return err; - - inode_data->deserialize(&buf[block_offset]); - - return 0; -} -int INode_Manager::save_inode(INode_Data *inode_data) { - char buf[IO_BLOCK_SIZE]; - int err; - - u_int64_t block_num = get_block_num(inode_data->inode_num); - if (block_num == 0) - return -1; - u_int64_t block_offset = get_block_offset(inode_data->inode_num); - - if ((err = fs->disk->read_block(block_num, buf)) < 0) - return err; - - inode_data->serialize(&buf[block_offset]); - - if ((err = fs->disk->write_block(block_num, buf)) < 0) - return err; - - return 0; -} - -int INode_Manager_Freelist::new_inode(u_int64_t uid, u_int64_t gid, - u_int64_t permissions, - INode_Data *inode_data) { - char buf[IO_BLOCK_SIZE]; - int err; - u_int64_t inode_num = fs->superblock.inode_list_head; - if (inode_num > max_num_inodes) - return -1; - - u_int64_t block_num = get_block_num(inode_num); - u_int64_t block_offset = get_block_offset(inode_num); - - if (block_num == 0) - return -1; - - if ((err = fs->disk->read_block(block_num, buf)) < 0) - return err; - - u_int64_t new_inode_list_head = 0; - read_u64(&new_inode_list_head, &buf[block_offset]); - if ((err = fs->save_inode_list_head(new_inode_list_head)) < 0) - return err; - - (*inode_data) = INode_Data(inode_num); - - inode_data->metadata.uid = uid; - inode_data->metadata.gid = gid; - inode_data->metadata.permissions = permissions; - - // It is debatable if this function should do this: - if ((err = save_inode(inode_data)) < 0) { - inode_data->inode_num = 0xFFFFFFFFFFFFFFFF; - return err; - } - - return 0; -} -int INode_Manager_Freelist::free_inode(INode_Data *inode_data) { - char buf[IO_BLOCK_SIZE]; - int err; - - u_int64_t block_num = get_block_num(inode_data->inode_num); - u_int64_t block_offset = get_block_offset(inode_data->inode_num); - - if (block_num == 0) - return -1; - - if ((err = fs->disk->read_block(block_num, buf)) < 0) - return err; - - write_u64(fs->superblock.inode_list_head, &buf[block_offset]); - - if ((err = fs->disk->write_block(block_num, buf)) < 0) - return err; - - if ((err = fs->save_inode_list_head(inode_data->inode_num)) < 0) - return err; - - return 0; -} - -int INode_Manager_Freelist::format() { - char buf[IO_BLOCK_SIZE]; - int err; - u_int64_t next_inode_num = 1; - for (u_int64_t i = block_segment_start; i < block_segment_end; ++i) { - for (int j = 0; j < INODES_PER_BLOCK; ++next_inode_num, ++j) - write_u64(next_inode_num, &buf[j * INODE_SIZE]); - if ((err = fs->disk->write_block(i, buf)) < 0) - return err; - } - if ((err = fs->save_inode_list_head(0)) < 0) - return err; - return 0; -} - - +#include "fs.hpp" + +INode_Manager::INode_Manager(Fs *fs, u_int64_t block_segment_start, + u_int64_t block_segment_end) + : fs(fs), block_segment_start(block_segment_start), + block_segment_end(block_segment_end) { + max_num_inodes = (block_segment_end - block_segment_start) * INODES_PER_BLOCK; +} + +u_int64_t INode_Manager::get_block_num(u_int64_t inode_num) { + u_int64_t block_num = block_segment_start + (inode_num / INODES_PER_BLOCK); + if (block_num >= block_segment_end) + return 0; + return block_num; +} +u_int64_t INode_Manager::get_block_offset(u_int64_t inode_num) { + return (inode_num % INODES_PER_BLOCK) * INODE_SIZE; +} + +int INode_Manager::load_inode(INode_Data *inode_data) { + char buf[IO_BLOCK_SIZE]; + int err; + + u_int64_t block_num = get_block_num(inode_data->inode_num); + if (block_num == 0) + return -1; + u_int64_t block_offset = get_block_offset(inode_data->inode_num); + + if ((err = fs->disk->read_block(block_num, buf)) < 0) + return err; + + inode_data->deserialize(&buf[block_offset]); + + return 0; +} +int INode_Manager::save_inode(INode_Data *inode_data) { + char buf[IO_BLOCK_SIZE]; + int err; + + u_int64_t block_num = get_block_num(inode_data->inode_num); + if (block_num == 0) + return -1; + u_int64_t block_offset = get_block_offset(inode_data->inode_num); + + if ((err = fs->disk->read_block(block_num, buf)) < 0) + return err; + + inode_data->serialize(&buf[block_offset]); + + if ((err = fs->disk->write_block(block_num, buf)) < 0) + return err; + + return 0; +} + +int INode_Manager_Freelist::new_inode(u_int64_t uid, u_int64_t gid, + u_int64_t permissions, + INode_Data *inode_data) { + char buf[IO_BLOCK_SIZE]; + int err; + u_int64_t inode_num = fs->superblock.inode_list_head; + if (inode_num > max_num_inodes) + return -1; + + u_int64_t block_num = get_block_num(inode_num); + u_int64_t block_offset = get_block_offset(inode_num); + + if (block_num == 0) + return -1; + + if ((err = fs->disk->read_block(block_num, buf)) < 0) + return err; + + u_int64_t new_inode_list_head = 0; + read_u64(&new_inode_list_head, &buf[block_offset]); + if ((err = fs->save_inode_list_head(new_inode_list_head)) < 0) + return err; + + (*inode_data) = INode_Data(inode_num); + + inode_data->metadata.uid = uid; + inode_data->metadata.gid = gid; + inode_data->metadata.permissions = permissions; + + // It is debatable if this function should do this: + if ((err = save_inode(inode_data)) < 0) { + inode_data->inode_num = 0xFFFFFFFFFFFFFFFF; + return err; + } + + return 0; +} +int INode_Manager_Freelist::free_inode(INode_Data *inode_data) { + char buf[IO_BLOCK_SIZE]; + int err; + + u_int64_t block_num = get_block_num(inode_data->inode_num); + u_int64_t block_offset = get_block_offset(inode_data->inode_num); + + if (block_num == 0) + return -1; + + if ((err = fs->disk->read_block(block_num, buf)) < 0) + return err; + + write_u64(fs->superblock.inode_list_head, &buf[block_offset]); + + if ((err = fs->disk->write_block(block_num, buf)) < 0) + return err; + + if ((err = fs->save_inode_list_head(inode_data->inode_num)) < 0) + return err; + + return 0; +} + +int INode_Manager_Freelist::format() { + char buf[IO_BLOCK_SIZE]; + int err; + u_int64_t next_inode_num = 1; + for (u_int64_t i = block_segment_start; i < block_segment_end; ++i) { + for (int j = 0; j < INODES_PER_BLOCK; ++next_inode_num, ++j) + write_u64(next_inode_num, &buf[j * INODE_SIZE]); + if ((err = fs->disk->write_block(i, buf)) < 0) + return err; + } + if ((err = fs->save_inode_list_head(0)) < 0) + return err; + return 0; +} + + From 9ed5936762e85ed1f5a2e9a7b4d81d68b36b81b6 Mon Sep 17 00:00:00 2001 From: Connor Date: Fri, 17 Nov 2023 01:33:19 -0800 Subject: [PATCH 10/13] half of tests added --- CMakeLists.txt | 4 +- include/fs.hpp | 8 +- lib/fs/datablock_manager.cpp | 270 +++++++++++++++++------------------ lib/fs/fs_resize.cpp | 64 +++++---- lib/fs/inode_manager.cpp | 266 +++++++++++++++++----------------- lib/main.cpp | 5 +- lib/rawdisk.cpp | 4 +- test/CMakeLists.txt | 23 ++- test/layer0.cpp | 43 +++--- test/layer1_API.cpp | 228 ++++++++++++++++------------- test/layer1_test1.cpp | 243 ++++++++++++++++--------------- 11 files changed, 614 insertions(+), 544 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f7455c4..684640d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -21,5 +21,5 @@ add_executable(fischl ) -#enable_testing() -#add_subdirectory(test) \ No newline at end of file +enable_testing() +add_subdirectory(test) \ No newline at end of file diff --git a/include/fs.hpp b/include/fs.hpp index 0a372bc..e570e57 100644 --- a/include/fs.hpp +++ b/include/fs.hpp @@ -12,8 +12,8 @@ public: Fs(RawDisk *disk); ~Fs(); - int allocate_datablock(INode_Data *inode_data); - int deallocate_datablock(INode_Data *inode_data); + int allocate_datablock(INode_Data *inode_data, u_int64_t *datablock_num); + int deallocate_datablock(INode_Data *inode_data, u_int64_t *datablock_num); int format(); @@ -29,8 +29,8 @@ public: int save_free_list_head(u_int64_t new_free_list_head); int save_inode_list_head(u_int64_t new_inode_list_head); - int allocate_indirect(u_int64_t *storage, int n); - int deallocate_indirect(u_int64_t *storage, int n); + int allocate_indirect(u_int64_t *storage, int n, u_int64_t *datablock_num); + int deallocate_indirect(u_int64_t *storage, int n, u_int64_t *datablock_num); }; #endif \ No newline at end of file diff --git a/lib/fs/datablock_manager.cpp b/lib/fs/datablock_manager.cpp index c5f5054..e6737d7 100644 --- a/lib/fs/datablock_manager.cpp +++ b/lib/fs/datablock_manager.cpp @@ -1,136 +1,136 @@ -#include "fs.hpp" - -DataBlock_Manager::DataBlock_Manager(Fs *fs, u_int64_t block_segment_start, - u_int64_t block_segment_end) - : fs(fs), block_segment_start(block_segment_start), - block_segment_end(block_segment_end) {} - -class BitmapBlock_Data { -public: - char buf[IO_BLOCK_SIZE]; - u_int64_t datablocks_per_bitmap; - - BitmapBlock_Data(u_int64_t datablocks_per_bitmap_) - : datablocks_per_bitmap(datablocks_per_bitmap_) {} - - u_int64_t get_next_node() { - u_int64_t block_num; - read_u64(&block_num, buf); - return block_num; - } - void set_next_node(u_int64_t block_num) { write_u64(block_num, buf); } - - u_int64_t find_unfilled() { - const char *data = &buf[8]; - u_int64_t i = 0; - - for (; i < datablocks_per_bitmap; ++i) - if ((data[i / 8] & (1 << (i % 8))) == 0) - return i + 1; - - return 0; - } - u_int64_t claim_relative_block() { - u_int64_t unfilled = find_unfilled(); - if (unfilled) - buf[((unfilled - 1) / 8) + 8] |= (1 << ((unfilled - 1) % 8)); - return unfilled; - } - - void release_relative_block(u_int64_t relative_block_num) { - relative_block_num -= 1; - size_t index = (relative_block_num / 8) + 8; - int offset = relative_block_num % 8; - buf[index] &= ~(1 << offset); - } -}; - -int DataBlock_Manager_Bitmap::new_datablock(u_int64_t *block_num) { - int err; - BitmapBlock_Data bitmap = BitmapBlock_Data(DATABLOCKS_PER_BITMAP_BLOCK); - u_int64_t bitmap_block_num = fs->superblock.free_list_head; - char zero_buf[IO_BLOCK_SIZE] = {0}; - - if (bitmap_block_num < block_segment_start || - bitmap_block_num >= block_segment_end) - return -1; - - if ((err = fs->disk->read_block(bitmap_block_num, bitmap.buf)) < 0) - return err; - - u_int64_t relative_block_num = bitmap.claim_relative_block(); - - if (relative_block_num == 0) - return -1; - - u_int64_t block_num_ = relative_block_num + bitmap_block_num; - - // NOTE: this could be removed for speed - if ((err = fs->disk->write_block(block_num_, zero_buf)) < 0) - return err; - - // Could be optimized - if (bitmap.find_unfilled() == 0) { - if ((err = fs->save_free_list_head(bitmap.get_next_node())) < 0) - return err; - bitmap.set_next_node(0); - } - - if ((err = fs->disk->write_block(bitmap_block_num, bitmap.buf)) < 0) - return err; - - (*block_num) = block_num_; - return 0; -} - -int DataBlock_Manager_Bitmap::free_datablock(u_int64_t block_num) { - int err; - BitmapBlock_Data bitmap = BitmapBlock_Data(DATABLOCKS_PER_BITMAP_BLOCK); - const u_int64_t bitmap_region_size = DATABLOCKS_PER_BITMAP_BLOCK + 1; - bool update_freelist = false; - - u_int64_t bitmap_block_num = - (((block_num - block_segment_start) / bitmap_region_size) * - bitmap_region_size) + - block_segment_start; - - if ((err = fs->disk->read_block(bitmap_block_num, bitmap.buf)) < 0) - return err; - - if (bitmap.find_unfilled() == 0) { - update_freelist = true; - bitmap.set_next_node(fs->superblock.free_list_head); - } - - bitmap.release_relative_block(block_num - bitmap_block_num); - - if ((err = fs->disk->write_block(bitmap_block_num, bitmap.buf)) < 0) - return err; - - if (update_freelist) - if ((err = fs->save_free_list_head(bitmap_block_num)) < 0) - return err; - - return 0; - - // placing almost full bitmaps back at start of freelist is slow - // potentially like 256 times slower throughput -} - -int DataBlock_Manager_Bitmap::format() { - const u_int64_t bitmap_region_size = DATABLOCKS_PER_BITMAP_BLOCK + 1; - char buf[IO_BLOCK_SIZE] = {0}; - int err; - u_int64_t i = block_segment_start; - for (; i <= block_segment_end - (2 * bitmap_region_size); - i += bitmap_region_size) { - write_u64(i + bitmap_region_size, buf); - if ((err = fs->disk->write_block(i, buf)) < 0) - return err; - } - if ((err = fs->disk->write_block(i, buf)) < 0) - return err; - if ((err = fs->save_free_list_head(block_segment_start)) < 0) - return err; - return 0; +#include "fs.hpp" + +DataBlock_Manager::DataBlock_Manager(Fs *fs, u_int64_t block_segment_start, + u_int64_t block_segment_end) + : fs(fs), block_segment_start(block_segment_start), + block_segment_end(block_segment_end) {} + +class BitmapBlock_Data { +public: + char buf[IO_BLOCK_SIZE]; + u_int64_t datablocks_per_bitmap; + + BitmapBlock_Data(u_int64_t datablocks_per_bitmap_) + : datablocks_per_bitmap(datablocks_per_bitmap_) {} + + u_int64_t get_next_node() { + u_int64_t block_num; + read_u64(&block_num, buf); + return block_num; + } + void set_next_node(u_int64_t block_num) { write_u64(block_num, buf); } + + u_int64_t find_unfilled() { + const char *data = &buf[8]; + u_int64_t i = 0; + + for (; i < datablocks_per_bitmap; ++i) + if ((data[i / 8] & (1 << (i % 8))) == 0) + return i + 1; + + return 0; + } + u_int64_t claim_relative_block() { + u_int64_t unfilled = find_unfilled(); + if (unfilled) + buf[((unfilled - 1) / 8) + 8] |= (1 << ((unfilled - 1) % 8)); + return unfilled; + } + + void release_relative_block(u_int64_t relative_block_num) { + relative_block_num -= 1; + size_t index = (relative_block_num / 8) + 8; + int offset = relative_block_num % 8; + buf[index] &= ~(1 << offset); + } +}; + +int DataBlock_Manager_Bitmap::new_datablock(u_int64_t *block_num) { + int err; + BitmapBlock_Data bitmap = BitmapBlock_Data(DATABLOCKS_PER_BITMAP_BLOCK); + u_int64_t bitmap_block_num = fs->superblock.free_list_head; + char zero_buf[IO_BLOCK_SIZE] = {0}; + + if (bitmap_block_num < block_segment_start || + bitmap_block_num >= block_segment_end) + return -1; + + if ((err = fs->disk->read_block(bitmap_block_num, bitmap.buf)) < 0) + return err; + + u_int64_t relative_block_num = bitmap.claim_relative_block(); + + if (relative_block_num == 0) + return -1; + + u_int64_t block_num_ = relative_block_num + bitmap_block_num; + + // NOTE: this could be removed for speed + if ((err = fs->disk->write_block(block_num_, zero_buf)) < 0) + return err; + + // Could be optimized + if (bitmap.find_unfilled() == 0) { + if ((err = fs->save_free_list_head(bitmap.get_next_node())) < 0) + return err; + bitmap.set_next_node(0); + } + + if ((err = fs->disk->write_block(bitmap_block_num, bitmap.buf)) < 0) + return err; + + (*block_num) = block_num_; + return 0; +} + +int DataBlock_Manager_Bitmap::free_datablock(u_int64_t block_num) { + int err; + BitmapBlock_Data bitmap = BitmapBlock_Data(DATABLOCKS_PER_BITMAP_BLOCK); + const u_int64_t bitmap_region_size = DATABLOCKS_PER_BITMAP_BLOCK + 1; + bool update_freelist = false; + + u_int64_t bitmap_block_num = + (((block_num - block_segment_start) / bitmap_region_size) * + bitmap_region_size) + + block_segment_start; + + if ((err = fs->disk->read_block(bitmap_block_num, bitmap.buf)) < 0) + return err; + + if (bitmap.find_unfilled() == 0) { + update_freelist = true; + bitmap.set_next_node(fs->superblock.free_list_head); + } + + bitmap.release_relative_block(block_num - bitmap_block_num); + + if ((err = fs->disk->write_block(bitmap_block_num, bitmap.buf)) < 0) + return err; + + if (update_freelist) + if ((err = fs->save_free_list_head(bitmap_block_num)) < 0) + return err; + + return 0; + + // placing almost full bitmaps back at start of freelist is slow + // potentially like 256 times slower throughput +} + +int DataBlock_Manager_Bitmap::format() { + const u_int64_t bitmap_region_size = DATABLOCKS_PER_BITMAP_BLOCK + 1; + char buf[IO_BLOCK_SIZE] = {0}; + int err; + u_int64_t i = block_segment_start; + for (; i <= block_segment_end - (2 * bitmap_region_size); + i += bitmap_region_size) { + write_u64(i + bitmap_region_size, buf); + if ((err = fs->disk->write_block(i, buf)) < 0) + return err; + } + if ((err = fs->disk->write_block(i, buf)) < 0) + return err; + if ((err = fs->save_free_list_head(block_segment_start)) < 0) + return err; + return 0; } \ No newline at end of file diff --git a/lib/fs/fs_resize.cpp b/lib/fs/fs_resize.cpp index c700828..194c064 100644 --- a/lib/fs/fs_resize.cpp +++ b/lib/fs/fs_resize.cpp @@ -1,25 +1,27 @@ #include "fs.hpp" -int Fs::allocate_datablock(INode_Data *inode_data) { +int Fs::allocate_datablock(INode_Data *inode_data, u_int64_t *datablock_num) { int result; - for (size_t i = 0; i < NUMBER_OF_DIRECT_BLOCKS; ++i) - if (inode_data->direct_blocks[i] == 0) { - if ((result = datablock_manager->new_datablock( - &(inode_data->direct_blocks[i]))) < 0) - return result; - return 0; - } + for (size_t i = 0; i < NUMBER_OF_DIRECT_BLOCKS; ++i) { + result = + allocate_indirect(&(inode_data->direct_blocks[i]), 0, datablock_num); + if (result <= 0) + return result; + } - result = allocate_indirect(&(inode_data->single_indirect_block), 1); + result = + allocate_indirect(&(inode_data->single_indirect_block), 1, datablock_num); if (result <= 0) return result; - result = allocate_indirect(&(inode_data->double_indirect_block), 2); + result = + allocate_indirect(&(inode_data->double_indirect_block), 2, datablock_num); if (result <= 0) return result; - result = allocate_indirect(&(inode_data->triple_indirect_block), 3); + result = + allocate_indirect(&(inode_data->triple_indirect_block), 3, datablock_num); if (result <= 0) return result; @@ -28,15 +30,17 @@ int Fs::allocate_datablock(INode_Data *inode_data) { // This can simply be made non recursive by copy pasting - it is just written // this way as a proof of concept -int Fs::allocate_indirect(u_int64_t *storage, int n) { +int Fs::allocate_indirect(u_int64_t *storage, int n, u_int64_t *datablock_num) { char buf[IO_BLOCK_SIZE]; int result; if ((*storage) == 0) { if ((result = datablock_manager->new_datablock(storage)) < 0) return result; - if (n == 0) + if (n == 0) { + (*datablock_num) = (*storage); return 0; + } } if (n == 0) @@ -49,7 +53,7 @@ int Fs::allocate_indirect(u_int64_t *storage, int n) { for (size_t i = 0; i < IO_BLOCK_SIZE; i += sizeof(u_int64_t)) { read_u64(&temp, &buf[i]); - result = allocate_indirect(&temp, n - 1); + result = allocate_indirect(&temp, n - 1, datablock_num); if (result < 0) return result; if (result == 0) { @@ -63,34 +67,36 @@ int Fs::allocate_indirect(u_int64_t *storage, int n) { return 1; } -int Fs::deallocate_datablock(INode_Data *inode_data) { +int Fs::deallocate_datablock(INode_Data *inode_data, u_int64_t *datablock_num) { int result; - result = deallocate_indirect(&(inode_data->triple_indirect_block), 3); + result = deallocate_indirect(&(inode_data->triple_indirect_block), 3, + datablock_num); if (result <= 0) return result; - result = deallocate_indirect(&(inode_data->double_indirect_block), 2); + result = deallocate_indirect(&(inode_data->double_indirect_block), 2, + datablock_num); if (result <= 0) return result; - result = deallocate_indirect(&(inode_data->single_indirect_block), 1); + result = deallocate_indirect(&(inode_data->single_indirect_block), 1, + datablock_num); if (result <= 0) return result; - for (size_t i = NUMBER_OF_DIRECT_BLOCKS - 1; i >= 0; --i) - if (inode_data->direct_blocks[i] != 0) { - if ((result = datablock_manager->free_datablock( - inode_data->direct_blocks[i])) < 0) - return result; - inode_data->direct_blocks[i] = 0; - return 0; - } + for (size_t i = NUMBER_OF_DIRECT_BLOCKS - 1; i >= 0; --i) { + result = + deallocate_indirect(&(inode_data->direct_blocks[i]), 0, datablock_num); + if (result <= 0) + return result; + } return -1; } -int Fs::deallocate_indirect(u_int64_t *storage, int n) { +int Fs::deallocate_indirect(u_int64_t *storage, int n, + u_int64_t *datablock_num) { char buf[IO_BLOCK_SIZE]; int result; @@ -98,8 +104,10 @@ int Fs::deallocate_indirect(u_int64_t *storage, int n) { return 1; if (n == 0) { + u_int64_t temp_datablock_num = (*storage); if ((result = datablock_manager->free_datablock(*storage)) < 0) return result; + (*datablock_num) = temp_datablock_num; (*storage) = 0; return 0; } @@ -112,7 +120,7 @@ int Fs::deallocate_indirect(u_int64_t *storage, int n) { for (size_t i = IO_BLOCK_SIZE - sizeof(u_int64_t); i >= 0; i -= sizeof(u_int64_t)) { read_u64(&temp, &buf[i]); - result = deallocate_indirect(&temp, n - 1); + result = deallocate_indirect(&temp, n - 1, datablock_num); if (result < 0) return result; if (result == 0) { diff --git a/lib/fs/inode_manager.cpp b/lib/fs/inode_manager.cpp index c9d2599..33166ad 100644 --- a/lib/fs/inode_manager.cpp +++ b/lib/fs/inode_manager.cpp @@ -1,132 +1,134 @@ -#include "fs.hpp" - -INode_Manager::INode_Manager(Fs *fs, u_int64_t block_segment_start, - u_int64_t block_segment_end) - : fs(fs), block_segment_start(block_segment_start), - block_segment_end(block_segment_end) { - max_num_inodes = (block_segment_end - block_segment_start) * INODES_PER_BLOCK; -} - -u_int64_t INode_Manager::get_block_num(u_int64_t inode_num) { - u_int64_t block_num = block_segment_start + (inode_num / INODES_PER_BLOCK); - if (block_num >= block_segment_end) - return 0; - return block_num; -} -u_int64_t INode_Manager::get_block_offset(u_int64_t inode_num) { - return (inode_num % INODES_PER_BLOCK) * INODE_SIZE; -} - -int INode_Manager::load_inode(INode_Data *inode_data) { - char buf[IO_BLOCK_SIZE]; - int err; - - u_int64_t block_num = get_block_num(inode_data->inode_num); - if (block_num == 0) - return -1; - u_int64_t block_offset = get_block_offset(inode_data->inode_num); - - if ((err = fs->disk->read_block(block_num, buf)) < 0) - return err; - - inode_data->deserialize(&buf[block_offset]); - - return 0; -} -int INode_Manager::save_inode(INode_Data *inode_data) { - char buf[IO_BLOCK_SIZE]; - int err; - - u_int64_t block_num = get_block_num(inode_data->inode_num); - if (block_num == 0) - return -1; - u_int64_t block_offset = get_block_offset(inode_data->inode_num); - - if ((err = fs->disk->read_block(block_num, buf)) < 0) - return err; - - inode_data->serialize(&buf[block_offset]); - - if ((err = fs->disk->write_block(block_num, buf)) < 0) - return err; - - return 0; -} - -int INode_Manager_Freelist::new_inode(u_int64_t uid, u_int64_t gid, - u_int64_t permissions, - INode_Data *inode_data) { - char buf[IO_BLOCK_SIZE]; - int err; - u_int64_t inode_num = fs->superblock.inode_list_head; - if (inode_num > max_num_inodes) - return -1; - - u_int64_t block_num = get_block_num(inode_num); - u_int64_t block_offset = get_block_offset(inode_num); - - if (block_num == 0) - return -1; - - if ((err = fs->disk->read_block(block_num, buf)) < 0) - return err; - - u_int64_t new_inode_list_head = 0; - read_u64(&new_inode_list_head, &buf[block_offset]); - if ((err = fs->save_inode_list_head(new_inode_list_head)) < 0) - return err; - - (*inode_data) = INode_Data(inode_num); - - inode_data->metadata.uid = uid; - inode_data->metadata.gid = gid; - inode_data->metadata.permissions = permissions; - - // It is debatable if this function should do this: - if ((err = save_inode(inode_data)) < 0) { - inode_data->inode_num = 0xFFFFFFFFFFFFFFFF; - return err; - } - - return 0; -} -int INode_Manager_Freelist::free_inode(INode_Data *inode_data) { - char buf[IO_BLOCK_SIZE]; - int err; - - u_int64_t block_num = get_block_num(inode_data->inode_num); - u_int64_t block_offset = get_block_offset(inode_data->inode_num); - - if (block_num == 0) - return -1; - - if ((err = fs->disk->read_block(block_num, buf)) < 0) - return err; - - write_u64(fs->superblock.inode_list_head, &buf[block_offset]); - - if ((err = fs->disk->write_block(block_num, buf)) < 0) - return err; - - if ((err = fs->save_inode_list_head(inode_data->inode_num)) < 0) - return err; - - return 0; -} - -int INode_Manager_Freelist::format() { - char buf[IO_BLOCK_SIZE]; - int err; - u_int64_t next_inode_num = 1; - for (u_int64_t i = block_segment_start; i < block_segment_end; ++i) { - for (int j = 0; j < INODES_PER_BLOCK; ++next_inode_num, ++j) - write_u64(next_inode_num, &buf[j * INODE_SIZE]); - if ((err = fs->disk->write_block(i, buf)) < 0) - return err; - } - if ((err = fs->save_inode_list_head(0)) < 0) - return err; - return 0; -} - - +#include "fs.hpp" + +INode_Manager::INode_Manager(Fs *fs, u_int64_t block_segment_start, + u_int64_t block_segment_end) + : fs(fs), block_segment_start(block_segment_start), + block_segment_end(block_segment_end) { + max_num_inodes = (block_segment_end - block_segment_start) * INODES_PER_BLOCK; +} + +u_int64_t INode_Manager::get_block_num(u_int64_t inode_num) { + if (inode_num > max_num_inodes || inode_num == 0) + return 0; + u_int64_t block_num = + block_segment_start + ((inode_num - 1) / INODES_PER_BLOCK); + return block_num; +} +u_int64_t INode_Manager::get_block_offset(u_int64_t inode_num) { + return ((inode_num - 1) % INODES_PER_BLOCK) * INODE_SIZE; +} + +int INode_Manager::load_inode(INode_Data *inode_data) { + char buf[IO_BLOCK_SIZE]; + int err; + + u_int64_t block_num = get_block_num(inode_data->inode_num); + if (block_num == 0) + return -1; + u_int64_t block_offset = get_block_offset(inode_data->inode_num); + + if ((err = fs->disk->read_block(block_num, buf)) < 0) + return err; + + inode_data->deserialize(&buf[block_offset]); + + return 0; +} +int INode_Manager::save_inode(INode_Data *inode_data) { + char buf[IO_BLOCK_SIZE]; + int err; + + u_int64_t block_num = get_block_num(inode_data->inode_num); + if (block_num == 0) + return -1; + u_int64_t block_offset = get_block_offset(inode_data->inode_num); + + if ((err = fs->disk->read_block(block_num, buf)) < 0) + return err; + + inode_data->serialize(&buf[block_offset]); + + if ((err = fs->disk->write_block(block_num, buf)) < 0) + return err; + + return 0; +} + +int INode_Manager_Freelist::new_inode(u_int64_t uid, u_int64_t gid, + u_int64_t permissions, + INode_Data *inode_data) { + char buf[IO_BLOCK_SIZE]; + int err; + u_int64_t inode_num = fs->superblock.inode_list_head; + if (inode_num > max_num_inodes) + return -1; + + u_int64_t block_num = get_block_num(inode_num); + u_int64_t block_offset = get_block_offset(inode_num); + + if (block_num == 0) + return -1; + + if ((err = fs->disk->read_block(block_num, buf)) < 0) + return err; + + u_int64_t new_inode_list_head = 0; + read_u64(&new_inode_list_head, &buf[block_offset]); + if ((err = fs->save_inode_list_head(new_inode_list_head)) < 0) + return err; + + (*inode_data) = INode_Data(inode_num); + + inode_data->metadata.uid = uid; + inode_data->metadata.gid = gid; + inode_data->metadata.permissions = permissions; + + // It is debatable if this function should do this: + if ((err = save_inode(inode_data)) < 0) { + inode_data->inode_num = 0xFFFFFFFFFFFFFFFF; + return err; + } + + return 0; +} +int INode_Manager_Freelist::free_inode(INode_Data *inode_data) { + char buf[IO_BLOCK_SIZE]; + int err; + + u_int64_t block_num = get_block_num(inode_data->inode_num); + u_int64_t block_offset = get_block_offset(inode_data->inode_num); + + if (block_num == 0) + return -1; + + if ((err = fs->disk->read_block(block_num, buf)) < 0) + return err; + + write_u64(fs->superblock.inode_list_head, &buf[block_offset]); + + if ((err = fs->disk->write_block(block_num, buf)) < 0) + return err; + + if ((err = fs->save_inode_list_head(inode_data->inode_num)) < 0) + return err; + + return 0; +} + +int INode_Manager_Freelist::format() { + char buf[IO_BLOCK_SIZE]; + int err; + u_int64_t next_inode_num = 2; + for (u_int64_t i = block_segment_start; i < block_segment_end; ++i) { + for (int j = 0; j < INODES_PER_BLOCK; ++next_inode_num, ++j) { + if (next_inode_num > max_num_inodes) + next_inode_num = 0; + write_u64(next_inode_num, &buf[j * INODE_SIZE]); + } + if ((err = fs->disk->write_block(i, buf)) < 0) + return err; + } + if ((err = fs->save_inode_list_head(1)) < 0) + return err; + return 0; +} diff --git a/lib/main.cpp b/lib/main.cpp index 8aed40b..13291c9 100644 --- a/lib/main.cpp +++ b/lib/main.cpp @@ -15,11 +15,12 @@ int main() { INode_Data inode_data = INode_Data(); fs->inode_manager->new_inode(1, 2, 3, &inode_data); int err; + u_int64_t block_num = 0; for (int i = 0; i < 56 + 512 + 4; ++i) - err = fs->allocate_datablock(&inode_data); + err = fs->allocate_datablock(&inode_data, &block_num); for (int i = 0; i < 5; ++i) - printf("%d\n", err = fs->deallocate_datablock(&inode_data)); + printf("%d\n", err = fs->deallocate_datablock(&inode_data, &block_num)); fs->inode_manager->save_inode(&inode_data); diff --git a/lib/rawdisk.cpp b/lib/rawdisk.cpp index c033bc2..c0ed0ab 100644 --- a/lib/rawdisk.cpp +++ b/lib/rawdisk.cpp @@ -12,7 +12,9 @@ void RawDisk::print_block(u_int64_t block_number) { printf("\nBlock %llu:\n", block_number); for (int i = 0; i < IO_BLOCK_SIZE; i += sizeof(u_int64_t)) { - read_u64(&num, &buf[i]); + num = 0; + for (int j = 0; j < 8; j++) + num |= ((u_int64_t)(unsigned char)buf[i + j]) << (8 * j); printf("%llu ", num); if ((i / sizeof(u_int64_t)) % nums_per_line == nums_per_line - 1) printf("\n"); diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 41d7049..e92ee57 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,23 +1,34 @@ set(TARGET_LAYER0 test_layer0) set(TARGET_LAYER1_API test_layer1_API) -set(TARGET_LAYER1_TEST1 test_layer1_test1) +# set(TARGET_LAYER1_TEST1 test_layer1_test1) set(DIR_PLACE /dev/vdb) # add test sources here ... add_executable(${TARGET_LAYER0} # add need lib and source code here layer0.cpp + + ../lib/rawdisk.cpp + ) add_executable(${TARGET_LAYER1_API} # add need lib and source code here layer1_API.cpp + + ../lib/fischl.cpp + ../lib/rawdisk.cpp + ../lib/fs/datablock_manager.cpp + ../lib/fs/fs_data_types.cpp + ../lib/fs/fs_resize.cpp + ../lib/fs/fs.cpp + ../lib/fs/inode_manager.cpp ) -add_executable(${TARGET_LAYER1_TEST1} - # add need lib and source code here - layer1_test1.cpp -) +# add_executable(${TARGET_LAYER1_TEST1} +# # add need lib and source code here +# layer1_test1.cpp +# ) # add test to activate ctest -VV add_test(NAME ${TARGET_LAYER0} COMMAND sudo ./${TARGET_LAYER0} ${DIR_PLACE}) add_test(NAME ${TARGET_LAYER1_API} COMMAND sudo ./${TARGET_LAYER1_API} ${DIR_PLACE}) -add_test(NAME ${TARGET_LAYER1_TEST1} COMMAND sudo ./${TARGET_LAYER1_TEST1} ${DIR_PLACE}) \ No newline at end of file +# add_test(NAME ${TARGET_LAYER1_TEST1} COMMAND sudo ./${TARGET_LAYER1_TEST1} ${DIR_PLACE}) \ No newline at end of file diff --git a/test/layer0.cpp b/test/layer0.cpp index 122f066..265ad60 100644 --- a/test/layer0.cpp +++ b/test/layer0.cpp @@ -1,29 +1,32 @@ +#include "rawdisk.hpp" +#include #include #include -#include -#include "rawdisk.h" int main(int argc, char *argv[]) { - const char* d = (argc < 2) ? "/dev/vdc" : argv[1]; - - RawDisk *H = new RawDisk(d); - - char *buf = "iloveosdfjlseirfnerig"; - char readBuffer[512] = {0}; // Initialize to zeros + const char *d = (argc < 2) ? "/dev/vdc" : argv[1]; - //printf("dir %s, numSectors %lld, diskSize %lld \n", H->dir, H->numSectors, H->diskSize); + RawDisk *H = new RealRawDisk(d); - //use number to substitute H->getnumSector(), getnumSectors() are not yest implemented - for(u_int64_t i = 0; i < 10; i++) { - H->rawdisk_write(i*512, buf, strlen(buf));//Change write_API - } - //use number to substitute H->getnumSector(), getnumSectors() are not yest implemented - for(u_int64_t i = 0; i < 10; i++) { - H->rawdisk_read(i*512, readBuffer, sizeof(readBuffer));//Change read_API - assert(strncmp(readBuffer, buf, strlen(buf)) == 0); - } + char *buf = "iloveosdfjlseirfnerig"; + char readBuffer[IO_BLOCK_SIZE] = {0}; // Initialize to zeros - delete H; // Delete the RawDisk object + // printf("dir %s, numSectors %lld, diskSize %lld \n", H->dir, H->numSectors, + // H->diskSize); - return 0; + // use number to substitute H->getnumSector(), getnumSectors() are not yest + // implemented + for (u_int64_t i = 0; i < 10; i++) { + H->write_block(i, buf); // Change write_API + } + // use number to substitute H->getnumSector(), getnumSectors() are not yest + // implemented + for (u_int64_t i = 0; i < 10; i++) { + H->read_block(i, readBuffer); // Change read_API + assert(strncmp(readBuffer, buf, strlen(buf)) == 0); + } + + delete H; // Delete the RawDisk object + + return 0; } diff --git a/test/layer1_API.cpp b/test/layer1_API.cpp index e898231..b49f0b2 100644 --- a/test/layer1_API.cpp +++ b/test/layer1_API.cpp @@ -1,118 +1,144 @@ +#include "fs.hpp" +#include +#include #include #include -#include -#include "fs.h" -#include int main(int argc, char *argv[]) { - const char* d = (argc < 2) ? "/dev/vdc" : argv[1]; - - RawDisk *H = new RawDisk(d); + // const char* d = (argc < 2) ? "/dev/vdc" : argv[1]; - printf("test inode\n"); - INodeOperation inop; - inop.initialize(*H);//for inode initialization and datablock initialization - char buffer[8] = {0}; - /**************************test inode Initialization***************************/ - //test the begining of inode 1th - H->rawdisk_read((1) * SECTOR_SIZE, buffer, sizeof(buffer)); - u_int64_t t = 0; - for (int j = 0; j < 8; j++) - t |= ((u_int64_t)(unsigned char)buffer[j]) << (8 * j); + RawDisk *H = new FakeRawDisk(2048); + Fs *fs = new Fs(H); - assert(t == 2);//the first 1th unused inode will store the next unused inode 2th - //test the number before end of inode 524286th - H->rawdisk_read((MAX_INODE - 2) * SECTOR_SIZE, buffer, sizeof(buffer)); - t = 0; - for (int j = 0; j < 8; j++) - t |= ((u_int64_t)(unsigned char)buffer[j]) << (8 * j); - - assert(t == MAX_INODE - 1);//store the maximun th inode - //test the end of inode 524287th - H->rawdisk_read((MAX_INODE - 1) * SECTOR_SIZE, buffer, sizeof(buffer)); - t = 0; - for (int j = 0; j < 8; j++) - t |= ((u_int64_t)(unsigned char)buffer[j]) << (8 * j); + printf("test inode\n"); + fs->format(); + char buffer[IO_BLOCK_SIZE] = {0}; + /**************************test inode + * Initialization***************************/ + // test the begining of inode 1th + H->read_block(1, buffer); + u_int64_t t = 0; + for (int j = 0; j < 8; j++) + t |= ((u_int64_t)(unsigned char)buffer[j]) << (8 * j); - assert(t == 0);//the end of inode(524287th inode) do not have the next inode address - /**************************test datablock Initialization***************************/ - //we separate 2048 4kB I/O block(1+2047) as a group and the first I/O block will manage the following 2047 I/O block usage. - //the first 8 bytes(0~7) in first I/O block store the address of next first I/O block, the following 256(8~263) bytes record 2047 I/O block usage. - //test the begining of free datablock - H->rawdisk_read((MAX_INODE) * SECTOR_SIZE, buffer, sizeof(buffer));//the begining of free datablock will store from address (MAX_INODE) * SECTOR_SIZE - t = 0; - for (int j = 0; j < 8; j++) - t |= ((u_int64_t)(unsigned char)buffer[j]) << (8 * j); + assert(t == + 2); // the first 1th unused inode will store the next unused inode 2th - assert(t == (MAX_INODE+2048*8)*SECTOR_SIZE);//the first 8 bytes of 4k I/O block will store the next address(after 2048*4k I/O block) - //test the end of the datablock - H->rawdisk_read((MAX_BLOCKNUM - 2048*8) * SECTOR_SIZE, buffer, sizeof(buffer)); - t = 0; - for (int j = 0; j < 8; j++) - t |= ((u_int64_t)(unsigned char)buffer[j]) << (8 * j); + assert(IO_BLOCK_SIZE == 4096); + assert(INODE_SIZE == 512); - assert(t == (MAX_BLOCKNUM)*SECTOR_SIZE); + // test the number before end of inode + H->read_block(NUM_INODE_BLOCKS, buffer); + t = 0; + for (int j = 0; j < 8; j++) + t |= + ((u_int64_t)(unsigned char)buffer[j + IO_BLOCK_SIZE - (INODE_SIZE * 2)]) + << (8 * j); - /***************************test inode de/allocation**********************************/ - //when requesting an inode, the inode_allocation will give you the inode number, we use inode_list to store the sequence allocate inode - //arrary version - int inode_list[20] = {0}; - int record_free[10] = {0};//should do a pop up structure to record the free inode - int rec = 9; - //printf("Allocate 20 inode num:{"); - for(int i=0;i<20;i++){ - inode_list[i] = inop.inode_allocate(*H); - assert(inode_list[i] == i+1); - //printf(" %d", inode_list[i]); + assert(t == NUM_INODE_BLOCKS * + (IO_BLOCK_SIZE / INODE_SIZE)); // store the maximun th inode + + // test the end of inode + t = 0; + for (int j = 0; j < 8; j++) + t |= ((u_int64_t)(unsigned char)buffer[j + IO_BLOCK_SIZE - INODE_SIZE]) + << (8 * j); + + assert( + t == + 0); // the end of inode(524287th inode) do not have the next inode address + /**************************test datablock + * Initialization***************************/ + // we separate 2048 4kB I/O block(1+2047) as a group and the first I/O block + // will manage the following 2047 I/O block usage. the first 8 bytes(0~7) in + // first I/O block store the address of next first I/O block, the following + // 256(8~263) bytes record 2047 I/O block usage. test the begining of free + // datablock + H->read_block(NUM_INODE_BLOCKS + 1, + buffer); // the begining of free datablock will store + // from address (MAX_INODE) * SECTOR_SIZE + t = 0; + for (int j = 0; j < 8; j++) + t |= ((u_int64_t)(unsigned char)buffer[j]) << (8 * j); + + assert(t == NUM_INODE_BLOCKS + 1 + DATABLOCKS_PER_BITMAP_BLOCK + + 1); // the first 8 bytes of 4k I/O block will store + // the next address(after 2048*4k I/O block) + // test the end of the datablock + H->read_block(NUM_BLOCKS - DATABLOCKS_PER_BITMAP_BLOCK - 1, buffer); + t = 0; + for (int j = 0; j < 8; j++) + t |= ((u_int64_t)(unsigned char)buffer[j]) << (8 * j); + + assert(t == NUM_BLOCKS - DATABLOCKS_PER_BITMAP_BLOCK - 1); + + /***************************test inode + * de/allocation**********************************/ + // when requesting an inode, the inode_allocation will give you the inode + // number, we use inode_list to store the sequence allocate inode arrary + // version + INode_Data inode_list[20]; + u_int64_t record_free[10] = { + 0}; // should do a pop up structure to record the free inode + int rec = 9; + // printf("Allocate 20 inode num:{"); + for (int i = 0; i < 20; i++) { + fs->inode_manager->new_inode(0, 0, 0, &inode_list[i]); + + assert(inode_list[i].inode_num == i + 1); + // printf(" %d", inode_list[i].inode_num); + } + // printf("}\n"); + for (int i = 10; i < 20; i++) { + record_free[i - 10] = inode_list[i].inode_num; + fs->inode_manager->free_inode( + &inode_list[i]); // free the 10 element from inode_list[10] + } + // allocate again the last 10 + printf("Allocate again: inode num:{"); + for (int i = 10; i < 20; i++) { + fs->inode_manager->new_inode(0, 0, 0, &inode_list[i]); + // printf("inode %d, rec_f %d\n,", inode_list[i],record_free[rec]); + assert(inode_list[i].inode_num == record_free[rec]); + rec--; + } + printf("}\n"); + /***************************test direct blocks[48] + * de/allocation**********************************/ + // after free the datablock, the program will find the first smallest address + // of datablock to give to the inode should test random resize each node, but + // should use datablock_free data structure to record + u_int64_t rec_datablock_free[10][3] = {0}; // array version + u_int64_t temp_block_num = 0; + for (int i = 0; i < 10; i++) { + // printf("%dth data block starting addres: ", i); + for (int j = 0; j < 6; j++) { + fs->allocate_datablock(&inode_list[i], &temp_block_num); + // printf("%d," ,inode_inside[i].datablock_allocate(*H)); } - //printf("}\n"); - for(int i=10;i<20;i++){ - inop.inode_free(*H,inode_list[i]);//free the 10 element from inode_list[10] - record_free[i-10] = inode_list[i]; - } - //allocate again the last 10 - printf("Allocate again: inode num:{"); - for(int i=10;i<20;i++){ - inode_list[i] = inop.inode_allocate(*H); - //printf("inode %d, rec_f %d\n,", inode_list[i],record_free[rec]); - assert(inode_list[i] == record_free[rec]); - rec--; - } - printf("}\n"); - /***************************test direct blocks[48] de/allocation**********************************/ - //after free the datablock, the program will find the first smallest address of datablock to give to the inode - //should test random resize each node, but should use datablock_free data structure to record - INode inode_inside[10]; - u_int64_t rec_datablock_free[10][3] = {0};//array version - for(int i=0;i<10;i++){ - inode_inside[i].inode_construct(inode_list[i],*H); - //printf("%dth data block starting addres: ", i); - for(int j=0;j<6;j++){ - inode_inside[i].datablock_allocate(*H); - //printf("%d," ,inode_inside[i].datablock_allocate(*H)); - } - //printf("\n"); - } - for(int i=0;i<10;i++){ - //printf("%dth data block free addres: ", i); - for(int j = 2;j >=0;j--){ - rec_datablock_free[i][j] = inode_inside[i].datablock_deallocate(*H); - //printf("", rec_datablock_free[i][j]); - } - //printf("\n"); + // printf("\n"); + } + for (int i = 0; i < 10; i++) { + // printf("%dth data block free addres: ", i); + for (int j = 2; j >= 0; j--) { + fs->deallocate_datablock(&inode_list[i], &(rec_datablock_free[i][j])); + // printf("", rec_datablock_free[i][j]); } + // printf("\n"); + } - for(int i=0;i<10;i++){ - //printf("%dth data block allocate again addres: ", i); - for(int j=0;j<3;j++){ - assert(inode_inside[i].datablock_allocate(*H) == rec_datablock_free[i][j]); - //printf("%d," ,inode_inside[i].datablock_allocate(*H)); - } - //printf("\n"); + for (int i = 0; i < 10; i++) { + // printf("%dth data block allocate again addres: ", i); + 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("%d," ,inode_inside[i].datablock_allocate(*H)); } + // printf("\n"); + } - //printf("}\n"); - delete H; // Delete the RawDisk object + // printf("}\n"); + delete H; // Delete the RawDisk object - return 0; + return 0; } diff --git a/test/layer1_test1.cpp b/test/layer1_test1.cpp index 2943ecd..ee760a4 100644 --- a/test/layer1_test1.cpp +++ b/test/layer1_test1.cpp @@ -1,113 +1,130 @@ -#include -#include -#include -#include "fs.h" -#include - -// in fs.h: -// #define MAX_INODE 2048 -// #define MAX_BLOCKNUM 51200 -// 51200 Sectors = 2048 * 25 Sectors = 25MB -// Free List Heads: 2048*512, 2048*9*512, 2048*17*512 -// Available INodes: 2047 (-1 because superblock) -// Available DataBlocks (including Indirect Blocks): 2047 * 3 = 6141 - -int main(int argc, char *argv[]) { - const char* d = (argc < 2) ? "/dev/vdc" : argv[1]; - - RawDisk *H = new RawDisk(d); - - printf("=== INode Alloc/Dealloc Test ===\n"); - INodeOperation inop; - inop.initialize(*H); - - // Test INode alloc and dealloc - int inode_list[2046] = {0}; // if we allocate 2047 inodes head will be 0 (faulty) - printf("freeInodeHead: %d \n", SuperBlock::getFreeINodeHead(*H)); // this impl should give 1 - for(int i=0;i<2046;i++){ - inode_list[i] = inop.inode_allocate(*H); - if (SuperBlock::getFreeINodeHead(*H) == 0) { - printf("%d\n",i); - assert(false); - } - } - printf("freeInodeHead: %d \n", SuperBlock::getFreeINodeHead(*H)); // this impl should give 2047 - for(int i=0;i<1024;i++){ - inop.inode_free(*H,inode_list[i]); - } - for(int i=0;i<1022;i++){ - inode_list[i] = inop.inode_allocate(*H); - assert(SuperBlock::getFreeINodeHead(*H) != 0); - } - printf("freeInodeHead: %d \n", SuperBlock::getFreeINodeHead(*H)); // this impl should give 2 - inode_list[1022] = inop.inode_allocate(*H); - printf("freeInodeHead: %d \n", SuperBlock::getFreeINodeHead(*H)); // this impl should give 1 - inode_list[1023] = inop.inode_allocate(*H); - printf("freeInodeHead: %d \n", SuperBlock::getFreeINodeHead(*H)); // this impl should give 2047 - - // Test Many Files - printf("=== Many Files Test ===\n"); - INode inode_inside[100]; - for(int i=0;i<100;i++){ - inode_inside[i].inode_construct(inode_list[i],*H); - for(int j=0;j<60;j++) { // Note that 1 indirect block is used for each file - u_int64_t allcBlockNum = inode_inside[i].datablock_allocate(*H); - if (SuperBlock::getFreeListHead(*H) >= (u_int64_t) 51200*512) { - printf("Bad FreeListHead: %d, %d, %llu\n", i, j, SuperBlock::getFreeListHead(*H)); - assert(false); - } - if (allcBlockNum % 2048 != 0 || allcBlockNum < 2048*512 || allcBlockNum >= 25*2048*512) { - printf("Bad Allocated Block Number: %d, %d, %llu\n", i, j, allcBlockNum); - assert(false); - } - } - } - printf("Finished Allocating\n"); - // in this impl should give 17*2048*512 = 17825792 - printf("freeListHead: %llu \n", SuperBlock::getFreeListHead(*H)); // if all 6141 blocks allocated, would give 51200*512 (faulty) - for(int i=0;i<100;i++){ - for(int j=0;j<59;j++){ - u_int64_t freedBlkNum = inode_inside[i].datablock_deallocate(*H); - u_int64_t fh = SuperBlock::getFreeListHead(*H); - if (freedBlkNum % 2048 != 0 || freedBlkNum < 2048*512 || freedBlkNum >= 25*2048*512 || fh >= 51200*512) { - printf("%d, %d, Freed Block Number: %llu\n", i, j, freedBlkNum); - printf("FreeListHead is %llu\n", fh); - assert(false); - } - } - } - printf("Finished Deallocating\n"); - printf("freeListHead: %d \n", SuperBlock::getFreeListHead(*H)); - - // Test Big File (Use direct, single indirect, double indirect) - printf("=== Big File Test ===\n"); - u_int64_t lastAllc = 0; - for(int j=0;j<5000;j++){ - u_int64_t allcBlockNum = inode_inside[0].datablock_allocate(*H); - lastAllc = allcBlockNum; - u_int64_t fh = SuperBlock::getFreeListHead(*H); - if (allcBlockNum % 2048 != 0 || allcBlockNum < 2048*512 || allcBlockNum >= 25*2048*512 || fh >= 51200*512) { - printf("%d, Alloc Block Number: %llu\n", j, allcBlockNum); - printf("FreeListHead is %llu\n", fh); - assert(false); - } - } - printf("last allocate for big file: %llu\n", lastAllc); - printf("Finished Allocating\n"); - printf("freeListHead: %d \n", SuperBlock::getFreeListHead(*H)); - for(int j=0;j<5000;j++){ - u_int64_t freedBlkNum = inode_inside[0].datablock_deallocate(*H); - u_int64_t fh = SuperBlock::getFreeListHead(*H); - if (freedBlkNum % 2048 != 0 || freedBlkNum < 2048*512 || freedBlkNum >= 25*2048*512 || fh >= 51200*512) { - printf("%d, Freed Block Number: %llu\n", j, freedBlkNum); - printf("FreeListHead is %llu\n", fh); - assert(false); - } - } - printf("Finished Deallocating\n"); - printf("freeListHead: %d \n", SuperBlock::getFreeListHead(*H)); - - delete H; // Delete the RawDisk object - - return 0; -} +// #include "fs.h" +// #include +// #include +// #include +// #include + +// // in fs.h: +// // #define MAX_INODE 2048 +// // #define MAX_BLOCKNUM 51200 +// // 51200 Sectors = 2048 * 25 Sectors = 25MB +// // Free List Heads: 2048*512, 2048*9*512, 2048*17*512 +// // Available INodes: 2047 (-1 because superblock) +// // Available DataBlocks (including Indirect Blocks): 2047 * 3 = 6141 + +// int main(int argc, char *argv[]) { +// const char *d = (argc < 2) ? "/dev/vdc" : argv[1]; + +// RawDisk *H = new FakeRawDisk(d); + +// printf("=== INode Alloc/Dealloc Test ===\n"); +// INodeOperation inop; +// inop.initialize(*H); + +// // Test INode alloc and dealloc +// int inode_list[2046] = { +// 0}; // if we allocate 2047 inodes head will be 0 (faulty) +// printf("freeInodeHead: %d \n", +// SuperBlock::getFreeINodeHead(*H)); // this impl should give 1 +// for (int i = 0; i < 2046; i++) { +// inode_list[i] = inop.inode_allocate(*H); +// if (SuperBlock::getFreeINodeHead(*H) == 0) { +// printf("%d\n", i); +// assert(false); +// } +// } +// printf("freeInodeHead: %d \n", +// SuperBlock::getFreeINodeHead(*H)); // this impl should give 2047 +// for (int i = 0; i < 1024; i++) { +// inop.inode_free(*H, inode_list[i]); +// } +// for (int i = 0; i < 1022; i++) { +// inode_list[i] = inop.inode_allocate(*H); +// assert(SuperBlock::getFreeINodeHead(*H) != 0); +// } +// printf("freeInodeHead: %d \n", +// SuperBlock::getFreeINodeHead(*H)); // this impl should give 2 +// inode_list[1022] = inop.inode_allocate(*H); +// printf("freeInodeHead: %d \n", +// SuperBlock::getFreeINodeHead(*H)); // this impl should give 1 +// inode_list[1023] = inop.inode_allocate(*H); +// printf("freeInodeHead: %d \n", +// SuperBlock::getFreeINodeHead(*H)); // this impl should give 2047 + +// // Test Many Files +// printf("=== Many Files Test ===\n"); +// INode inode_inside[100]; +// for (int i = 0; i < 100; i++) { +// inode_inside[i].inode_construct(inode_list[i], *H); +// for (int j = 0; j < 60; +// j++) { // Note that 1 indirect block is used for each file +// u_int64_t allcBlockNum = inode_inside[i].datablock_allocate(*H); +// if (SuperBlock::getFreeListHead(*H) >= (u_int64_t)51200 * 512) { +// printf("Bad FreeListHead: %d, %d, %llu\n", i, j, +// SuperBlock::getFreeListHead(*H)); +// assert(false); +// } +// if (allcBlockNum % 2048 != 0 || allcBlockNum < 2048 * 512 || +// allcBlockNum >= 25 * 2048 * 512) { +// printf("Bad Allocated Block Number: %d, %d, %llu\n", i, j, +// allcBlockNum); +// assert(false); +// } +// } +// } +// printf("Finished Allocating\n"); +// // in this impl should give 17*2048*512 = 17825792 +// printf( +// "freeListHead: %llu \n", +// SuperBlock::getFreeListHead( +// *H)); // if all 6141 blocks allocated, would give 51200*512 +// (faulty) +// for (int i = 0; i < 100; i++) { +// for (int j = 0; j < 59; j++) { +// u_int64_t freedBlkNum = inode_inside[i].datablock_deallocate(*H); +// u_int64_t fh = SuperBlock::getFreeListHead(*H); +// if (freedBlkNum % 2048 != 0 || freedBlkNum < 2048 * 512 || +// freedBlkNum >= 25 * 2048 * 512 || fh >= 51200 * 512) { +// printf("%d, %d, Freed Block Number: %llu\n", i, j, freedBlkNum); +// printf("FreeListHead is %llu\n", fh); +// assert(false); +// } +// } +// } +// printf("Finished Deallocating\n"); +// printf("freeListHead: %d \n", SuperBlock::getFreeListHead(*H)); + +// // Test Big File (Use direct, single indirect, double indirect) +// printf("=== Big File Test ===\n"); +// u_int64_t lastAllc = 0; +// for (int j = 0; j < 5000; j++) { +// u_int64_t allcBlockNum = inode_inside[0].datablock_allocate(*H); +// lastAllc = allcBlockNum; +// u_int64_t fh = SuperBlock::getFreeListHead(*H); +// if (allcBlockNum % 2048 != 0 || allcBlockNum < 2048 * 512 || +// allcBlockNum >= 25 * 2048 * 512 || fh >= 51200 * 512) { +// printf("%d, Alloc Block Number: %llu\n", j, allcBlockNum); +// printf("FreeListHead is %llu\n", fh); +// assert(false); +// } +// } +// printf("last allocate for big file: %llu\n", lastAllc); +// printf("Finished Allocating\n"); +// printf("freeListHead: %d \n", SuperBlock::getFreeListHead(*H)); +// for (int j = 0; j < 5000; j++) { +// u_int64_t freedBlkNum = inode_inside[0].datablock_deallocate(*H); +// u_int64_t fh = SuperBlock::getFreeListHead(*H); +// if (freedBlkNum % 2048 != 0 || freedBlkNum < 2048 * 512 || +// freedBlkNum >= 25 * 2048 * 512 || fh >= 51200 * 512) { +// printf("%d, Freed Block Number: %llu\n", j, freedBlkNum); +// printf("FreeListHead is %llu\n", fh); +// assert(false); +// } +// } +// printf("Finished Deallocating\n"); +// printf("freeListHead: %d \n", SuperBlock::getFreeListHead(*H)); + +// delete H; // Delete the RawDisk object + +// return 0; +// } From d8f8594c1394b26303b3c3d549b6dc344c00f00b Mon Sep 17 00:00:00 2001 From: Connor Date: Wed, 22 Nov 2023 02:25:30 -0800 Subject: [PATCH 11/13] chnages to file io --- include/fs.hpp | 15 +++ lib/fs/fs_data_types.cpp | 16 +-- lib/fs/fs_read_write.cpp | 212 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 235 insertions(+), 8 deletions(-) create mode 100644 lib/fs/fs_read_write.cpp diff --git a/include/fs.hpp b/include/fs.hpp index e570e57..7a0cd7f 100644 --- a/include/fs.hpp +++ b/include/fs.hpp @@ -7,6 +7,9 @@ #include "fs_constants.hpp" #include "rawdisk.hpp" +// TEMP: +class DatablockOperation; + class Fs { public: Fs(RawDisk *disk); @@ -15,6 +18,18 @@ public: int allocate_datablock(INode_Data *inode_data, u_int64_t *datablock_num); int deallocate_datablock(INode_Data *inode_data, u_int64_t *datablock_num); + ssize_t read(INode_Data *inode_data, char buf[], size_t count, size_t offset); + ssize_t write(INode_Data *inode_data, char buf[], size_t count, + size_t offset); + + int sweep_inode_datablocks(INode_Data *inode_data, + u_int64_t start_block_index, bool allocate, + DatablockOperation *op); + + int sweep_datablocks(u_int64_t *block_num, int indirect_num, + u_int64_t start_block_index, bool allocate, + DatablockOperation *op); + int format(); // should probably be private but is not for testing diff --git a/lib/fs/fs_data_types.cpp b/lib/fs/fs_data_types.cpp index ee8b8d1..c253b02 100644 --- a/lib/fs/fs_data_types.cpp +++ b/lib/fs/fs_data_types.cpp @@ -86,19 +86,19 @@ size_t INode_Data::deserialize_metadata(char buf[]) { void INode_Data::serialize(char buf[]) { size_t i = 0; - i += serialize_metadata(&buf[i]); - i += write_u64(triple_indirect_block, &buf[i]); - i += write_u64(double_indirect_block, &buf[i]); - i += write_u64(single_indirect_block, &buf[i]); for (size_t j = 0; j < NUMBER_OF_DIRECT_BLOCKS; ++j) i += write_u64(direct_blocks[j], &buf[i]); + i += write_u64(single_indirect_block, &buf[i]); + i += write_u64(double_indirect_block, &buf[i]); + i += write_u64(triple_indirect_block, &buf[i]); + i += serialize_metadata(&buf[i]); } void INode_Data::deserialize(char buf[]) { size_t i = 0; - i += deserialize_metadata(&buf[i]); - i += read_u64(&triple_indirect_block, &buf[i]); - i += read_u64(&double_indirect_block, &buf[i]); - i += read_u64(&single_indirect_block, &buf[i]); for (size_t j = 0; j < NUMBER_OF_DIRECT_BLOCKS; ++j) i += read_u64(&direct_blocks[j], &buf[i]); + i += read_u64(&single_indirect_block, &buf[i]); + i += read_u64(&double_indirect_block, &buf[i]); + i += read_u64(&triple_indirect_block, &buf[i]); + i += deserialize_metadata(&buf[i]); } \ No newline at end of file diff --git a/lib/fs/fs_read_write.cpp b/lib/fs/fs_read_write.cpp new file mode 100644 index 0000000..f92b99d --- /dev/null +++ b/lib/fs/fs_read_write.cpp @@ -0,0 +1,212 @@ +#include "fs.hpp" +#include + +class DatablockOperation { +public: + char *buf; + size_t count; + size_t offset; + size_t bytes_completed; + RawDisk *disk; + virtual int operation(u_int64_t block_num) = 0; +}; + +int Fs::sweep_inode_datablocks(INode_Data *inode_data, + u_int64_t start_block_index, bool allocate, + DatablockOperation *op) { + int result; + + u_int64_t start_index = start_block_index; + for (size_t i = start_index; i < NUMBER_OF_DIRECT_BLOCKS; ++i) { + if ((result = sweep_datablocks(&(inode_data->direct_blocks[i]), 0, 0, + allocate, op)) <= 0) + return result; + start_index = NUMBER_OF_DIRECT_BLOCKS; + } + + start_index -= NUMBER_OF_DIRECT_BLOCKS; + + if (start_index < IO_BLOCK_SIZE) { + if ((result = sweep_datablocks(&(inode_data->single_indirect_block), 1, + start_index, allocate, op)) <= 0) + return result; + start_index = IO_BLOCK_SIZE; + } + + start_index -= IO_BLOCK_SIZE; + + if (start_index < IO_BLOCK_SIZE * IO_BLOCK_SIZE) { + if ((result = sweep_datablocks(&(inode_data->double_indirect_block), 2, + start_index, allocate, op)) <= 0) + return result; + start_index = IO_BLOCK_SIZE * IO_BLOCK_SIZE; + } + + start_index -= IO_BLOCK_SIZE * IO_BLOCK_SIZE; + + if (start_index < IO_BLOCK_SIZE * IO_BLOCK_SIZE * IO_BLOCK_SIZE) { + if ((result = sweep_datablocks(&(inode_data->triple_indirect_block), 3, + start_index, allocate, op)) <= 0) + return result; + } + + return -1; +} + +// This can simply be made non recursive by copy pasting - it is just +// written this way as a proof of concept +int Fs::sweep_datablocks(u_int64_t *block_num, int indirect_num, + u_int64_t start_block_index, bool allocate, + DatablockOperation *op) { + char buf[IO_BLOCK_SIZE]; + int err; + int result = -1; + u_int64_t temp; + u_int64_t next_block_num; + bool modified = false; + + if (allocate && (*block_num) == 0) + if ((err = datablock_manager->new_datablock(block_num)) < 0) + return err; + + if (indirect_num == 0) + return op->operation(*block_num); + + if ((*block_num) == 0) { + memset(buf, 0, sizeof(buf)); + } else { + if ((err = disk->read_block(*block_num, buf)) < 0) + return err; + } + + u_int64_t indirect_block_size = 1; + for (int i = 1; i < indirect_num; ++i) + indirect_block_size *= IO_BLOCK_SIZE; + + u_int64_t this_layer_start_index = start_block_index / indirect_block_size; + u_int64_t next_layer_start_index = + start_block_index - (indirect_block_size * this_layer_start_index); + + u_int64_t temp; + u_int64_t next_block_num; + bool modified = false; + + for (size_t i = this_layer_start_index * sizeof(u_int64_t); i < IO_BLOCK_SIZE; + i += *sizeof(u_int64_t)) { + read_u64(&temp, &buf[i]); + next_block_num = temp; + if ((result = sweep_datablocks(&next_block_num, indirect_num - 1, + next_layer_start_index, allocate, func)) < 0) + return result; + if (next_block_num != temp) { + write_u64(&next_block_num, &buf[i]); + modified = true; + } + if (result == 0) + break; + } + + if (modified) + if ((err = disk->write_block(*block_num, buf)) < 0) + return err; + + return result; +} + +class ReadDatablockOperation : public DatablockOperation { +public: + int operation(u_int64_t block_num) override { + char datablock_buf[IO_BLOCK_SIZE]; + int err; + + size_t read_size = min(IO_BLOCK_SIZE - offset, count); + + if (block_num != 0) { + if ((err = disk->read_block(block_num, datablock_buf)) < 0) + return err; + + memcpy(&buf[bytes_completed], &datablock_buf[offset], read_size); + } else { + memset(&buf[bytes_completed], 0, read_size); + } + + offset = 0; + bytes_completed += read_size; + + if (bytes_completed >= count) + return 0; + return 1; + } +}; + +class WriteDatablockOperation : public DatablockOperation { +public: + int operation(u_int64_t block_num) override { + char datablock_buf[IO_BLOCK_SIZE]; + int err; + + size_t write_size = min(IO_BLOCK_SIZE - offset, count); + + if (write_size < IO_BLOCK_SIZE) + if ((err = disk->read_block(block_num, datablock_buf)) < 0) + return err; + + size_t write_size = min(IO_BLOCK_SIZE - offset, count); + memcpy(&datablock_buf[offset], &buf[bytes_completed], write_size); + + if ((err = disk->write_block(block_num, datablock_buf)) < 0) + return err; + + offset = 0; + bytes_completed += write_size; + + if (bytes_completed >= count) + return 0; + return 1; + } +}; + +ssize_t Fs::read(INode_Data *inode_data, char buf[], size_t count, + size_t offset) { + int err; + + u_int64_t start_block_index = offset / IO_BLOCK_SIZE; + size_t internal_offset = offset - block_start; + + ReadDatablockOperation op = ReadDatablockOperation(); + op.offset = internal_offset; + op.buf = buf; + op.count = min(count, inode_data->metadata.size - offset); + op.bytes_completed = 0; + op.disk = disk; + + if ((err = sweep_inode_datablocks(inode_data, start_block_index, false, op)) < + 0) + return err; + + return op.bytes_completed; +} + +ssize_t Fs::write(INode_Data *inode_data, char buf[], size_t count, + size_t offset) { + int err; + + u_int64_t start_block_index = offset / IO_BLOCK_SIZE; + size_t internal_offset = offset - block_start; + + ReadDatablockOperation op = WriteDatablockOperation(); + op.offset = internal_offset; + op.buf = buf; + op.count = count; + op.bytes_completed = 0; + op.disk = disk; + + if ((err = sweep_inode_datablocks(inode_data, start_block_index, true, op)) < + 0) + return err; + + inode_data->metadata.size = + max(offset + op.bytes_completed, inode_data->metadata.size); + + return op.bytes_completed; +} \ No newline at end of file From 81f81d8e800e02c58010ca3283f2d02e5553e85c Mon Sep 17 00:00:00 2001 From: Connor Date: Wed, 22 Nov 2023 03:30:01 -0800 Subject: [PATCH 12/13] file io bug fixes --- CMakeLists.txt | 1 + include/fs_constants.hpp | 2 +- lib/fs/fs_read_write.cpp | 38 ++++++++++----------- lib/main.cpp | 73 +++++++++++++++++++++++++++++++++------- 4 files changed, 82 insertions(+), 32 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 684640d..d438466 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,6 +16,7 @@ add_executable(fischl 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 diff --git a/include/fs_constants.hpp b/include/fs_constants.hpp index 806aaed..e74e3ba 100644 --- a/include/fs_constants.hpp +++ b/include/fs_constants.hpp @@ -1,6 +1,7 @@ #ifndef FS_CONSTANTS_HPP #define FS_CONSTANTS_HPP +#include #include #include #include @@ -10,7 +11,6 @@ #include #include - #define IO_BLOCK_SIZE 4096 #define NUM_INODE_BLOCKS 1023 diff --git a/lib/fs/fs_read_write.cpp b/lib/fs/fs_read_write.cpp index f92b99d..1aabf8a 100644 --- a/lib/fs/fs_read_write.cpp +++ b/lib/fs/fs_read_write.cpp @@ -1,5 +1,4 @@ #include "fs.hpp" -#include class DatablockOperation { public: @@ -44,7 +43,7 @@ int Fs::sweep_inode_datablocks(INode_Data *inode_data, start_index -= IO_BLOCK_SIZE * IO_BLOCK_SIZE; - if (start_index < IO_BLOCK_SIZE * IO_BLOCK_SIZE * IO_BLOCK_SIZE) { + if (start_index < (u_int64_t)IO_BLOCK_SIZE * IO_BLOCK_SIZE * IO_BLOCK_SIZE) { if ((result = sweep_datablocks(&(inode_data->triple_indirect_block), 3, start_index, allocate, op)) <= 0) return result; @@ -61,9 +60,6 @@ int Fs::sweep_datablocks(u_int64_t *block_num, int indirect_num, char buf[IO_BLOCK_SIZE]; int err; int result = -1; - u_int64_t temp; - u_int64_t next_block_num; - bool modified = false; if (allocate && (*block_num) == 0) if ((err = datablock_manager->new_datablock(block_num)) < 0) @@ -92,14 +88,14 @@ int Fs::sweep_datablocks(u_int64_t *block_num, int indirect_num, bool modified = false; for (size_t i = this_layer_start_index * sizeof(u_int64_t); i < IO_BLOCK_SIZE; - i += *sizeof(u_int64_t)) { + i += sizeof(u_int64_t)) { read_u64(&temp, &buf[i]); next_block_num = temp; if ((result = sweep_datablocks(&next_block_num, indirect_num - 1, - next_layer_start_index, allocate, func)) < 0) + next_layer_start_index, allocate, op)) < 0) return result; if (next_block_num != temp) { - write_u64(&next_block_num, &buf[i]); + write_u64(next_block_num, &buf[i]); modified = true; } if (result == 0) @@ -119,7 +115,11 @@ public: char datablock_buf[IO_BLOCK_SIZE]; int err; - size_t read_size = min(IO_BLOCK_SIZE - offset, count); + // printf("PRINT: (%d) %d %d %d\n", block_num, count, offset, + // bytes_completed); + + size_t read_size = + std::min(IO_BLOCK_SIZE - offset, count - bytes_completed); if (block_num != 0) { if ((err = disk->read_block(block_num, datablock_buf)) < 0) @@ -145,13 +145,13 @@ public: char datablock_buf[IO_BLOCK_SIZE]; int err; - size_t write_size = min(IO_BLOCK_SIZE - offset, count); + size_t write_size = + std::min(IO_BLOCK_SIZE - offset, count - bytes_completed); if (write_size < IO_BLOCK_SIZE) if ((err = disk->read_block(block_num, datablock_buf)) < 0) return err; - size_t write_size = min(IO_BLOCK_SIZE - offset, count); memcpy(&datablock_buf[offset], &buf[bytes_completed], write_size); if ((err = disk->write_block(block_num, datablock_buf)) < 0) @@ -171,17 +171,17 @@ ssize_t Fs::read(INode_Data *inode_data, char buf[], size_t count, int err; u_int64_t start_block_index = offset / IO_BLOCK_SIZE; - size_t internal_offset = offset - block_start; + size_t internal_offset = offset - (start_block_index * IO_BLOCK_SIZE); ReadDatablockOperation op = ReadDatablockOperation(); op.offset = internal_offset; op.buf = buf; - op.count = min(count, inode_data->metadata.size - offset); + op.count = std::min(count, inode_data->metadata.size - offset); op.bytes_completed = 0; op.disk = disk; - if ((err = sweep_inode_datablocks(inode_data, start_block_index, false, op)) < - 0) + if ((err = sweep_inode_datablocks(inode_data, start_block_index, false, + &op)) < 0) return err; return op.bytes_completed; @@ -192,21 +192,21 @@ ssize_t Fs::write(INode_Data *inode_data, char buf[], size_t count, int err; u_int64_t start_block_index = offset / IO_BLOCK_SIZE; - size_t internal_offset = offset - block_start; + size_t internal_offset = offset - (start_block_index * IO_BLOCK_SIZE); - ReadDatablockOperation op = WriteDatablockOperation(); + WriteDatablockOperation op = WriteDatablockOperation(); op.offset = internal_offset; op.buf = buf; op.count = count; op.bytes_completed = 0; op.disk = disk; - if ((err = sweep_inode_datablocks(inode_data, start_block_index, true, op)) < + if ((err = sweep_inode_datablocks(inode_data, start_block_index, true, &op)) < 0) return err; inode_data->metadata.size = - max(offset + op.bytes_completed, inode_data->metadata.size); + std::max(offset + op.bytes_completed, inode_data->metadata.size); return op.bytes_completed; } \ No newline at end of file diff --git a/lib/main.cpp b/lib/main.cpp index 13291c9..049c062 100644 --- a/lib/main.cpp +++ b/lib/main.cpp @@ -7,31 +7,80 @@ int main() { // fischl *F = new fischl; // F->init(); // char *d = strdup("/dev/vdc"); + + // RawDisk *disk = new FakeRawDisk(2048); + // Fs *fs = new Fs(disk); + // fs->format(); + // disk->print_block(0); + // disk->print_block(1); + // INode_Data inode_data = INode_Data(); + // fs->inode_manager->new_inode(1, 2, 3, &inode_data); + // int err; + // u_int64_t block_num = 0; + // for (int i = 0; i < 56 + 512 + 4; ++i) + // err = fs->allocate_datablock(&inode_data, &block_num); + + // for (int i = 0; i < 5; ++i) + // printf("%d\n", err = fs->deallocate_datablock(&inode_data, &block_num)); + + // fs->inode_manager->save_inode(&inode_data); + + // disk->print_block(0); + // disk->print_block(1); + + // disk->print_block(1081); + + // disk->print_block(1596); + + // disk->print_block(1597); + + int err; + RawDisk *disk = new FakeRawDisk(2048); Fs *fs = new Fs(disk); fs->format(); disk->print_block(0); disk->print_block(1); - INode_Data inode_data = INode_Data(); + + INode_Data inode_data; fs->inode_manager->new_inode(1, 2, 3, &inode_data); - int err; - u_int64_t block_num = 0; - for (int i = 0; i < 56 + 512 + 4; ++i) - err = fs->allocate_datablock(&inode_data, &block_num); - - for (int i = 0; i < 5; ++i) - printf("%d\n", err = fs->deallocate_datablock(&inode_data, &block_num)); - - fs->inode_manager->save_inode(&inode_data); disk->print_block(0); disk->print_block(1); + int BL_SIZE = 4096 / 8; + + u_int64_t buf[BL_SIZE * (56 + 512 + 10)]; + + for (int i = 0; i < BL_SIZE * (56 + 512 + 10); ++i) + buf[i] = (i / BL_SIZE) + 1; + + err = fs->write(&inode_data, (char *)buf, 4096 * (56 + 3) + 16 + 8, 0); + fs->inode_manager->save_inode(&inode_data); + + printf("Write %d", err); + + disk->print_block(0); + disk->print_block(1); + disk->print_block(1025); + disk->print_block(1026); + disk->print_block(1027); + disk->print_block(1080); disk->print_block(1081); + disk->print_block(1082); + disk->print_block(1083); + disk->print_block(1084); + disk->print_block(1085); - disk->print_block(1596); + int N = 5; - disk->print_block(1597); + u_int64_t buf2[4096] = {0}; + err = fs->read(&inode_data, (char *)buf2, (8 * N), 4096 - 8 - 8); + + printf("\n\nREAD: %d\n", err); + for (int i = 0; i < N; ++i) + printf("%d ", buf2[i]); + printf("\n"); return 0; } \ No newline at end of file From 9e34e025a3459c0b22cb2282464d3f3ff0b081f8 Mon Sep 17 00:00:00 2001 From: FactorialN Date: Wed, 22 Nov 2023 23:52:05 -0800 Subject: [PATCH 13/13] fixed a constant to meet the current design --- include/fs_constants.hpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/fs_constants.hpp b/include/fs_constants.hpp index e74e3ba..8353020 100644 --- a/include/fs_constants.hpp +++ b/include/fs_constants.hpp @@ -18,6 +18,7 @@ #define INODE_SIZE 512 -#define DATABLOCKS_PER_BITMAP_BLOCK 255 +// TODO: explore the optimal value for this +#define DATABLOCKS_PER_BITMAP_BLOCK 2047 #endif \ No newline at end of file