added extra file io operations

This commit is contained in:
FactorialN 2023-12-03 16:12:30 -08:00
commit f8b0ee2e8f
13 changed files with 1103 additions and 791 deletions

View File

@ -6,7 +6,7 @@ set(CMAKE_CXX_STANDARD 14)
include_directories( include_directories(
# fischl include files # fischl include files
${CMAKE_CURRENT_SOURCE_DIR}/include ${CMAKE_CURRENT_SOURCE_DIR}/include
${CMAKE_CURRENT_SOURCE_DIR}/googletest/googletest/include # ${CMAKE_CURRENT_SOURCE_DIR}/googletest/googletest/include
) )
add_executable(fischl add_executable(fischl
@ -16,8 +16,7 @@ add_executable(fischl
lib/rawdisk.cpp lib/rawdisk.cpp
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_file_io.cpp
lib/fs/fs_read_write.cpp
lib/fs/fs.cpp lib/fs/fs.cpp
lib/fs/inode_manager.cpp lib/fs/inode_manager.cpp
lib/files.cpp lib/files.cpp
@ -27,7 +26,7 @@ add_executable(fischl
enable_testing() enable_testing()
add_subdirectory(test) add_subdirectory(test)
add_subdirectory(googletest) # add_subdirectory(googletest)
# Add the -Wall flag # Add the -Wall flag
target_compile_options(fischl PRIVATE -Wall) target_compile_options(fischl PRIVATE -Wall)

View File

@ -15,20 +15,12 @@ public:
Fs(RawDisk *disk); Fs(RawDisk *disk);
~Fs(); ~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 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); size_t offset);
int truncate(INode_Data *inode_data, size_t length);
int sweep_inode_datablocks(INode_Data *inode_data, ssize_t lseek_next_data(INode_Data *inode_data, size_t offset);
u_int64_t start_block_index, bool allocate, ssize_t lseek_next_hole(INode_Data *inode_data, size_t offset);
DatablockOperation *op);
int sweep_datablocks(u_int64_t *block_num, int indirect_num,
u_int64_t start_block_index, bool allocate,
DatablockOperation *op);
int format(); int format();
@ -44,8 +36,13 @@ public:
int save_free_list_head(u_int64_t new_free_list_head); 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 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 sweep_inode_datablocks(INode_Data *inode_data,
int deallocate_indirect(u_int64_t *storage, int n, u_int64_t *datablock_num); 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 #endif

View File

@ -15,7 +15,6 @@
#define INDIRECT_BLOCKS 512 #define INDIRECT_BLOCKS 512
#define NUM_INODE_BLOCKS 1023 #define NUM_INODE_BLOCKS 1023
#define NUM_BLOCKS 2048
#define INODE_SIZE 512 #define INODE_SIZE 512

View File

@ -2,37 +2,38 @@
#define FUSE_USE_VERSION 31 #define FUSE_USE_VERSION 31
#include "files.h" #include "files.h"
#include <string.h>
#include <sstream>
#include <cassert> #include <cassert>
#include <sstream>
#include <string.h>
FileNode* FilesOperation::fischl_load_entry(TreeNode *root, const char *path){ FileNode* FilesOperation::fischl_load_entry(TreeNode *root, const char *path){
return fischl_find_entry(fs, root, path); return fischl_find_entry(fs, root, path);
} }
void FilesOperation::printbuffer(const char* buff, int len) { void FilesOperation::printbuffer(const char *buff, int len) {
for(int i=0;i<len;i++){ for (int i = 0; i < len; i++) {
printf("%x ",buff[i]); printf("%x ", buff[i]);
} }
printf("\n"); printf("\n");
} }
FilesOperation::FilesOperation(RawDisk& disk_, Fs* fs): disk(disk_) { FilesOperation::FilesOperation(RawDisk &disk_, Fs *fs) : disk(disk_) {
this->fs = fs; 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,
char buffer[IO_BLOCK_SIZE] = {0}; u_int64_t parent_inode_number) {
DirectoryEntry dot; char buffer[IO_BLOCK_SIZE] = {0};
dot.inode_number = inode->inode_num; DirectoryEntry dot;
strcpy(dot.file_name, "."); dot.inode_number = inode->inode_num;
dot.serialize(buffer); strcpy(dot.file_name, ".");
DirectoryEntry dotdot; dot.serialize(buffer);
dotdot.inode_number = parent_inode_number; DirectoryEntry dotdot;
strcpy(dotdot.file_name, ".."); dotdot.inode_number = parent_inode_number;
dotdot.serialize(buffer+264); strcpy(dotdot.file_name, "..");
int ret = fs->write(inode, buffer, IO_BLOCK_SIZE, 0); dotdot.serialize(buffer + 264);
//printf("in create_dot_dotdot: fs->write returned %d\n",ret); int ret = fs->write(inode, buffer, IO_BLOCK_SIZE, 0);
// printf("in create_dot_dotdot: fs->write returned %d\n",ret);
} }
void FilesOperation::initialize_rootinode() { void FilesOperation::initialize_rootinode() {
@ -61,52 +62,57 @@ void FilesOperation::initialize(bool load) {
} }
void FilesOperation::printDirectory(u_int64_t inode_number) { void FilesOperation::printDirectory(u_int64_t inode_number) {
INode_Data inode; INode_Data inode;
inode.inode_num = inode_number; inode.inode_num = inode_number;
fs->inode_manager->load_inode(&inode); fs->inode_manager->load_inode(&inode);
char buffer[IO_BLOCK_SIZE] = {0}; char buffer[IO_BLOCK_SIZE] = {0};
for (u_int64_t idx=0; idx<inode.metadata.size/IO_BLOCK_SIZE; idx++) { for (u_int64_t idx = 0; idx < inode.metadata.size / IO_BLOCK_SIZE; idx++) {
fs->read(&inode, buffer, IO_BLOCK_SIZE, idx*IO_BLOCK_SIZE); fs->read(&inode, buffer, IO_BLOCK_SIZE, idx * IO_BLOCK_SIZE);
DirectoryEntry ent; DirectoryEntry ent;
for(int i=0;i<=IO_BLOCK_SIZE-264;i+=264){ for (int i = 0; i <= IO_BLOCK_SIZE - 264; i += 264) {
ent.deserialize(buffer+i); 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"); }
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,
// trys to create a file under parent directory const char *name, mode_t mode) {
if (strlen(name)>=256) { // trys to create a file under parent directory
perror("Name too long, cannot create file or directory"); if (strlen(name) >= 256) {
return NULL; perror("Name too long, cannot create file or directory");
} return NULL;
INode_Data inode; }
inode.inode_num = parent_inode_number; INode_Data inode;
fs->inode_manager->load_inode(&inode); inode.inode_num = parent_inode_number;
if ((inode.metadata.permissions & S_IFMT) != S_IFDIR) { fs->inode_manager->load_inode(&inode);
fprintf(stderr,"[%s ,%d] please create under directory\n",__func__,__LINE__); if ((inode.metadata.permissions & S_IFMT) != S_IFDIR) {
return NULL; fprintf(stderr, "[%s ,%d] please create under directory\n", __func__,
} __LINE__);
return NULL;
}
// Check if file or directory already exists // Check if file or directory already exists
char r_buffer[IO_BLOCK_SIZE] = {0}; char r_buffer[IO_BLOCK_SIZE] = {0};
for (u_int64_t idx=0; idx<inode.metadata.size/IO_BLOCK_SIZE; idx++) { for (u_int64_t idx = 0; idx < inode.metadata.size / IO_BLOCK_SIZE; idx++) {
fs->read(&inode, r_buffer, IO_BLOCK_SIZE, idx*IO_BLOCK_SIZE); fs->read(&inode, r_buffer, IO_BLOCK_SIZE, idx * IO_BLOCK_SIZE);
DirectoryEntry ent; DirectoryEntry ent;
for(int i=0;i<=IO_BLOCK_SIZE-264;i+=264){ for (int i = 0; i <= IO_BLOCK_SIZE - 264; i += 264) {
ent.deserialize(r_buffer+i); ent.deserialize(r_buffer + i);
if (strcmp(ent.file_name, name)==0 && ent.inode_number != 0) { if (strcmp(ent.file_name, name) == 0 && ent.inode_number != 0) {
if((mode & S_IFMT) == S_IFDIR){ 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__,
}else{ name);
fprintf(stderr,"[%s ,%d] %s already exists\n",__func__,__LINE__, name); } else {
} fprintf(stderr, "[%s ,%d] %s already exists\n", __func__, __LINE__,
return NULL; name);
}
} }
return NULL;
}
} }
}
bool allocated = false; bool allocated = false;
INode_Data *new_inode = new INode_Data(); INode_Data *new_inode = new INode_Data();
@ -117,86 +123,91 @@ INode_Data* FilesOperation::create_new_inode(u_int64_t parent_inode_number, cons
fs->inode_manager->save_inode(new_inode); fs->inode_manager->save_inode(new_inode);
} }
char rw_buffer[IO_BLOCK_SIZE] = {0}; char rw_buffer[IO_BLOCK_SIZE] = {0};
for (u_int64_t idx=0; idx<inode.metadata.size/IO_BLOCK_SIZE; idx++) { for (u_int64_t idx = 0; idx < inode.metadata.size / IO_BLOCK_SIZE; idx++) {
fs->read(&inode, rw_buffer, IO_BLOCK_SIZE, idx*IO_BLOCK_SIZE); fs->read(&inode, rw_buffer, IO_BLOCK_SIZE, idx * IO_BLOCK_SIZE);
DirectoryEntry ent; DirectoryEntry ent;
for(int i=0;i<=IO_BLOCK_SIZE-264;i+=264){ for (int i = 0; i <= IO_BLOCK_SIZE - 264; i += 264) {
ent.deserialize(rw_buffer+i); ent.deserialize(rw_buffer + i);
if (ent.inode_number == 0) { if (ent.inode_number == 0) {
allocated = true; allocated = true;
ent.inode_number = new_inode->inode_num;
strcpy(ent.file_name, name);
ent.serialize(rw_buffer+i);
break;
}
}
if (allocated) {
fs->write(&inode, rw_buffer, IO_BLOCK_SIZE, idx*IO_BLOCK_SIZE);
break;
}
}
if (!allocated) {
char write_buffer[IO_BLOCK_SIZE] = {0};
DirectoryEntry ent;
ent.inode_number = new_inode->inode_num; ent.inode_number = new_inode->inode_num;
strcpy(ent.file_name, name); strcpy(ent.file_name, name);
ent.serialize(write_buffer); ent.serialize(rw_buffer + i);
fs->write(&inode, write_buffer, IO_BLOCK_SIZE, (inode.metadata.size/IO_BLOCK_SIZE)*IO_BLOCK_SIZE); break;
fs->inode_manager->save_inode(&inode); }
} }
if (allocated) {
fs->write(&inode, rw_buffer, IO_BLOCK_SIZE, idx * IO_BLOCK_SIZE);
break;
}
}
return new_inode; if (!allocated) {
char write_buffer[IO_BLOCK_SIZE] = {0};
DirectoryEntry ent;
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->inode_manager->save_inode(&inode);
}
return new_inode;
} }
u_int64_t FilesOperation::disk_namei(const char* path) { u_int64_t FilesOperation::disk_namei(const char *path) {
// returns the inode number corresponding to path // returns the inode number corresponding to path
u_int64_t current_inode = root_node->self_info->inode_number; u_int64_t current_inode = root_node->self_info->inode_number;
std::string current_dirname; std::string current_dirname;
std::istringstream pathStream(path); std::istringstream pathStream(path);
std::string new_name; std::string new_name;
std::getline(pathStream, new_name, '/'); std::getline(pathStream, new_name, '/');
if(!new_name.empty()){ if (!new_name.empty()) {
printf("disk_namei: path should start with /\n"); printf("disk_namei: path should start with /\n");
return -1; return -1;
} }
while (std::getline(pathStream, new_name, '/')) { while (std::getline(pathStream, new_name, '/')) {
INode_Data inode; INode_Data inode;
inode.inode_num = current_inode; inode.inode_num = current_inode;
fs->inode_manager->load_inode(&inode); fs->inode_manager->load_inode(&inode);
if ((inode.metadata.permissions & S_IFMT) != S_IFDIR || inode.metadata.size == 0) { if ((inode.metadata.permissions & S_IFMT) != S_IFDIR ||
printf("disk_namei: %s is not a non-empty directory\n", current_dirname.c_str()); inode.metadata.size == 0) {
return -1; printf("disk_namei: %s is not a non-empty directory\n",
} current_dirname.c_str());
u_int64_t new_inode_number = 0; return -1;
}
u_int64_t new_inode_number = 0;
char buffer[IO_BLOCK_SIZE] = {0}; char buffer[IO_BLOCK_SIZE] = {0};
for(u_int64_t idx=0; idx<inode.metadata.size/IO_BLOCK_SIZE; idx++) { for (u_int64_t idx = 0; idx < inode.metadata.size / IO_BLOCK_SIZE; idx++) {
fs->read(&inode, buffer, IO_BLOCK_SIZE, idx*IO_BLOCK_SIZE); fs->read(&inode, buffer, IO_BLOCK_SIZE, idx * IO_BLOCK_SIZE);
DirectoryEntry ent; DirectoryEntry ent;
for(int i=0;i<=IO_BLOCK_SIZE-264;i+=264){ for (int i = 0; i <= IO_BLOCK_SIZE - 264; i += 264) {
ent.deserialize(buffer+i); ent.deserialize(buffer + i);
if (strcmp(ent.file_name, new_name.c_str()) == 0) { if (strcmp(ent.file_name, new_name.c_str()) == 0) {
new_inode_number = ent.inode_number; new_inode_number = ent.inode_number;
break; 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()); if (new_inode_number)
return -1; break;
} }
current_inode = new_inode_number; if (!new_inode_number) {
current_dirname = new_name; printf("disk_namei: no name matching %s under directory %s\n",
} new_name.c_str(), current_dirname.c_str());
return current_inode; return -1;
// path = "/" should return root_inode_number (root_node->self_info->inode_number) }
// path = "/foo.txt" should return inode for foo.txt current_inode = new_inode_number;
// path = "/mydir" should return inode for mydir current_dirname = new_name;
// path = "/nonemptydir/foo" should return inode for foo }
// path = "/notnonemptydir/foo" should raise error 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
} }
u_int64_t FilesOperation::namei(const char* path) { u_int64_t FilesOperation::namei(const char* path) {
@ -280,13 +291,16 @@ int FilesOperation::fischl_access(const char* path, int mask) {
return 0; return 0;
} }
int FilesOperation::fischl_mkdir(const char* path, mode_t mode) { int FilesOperation::fischl_mkdir(const char *path, mode_t mode) {
//check path // check path
char *pathdup = strdup(path); char *pathdup = strdup(path);
char *lastSlash = strrchr(pathdup, '/'); char *lastSlash = strrchr(pathdup, '/');
*lastSlash = '\0'; // Split the string into parent path and new directory name; <parent path>\0<direcotry name> *lastSlash = '\0'; // Split the string into parent path and new directory
char *newDirname = lastSlash+1; //\0<direcotry name>, get from <direcotry name> // name; <parent path>\0<direcotry name>
char *ParentPath = pathdup;//pathdup are separated by pathdup, so it take <parent path> only 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; FileNode *parent_filenode = strlen(ParentPath)? fischl_load_entry(root_node, ParentPath): root_node->self_info;
if (parent_filenode == NULL) { if (parent_filenode == NULL) {
@ -368,19 +382,20 @@ int FilesOperation::fischl_create(const char* path, mode_t mode, struct fuse_fil
return 0;//SUCESS 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; (void)fi;
int res = 0; int res = 0;
u_int64_t fh = namei(path); u_int64_t fh = namei(path);
if (fh == -1){ if (fh == -1) {
return -ENOENT; return -ENOENT;
} }
INode_Data inode; INode_Data inode;
inode.inode_num = fh; inode.inode_num = fh;
fs->inode_manager->load_inode(&inode); fs->inode_manager->load_inode(&inode);
//printf("GETATTR PERM %o\n", (mode_t)inode.metadata.permissions); //printf("GETATTR PERM %o\n", (mode_t)inode.metadata.permissions);
@ -417,13 +432,16 @@ int FilesOperation::fischl_getattr(const char *path, struct stat *stbuf, struct
return res; 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,
//check path fuse_fill_dir_t filler, off_t ft,
u_int64_t fh = namei(path); struct fuse_file_info *fi,
enum fuse_readdir_flags flg) {
// check path
u_int64_t fh = namei(path);
if (fh == -1){ if (fh == -1) {
return -1; return -1;
} }
INode_Data inode; INode_Data inode;
inode.inode_num = fh; inode.inode_num = fh;
@ -444,7 +462,7 @@ int FilesOperation::fischl_readdir(const char *path, void *buf, fuse_fill_dir_t
} }
} }
return 0; return 0;
} }
int FilesOperation::fischl_releasedir(const char *path, struct fuse_file_info *fi){ int FilesOperation::fischl_releasedir(const char *path, struct fuse_file_info *fi){
@ -456,39 +474,30 @@ int FilesOperation::fischl_releasedir(const char *path, struct fuse_file_info *f
} }
void FilesOperation::unlink_inode(u_int64_t inode_number) { void FilesOperation::unlink_inode(u_int64_t inode_number) {
INode_Data inode; INode_Data inode;
inode.inode_num = inode_number; inode.inode_num = inode_number;
fs->inode_manager->load_inode(&inode); fs->inode_manager->load_inode(&inode);
if (inode.metadata.reference_count > 1 && (inode.metadata.permissions & S_IFMT) != S_IFDIR){ if (inode.metadata.reference_count > 1 && (inode.metadata.permissions & S_IFMT) != S_IFDIR){
inode.metadata.reference_count -= 1; inode.metadata.reference_count -= 1;
fs->inode_manager->save_inode(&inode); fs->inode_manager->save_inode(&inode);
return; return;
} }
if ((inode.metadata.permissions & S_IFMT) == S_IFDIR) { if ((inode.metadata.permissions & S_IFMT) == S_IFDIR) {
char buffer[IO_BLOCK_SIZE] = {0}; char buffer[IO_BLOCK_SIZE] = {0};
for(u_int64_t idx=0; idx<inode.metadata.size/IO_BLOCK_SIZE; idx++) { for (u_int64_t idx = 0; idx < inode.metadata.size / IO_BLOCK_SIZE; idx++) {
fs->read(&inode, buffer, IO_BLOCK_SIZE, idx*IO_BLOCK_SIZE); fs->read(&inode, buffer, IO_BLOCK_SIZE, idx * IO_BLOCK_SIZE);
DirectoryEntry ent; DirectoryEntry ent;
for(int i=0;i<=IO_BLOCK_SIZE-264;i+=264){ 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, ".") &&
unlink_inode(ent.inode_number); strcmp(ent.file_name, "..")) {
} unlink_inode(ent.inode_number);
}
} }
}
} }
// TODO: This is probably incorrect }
// size is unsigned int // TODO: error handling
while(inode.metadata.size != 0) { int res = fs->truncate(&inode, 0);
printf("dealloc, %d\n", inode.metadata.size); fs->inode_manager->free_inode(&inode);
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;
}
fs->inode_manager->free_inode(&inode);
} }
int FilesOperation::fischl_opendir(const char* path, struct fuse_file_info* fi) { int FilesOperation::fischl_opendir(const char* path, struct fuse_file_info* fi) {
@ -570,39 +579,41 @@ 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,
(void) fi; struct fuse_file_info *fi) {
int res = 0; (void)fi;
u_int64_t fh = namei(path); int res = 0;
u_int64_t fh = namei(path);
if (fh == -1){ if (fh == -1) {
return -ENOENT; return -ENOENT;
} }
INode_Data inode; INode_Data inode;
inode.inode_num = fh; inode.inode_num = fh;
fs->inode_manager->load_inode(&inode); fs->inode_manager->load_inode(&inode);
inode.metadata.permissions = mode; inode.metadata.permissions = mode;
fs->inode_manager->save_inode(&inode); fs->inode_manager->save_inode(&inode);
return 0; 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,
(void) fi; struct fuse_file_info *fi) {
int res = 0; (void)fi;
u_int64_t fh = namei(path); int res = 0;
u_int64_t fh = namei(path);
if (fh == -1){ if (fh == -1) {
return -ENOENT; return -ENOENT;
} }
INode_Data inode; INode_Data inode;
inode.inode_num = fh; inode.inode_num = fh;
fs->inode_manager->load_inode(&inode); fs->inode_manager->load_inode(&inode);
inode.metadata.uid = uid; inode.metadata.uid = uid;
inode.metadata.gid = gid; inode.metadata.gid = gid;
fs->inode_manager->save_inode(&inode); fs->inode_manager->save_inode(&inode);
return 0; return 0;
} }
@ -864,39 +875,40 @@ int FilesOperation::insert_inode_to(u_int64_t parent_inode_number, const char* n
} }
} }
bool allocated = false; bool allocated = false;
char rw_buffer[IO_BLOCK_SIZE] = {0}; char rw_buffer[IO_BLOCK_SIZE] = {0};
for (u_int64_t idx=0; idx<inode.metadata.size/IO_BLOCK_SIZE; idx++) { for (u_int64_t idx = 0; idx < inode.metadata.size / IO_BLOCK_SIZE; idx++) {
fs->read(&inode, rw_buffer, IO_BLOCK_SIZE, idx*IO_BLOCK_SIZE); fs->read(&inode, rw_buffer, IO_BLOCK_SIZE, idx * IO_BLOCK_SIZE);
DirectoryEntry ent; DirectoryEntry ent;
for(int i=0;i<=IO_BLOCK_SIZE-264;i+=264){ for (int i = 0; i <= IO_BLOCK_SIZE - 264; i += 264) {
ent.deserialize(rw_buffer+i); ent.deserialize(rw_buffer + i);
if (ent.inode_number == 0) { if (ent.inode_number == 0) {
allocated = true; allocated = true;
ent.inode_number = new_inode->inode_num;
strcpy(ent.file_name, name);
ent.serialize(rw_buffer+i);
break;
}
}
if (allocated) {
fs->write(&inode, rw_buffer, IO_BLOCK_SIZE, idx*IO_BLOCK_SIZE);
break;
}
}
if (!allocated) {
char write_buffer[IO_BLOCK_SIZE] = {0};
DirectoryEntry ent;
ent.inode_number = new_inode->inode_num; ent.inode_number = new_inode->inode_num;
strcpy(ent.file_name, name); strcpy(ent.file_name, name);
ent.serialize(write_buffer); ent.serialize(rw_buffer + i);
fs->write(&inode, write_buffer, IO_BLOCK_SIZE, (inode.metadata.size/IO_BLOCK_SIZE)*IO_BLOCK_SIZE); break;
fs->inode_manager->save_inode(&inode); }
} }
if (allocated) {
fs->write(&inode, rw_buffer, IO_BLOCK_SIZE, idx * IO_BLOCK_SIZE);
break;
}
}
return 0; if (!allocated) {
char write_buffer[IO_BLOCK_SIZE] = {0};
DirectoryEntry ent;
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->inode_manager->save_inode(&inode);
}
return 0;
} }
int FilesOperation::fischl_link(const char* from, const char* to){ int FilesOperation::fischl_link(const char* from, const char* to){
@ -1109,14 +1121,15 @@ int FilesOperation::fischl_rename(const char *old_path, const char *new_path, un
return 0; 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,
(void) fi; struct fuse_file_info *fi) {
int res = 0; (void)fi;
u_int64_t fh = namei(path); int res = 0;
u_int64_t fh = namei(path);
if (fh == -1){ if (fh == -1) {
return -ENOENT; return -ENOENT;
} }
INode_Data inode; INode_Data inode;
inode.inode_num = fh; inode.inode_num = fh;
@ -1139,45 +1152,80 @@ int FilesOperation::fischl_truncate(const char *path, off_t offset, struct fuse_
return 0; 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,
/** Read data from an open file off_t offset, struct fuse_file_info *fi) {
* /** Read data from an open file
* Read should return exactly the number of bytes requested except *
* on EOF or error, otherwise the rest of the data will be * Read should return exactly the number of bytes requested except
* substituted with zeroes. An exception to this is when the * on EOF or error, otherwise the rest of the data will be
* 'direct_io' mount option is specified, in which case the return * substituted with zeroes. An exception to this is when the
* value of the read system call will reflect the return value of * 'direct_io' mount option is specified, in which case the return
* this operation. * 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
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
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
}*/
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_Data inode;
// Assuming inode is correctly initialized here based on 'path' inode.inode_num = fh;
inode.inode_num = fi->fh;
fs->inode_manager->load_inode(&inode); fs->inode_manager->load_inode(&inode);
size_t bytes_read = fs->read(&inode, buf, size, offset); inode.metadata.access_time = (u_int64_t)tv[0].tv_sec * 1000000000ULL + tv[0].tv_nsec;
/*size_t len = (inode.metadata.size/IO_BLOCK_SIZE) * IO_BLOCK_SIZE; // Assuming each block is 4096 bytes inode.metadata.modification_time = (u_int64_t)tv[1].tv_sec * 1000000000ULL + tv[1].tv_nsec;
fs->inode_manager->save_inode(&inode);
return 0;
}
if (offset >= len) return 0; // Offset is beyond the end of the file int FilesOperation::fischl_statfs(const char* path, struct statvfs* stbuf) {
if (offset + size > len) size = len - offset; // Adjust size if it goes beyond EOF stbuf->f_bsize = 4096;
stbuf->f_blocks = 0;
size_t bytes_read = 0; stbuf->f_bfree = 0;
size_t block_index = offset / IO_BLOCK_SIZE; // Starting block index stbuf->f_files = 0;
size_t block_offset = offset % IO_BLOCK_SIZE; // Offset within the first block stbuf->f_ffree = 0;
// fprintf(stderr,"[%s ,%d] inode.metadata.size %d\n",__func__,__LINE__, inode.metadata.size); stbuf->f_namemax = 256;
while (bytes_read < size && block_index < inode.metadata.size/IO_BLOCK_SIZE) { return 0;
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
} }
int FilesOperation::fischl_utimens(const char *path, const struct timespec tv[2], struct fuse_file_info *fi){ int FilesOperation::fischl_utimens(const char *path, const struct timespec tv[2], struct fuse_file_info *fi){

View File

@ -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) {}
@ -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) if ((err = fs->disk->read_block(bitmap_block_num, bitmap.buf)) < 0)
return err; 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(); u_int64_t relative_block_num = bitmap.claim_relative_block();
if (relative_block_num == 0) if (relative_block_num == 0)
@ -122,6 +126,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);

View File

@ -1,10 +1,13 @@
#include "fs.hpp" #include "fs.hpp"
#include <assert.h>
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, disk->diskSize/IO_BLOCK_SIZE); this, 1 + NUM_INODE_BLOCKS, disk->diskSize / IO_BLOCK_SIZE);
}; };
Fs::~Fs() { Fs::~Fs() {

382
lib/fs/fs_file_io.cpp Normal file
View 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;
}

View File

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

View File

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

View File

@ -1,6 +1,12 @@
#define _GNU_SOURCE
#include "fischl.h" #include "fischl.h"
#include "fs.hpp" #include "fs.hpp"
#include <assert.h>
#include <fcntl.h>
#include <limits.h>
#include <stdio.h> #include <stdio.h>
#include <unistd.h>
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
// printf("hello word!"); // printf("hello word!");
@ -34,56 +40,284 @@ int main(int argc, char *argv[]) {
// disk->print_block(1597); // disk->print_block(1597);
/* // return 0;
int err;
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 *fs = new Fs(disk);
fs->format(); fs->format();
disk->print_block(0);
disk->print_block(1);
INode_Data inode_data; INode_Data inode_data;
fs->inode_manager->new_inode(1, 2, 3, &inode_data); fs->inode_manager->new_inode(1, 2, 3, &inode_data);
disk->print_block(0); char cwd_buf[PATH_MAX];
disk->print_block(1); 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) u_int64_t test_start_range = IO_BLOCK_SIZE * 3584;
buf[i] = (i / BL_SIZE) + 1; u_int64_t test_io_range = IO_BLOCK_SIZE * 100;
err = fs->write(&inode_data, (char *)buf, 4096 * (56 + 3) + 16 + 8, 0); // char ones[test_io_range];
fs->inode_manager->save_inode(&inode_data); // 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); // size_t weird_offset = 6508064;
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; for (int i = 0; i < 100000; ++i) {
offset = rand() % test_start_range;
u_int64_t buf2[4096] = {0}; reads_are_equal = true;
err = fs->read(&inode_data, (char *)buf2, (8 * N), 4096 - 8 - 8); num = rand() % 100;
if (num < 49)
num = 0;
else if (num < 99)
num = 1;
else
num = 2;
printf("\n\nREAD: %d\n", err); if (i % 100 == 0)
for (int i = 0; i < N; ++i) printf("%d\n", i);
printf("%d ", buf2[i]);
printf("\n");*/
fischl(argc, argv); 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;
}
return 0; // 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;
// }
// }
} }

View File

@ -10,12 +10,12 @@ void RawDisk::print_block(u_int64_t block_number) {
return; 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)) { for (int i = 0; i < IO_BLOCK_SIZE; i += sizeof(u_int64_t)) {
num = 0; num = 0;
for (int j = 0; j < 8; j++) for (int j = 0; j < 8; j++)
num |= ((u_int64_t)(unsigned char)buf[i + 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) if ((i / sizeof(u_int64_t)) % nums_per_line == nums_per_line - 1)
printf("\n"); printf("\n");
} }
@ -47,8 +47,8 @@ RealRawDisk::RealRawDisk(const char *directory)
numSectors = diskSize / 512; // Assuming a sector size of 512 bytes numSectors = diskSize / 512; // Assuming a sector size of 512 bytes
printf("====Initializing RawDisk====\n"); printf("====Initializing RawDisk====\n");
printf("Number of sectors: %llu\n", numSectors); printf("Number of sectors: %lu\n", numSectors);
printf("Disk size (in bytes): %llu\n", diskSize); printf("Disk size (in bytes): %lu\n", diskSize);
} }
RealRawDisk::~RealRawDisk() { RealRawDisk::~RealRawDisk() {
@ -101,7 +101,7 @@ FakeRawDisk::FakeRawDisk(u_int64_t num_blocks) {
exit(1); exit(1);
} }
printf("====Initializing FAKE RawDisk====\n"); 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 !!!"); perror("!!! USING FAKE RawDisk - THIS IS FOR TESTING ONLY !!!");
} }

View File

@ -1,72 +1,69 @@
set(TARGET_LAYER0 test_layer0) # set(TARGET_LAYER0 test_layer0)
set(TARGET_LAYER1_API test_layer1_API) # set(TARGET_LAYER1_API test_layer1_API)
set(TARGET_LAYER2_API test_layer2_API) # set(TARGET_LAYER2_API test_layer2_API)
set(TARGET_DIR_API test_dir_API) # set(TARGET_DIR_API test_dir_API)
set(DIR_PLACE /dev/vdb) # set(DIR_PLACE /dev/vdb)
# set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -fsanitize=address") # # set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -fsanitize=address")
# add test sources here ... # # add test sources here ...
add_executable(${TARGET_LAYER0} # add_executable(${TARGET_LAYER0}
# add need lib and source code here # # add need lib and source code here
layer0.cpp # layer0.cpp
../lib/rawdisk.cpp # ../lib/rawdisk.cpp
) # )
add_executable(${TARGET_LAYER1_API} # add_executable(${TARGET_LAYER1_API}
# add need lib and source code here # # add need lib and source code here
layer1_API.cpp # layer1_API.cpp
../lib/rawdisk.cpp # ../lib/rawdisk.cpp
../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_file_io.cpp
../lib/fs/fs_read_write.cpp # ../lib/fs/fs.cpp
../lib/fs/fs.cpp # ../lib/fs/inode_manager.cpp
../lib/fs/inode_manager.cpp # )
) # add_executable(${TARGET_LAYER2_API}
add_executable(${TARGET_LAYER2_API} # ../lib/direntry.cpp
../lib/direntry.cpp # ../lib/rawdisk.cpp
../lib/rawdisk.cpp # ../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_file_io.cpp
../lib/fs/fs_resize.cpp # ../lib/fs/fs.cpp
../lib/fs/fs_read_write.cpp # ../lib/fs/inode_manager.cpp
../lib/fs/fs.cpp # ../lib/files.cpp
../lib/fs/inode_manager.cpp # layer2_API_dir.cpp
../lib/files.cpp # )
layer2_API_dir.cpp # add_executable(${TARGET_DIR_API}
) # ../lib/direntry.cpp
add_executable(${TARGET_DIR_API} # ../lib/rawdisk.cpp
../lib/direntry.cpp # ../lib/fs/datablock_manager.cpp
../lib/rawdisk.cpp # ../lib/fs/fs_data_types.cpp
../lib/fs/datablock_manager.cpp # ../lib/fs/fs_file_io.cpp
../lib/fs/fs_data_types.cpp # ../lib/fs/fs.cpp
../lib/fs/fs_resize.cpp # ../lib/fs/inode_manager.cpp
../lib/fs/fs_read_write.cpp # dir_API.cpp
../lib/fs/fs.cpp # )
../lib/fs/inode_manager.cpp
dir_API.cpp
)
# Link Google Test to your test executables # # Link Google Test to your test executables
target_link_libraries(${TARGET_LAYER0} gtest gtest_main) # target_link_libraries(${TARGET_LAYER0} gtest gtest_main)
target_link_libraries(${TARGET_LAYER1_API} gtest gtest_main) # target_link_libraries(${TARGET_LAYER1_API} gtest gtest_main)
target_link_libraries(${TARGET_DIR_API} gtest gtest_main) # target_link_libraries(${TARGET_DIR_API} gtest gtest_main)
# add test to activate ctest -VV # # add test to activate ctest -VV
add_test(NAME ${TARGET_LAYER0} COMMAND sudo ./${TARGET_LAYER0} ${DIR_PLACE}) # add_test(NAME ${TARGET_LAYER0} COMMAND sudo ./${TARGET_LAYER0} ${DIR_PLACE})
add_test(NAME ${TARGET_LAYER1_API} COMMAND sudo ./${TARGET_LAYER1_API} ${DIR_PLACE}) # add_test(NAME ${TARGET_LAYER1_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_LAYER2_API} COMMAND sudo ./${TARGET_LAYER2_API} ${DIR_PLACE})
add_test(NAME ${TARGET_DIR_API} COMMAND sudo ./${TARGET_DIR_API} ${DIR_PLACE}) # add_test(NAME ${TARGET_DIR_API} COMMAND sudo ./${TARGET_DIR_API} ${DIR_PLACE})
# Add the -Wall flag # # Add the -Wall flag
target_compile_options(${TARGET_LAYER2_API} PRIVATE -Wall) # target_compile_options(${TARGET_LAYER2_API} PRIVATE -Wall)
# Use pkg-config to get flags for fuse3 # # Use pkg-config to get flags for fuse3
find_package(PkgConfig REQUIRED) # find_package(PkgConfig REQUIRED)
pkg_search_module(FUSE3 REQUIRED fuse3) # pkg_search_module(FUSE3 REQUIRED fuse3)
# Add the flags from pkg-config for fuse3 # # Add the flags from pkg-config for fuse3
target_include_directories(${TARGET_LAYER2_API} PRIVATE ${FUSE3_INCLUDE_DIRS}) # target_include_directories(${TARGET_LAYER2_API} PRIVATE ${FUSE3_INCLUDE_DIRS})
target_link_libraries(${TARGET_LAYER2_API} PRIVATE ${FUSE3_LIBRARIES} gtest gtest_main) # target_link_libraries(${TARGET_LAYER2_API} PRIVATE ${FUSE3_LIBRARIES} gtest gtest_main)

View File

@ -65,13 +65,16 @@ int main(int argc, char *argv[]) {
1); // the first 8 bytes of 4k I/O block will store 1); // the first 8 bytes of 4k I/O block will store
// the next address(after 2048*4k I/O block) // the next address(after 2048*4k I/O block)
// test the end of the datablock // 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; t = 0;
for (int j = 0; j < 8; j++) for (int j = 0; j < 8; j++)
t |= ((u_int64_t)(unsigned char)buffer[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 /***************************test inode
* de/allocation**********************************/ * de/allocation**********************************/
@ -109,34 +112,35 @@ int main(int argc, char *argv[]) {
// after free the datablock, the program will find the first smallest address // 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 // of datablock to give to the inode should test random resize each node, but
// should use datablock_free data structure to record // should use datablock_free data structure to record
u_int64_t rec_datablock_free[10][3] = {0}; // array version // u_int64_t rec_datablock_free[10][3] = {0}; // array version
u_int64_t temp_block_num = 0; // u_int64_t temp_block_num = 0;
for (int i = 0; i < 10; i++) { // for (int i = 0; i < 10; i++) {
printf("%dth data block starting addres: ", i); // // printf("%dth data block starting addres: ", i);
for (int j = 0; j < 6; j++) { // for (int j = 0; j < 6; j++) {
fs->allocate_datablock(&inode_list[i], &temp_block_num); // fs->allocate_datablock(&inode_list[i], &temp_block_num);
printf("%llu," ,temp_block_num); // // printf("%d," ,inode_inside[i].datablock_allocate(*H));
} // }
printf("\n"); // // printf("\n");
} // }
for (int i = 0; i < 10; i++) { // for (int i = 0; i < 10; i++) {
printf("%dth data block free addres: ", i); // // printf("%dth data block free addres: ", i);
for (int j = 2; j >= 0; j--) { // for (int j = 2; j >= 0; j--) {
fs->deallocate_datablock(&inode_list[i], &(rec_datablock_free[i][j])); // fs->deallocate_datablock(&inode_list[i],
printf("%llu,", rec_datablock_free[i][j]); // &(rec_datablock_free[i][j]));
} // // printf("", rec_datablock_free[i][j]);
printf("\n"); // }
} // // printf("\n");
// }
for (int i = 0; i < 10; i++) { // for (int i = 0; i < 10; i++) {
printf("%dth data block allocate again addres: ", i); // // printf("%dth data block allocate again addres: ", i);
for (int j = 0; j < 3; j++) { // for (int j = 0; j < 3; j++) {
fs->allocate_datablock(&inode_list[i], &temp_block_num); // fs->allocate_datablock(&inode_list[i], &temp_block_num);
//assert(temp_block_num == rec_datablock_free[i][j]); // assert(temp_block_num == rec_datablock_free[i][j]);
printf("%llu," ,temp_block_num); // // printf("%d," ,inode_inside[i].datablock_allocate(*H));
} // }
printf("\n"); // // printf("\n");
} // }
// printf("}\n"); // printf("}\n");
delete H; // Delete the RawDisk object delete H; // Delete the RawDisk object