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; +} + +