added extra file io operations
This commit is contained in:
parent
81f81d8e80
commit
cadf11b857
@ -16,7 +16,7 @@ add_executable(fischl
|
|||||||
lib/fs/datablock_manager.cpp
|
lib/fs/datablock_manager.cpp
|
||||||
lib/fs/fs_data_types.cpp
|
lib/fs/fs_data_types.cpp
|
||||||
lib/fs/fs_resize.cpp
|
lib/fs/fs_resize.cpp
|
||||||
lib/fs/fs_read_write.cpp
|
lib/fs/fs_file_io.cpp
|
||||||
lib/fs/fs.cpp
|
lib/fs/fs.cpp
|
||||||
lib/fs/inode_manager.cpp
|
lib/fs/inode_manager.cpp
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#include "fs.hpp"
|
#include "fs.hpp"
|
||||||
|
|
||||||
DataBlock_Manager::DataBlock_Manager(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)
|
u_int64_t block_segment_end)
|
||||||
: fs(fs), block_segment_start(block_segment_start),
|
: fs(fs), block_segment_start(block_segment_start),
|
||||||
block_segment_end(block_segment_end) {}
|
block_segment_end(block_segment_end) {}
|
||||||
|
|
||||||
@ -122,6 +122,7 @@ int DataBlock_Manager_Bitmap::format() {
|
|||||||
char buf[IO_BLOCK_SIZE] = {0};
|
char buf[IO_BLOCK_SIZE] = {0};
|
||||||
int err;
|
int err;
|
||||||
u_int64_t i = block_segment_start;
|
u_int64_t i = block_segment_start;
|
||||||
|
write_u64(i, buf);
|
||||||
for (; i <= block_segment_end - (2 * bitmap_region_size);
|
for (; i <= block_segment_end - (2 * bitmap_region_size);
|
||||||
i += bitmap_region_size) {
|
i += bitmap_region_size) {
|
||||||
write_u64(i + bitmap_region_size, buf);
|
write_u64(i + bitmap_region_size, buf);
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
#include "fs.hpp"
|
#include "fs.hpp"
|
||||||
|
|
||||||
Fs::Fs(RawDisk *disk) : disk(disk) {
|
Fs::Fs(RawDisk *disk) : disk(disk) {
|
||||||
|
assert((disk->diskSize / IO_BLOCK_SIZE) >
|
||||||
|
2 + NUM_INODE_BLOCKS + DATABLOCKS_PER_BITMAP_BLOCK);
|
||||||
superblock = SuperBlock_Data();
|
superblock = SuperBlock_Data();
|
||||||
inode_manager = new INode_Manager_Freelist(this, 1, 1 + NUM_INODE_BLOCKS);
|
inode_manager = new INode_Manager_Freelist(this, 1, 1 + NUM_INODE_BLOCKS);
|
||||||
datablock_manager =
|
datablock_manager = new DataBlock_Manager_Bitmap(
|
||||||
new DataBlock_Manager_Bitmap(this, 1 + NUM_INODE_BLOCKS, NUM_BLOCKS);
|
this, 1 + NUM_INODE_BLOCKS, disk->diskSize / IO_BLOCK_SIZE);
|
||||||
};
|
};
|
||||||
|
|
||||||
Fs::~Fs() {
|
Fs::~Fs() {
|
||||||
|
@ -6,10 +6,24 @@ public:
|
|||||||
size_t count;
|
size_t count;
|
||||||
size_t offset;
|
size_t offset;
|
||||||
size_t bytes_completed;
|
size_t bytes_completed;
|
||||||
RawDisk *disk;
|
Fs *fs;
|
||||||
virtual int operation(u_int64_t block_num) = 0;
|
virtual int operation(u_int64_t block_num, bool *delete_block) = 0;
|
||||||
|
int (*skip)(DatablockOperation *, u_int64_t) = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
int default_skip_func(DatablockOperation *this_op, u_int64_t num_blocks) {
|
||||||
|
this_op->bytes_completed += (num_blocks * IO_BLOCK_SIZE) - this_op->offset;
|
||||||
|
this_op->offset = 0;
|
||||||
|
|
||||||
|
if (this_op->bytes_completed >= this_op->count)
|
||||||
|
return 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int pass_skip_func(DatablockOperation *this_op, u_int64_t num_blocks) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
int Fs::sweep_inode_datablocks(INode_Data *inode_data,
|
int Fs::sweep_inode_datablocks(INode_Data *inode_data,
|
||||||
u_int64_t start_block_index, bool allocate,
|
u_int64_t start_block_index, bool allocate,
|
||||||
DatablockOperation *op) {
|
DatablockOperation *op) {
|
||||||
@ -49,7 +63,7 @@ int Fs::sweep_inode_datablocks(INode_Data *inode_data,
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
return -1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// This can simply be made non recursive by copy pasting - it is just
|
// This can simply be made non recursive by copy pasting - it is just
|
||||||
@ -61,12 +75,30 @@ int Fs::sweep_datablocks(u_int64_t *block_num, int indirect_num,
|
|||||||
int err;
|
int err;
|
||||||
int result = -1;
|
int result = -1;
|
||||||
|
|
||||||
if (allocate && (*block_num) == 0)
|
u_int64_t indirect_block_size = 1;
|
||||||
if ((err = datablock_manager->new_datablock(block_num)) < 0)
|
for (int i = 1; i < indirect_num; ++i)
|
||||||
return err;
|
indirect_block_size *= IO_BLOCK_SIZE;
|
||||||
|
|
||||||
if (indirect_num == 0)
|
if ((*block_num) == 0) {
|
||||||
return op->operation(*block_num);
|
if (allocate) {
|
||||||
|
if ((err = datablock_manager->new_datablock(block_num)) < 0)
|
||||||
|
return err;
|
||||||
|
} else if (op->skip != nullptr) {
|
||||||
|
return (*(op->skip))(op, indirect_block_size * IO_BLOCK_SIZE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (indirect_num == 0) {
|
||||||
|
bool delete_block = false;
|
||||||
|
if ((result = op->operation(*block_num, &delete_block)) < 0)
|
||||||
|
return result;
|
||||||
|
if (delete_block) {
|
||||||
|
if ((err = datablock_manager->free_datablock(*block_num)) < 0)
|
||||||
|
return err;
|
||||||
|
(*block_num) = 0;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
if ((*block_num) == 0) {
|
if ((*block_num) == 0) {
|
||||||
memset(buf, 0, sizeof(buf));
|
memset(buf, 0, sizeof(buf));
|
||||||
@ -75,10 +107,6 @@ int Fs::sweep_datablocks(u_int64_t *block_num, int indirect_num,
|
|||||||
return err;
|
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 this_layer_start_index = start_block_index / indirect_block_size;
|
||||||
u_int64_t next_layer_start_index =
|
u_int64_t next_layer_start_index =
|
||||||
start_block_index - (indirect_block_size * this_layer_start_index);
|
start_block_index - (indirect_block_size * this_layer_start_index);
|
||||||
@ -102,16 +130,29 @@ int Fs::sweep_datablocks(u_int64_t *block_num, int indirect_num,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (modified)
|
if (modified) {
|
||||||
if ((err = disk->write_block(*block_num, buf)) < 0)
|
bool delete_block = true;
|
||||||
return err;
|
for (size_t i = 0; i < IO_BLOCK_SIZE; ++i)
|
||||||
|
if (buf[i] != 0) {
|
||||||
|
delete_block = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (delete_block) {
|
||||||
|
if ((err = datablock_manager->free_datablock(*block_num)) < 0)
|
||||||
|
return err;
|
||||||
|
(*block_num) = 0;
|
||||||
|
} else {
|
||||||
|
if ((err = disk->write_block(*block_num, buf)) < 0)
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
class ReadDatablockOperation : public DatablockOperation {
|
class ReadDatablockOperation : public DatablockOperation {
|
||||||
public:
|
public:
|
||||||
int operation(u_int64_t block_num) override {
|
int operation(u_int64_t block_num, bool *delete_block) override {
|
||||||
char datablock_buf[IO_BLOCK_SIZE];
|
char datablock_buf[IO_BLOCK_SIZE];
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
@ -122,7 +163,7 @@ public:
|
|||||||
std::min(IO_BLOCK_SIZE - offset, count - bytes_completed);
|
std::min(IO_BLOCK_SIZE - offset, count - bytes_completed);
|
||||||
|
|
||||||
if (block_num != 0) {
|
if (block_num != 0) {
|
||||||
if ((err = disk->read_block(block_num, datablock_buf)) < 0)
|
if ((err = fs->disk->read_block(block_num, datablock_buf)) < 0)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
memcpy(&buf[bytes_completed], &datablock_buf[offset], read_size);
|
memcpy(&buf[bytes_completed], &datablock_buf[offset], read_size);
|
||||||
@ -141,7 +182,7 @@ public:
|
|||||||
|
|
||||||
class WriteDatablockOperation : public DatablockOperation {
|
class WriteDatablockOperation : public DatablockOperation {
|
||||||
public:
|
public:
|
||||||
int operation(u_int64_t block_num) override {
|
int operation(u_int64_t block_num, bool *delete_block) override {
|
||||||
char datablock_buf[IO_BLOCK_SIZE];
|
char datablock_buf[IO_BLOCK_SIZE];
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
@ -149,12 +190,12 @@ public:
|
|||||||
std::min(IO_BLOCK_SIZE - offset, count - bytes_completed);
|
std::min(IO_BLOCK_SIZE - offset, count - bytes_completed);
|
||||||
|
|
||||||
if (write_size < IO_BLOCK_SIZE)
|
if (write_size < IO_BLOCK_SIZE)
|
||||||
if ((err = disk->read_block(block_num, datablock_buf)) < 0)
|
if ((err = fs->disk->read_block(block_num, datablock_buf)) < 0)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
memcpy(&datablock_buf[offset], &buf[bytes_completed], write_size);
|
memcpy(&datablock_buf[offset], &buf[bytes_completed], write_size);
|
||||||
|
|
||||||
if ((err = disk->write_block(block_num, datablock_buf)) < 0)
|
if ((err = fs->disk->write_block(block_num, datablock_buf)) < 0)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
offset = 0;
|
offset = 0;
|
||||||
@ -166,6 +207,42 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class TruncateDatablockOperation : public DatablockOperation {
|
||||||
|
public:
|
||||||
|
TruncateDatablockOperation() : skip(pass_skip_func) {}
|
||||||
|
int operation(u_int64_t block_num, bool *delete_block) override {
|
||||||
|
if (offset != 0)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
offset = 0;
|
||||||
|
|
||||||
|
delete_block = true;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class LseekNextDataDatablockOperation : public DatablockOperation {
|
||||||
|
public:
|
||||||
|
LseekNextDataDatablockOperation() : skip(default_skip_func) {}
|
||||||
|
int operation(u_int64_t block_num, bool *delete_block) override { return 0; }
|
||||||
|
};
|
||||||
|
|
||||||
|
class LseekNextHoleDatablockOperation : public DatablockOperation {
|
||||||
|
public:
|
||||||
|
int operation(u_int64_t block_num, bool *delete_block) override {
|
||||||
|
if (block_num == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
bytes_completed += (IO_BLOCK_SIZE)-offset;
|
||||||
|
offset = 0;
|
||||||
|
|
||||||
|
if (bytes_completed >= count)
|
||||||
|
return 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
ssize_t Fs::read(INode_Data *inode_data, char buf[], size_t count,
|
ssize_t Fs::read(INode_Data *inode_data, char buf[], size_t count,
|
||||||
size_t offset) {
|
size_t offset) {
|
||||||
int err;
|
int err;
|
||||||
@ -178,10 +255,10 @@ ssize_t Fs::read(INode_Data *inode_data, char buf[], size_t count,
|
|||||||
op.buf = buf;
|
op.buf = buf;
|
||||||
op.count = std::min(count, inode_data->metadata.size - offset);
|
op.count = std::min(count, inode_data->metadata.size - offset);
|
||||||
op.bytes_completed = 0;
|
op.bytes_completed = 0;
|
||||||
op.disk = disk;
|
op.fs = this;
|
||||||
|
|
||||||
if ((err = sweep_inode_datablocks(inode_data, start_block_index, false,
|
if ((err = sweep_inode_datablocks(inode_data, start_block_index, false,
|
||||||
&op)) < 0)
|
&op)) != 0)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
return op.bytes_completed;
|
return op.bytes_completed;
|
||||||
@ -199,14 +276,83 @@ ssize_t Fs::write(INode_Data *inode_data, char buf[], size_t count,
|
|||||||
op.buf = buf;
|
op.buf = buf;
|
||||||
op.count = count;
|
op.count = count;
|
||||||
op.bytes_completed = 0;
|
op.bytes_completed = 0;
|
||||||
op.disk = disk;
|
op.fs = this;
|
||||||
|
|
||||||
if ((err = sweep_inode_datablocks(inode_data, start_block_index, true, &op)) <
|
if ((err = sweep_inode_datablocks(inode_data, start_block_index, true,
|
||||||
0)
|
&op)) != 0)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
inode_data->metadata.size =
|
inode_data->metadata.size =
|
||||||
std::max(offset + op.bytes_completed, inode_data->metadata.size);
|
std::max(offset + op.bytes_completed, inode_data->metadata.size);
|
||||||
|
|
||||||
|
return op.bytes_completed;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Fs::truncate(INode_Data *inode_data, size_t length) {
|
||||||
|
int err;
|
||||||
|
|
||||||
|
u_int64_t start_block_index = length / IO_BLOCK_SIZE;
|
||||||
|
size_t internal_offset = length - (start_block_index * IO_BLOCK_SIZE);
|
||||||
|
|
||||||
|
TruncateDatablockOperation op = TruncateDatablockOperation();
|
||||||
|
op.offset = internal_offset;
|
||||||
|
op.fs = this;
|
||||||
|
|
||||||
|
if ((err = sweep_inode_datablocks(inode_data, start_block_index, false,
|
||||||
|
&op)) < 0)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
inode_data->metadata.size = length;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Fs::lseek_next_data(INode_Data *inode_data, size_t offset) {
|
||||||
|
int err;
|
||||||
|
|
||||||
|
if (offset >= inode_data->metadata.size)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
u_int64_t start_block_index = offset / IO_BLOCK_SIZE;
|
||||||
|
size_t internal_offset = offset - (start_block_index * IO_BLOCK_SIZE);
|
||||||
|
|
||||||
|
LseekNextDataDatablockOperation op = LseekNextDataDatablockOperation();
|
||||||
|
op.offset = internal_offset;
|
||||||
|
op.count = inode_data->metadata.size;
|
||||||
|
op.bytes_completed = offset;
|
||||||
|
op.fs = this;
|
||||||
|
|
||||||
|
if ((err = sweep_inode_datablocks(inode_data, start_block_index, false,
|
||||||
|
&op)) < 0)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
if (op.bytes_completed >= inode_data->metadata.size)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return op.bytes_completed;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Fs::lseek_next_hole(INode_Data *inode_data, size_t offset) {
|
||||||
|
int err;
|
||||||
|
|
||||||
|
if (offset >= inode_data->metadata.size)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
u_int64_t start_block_index = offset / IO_BLOCK_SIZE;
|
||||||
|
size_t internal_offset = offset - (start_block_index * IO_BLOCK_SIZE);
|
||||||
|
|
||||||
|
LseekNextHoleDatablockOperation op = LseekNextHoleDatablockOperation();
|
||||||
|
op.offset = internal_offset;
|
||||||
|
op.count = inode_data->metadata.size;
|
||||||
|
op.bytes_completed = offset;
|
||||||
|
op.fs = this;
|
||||||
|
|
||||||
|
if ((err = sweep_inode_datablocks(inode_data, start_block_index, false,
|
||||||
|
&op)) < 0)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
if (op.bytes_completed >= inode_data->metadata.size)
|
||||||
|
return inode_data->metadata.size;
|
||||||
|
|
||||||
return op.bytes_completed;
|
return op.bytes_completed;
|
||||||
}
|
}
|
@ -1,72 +1,5 @@
|
|||||||
#include "fs.hpp"
|
#include "fs.hpp"
|
||||||
|
|
||||||
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) {
|
|
||||||
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, datablock_num);
|
|
||||||
if (result <= 0)
|
|
||||||
return result;
|
|
||||||
|
|
||||||
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, datablock_num);
|
|
||||||
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, 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) {
|
|
||||||
(*datablock_num) = (*storage);
|
|
||||||
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, datablock_num);
|
|
||||||
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, u_int64_t *datablock_num) {
|
int Fs::deallocate_datablock(INode_Data *inode_data, u_int64_t *datablock_num) {
|
||||||
int result;
|
int result;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user