added extra file io operations
This commit is contained in:
commit
f8b0ee2e8f
@ -6,7 +6,7 @@ set(CMAKE_CXX_STANDARD 14)
|
||||
include_directories(
|
||||
# fischl include files
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/googletest/googletest/include
|
||||
# ${CMAKE_CURRENT_SOURCE_DIR}/googletest/googletest/include
|
||||
)
|
||||
|
||||
add_executable(fischl
|
||||
@ -16,8 +16,7 @@ add_executable(fischl
|
||||
lib/rawdisk.cpp
|
||||
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_file_io.cpp
|
||||
lib/fs/fs.cpp
|
||||
lib/fs/inode_manager.cpp
|
||||
lib/files.cpp
|
||||
@ -27,7 +26,7 @@ add_executable(fischl
|
||||
|
||||
enable_testing()
|
||||
add_subdirectory(test)
|
||||
add_subdirectory(googletest)
|
||||
# add_subdirectory(googletest)
|
||||
|
||||
# Add the -Wall flag
|
||||
target_compile_options(fischl PRIVATE -Wall)
|
||||
|
@ -15,20 +15,12 @@ public:
|
||||
Fs(RawDisk *disk);
|
||||
~Fs();
|
||||
|
||||
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,
|
||||
ssize_t write(INode_Data *inode_data, const 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 truncate(INode_Data *inode_data, size_t length);
|
||||
ssize_t lseek_next_data(INode_Data *inode_data, size_t offset);
|
||||
ssize_t lseek_next_hole(INode_Data *inode_data, size_t offset);
|
||||
|
||||
int format();
|
||||
|
||||
@ -44,8 +36,13 @@ 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, u_int64_t *datablock_num);
|
||||
int deallocate_indirect(u_int64_t *storage, int n, u_int64_t *datablock_num);
|
||||
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);
|
||||
};
|
||||
|
||||
#endif
|
@ -15,7 +15,6 @@
|
||||
#define INDIRECT_BLOCKS 512
|
||||
|
||||
#define NUM_INODE_BLOCKS 1023
|
||||
#define NUM_BLOCKS 2048
|
||||
|
||||
#define INODE_SIZE 512
|
||||
|
||||
|
162
lib/files.cpp
162
lib/files.cpp
@ -2,9 +2,9 @@
|
||||
#define FUSE_USE_VERSION 31
|
||||
|
||||
#include "files.h"
|
||||
#include <string.h>
|
||||
#include <sstream>
|
||||
#include <cassert>
|
||||
#include <sstream>
|
||||
#include <string.h>
|
||||
|
||||
FileNode* FilesOperation::fischl_load_entry(TreeNode *root, const char *path){
|
||||
return fischl_find_entry(fs, root, path);
|
||||
@ -21,7 +21,8 @@ FilesOperation::FilesOperation(RawDisk& disk_, Fs* fs): disk(disk_) {
|
||||
this->fs = fs;
|
||||
}
|
||||
|
||||
void FilesOperation::create_dot_dotdot(INode_Data* inode, u_int64_t parent_inode_number) {
|
||||
void FilesOperation::create_dot_dotdot(INode_Data *inode,
|
||||
u_int64_t parent_inode_number) {
|
||||
char buffer[IO_BLOCK_SIZE] = {0};
|
||||
DirectoryEntry dot;
|
||||
dot.inode_number = inode->inode_num;
|
||||
@ -70,13 +71,15 @@ void FilesOperation::printDirectory(u_int64_t inode_number) {
|
||||
DirectoryEntry ent;
|
||||
for (int i = 0; i <= IO_BLOCK_SIZE - 264; i += 264) {
|
||||
ent.deserialize(buffer + i);
|
||||
if (ent.inode_number) printf("%s\t%llu;\t", ent.file_name, ent.inode_number);
|
||||
if (ent.inode_number)
|
||||
printf("%s\t%llu;\t", ent.file_name, ent.inode_number);
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
INode_Data* FilesOperation::create_new_inode(u_int64_t parent_inode_number, const char* name, mode_t mode) {
|
||||
INode_Data *FilesOperation::create_new_inode(u_int64_t parent_inode_number,
|
||||
const char *name, mode_t mode) {
|
||||
// trys to create a file under parent directory
|
||||
if (strlen(name) >= 256) {
|
||||
perror("Name too long, cannot create file or directory");
|
||||
@ -86,7 +89,8 @@ INode_Data* FilesOperation::create_new_inode(u_int64_t parent_inode_number, cons
|
||||
inode.inode_num = parent_inode_number;
|
||||
fs->inode_manager->load_inode(&inode);
|
||||
if ((inode.metadata.permissions & S_IFMT) != S_IFDIR) {
|
||||
fprintf(stderr,"[%s ,%d] please create under directory\n",__func__,__LINE__);
|
||||
fprintf(stderr, "[%s ,%d] please create under directory\n", __func__,
|
||||
__LINE__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -99,9 +103,11 @@ INode_Data* FilesOperation::create_new_inode(u_int64_t parent_inode_number, cons
|
||||
ent.deserialize(r_buffer + i);
|
||||
if (strcmp(ent.file_name, name) == 0 && ent.inode_number != 0) {
|
||||
if ((mode & S_IFMT) == S_IFDIR) {
|
||||
fprintf(stderr,"[%s ,%d] %s/ already exists\n",__func__,__LINE__, name);
|
||||
fprintf(stderr, "[%s ,%d] %s/ already exists\n", __func__, __LINE__,
|
||||
name);
|
||||
} else {
|
||||
fprintf(stderr,"[%s ,%d] %s already exists\n",__func__,__LINE__, name);
|
||||
fprintf(stderr, "[%s ,%d] %s already exists\n", __func__, __LINE__,
|
||||
name);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
@ -143,7 +149,8 @@ INode_Data* FilesOperation::create_new_inode(u_int64_t parent_inode_number, cons
|
||||
ent.inode_number = new_inode->inode_num;
|
||||
strcpy(ent.file_name, name);
|
||||
ent.serialize(write_buffer);
|
||||
fs->write(&inode, write_buffer, IO_BLOCK_SIZE, (inode.metadata.size/IO_BLOCK_SIZE)*IO_BLOCK_SIZE);
|
||||
fs->write(&inode, write_buffer, IO_BLOCK_SIZE,
|
||||
(inode.metadata.size / IO_BLOCK_SIZE) * IO_BLOCK_SIZE);
|
||||
fs->inode_manager->save_inode(&inode);
|
||||
}
|
||||
|
||||
@ -165,8 +172,10 @@ u_int64_t FilesOperation::disk_namei(const char* path) {
|
||||
INode_Data inode;
|
||||
inode.inode_num = current_inode;
|
||||
fs->inode_manager->load_inode(&inode);
|
||||
if ((inode.metadata.permissions & S_IFMT) != S_IFDIR || inode.metadata.size == 0) {
|
||||
printf("disk_namei: %s is not a non-empty directory\n", current_dirname.c_str());
|
||||
if ((inode.metadata.permissions & S_IFMT) != S_IFDIR ||
|
||||
inode.metadata.size == 0) {
|
||||
printf("disk_namei: %s is not a non-empty directory\n",
|
||||
current_dirname.c_str());
|
||||
return -1;
|
||||
}
|
||||
u_int64_t new_inode_number = 0;
|
||||
@ -182,21 +191,23 @@ u_int64_t FilesOperation::disk_namei(const char* path) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (new_inode_number) break;
|
||||
if (new_inode_number)
|
||||
break;
|
||||
}
|
||||
if (!new_inode_number) {
|
||||
printf("disk_namei: no name matching %s under directory %s\n", new_name.c_str(), current_dirname.c_str());
|
||||
printf("disk_namei: no name matching %s under directory %s\n",
|
||||
new_name.c_str(), current_dirname.c_str());
|
||||
return -1;
|
||||
}
|
||||
current_inode = new_inode_number;
|
||||
current_dirname = new_name;
|
||||
}
|
||||
return current_inode;
|
||||
// path = "/" should return root_inode_number (root_node->self_info->inode_number)
|
||||
// path = "/foo.txt" should return inode for foo.txt
|
||||
// path = "/mydir" should return inode for mydir
|
||||
// path = "/nonemptydir/foo" should return inode for foo
|
||||
// path = "/notnonemptydir/foo" should raise error
|
||||
// path = "/" should return root_inode_number
|
||||
// (root_node->self_info->inode_number) path = "/foo.txt" should return inode
|
||||
// for foo.txt path = "/mydir" should return inode for mydir path =
|
||||
// "/nonemptydir/foo" should return inode for foo path = "/notnonemptydir/foo"
|
||||
// should raise error
|
||||
}
|
||||
|
||||
u_int64_t FilesOperation::namei(const char* path) {
|
||||
@ -284,9 +295,12 @@ int FilesOperation::fischl_mkdir(const char* path, mode_t mode) {
|
||||
// check path
|
||||
char *pathdup = strdup(path);
|
||||
char *lastSlash = strrchr(pathdup, '/');
|
||||
*lastSlash = '\0'; // Split the string into parent path and new directory name; <parent path>\0<direcotry name>
|
||||
char *newDirname = lastSlash+1; //\0<direcotry name>, get from <direcotry name>
|
||||
char *ParentPath = pathdup;//pathdup are separated by pathdup, so it take <parent path> only
|
||||
*lastSlash = '\0'; // Split the string into parent path and new directory
|
||||
// name; <parent path>\0<direcotry name>
|
||||
char *newDirname =
|
||||
lastSlash + 1; //\0<direcotry name>, get from <direcotry name>
|
||||
char *ParentPath = pathdup; // pathdup are separated by pathdup, so it take
|
||||
// <parent path> only
|
||||
|
||||
FileNode *parent_filenode = strlen(ParentPath)? fischl_load_entry(root_node, ParentPath): root_node->self_info;
|
||||
if (parent_filenode == NULL) {
|
||||
@ -368,7 +382,8 @@ int FilesOperation::fischl_create(const char* path, mode_t mode, struct fuse_fil
|
||||
return 0;//SUCESS
|
||||
}
|
||||
|
||||
int FilesOperation::fischl_getattr(const char *path, struct stat *stbuf, struct fuse_file_info *fi) {
|
||||
int FilesOperation::fischl_getattr(const char *path, struct stat *stbuf,
|
||||
struct fuse_file_info *fi) {
|
||||
|
||||
(void)fi;
|
||||
int res = 0;
|
||||
@ -417,7 +432,10 @@ int FilesOperation::fischl_getattr(const char *path, struct stat *stbuf, struct
|
||||
return res;
|
||||
}
|
||||
|
||||
int FilesOperation::fischl_readdir(const char *path, void *buf, fuse_fill_dir_t filler, off_t ft, struct fuse_file_info *fi, enum fuse_readdir_flags flg) {
|
||||
int FilesOperation::fischl_readdir(const char *path, void *buf,
|
||||
fuse_fill_dir_t filler, off_t ft,
|
||||
struct fuse_file_info *fi,
|
||||
enum fuse_readdir_flags flg) {
|
||||
// check path
|
||||
u_int64_t fh = namei(path);
|
||||
|
||||
@ -470,24 +488,15 @@ void FilesOperation::unlink_inode(u_int64_t inode_number) {
|
||||
fs->read(&inode, buffer, IO_BLOCK_SIZE, idx * IO_BLOCK_SIZE);
|
||||
DirectoryEntry ent;
|
||||
for (int i = 0; i <= IO_BLOCK_SIZE - 264; i += 264) {
|
||||
if(ent.inode_number && strcmp(ent.file_name,".") && strcmp(ent.file_name,"..")){
|
||||
if (ent.inode_number && strcmp(ent.file_name, ".") &&
|
||||
strcmp(ent.file_name, "..")) {
|
||||
unlink_inode(ent.inode_number);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// TODO: This is probably incorrect
|
||||
// size is unsigned int
|
||||
while(inode.metadata.size != 0) {
|
||||
printf("dealloc, %d\n", inode.metadata.size);
|
||||
u_int64_t dummy;
|
||||
fs->deallocate_datablock(&inode, &dummy);
|
||||
if (inode.metadata.size < IO_BLOCK_SIZE){
|
||||
inode.metadata.size = 0;
|
||||
break;
|
||||
}
|
||||
inode.metadata.size-=IO_BLOCK_SIZE;
|
||||
}
|
||||
// TODO: error handling
|
||||
int res = fs->truncate(&inode, 0);
|
||||
fs->inode_manager->free_inode(&inode);
|
||||
}
|
||||
|
||||
@ -570,7 +579,8 @@ int FilesOperation::fischl_rmdir(const char* path) {
|
||||
}
|
||||
}
|
||||
|
||||
int FilesOperation::fischl_chmod(const char *path, mode_t mode, struct fuse_file_info *fi) {
|
||||
int FilesOperation::fischl_chmod(const char *path, mode_t mode,
|
||||
struct fuse_file_info *fi) {
|
||||
(void)fi;
|
||||
int res = 0;
|
||||
u_int64_t fh = namei(path);
|
||||
@ -587,7 +597,8 @@ int FilesOperation::fischl_chmod(const char *path, mode_t mode, struct fuse_file
|
||||
return 0;
|
||||
}
|
||||
|
||||
int FilesOperation::fischl_chown(const char *path, uid_t uid, gid_t gid, struct fuse_file_info *fi) {
|
||||
int FilesOperation::fischl_chown(const char *path, uid_t uid, gid_t gid,
|
||||
struct fuse_file_info *fi) {
|
||||
(void)fi;
|
||||
int res = 0;
|
||||
u_int64_t fh = namei(path);
|
||||
@ -892,7 +903,8 @@ int FilesOperation::insert_inode_to(u_int64_t parent_inode_number, const char* n
|
||||
ent.inode_number = new_inode->inode_num;
|
||||
strcpy(ent.file_name, name);
|
||||
ent.serialize(write_buffer);
|
||||
fs->write(&inode, write_buffer, IO_BLOCK_SIZE, (inode.metadata.size/IO_BLOCK_SIZE)*IO_BLOCK_SIZE);
|
||||
fs->write(&inode, write_buffer, IO_BLOCK_SIZE,
|
||||
(inode.metadata.size / IO_BLOCK_SIZE) * IO_BLOCK_SIZE);
|
||||
fs->inode_manager->save_inode(&inode);
|
||||
}
|
||||
|
||||
@ -1109,7 +1121,8 @@ int FilesOperation::fischl_rename(const char *old_path, const char *new_path, un
|
||||
return 0;
|
||||
}
|
||||
|
||||
int FilesOperation::fischl_truncate(const char *path, off_t offset, struct fuse_file_info *fi){
|
||||
int FilesOperation::fischl_truncate(const char *path, off_t offset,
|
||||
struct fuse_file_info *fi) {
|
||||
(void)fi;
|
||||
int res = 0;
|
||||
u_int64_t fh = namei(path);
|
||||
@ -1139,7 +1152,8 @@ int FilesOperation::fischl_truncate(const char *path, off_t offset, struct fuse_
|
||||
return 0;
|
||||
}
|
||||
|
||||
int FilesOperation::fischl_read(const char *path, char *buf, size_t size, off_t offset, struct fuse_file_info *fi){
|
||||
int FilesOperation::fischl_read(const char *path, char *buf, size_t size,
|
||||
off_t offset, struct fuse_file_info *fi) {
|
||||
/** Read data from an open file
|
||||
*
|
||||
* Read should return exactly the number of bytes requested except
|
||||
@ -1149,35 +1163,69 @@ int FilesOperation::fischl_read(const char *path, char *buf, size_t size, off_t
|
||||
* value of the read system call will reflect the return value of
|
||||
* this operation.
|
||||
*/
|
||||
// Caution! this based on content in file are multiple of IO_BLOCK_SIZE, not the exact write size.
|
||||
// based on current read_datablock API implement, when read_datablock pass with actual size not index this function should be fixed
|
||||
// Caution! this based on content in file are multiple of IO_BLOCK_SIZE, not
|
||||
// the exact write size. based on current read_datablock API implement, when
|
||||
// read_datablock pass with actual size not index this function should be
|
||||
// fixed
|
||||
INode_Data inode;
|
||||
// Assuming inode is correctly initialized here based on 'path'
|
||||
inode.inode_num = fi->fh;
|
||||
fs->inode_manager->load_inode(&inode);
|
||||
size_t bytes_read = fs->read(&inode, buf, size, offset);
|
||||
/*size_t len = (inode.metadata.size/IO_BLOCK_SIZE) * IO_BLOCK_SIZE; // Assuming each block is 4096 bytes
|
||||
/*size_t len = (inode.metadata.size/IO_BLOCK_SIZE) * IO_BLOCK_SIZE; //
|
||||
Assuming each block is 4096 bytes
|
||||
|
||||
if (offset >= len) return 0; // Offset is beyond the end of the file
|
||||
if (offset + size > len) size = len - offset; // Adjust size if it goes beyond EOF
|
||||
if (offset + size > len) size = len - offset; // Adjust size if it goes
|
||||
beyond EOF
|
||||
|
||||
size_t bytes_read = 0;
|
||||
size_t block_index = offset / IO_BLOCK_SIZE; // Starting block index
|
||||
size_t block_offset = offset % IO_BLOCK_SIZE; // Offset within the first block
|
||||
// fprintf(stderr,"[%s ,%d] inode.metadata.size %d\n",__func__,__LINE__, inode.metadata.size);
|
||||
while (bytes_read < size && block_index < inode.metadata.size/IO_BLOCK_SIZE) {
|
||||
char block_buffer[IO_BLOCK_SIZE]; // Temporary buffer for each block
|
||||
fs->read(&inode, block_buffer, IO_BLOCK_SIZE, block_index*IO_BLOCK_SIZE);
|
||||
// fprintf(stderr,"[%s ,%d] block_index %d\n",__func__,__LINE__, block_index);
|
||||
size_t copy_size = std::min(size - bytes_read, IO_BLOCK_SIZE - block_offset);
|
||||
memcpy(buf + bytes_read, block_buffer + block_offset, copy_size);
|
||||
// fprintf(stderr,"[%s ,%d] buf %s, block_buffer %s\n",__func__,__LINE__, buf, block_buffer);
|
||||
bytes_read += copy_size;
|
||||
block_index++;
|
||||
block_offset = 0; // Only the first block might have a non-zero offset
|
||||
// fprintf(stderr,"[%s ,%d] inode.metadata.size %d\n",__func__,__LINE__,
|
||||
inode.metadata.size); while (bytes_read < size && block_index <
|
||||
inode.metadata.size/IO_BLOCK_SIZE) { char block_buffer[IO_BLOCK_SIZE]; //
|
||||
Temporary buffer for each block fs->read(&inode, block_buffer, IO_BLOCK_SIZE,
|
||||
block_index*IO_BLOCK_SIZE);
|
||||
// fprintf(stderr,"[%s ,%d] block_index %d\n",__func__,__LINE__,
|
||||
block_index); size_t copy_size = std::min(size - bytes_read, IO_BLOCK_SIZE -
|
||||
block_offset); memcpy(buf + bytes_read, block_buffer + block_offset,
|
||||
copy_size);
|
||||
// fprintf(stderr,"[%s ,%d] buf %s, block_buffer %s\n",__func__,__LINE__,
|
||||
buf, block_buffer); bytes_read += copy_size; block_index++; block_offset = 0;
|
||||
// Only the first block might have a non-zero offset
|
||||
}*/
|
||||
|
||||
return bytes_read; // Return the actual number of bytes read
|
||||
r
|
||||
eturn bytes_read; // Return the actual number of bytes read
|
||||
}
|
||||
|
||||
int FilesOperation::fischl_utimens(const char *path, const struct timespec tv[2], struct fuse_file_info *fi){
|
||||
(void) fi;
|
||||
int res = 0;
|
||||
u_int64_t fh = namei(path);
|
||||
|
||||
if (fh == -1){
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
INode_Data inode;
|
||||
inode.inode_num = fh;
|
||||
fs->inode_manager->load_inode(&inode);
|
||||
inode.metadata.access_time = (u_int64_t)tv[0].tv_sec * 1000000000ULL + tv[0].tv_nsec;
|
||||
inode.metadata.modification_time = (u_int64_t)tv[1].tv_sec * 1000000000ULL + tv[1].tv_nsec;
|
||||
fs->inode_manager->save_inode(&inode);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int FilesOperation::fischl_statfs(const char* path, struct statvfs* stbuf) {
|
||||
stbuf->f_bsize = 4096;
|
||||
stbuf->f_blocks = 0;
|
||||
stbuf->f_bfree = 0;
|
||||
stbuf->f_files = 0;
|
||||
stbuf->f_ffree = 0;
|
||||
stbuf->f_namemax = 256;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int FilesOperation::fischl_utimens(const char *path, const struct timespec tv[2], struct fuse_file_info *fi){
|
||||
|
@ -58,6 +58,10 @@ int DataBlock_Manager_Bitmap::new_datablock(u_int64_t *block_num) {
|
||||
if ((err = fs->disk->read_block(bitmap_block_num, bitmap.buf)) < 0)
|
||||
return err;
|
||||
|
||||
// if (bitmap.get_next_node() == fs->superblock.free_list_head)
|
||||
// printf("WARNING: ON LAST BITMAP "
|
||||
// "BLOCK!\n");
|
||||
|
||||
u_int64_t relative_block_num = bitmap.claim_relative_block();
|
||||
|
||||
if (relative_block_num == 0)
|
||||
@ -122,6 +126,7 @@ int DataBlock_Manager_Bitmap::format() {
|
||||
char buf[IO_BLOCK_SIZE] = {0};
|
||||
int err;
|
||||
u_int64_t i = block_segment_start;
|
||||
write_u64(i, buf);
|
||||
for (; i <= block_segment_end - (2 * bitmap_region_size);
|
||||
i += bitmap_region_size) {
|
||||
write_u64(i + bitmap_region_size, buf);
|
||||
|
@ -1,10 +1,13 @@
|
||||
#include "fs.hpp"
|
||||
#include <assert.h>
|
||||
|
||||
Fs::Fs(RawDisk *disk) : disk(disk) {
|
||||
assert((disk->diskSize / IO_BLOCK_SIZE) >
|
||||
2 + NUM_INODE_BLOCKS + DATABLOCKS_PER_BITMAP_BLOCK);
|
||||
superblock = SuperBlock_Data();
|
||||
inode_manager = new INode_Manager_Freelist(this, 1, 1 + NUM_INODE_BLOCKS);
|
||||
datablock_manager =
|
||||
new DataBlock_Manager_Bitmap(this, 1 + NUM_INODE_BLOCKS, disk->diskSize/IO_BLOCK_SIZE);
|
||||
datablock_manager = new DataBlock_Manager_Bitmap(
|
||||
this, 1 + NUM_INODE_BLOCKS, disk->diskSize / IO_BLOCK_SIZE);
|
||||
};
|
||||
|
||||
Fs::~Fs() {
|
||||
|
382
lib/fs/fs_file_io.cpp
Normal file
382
lib/fs/fs_file_io.cpp
Normal file
@ -0,0 +1,382 @@
|
||||
#include "fs.hpp"
|
||||
|
||||
class DatablockOperation {
|
||||
public:
|
||||
DatablockOperation(int (*_skip)(DatablockOperation *, u_int64_t) = nullptr)
|
||||
: skip(_skip) {}
|
||||
size_t count;
|
||||
size_t offset;
|
||||
size_t bytes_completed;
|
||||
Fs *fs;
|
||||
virtual int operation(u_int64_t block_num, bool *delete_block) = 0;
|
||||
int (*skip)(DatablockOperation *, u_int64_t);
|
||||
};
|
||||
|
||||
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 truncate_skip_func(DatablockOperation *this_op, u_int64_t num_blocks) {
|
||||
this_op->offset = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
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 < INDIRECT_BLOCKS) {
|
||||
if ((result = sweep_datablocks(&(inode_data->single_indirect_block), 1,
|
||||
start_index, allocate, op)) <= 0)
|
||||
return result;
|
||||
start_index = INDIRECT_BLOCKS;
|
||||
}
|
||||
|
||||
start_index -= INDIRECT_BLOCKS;
|
||||
|
||||
if (start_index < INDIRECT_BLOCKS * INDIRECT_BLOCKS) {
|
||||
if ((result = sweep_datablocks(&(inode_data->double_indirect_block), 2,
|
||||
start_index, allocate, op)) <= 0)
|
||||
return result;
|
||||
start_index = INDIRECT_BLOCKS * INDIRECT_BLOCKS;
|
||||
}
|
||||
|
||||
start_index -= INDIRECT_BLOCKS * INDIRECT_BLOCKS;
|
||||
|
||||
if (start_index <
|
||||
(u_int64_t)INDIRECT_BLOCKS * INDIRECT_BLOCKS * INDIRECT_BLOCKS) {
|
||||
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 num_blocks_indirect;
|
||||
u_int64_t num_blocks = 1;
|
||||
for (int i = 0; i < indirect_num; ++i) {
|
||||
num_blocks_indirect = num_blocks;
|
||||
num_blocks *= INDIRECT_BLOCKS;
|
||||
}
|
||||
|
||||
if ((*block_num) == 0) {
|
||||
if (allocate) {
|
||||
if ((err = datablock_manager->new_datablock(block_num)) < 0)
|
||||
return err;
|
||||
} else if (op->skip != nullptr) {
|
||||
return (*(op->skip))(op, num_blocks);
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
memset(buf, 0, sizeof(buf));
|
||||
} else {
|
||||
if ((err = disk->read_block(*block_num, buf)) < 0)
|
||||
return err;
|
||||
}
|
||||
|
||||
u_int64_t this_layer_start_index = start_block_index / num_blocks_indirect;
|
||||
u_int64_t next_layer_start_index =
|
||||
start_block_index - (num_blocks_indirect * 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, op)) < 0)
|
||||
return result;
|
||||
if (next_block_num != temp) {
|
||||
write_u64(next_block_num, &buf[i]);
|
||||
modified = true;
|
||||
}
|
||||
if (result == 0)
|
||||
break;
|
||||
next_layer_start_index = 0;
|
||||
}
|
||||
|
||||
if (modified) {
|
||||
bool delete_block = true;
|
||||
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;
|
||||
}
|
||||
|
||||
class ReadDatablockOperation : public DatablockOperation {
|
||||
public:
|
||||
char *buf;
|
||||
ReadDatablockOperation() : DatablockOperation() {}
|
||||
int operation(u_int64_t block_num, bool *delete_block) override {
|
||||
char datablock_buf[IO_BLOCK_SIZE];
|
||||
int err;
|
||||
|
||||
size_t read_size =
|
||||
std::min(IO_BLOCK_SIZE - offset, count - bytes_completed);
|
||||
|
||||
if (block_num != 0) {
|
||||
if ((err = fs->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:
|
||||
const char *buf;
|
||||
WriteDatablockOperation() : DatablockOperation() {}
|
||||
int operation(u_int64_t block_num, bool *delete_block) override {
|
||||
char datablock_buf[IO_BLOCK_SIZE];
|
||||
int err;
|
||||
|
||||
size_t write_size =
|
||||
std::min(IO_BLOCK_SIZE - offset, count - bytes_completed);
|
||||
|
||||
if (write_size < IO_BLOCK_SIZE)
|
||||
if ((err = fs->disk->read_block(block_num, datablock_buf)) < 0)
|
||||
return err;
|
||||
|
||||
memcpy(&datablock_buf[offset], &buf[bytes_completed], write_size);
|
||||
|
||||
if ((err = fs->disk->write_block(block_num, datablock_buf)) < 0)
|
||||
return err;
|
||||
|
||||
offset = 0;
|
||||
bytes_completed += write_size;
|
||||
|
||||
if (bytes_completed >= count)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
|
||||
class TruncateDatablockOperation : public DatablockOperation {
|
||||
public:
|
||||
TruncateDatablockOperation() : DatablockOperation(truncate_skip_func) {}
|
||||
int operation(u_int64_t block_num, bool *delete_block) override {
|
||||
char datablock_buf[IO_BLOCK_SIZE];
|
||||
int err;
|
||||
|
||||
if (offset == 0) {
|
||||
(*delete_block) = true;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ((err = fs->disk->read_block(block_num, datablock_buf)) < 0)
|
||||
return err;
|
||||
|
||||
memset(&datablock_buf[offset], 0, IO_BLOCK_SIZE - offset);
|
||||
|
||||
if ((err = fs->disk->write_block(block_num, datablock_buf)) < 0)
|
||||
return err;
|
||||
|
||||
offset = 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
|
||||
class LseekNextDataDatablockOperation : public DatablockOperation {
|
||||
public:
|
||||
LseekNextDataDatablockOperation() : DatablockOperation(default_skip_func) {}
|
||||
int operation(u_int64_t block_num, bool *delete_block) override { return 0; }
|
||||
};
|
||||
|
||||
class LseekNextHoleDatablockOperation : public DatablockOperation {
|
||||
public:
|
||||
LseekNextHoleDatablockOperation() : DatablockOperation() {}
|
||||
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,
|
||||
size_t offset) {
|
||||
int err;
|
||||
|
||||
if (offset >= inode_data->metadata.size)
|
||||
return 0;
|
||||
|
||||
u_int64_t start_block_index = offset / IO_BLOCK_SIZE;
|
||||
size_t internal_offset = offset - (start_block_index * IO_BLOCK_SIZE);
|
||||
|
||||
ReadDatablockOperation op = ReadDatablockOperation();
|
||||
op.offset = internal_offset;
|
||||
op.buf = buf;
|
||||
op.count = std::min(count, inode_data->metadata.size - offset);
|
||||
op.bytes_completed = 0;
|
||||
op.fs = this;
|
||||
|
||||
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, const 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 - (start_block_index * IO_BLOCK_SIZE);
|
||||
|
||||
WriteDatablockOperation op = WriteDatablockOperation();
|
||||
op.offset = internal_offset;
|
||||
op.buf = buf;
|
||||
op.count = count;
|
||||
op.bytes_completed = 0;
|
||||
op.fs = this;
|
||||
|
||||
if ((err = sweep_inode_datablocks(inode_data, start_block_index, true,
|
||||
&op)) != 0)
|
||||
return err;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
ssize_t 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;
|
||||
}
|
||||
|
||||
ssize_t 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;
|
||||
}
|
@ -1,215 +0,0 @@
|
||||
#include "fs.hpp"
|
||||
|
||||
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 < INDIRECT_BLOCKS) {
|
||||
if ((result = sweep_datablocks(&(inode_data->single_indirect_block), 1,
|
||||
start_index, allocate, op)) <= 0)
|
||||
return result;
|
||||
start_index = INDIRECT_BLOCKS;
|
||||
}
|
||||
|
||||
start_index -= INDIRECT_BLOCKS;
|
||||
|
||||
if (start_index < INDIRECT_BLOCKS * INDIRECT_BLOCKS) {
|
||||
if ((result = sweep_datablocks(&(inode_data->double_indirect_block), 2,
|
||||
start_index, allocate, op)) <= 0)
|
||||
return result;
|
||||
start_index = INDIRECT_BLOCKS * INDIRECT_BLOCKS;
|
||||
}
|
||||
|
||||
start_index -= INDIRECT_BLOCKS * INDIRECT_BLOCKS;
|
||||
|
||||
if (start_index < (u_int64_t)INDIRECT_BLOCKS * INDIRECT_BLOCKS * INDIRECT_BLOCKS) {
|
||||
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;
|
||||
|
||||
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 *= INDIRECT_BLOCKS;
|
||||
|
||||
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, op)) < 0)
|
||||
return result;
|
||||
if (next_block_num != temp) {
|
||||
write_u64(next_block_num, &buf[i]);
|
||||
modified = true;
|
||||
}
|
||||
if (result == 0)
|
||||
break;
|
||||
next_layer_start_index = 0;
|
||||
}
|
||||
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;
|
||||
|
||||
// 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)
|
||||
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 =
|
||||
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;
|
||||
|
||||
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 - (start_block_index * IO_BLOCK_SIZE);
|
||||
|
||||
ReadDatablockOperation op = ReadDatablockOperation();
|
||||
op.offset = internal_offset;
|
||||
op.buf = buf;
|
||||
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)
|
||||
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 - (start_block_index * IO_BLOCK_SIZE);
|
||||
|
||||
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)) <
|
||||
0)
|
||||
return err;
|
||||
|
||||
inode_data->metadata.size =
|
||||
std::max(offset + op.bytes_completed, inode_data->metadata.size);
|
||||
|
||||
return op.bytes_completed;
|
||||
}
|
@ -1,141 +0,0 @@
|
||||
#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 result;
|
||||
|
||||
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,
|
||||
datablock_num);
|
||||
if (result <= 0)
|
||||
return result;
|
||||
|
||||
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) {
|
||||
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,
|
||||
u_int64_t *datablock_num) {
|
||||
char buf[IO_BLOCK_SIZE];
|
||||
int result;
|
||||
|
||||
if (*storage == 0)
|
||||
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;
|
||||
}
|
||||
|
||||
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, datablock_num);
|
||||
if (result < 0)
|
||||
return result;
|
||||
if (result == 0) {
|
||||
if (i == 0 && temp == 0) {
|
||||
if ((result = datablock_manager->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;
|
||||
}
|
304
lib/main.cpp
304
lib/main.cpp
@ -1,6 +1,12 @@
|
||||
#define _GNU_SOURCE
|
||||
|
||||
#include "fischl.h"
|
||||
#include "fs.hpp"
|
||||
#include <assert.h>
|
||||
#include <fcntl.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
// printf("hello word!");
|
||||
@ -34,56 +40,284 @@ int main(int argc, char *argv[]) {
|
||||
|
||||
// disk->print_block(1597);
|
||||
|
||||
/*
|
||||
int err;
|
||||
// return 0;
|
||||
|
||||
RawDisk *disk = new FakeRawDisk(2048);
|
||||
// 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;
|
||||
// fs->inode_manager->new_inode(1, 2, 3, &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);
|
||||
|
||||
// int N = 5;
|
||||
|
||||
// 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");
|
||||
|
||||
// u_int64_t big_buf[BL_SIZE * 1000];
|
||||
// char *buf = (char *)big_buf;
|
||||
|
||||
// int offs = 55 * 4096;
|
||||
|
||||
// RawDisk *disk = new FakeRawDisk(2048);
|
||||
// Fs *fs = new Fs(disk);
|
||||
|
||||
// fs->format();
|
||||
// disk->print_block(0);
|
||||
// disk->print_block(1);
|
||||
|
||||
// INode_Data inode_data;
|
||||
// fs->inode_manager->new_inode(1, 2, 3, &inode_data);
|
||||
|
||||
// disk->print_block(0);
|
||||
// disk->print_block(1);
|
||||
// disk->print_block(1024);
|
||||
|
||||
// for (int i = 0; i < BL_SIZE * 3; ++i)
|
||||
// big_buf[i] = 1;
|
||||
|
||||
// err = fs->write(&inode_data, buf, 4096 * 3, offs);
|
||||
|
||||
// for (int i = 0; i < BL_SIZE * 3; ++i)
|
||||
// big_buf[i] = 2;
|
||||
|
||||
// err = fs->truncate(&inode_data, offs + 4096);
|
||||
// err = fs->write(&inode_data, buf, 4096 * 2, offs + 4096 * 2);
|
||||
// err = fs->truncate(&inode_data, offs + 4096 * 2);
|
||||
|
||||
// fs->inode_manager->save_inode(&inode_data);
|
||||
// printf("Write %d", err);
|
||||
|
||||
// disk->print_block(0);
|
||||
// disk->print_block(1);
|
||||
// disk->print_block(1024);
|
||||
// disk->print_block(1025);
|
||||
// disk->print_block(1026);
|
||||
// disk->print_block(1027);
|
||||
// disk->print_block(1028);
|
||||
// disk->print_block(1029);
|
||||
// // disk->print_block(1080);
|
||||
// // disk->print_block(1081);
|
||||
// // disk->print_block(1082);
|
||||
// // disk->print_block(1083);
|
||||
// // disk->print_block(1084);
|
||||
// // disk->print_block(1085);
|
||||
|
||||
// // err = fs->truncate(&inode_data, 4096 + 4);
|
||||
// // fs->inode_manager->save_inode(&inode_data);
|
||||
// // printf("Truncate %d", err);
|
||||
|
||||
// // disk->print_block(0);
|
||||
// // disk->print_block(1);
|
||||
// // disk->print_block(1024);
|
||||
// // disk->print_block(1025);
|
||||
// // disk->print_block(1026);
|
||||
// // disk->print_block(1027);
|
||||
// // disk->print_block(1028);
|
||||
|
||||
// err = fs->lseek_next_hole(&inode_data, offs + 0);
|
||||
// printf("lseek_next_hole (%d): %d\n\n", offs + 0, err);
|
||||
// err = fs->lseek_next_hole(&inode_data, offs + 1);
|
||||
// printf("lseek_next_hole (%d): %d\n\n", offs + 1, err);
|
||||
// err = fs->lseek_next_hole(&inode_data, offs + 4096);
|
||||
// printf("lseek_next_hole (%d): %d\n\n", offs + 4096, err);
|
||||
// err = fs->lseek_next_hole(&inode_data, offs + 4097);
|
||||
// printf("lseek_next_hole (%d): %d\n\n", offs + 4097, err);
|
||||
// err = fs->lseek_next_hole(&inode_data, offs + 8192);
|
||||
// printf("lseek_next_hole (%d): %d\n\n", offs + 8192, err);
|
||||
// err = fs->lseek_next_hole(&inode_data, offs + 8193);
|
||||
// printf("lseek_next_hole (%d): %d\n\n", offs + 8193, err);
|
||||
// err = fs->lseek_next_hole(&inode_data, offs + 12288);
|
||||
// printf("lseek_next_hole (%d): %d\n\n", offs + 12288, err);
|
||||
// err = fs->lseek_next_hole(&inode_data, offs + 12289);
|
||||
// printf("lseek_next_hole (%d): %d\n\n", offs + 12289, err);
|
||||
// err = fs->lseek_next_hole(&inode_data, offs + 100000);
|
||||
// printf("lseek_next_hole (%d): %d\n\n", offs + 100000, err);
|
||||
|
||||
RawDisk *disk = new FakeRawDisk(5120);
|
||||
Fs *fs = new Fs(disk);
|
||||
fs->format();
|
||||
disk->print_block(0);
|
||||
disk->print_block(1);
|
||||
|
||||
INode_Data inode_data;
|
||||
fs->inode_manager->new_inode(1, 2, 3, &inode_data);
|
||||
|
||||
disk->print_block(0);
|
||||
disk->print_block(1);
|
||||
char cwd_buf[PATH_MAX];
|
||||
int fd;
|
||||
|
||||
int BL_SIZE = 4096 / 8;
|
||||
assert(getcwd(cwd_buf, sizeof(cwd_buf)) != NULL);
|
||||
|
||||
u_int64_t buf[BL_SIZE * (56 + 512 + 10)];
|
||||
fd = open("/tmp", O_TMPFILE | O_RDWR | O_EXCL, S_IRUSR | S_IWUSR);
|
||||
assert(fd != -1);
|
||||
|
||||
for (int i = 0; i < BL_SIZE * (56 + 512 + 10); ++i)
|
||||
buf[i] = (i / BL_SIZE) + 1;
|
||||
u_int64_t test_start_range = IO_BLOCK_SIZE * 3584;
|
||||
u_int64_t test_io_range = IO_BLOCK_SIZE * 100;
|
||||
|
||||
err = fs->write(&inode_data, (char *)buf, 4096 * (56 + 3) + 16 + 8, 0);
|
||||
fs->inode_manager->save_inode(&inode_data);
|
||||
// char ones[test_io_range];
|
||||
// memset(ones, 1, test_io_range);
|
||||
// char twos[test_io_range];
|
||||
// memset(twos, 2, test_io_range);
|
||||
|
||||
printf("Write %d", err);
|
||||
char write_buf[test_io_range];
|
||||
char reference_read_buf[test_io_range];
|
||||
char test_read_buf[test_io_range];
|
||||
size_t offset, count;
|
||||
int test_res, ref_res;
|
||||
bool reads_are_equal;
|
||||
int num;
|
||||
|
||||
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);
|
||||
// size_t weird_offset = 6508064;
|
||||
|
||||
int N = 5;
|
||||
for (int i = 0; i < 100000; ++i) {
|
||||
offset = rand() % test_start_range;
|
||||
|
||||
u_int64_t buf2[4096] = {0};
|
||||
err = fs->read(&inode_data, (char *)buf2, (8 * N), 4096 - 8 - 8);
|
||||
reads_are_equal = true;
|
||||
num = rand() % 100;
|
||||
if (num < 49)
|
||||
num = 0;
|
||||
else if (num < 99)
|
||||
num = 1;
|
||||
else
|
||||
num = 2;
|
||||
|
||||
printf("\n\nREAD: %d\n", err);
|
||||
for (int i = 0; i < N; ++i)
|
||||
printf("%d ", buf2[i]);
|
||||
printf("\n");*/
|
||||
if (i % 100 == 0)
|
||||
printf("%d\n", i);
|
||||
|
||||
fischl(argc, argv);
|
||||
|
||||
return 0;
|
||||
switch (num) {
|
||||
case 0:
|
||||
count = rand() % test_io_range;
|
||||
memset(write_buf, i, count);
|
||||
// write_buf = (write_buf == ones) ? twos : ones;
|
||||
// if (offset <= weird_offset && (count + offset) > weird_offset ||
|
||||
// ((char)i == -77))
|
||||
// printf("write: %ds count=%d offset=%d\n", write_buf[0], count, offset);
|
||||
test_res = fs->write(&inode_data, write_buf, count, offset);
|
||||
assert(lseek(fd, offset, SEEK_SET) == offset);
|
||||
ref_res = write(fd, write_buf, count);
|
||||
break;
|
||||
case 1:
|
||||
count = rand() % test_io_range;
|
||||
// if (offset <= weird_offset && (count + offset) > weird_offset)
|
||||
// printf("read: count=%d offset=%d\n", count, offset);
|
||||
test_res = fs->read(&inode_data, test_read_buf, count, offset);
|
||||
assert(lseek(fd, offset, SEEK_SET) == offset);
|
||||
ref_res = read(fd, reference_read_buf, count);
|
||||
for (size_t j = 0; j < count; ++j)
|
||||
if (test_read_buf[i] != reference_read_buf[i]) {
|
||||
reads_are_equal = false;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
// if (offset <= weird_offset)
|
||||
// printf("truncate: length=%d\n", offset);
|
||||
test_res = fs->truncate(&inode_data, offset);
|
||||
ref_res = ftruncate(fd, offset);
|
||||
break;
|
||||
}
|
||||
|
||||
// printf("test_res=%d, ref_res=%d\n", test_res, ref_res);
|
||||
assert(test_res == ref_res);
|
||||
|
||||
if (!reads_are_equal && count > 0) {
|
||||
int prev_test = test_read_buf[0], prev_ref = reference_read_buf[0],
|
||||
same_count = 1;
|
||||
for (size_t j = 1; j < count; ++j) {
|
||||
u_int64_t byte_index = (j + offset);
|
||||
if (byte_index % IO_BLOCK_SIZE == 0)
|
||||
printf("Block: %d\n", byte_index / IO_BLOCK_SIZE);
|
||||
if (prev_test != test_read_buf[j] ||
|
||||
prev_ref != reference_read_buf[j]) {
|
||||
printf("rt %d %d%s\n", prev_ref, prev_test,
|
||||
(prev_test != prev_ref)
|
||||
? " -----DIFF----- -----DIFF----- -----DIFF-----"
|
||||
: "");
|
||||
printf("^^^^ same for %d bytes ending at %d, starting at %d ^^^^\n",
|
||||
same_count, byte_index, byte_index - same_count);
|
||||
prev_test = test_read_buf[j];
|
||||
prev_ref = reference_read_buf[j];
|
||||
same_count = 1;
|
||||
} else {
|
||||
same_count++;
|
||||
}
|
||||
}
|
||||
printf("rt %d %d%s\n", prev_test, prev_test,
|
||||
(prev_test != prev_ref)
|
||||
? " -----DIFF----- -----DIFF----- -----DIFF-----"
|
||||
: "");
|
||||
printf("^^^^ same for %d bytes ^^^^\n", same_count);
|
||||
}
|
||||
|
||||
assert(reads_are_equal);
|
||||
}
|
||||
|
||||
// RawDisk *disk = new FakeRawDisk(5120);
|
||||
// Fs *fs = new Fs(disk);
|
||||
// fs->format();
|
||||
|
||||
// int buf_size = IO_BLOCK_SIZE * 200;
|
||||
// int loops = 14 * 1024 * 1024 / buf_size;
|
||||
|
||||
// char buf[buf_size];
|
||||
|
||||
// memset(buf, 1, sizeof(buf));
|
||||
|
||||
// INode_Data inode_data;
|
||||
// fs->inode_manager->new_inode(1, 2, 3, &inode_data);
|
||||
|
||||
// int res;
|
||||
|
||||
// for (int j = 0; j < loops; ++j) {
|
||||
// res = fs->write(&inode_data, buf, sizeof(buf), sizeof(buf) * j);
|
||||
// printf("write: %d j=%d\n", res, j);
|
||||
// }
|
||||
|
||||
// for (int j = 0; j < loops; ++j) {
|
||||
|
||||
// memset(buf, 0, sizeof(buf));
|
||||
// res = fs->read(&inode_data, buf, sizeof(buf), sizeof(buf) * j);
|
||||
|
||||
// printf("read: %d j=%d\n", res, j);
|
||||
|
||||
// for (int i = 0; i < sizeof(buf); ++i)
|
||||
// if (buf[1] != 1) {
|
||||
// printf("error: %d\n", i);
|
||||
// return -1;
|
||||
// }
|
||||
// }
|
||||
}
|
@ -10,12 +10,12 @@ void RawDisk::print_block(u_int64_t block_number) {
|
||||
return;
|
||||
}
|
||||
|
||||
printf("\nBlock %llu:\n", block_number);
|
||||
printf("\nBlock %lu:\n", block_number);
|
||||
for (int i = 0; i < IO_BLOCK_SIZE; i += sizeof(u_int64_t)) {
|
||||
num = 0;
|
||||
for (int j = 0; j < 8; j++)
|
||||
num |= ((u_int64_t)(unsigned char)buf[i + j]) << (8 * j);
|
||||
printf("%llu ", num);
|
||||
printf("%lu ", num);
|
||||
if ((i / sizeof(u_int64_t)) % nums_per_line == nums_per_line - 1)
|
||||
printf("\n");
|
||||
}
|
||||
@ -47,8 +47,8 @@ RealRawDisk::RealRawDisk(const char *directory)
|
||||
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);
|
||||
printf("Number of sectors: %lu\n", numSectors);
|
||||
printf("Disk size (in bytes): %lu\n", diskSize);
|
||||
}
|
||||
|
||||
RealRawDisk::~RealRawDisk() {
|
||||
@ -101,7 +101,7 @@ FakeRawDisk::FakeRawDisk(u_int64_t num_blocks) {
|
||||
exit(1);
|
||||
}
|
||||
printf("====Initializing FAKE RawDisk====\n");
|
||||
printf("FAKE Disk size (in bytes): %llu\n", diskSize);
|
||||
printf("FAKE Disk size (in bytes): %lu\n", diskSize);
|
||||
perror("!!! USING FAKE RawDisk - THIS IS FOR TESTING ONLY !!!");
|
||||
}
|
||||
|
||||
|
@ -1,72 +1,69 @@
|
||||
set(TARGET_LAYER0 test_layer0)
|
||||
set(TARGET_LAYER1_API test_layer1_API)
|
||||
set(TARGET_LAYER2_API test_layer2_API)
|
||||
set(TARGET_DIR_API test_dir_API)
|
||||
set(DIR_PLACE /dev/vdb)
|
||||
# set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -fsanitize=address")
|
||||
# set(TARGET_LAYER0 test_layer0)
|
||||
# set(TARGET_LAYER1_API test_layer1_API)
|
||||
# set(TARGET_LAYER2_API test_layer2_API)
|
||||
# set(TARGET_DIR_API test_dir_API)
|
||||
# set(DIR_PLACE /dev/vdb)
|
||||
# # set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -fsanitize=address")
|
||||
|
||||
# add test sources here ...
|
||||
add_executable(${TARGET_LAYER0}
|
||||
# add need lib and source code here
|
||||
layer0.cpp
|
||||
# # add test sources here ...
|
||||
# add_executable(${TARGET_LAYER0}
|
||||
# # add need lib and source code here
|
||||
# layer0.cpp
|
||||
|
||||
../lib/rawdisk.cpp
|
||||
# ../lib/rawdisk.cpp
|
||||
|
||||
)
|
||||
add_executable(${TARGET_LAYER1_API}
|
||||
# add need lib and source code here
|
||||
layer1_API.cpp
|
||||
../lib/rawdisk.cpp
|
||||
../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
|
||||
)
|
||||
add_executable(${TARGET_LAYER2_API}
|
||||
../lib/direntry.cpp
|
||||
../lib/rawdisk.cpp
|
||||
../lib/fs/datablock_manager.cpp
|
||||
../lib/fs/fs_data_types.cpp
|
||||
../lib/fs/fs_resize.cpp
|
||||
../lib/fs/fs_read_write.cpp
|
||||
../lib/fs/fs.cpp
|
||||
../lib/fs/inode_manager.cpp
|
||||
../lib/files.cpp
|
||||
layer2_API_dir.cpp
|
||||
)
|
||||
add_executable(${TARGET_DIR_API}
|
||||
../lib/direntry.cpp
|
||||
../lib/rawdisk.cpp
|
||||
../lib/fs/datablock_manager.cpp
|
||||
../lib/fs/fs_data_types.cpp
|
||||
../lib/fs/fs_resize.cpp
|
||||
../lib/fs/fs_read_write.cpp
|
||||
../lib/fs/fs.cpp
|
||||
../lib/fs/inode_manager.cpp
|
||||
dir_API.cpp
|
||||
)
|
||||
# )
|
||||
# add_executable(${TARGET_LAYER1_API}
|
||||
# # add need lib and source code here
|
||||
# layer1_API.cpp
|
||||
# ../lib/rawdisk.cpp
|
||||
# ../lib/fs/datablock_manager.cpp
|
||||
# ../lib/fs/fs_data_types.cpp
|
||||
# ../lib/fs/fs_file_io.cpp
|
||||
# ../lib/fs/fs.cpp
|
||||
# ../lib/fs/inode_manager.cpp
|
||||
# )
|
||||
# add_executable(${TARGET_LAYER2_API}
|
||||
# ../lib/direntry.cpp
|
||||
# ../lib/rawdisk.cpp
|
||||
# ../lib/fs/datablock_manager.cpp
|
||||
# ../lib/fs/fs_data_types.cpp
|
||||
# ../lib/fs/fs_file_io.cpp
|
||||
# ../lib/fs/fs.cpp
|
||||
# ../lib/fs/inode_manager.cpp
|
||||
# ../lib/files.cpp
|
||||
# layer2_API_dir.cpp
|
||||
# )
|
||||
# add_executable(${TARGET_DIR_API}
|
||||
# ../lib/direntry.cpp
|
||||
# ../lib/rawdisk.cpp
|
||||
# ../lib/fs/datablock_manager.cpp
|
||||
# ../lib/fs/fs_data_types.cpp
|
||||
# ../lib/fs/fs_file_io.cpp
|
||||
# ../lib/fs/fs.cpp
|
||||
# ../lib/fs/inode_manager.cpp
|
||||
# dir_API.cpp
|
||||
# )
|
||||
|
||||
# Link Google Test to your test executables
|
||||
target_link_libraries(${TARGET_LAYER0} gtest gtest_main)
|
||||
target_link_libraries(${TARGET_LAYER1_API} gtest gtest_main)
|
||||
target_link_libraries(${TARGET_DIR_API} gtest gtest_main)
|
||||
# # Link Google Test to your test executables
|
||||
# target_link_libraries(${TARGET_LAYER0} gtest gtest_main)
|
||||
# target_link_libraries(${TARGET_LAYER1_API} gtest gtest_main)
|
||||
# target_link_libraries(${TARGET_DIR_API} gtest gtest_main)
|
||||
|
||||
# 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_LAYER2_API} COMMAND sudo ./${TARGET_LAYER2_API} ${DIR_PLACE})
|
||||
add_test(NAME ${TARGET_DIR_API} COMMAND sudo ./${TARGET_DIR_API} ${DIR_PLACE})
|
||||
# # 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_LAYER2_API} COMMAND sudo ./${TARGET_LAYER2_API} ${DIR_PLACE})
|
||||
# add_test(NAME ${TARGET_DIR_API} COMMAND sudo ./${TARGET_DIR_API} ${DIR_PLACE})
|
||||
|
||||
|
||||
# Add the -Wall flag
|
||||
target_compile_options(${TARGET_LAYER2_API} PRIVATE -Wall)
|
||||
# # Add the -Wall flag
|
||||
# target_compile_options(${TARGET_LAYER2_API} PRIVATE -Wall)
|
||||
|
||||
# Use pkg-config to get flags for fuse3
|
||||
find_package(PkgConfig REQUIRED)
|
||||
pkg_search_module(FUSE3 REQUIRED fuse3)
|
||||
# # Use pkg-config to get flags for fuse3
|
||||
# find_package(PkgConfig REQUIRED)
|
||||
# pkg_search_module(FUSE3 REQUIRED fuse3)
|
||||
|
||||
# Add the flags from pkg-config for fuse3
|
||||
target_include_directories(${TARGET_LAYER2_API} PRIVATE ${FUSE3_INCLUDE_DIRS})
|
||||
target_link_libraries(${TARGET_LAYER2_API} PRIVATE ${FUSE3_LIBRARIES} gtest gtest_main)
|
||||
# # Add the flags from pkg-config for fuse3
|
||||
# target_include_directories(${TARGET_LAYER2_API} PRIVATE ${FUSE3_INCLUDE_DIRS})
|
||||
# target_link_libraries(${TARGET_LAYER2_API} PRIVATE ${FUSE3_LIBRARIES} gtest gtest_main)
|
@ -66,12 +66,15 @@ int main(int argc, char *argv[]) {
|
||||
// the next address(after 2048*4k I/O block)
|
||||
// test the end of the datablock
|
||||
|
||||
H->read_block(fs->disk->diskSize/IO_BLOCK_SIZE - DATABLOCKS_PER_BITMAP_BLOCK - 1, buffer);
|
||||
H->read_block(fs->disk->diskSize / IO_BLOCK_SIZE -
|
||||
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 == fs->disk->diskSize/IO_BLOCK_SIZE - DATABLOCKS_PER_BITMAP_BLOCK - 1);
|
||||
assert(t ==
|
||||
fs->disk->diskSize / IO_BLOCK_SIZE - DATABLOCKS_PER_BITMAP_BLOCK - 1);
|
||||
|
||||
/***************************test inode
|
||||
* de/allocation**********************************/
|
||||
@ -109,34 +112,35 @@ int main(int argc, char *argv[]) {
|
||||
// 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("%llu," ,temp_block_num);
|
||||
}
|
||||
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("%llu,", rec_datablock_free[i][j]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
// 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 = 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++) {
|
||||
fs->allocate_datablock(&inode_list[i], &temp_block_num);
|
||||
// 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("%llu," ,temp_block_num);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
// // printf("%d," ,inode_inside[i].datablock_allocate(*H));
|
||||
// }
|
||||
// // printf("\n");
|
||||
// }
|
||||
|
||||
// printf("}\n");
|
||||
delete H; // Delete the RawDisk object
|
||||
|
Loading…
x
Reference in New Issue
Block a user