temporary addition of inode/datablock allocation

This commit is contained in:
Connor 2023-11-14 22:24:00 -08:00
parent 85bf159ee0
commit 8c263f02b1
7 changed files with 233 additions and 53 deletions

View File

@ -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

View File

@ -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[]);

View File

@ -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 {

View File

@ -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;
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);
}
int DataBlock_Allocator_Bitmap::format() { return -1; }
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;
}

View File

@ -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;

View File

@ -1,22 +1,41 @@
#include "fs.hpp"
size_t write_u64(u_int64_t num, char buf[]) {
template <typename T> 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 <typename T> 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<u_int64_t>(num, buf);
}
size_t read_u64(u_int64_t *num, char buf[]) {
return read_int<u_int64_t>(num, buf);
}
size_t write_u32(u_int32_t num, char buf[]) {
return write_int<u_int32_t>(num, buf);
}
size_t read_u32(u_int32_t *num, char buf[]) {
return read_int<u_int32_t>(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;
}

View File

@ -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;
char buf[BLOCK_SIZE];
int err;
u_int64_t inode_num = fs->superblock.inode_list_head;
if(inode_num > max_num_inodes)
return -1;
}
int INode_Allocator_Freelist::free_inode(INode_Data *inode_data) { return -1; }
int INode_Allocator_Freelist::format() { 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;
}