Merge pull request #14 from SuperconductZB/guangzheliu/layer3dev

Implement Layer3
This commit is contained in:
FactorialN 2023-12-04 10:09:32 -08:00 committed by GitHub
commit fb961a9cd5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
25 changed files with 1991 additions and 810 deletions

BIN
.DS_Store vendored

Binary file not shown.

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,4 +26,15 @@ add_executable(fischl
enable_testing() enable_testing()
add_subdirectory(test) add_subdirectory(test)
add_subdirectory(googletest) add_subdirectory(googletest)
# Add the -Wall flag
target_compile_options(fischl PRIVATE -Wall)
# 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(fischl PRIVATE ${FUSE3_INCLUDE_DIRS})
target_link_libraries(fischl PRIVATE ${FUSE3_LIBRARIES})

View File

@ -19,6 +19,29 @@ cmake ..
make # cmake --build . is same make # cmake --build . is same
``` ```
## mount and test
normal usage:
```bash
./fischl diskpath n -s mountpoint
```
diskpath must be provided following ./fischl
l/n must be provided following diskpath indicating whether to load the exisiting file system or create a new one.
for loading:
```bash
./fischl diskpath l -s mountpoint
```
-s is also required because our fs doesn't support multi-threading.
if the diskpath need to be accessed by root:
```bash
sudo ./fischl diskpath n -o allow_other -s mountpoint
```
for debugging:
```bash
sudo ./fischl diskpath n -o allow_other -d -s mountpoint
```
## run test ## run test
### add your own test file on test/CMakeList.txt ### add your own test file on test/CMakeList.txt
``` ```

View File

@ -19,18 +19,48 @@ typedef struct treeNode {
FileNode *self_info; //self fileNode infromation FileNode *self_info; //self fileNode infromation
} TreeNode; } TreeNode;
typedef struct RenameInfo {
FileNode *oldFileNode; // The file node being renamed.
FileNode *oldParentNode; // The parent directory of the file node being renamed.
FileNode *newParentNode; // The target parent directory where the file node will be moved.
char *newName; // The new name of the file node after the rename.
FileNode *newFileNode; // The new file node, if one already exists at the target location.
bool exchangeExist; // Flag to indicate if the rename should replace an existing file node.
} RenameInfo;
/*for root*/ /*for root*/
TreeNode *fischl_init_entry(int new_inode_number, const char *fileName, INode_Data *new_inode); TreeNode *fischl_init_entry(int new_inode_number, const char *fileName, INode_Data *new_inode);
/*the to be added file in add_entry should be parent-child relationship with treenode, otherwise will wrong */ /*the to be added file in add_entry should be parent-child relationship with treenode, otherwise will wrong */
/*see Add_FindFiletest in dir_API.cpp*/ /*see Add_FindFiletest in dir_API.cpp*/
FileNode* fischl_add_entry_for_cache(TreeNode *parent, int new_inode_number, const char *fileName, INode_Data *new_inode);
int fischl_add_entry(TreeNode *parent, int new_inode_number, const char *fileName, INode_Data *new_inode); int fischl_add_entry(TreeNode *parent, int new_inode_number, const char *fileName, INode_Data *new_inode);
int fischl_rm_entry(TreeNode *parent, const char *fileName); int fischl_rm_entry(TreeNode *parent, const char *fileName);
/*if want to use dir mode use the subdirectory treeNode pointer */ /*if want to use dir mode use the subdirectory treeNode pointer */
//e.g. FileNode *Dirnode = fischl_find_entry(); can see file inside with Dirnode->subdirectory //e.g. FileNode *Dirnode = fischl_find_entry(); can see file inside with Dirnode->subdirectory
//e.g. go to the current Dirnode parent directory, use TreeNode *get_Dir_parent = Dirnode->subdirectory->parent; //e.g. go to the current Dirnode parent directory, use TreeNode *get_Dir_parent = Dirnode->subdirectory->parent;
FileNode *fischl_find_entry(TreeNode *root, const char *path); FileNode *fischl_find_entry(Fs *fs, TreeNode *root, const char *path);
void freeTree(TreeNode *node); void freeTree(TreeNode *node);
/*for debug use*/ /*for debug use*/
TreeNode *createDirectory(const char *dirName, TreeNode *parent, int hashSize); TreeNode *createDirectory(const char *dirName, TreeNode *parent, int hashSize);
TreeNode *find_parentPath(TreeNode *root, const char *path); TreeNode *find_parentPath(TreeNode *root, const char *path);
struct DirectoryEntry {
u_int64_t inode_number;
char file_name[256];
void serialize(char* buffer) {
u_int64_t t = inode_number;
for (int j = 0; j < 8; j++){
buffer[j] = t & (((u_int64_t)1<<(8))-1);
t >>= 8;
}
strcpy(buffer+8, file_name);
}
void deserialize(char* buffer) {
inode_number = 0;
for (int j = 0; j < 8; j++)
inode_number = inode_number | (((u_int64_t)(unsigned char)buffer[j])<<(8*j));
strcpy(file_name, buffer+8);
}
};

View File

@ -1,6 +1,6 @@
#include <sys/types.h> #include <sys/types.h>
#include <fs.hpp> #include <fs.hpp>
#include "fuse_common.h" #include <fuse.h>
#include "direntry.h" #include "direntry.h"
class FilesOperation { class FilesOperation {
@ -8,25 +8,44 @@ class FilesOperation {
Fs *fs; Fs *fs;
void create_dot_dotdot(INode_Data*, u_int64_t); void create_dot_dotdot(INode_Data*, u_int64_t);
public: public:
TreeNode *root_node; TreeNode *root_node;
FilesOperation(RawDisk&, Fs*); FilesOperation(RawDisk&, Fs*);
//int read_datablock(const INode_Data& inode, u_int64_t index, char* buffer); //int read_datablock(const INode_Data& inode, u_int64_t index, char* buffer);
//int write_datablock(INode_Data& inode, u_int64_t index, char* buffer); //int write_datablock(INode_Data& inode, u_int64_t index, char* buffer);
void initialize_rootinode(); void initialize_rootinode();
void initialize(bool load);
void printbuffer(const char*,int); void printbuffer(const char*,int);
void printDirectory(u_int64_t); void printDirectory(u_int64_t);
bool permission_check(int, INode_Data*);
bool permission_check_by_inode_num(int, u_int64_t);
INode_Data* create_new_inode(u_int64_t parent_inode_number, const char* name, mode_t mode); INode_Data* create_new_inode(u_int64_t parent_inode_number, const char* name, mode_t mode);
int insert_inode_to(u_int64_t parent_inode_number, const char* name, INode_Data *new_inode, bool check_replace);
void unlink_inode(u_int64_t inode_number); void unlink_inode(u_int64_t inode_number);
u_int64_t disk_namei(const char* path); u_int64_t disk_namei(const char* path);
u_int64_t namei(const char* path); u_int64_t namei(const char* path);
int fischl_mkdir(const char*, mode_t); int fischl_mkdir(const char*, mode_t);
int fischl_mknod(const char*, mode_t, dev_t);//for special file int fischl_mknod(const char*, mode_t, dev_t);//for special file
int fischl_access(const char* path, int mask);
int fischl_create(const char *, mode_t, struct fuse_file_info *);//for regular file int fischl_create(const char *, mode_t, struct fuse_file_info *);//for regular file
//int fischl_readdir(const char *, void *, fuse_fill_dir_t, off_t, struct fuse_file_info *, enum fuse_readdir_flags); int fischl_getattr(const char *path, struct stat *stbuf, struct fuse_file_info *fi);
int fischl_readdir(const char *, void *, fuse_fill_dir_t, off_t, struct fuse_file_info *, enum fuse_readdir_flags);
int fischl_releasedir(const char* path, struct fuse_file_info *fi);
int fischl_unlink (const char *); int fischl_unlink (const char *);
int fischl_opendir(const char* path, struct fuse_file_info* fi);
int fischl_rmdir(const char *);
int fischl_readlink(const char* path, char* buf, size_t size);
int fischl_symlink(const char* from, const char* to);
int fischl_link(const char* from, const char* to);
int fischl_rename(const char *path, const char *, unsigned int flags);
int fischl_truncate(const char *path, off_t, struct fuse_file_info *fi);
int fischl_chmod(const char *path, mode_t, struct fuse_file_info *fi);
int fischl_chown(const char *path, uid_t uid, gid_t gid, struct fuse_file_info *fi);
int fischl_open (const char *, struct fuse_file_info *);//open file int fischl_open (const char *, struct fuse_file_info *);//open file
int fischl_release (const char *, struct fuse_file_info *);//close file int fischl_release (const char *, struct fuse_file_info *);//close file
int fischl_write(const char *, const char *, size_t, off_t, struct fuse_file_info *); int fischl_write(const char *, const char *, size_t, off_t, struct fuse_file_info *);
int fischl_read(const char *, char *, size_t, off_t, struct fuse_file_info *); int fischl_read(const char *, char *, size_t, off_t, struct fuse_file_info *);
}; int fischl_utimens(const char *path, const struct timespec tv[2], struct fuse_file_info *fi);
int fischl_statfs(const char* path, struct statvfs* stbuf);
FileNode *fischl_load_entry(TreeNode *root, const char *path);
};

View File

@ -1,7 +1,3 @@
class fischl{
// declare
public:
int init();
}; int fischl(int argc, char *argv[]);

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

@ -25,12 +25,14 @@ public:
u_int64_t inode_num; u_int64_t inode_num;
#define NUMBER_OF_METADATA_BYTES \ #define NUMBER_OF_METADATA_BYTES \
(4 * sizeof(u_int64_t) + (2 * sizeof(u_int32_t))) (6 * sizeof(u_int64_t) + (2 * sizeof(u_int32_t)))
struct INode_MetaData { struct INode_MetaData {
u_int64_t uid; u_int64_t uid;
u_int64_t gid; u_int64_t gid;
u_int64_t permissions; u_int64_t permissions;
u_int64_t size; // not yet implemented u_int64_t size; // not yet implemented
u_int64_t access_time;
u_int64_t modification_time;
u_int32_t reference_count; u_int32_t reference_count;
u_int32_t flags; u_int32_t flags;
} metadata; } metadata;

View File

@ -12,9 +12,9 @@
#include <unistd.h> #include <unistd.h>
#define IO_BLOCK_SIZE 4096 #define IO_BLOCK_SIZE 4096
#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

@ -1,82 +0,0 @@
#ifndef FUSE_COMMON_H_
#define FUSE_COMMON_H_
#include <stdint.h>
#include <sys/types.h>
/**
* Information about an open file.
*
* File Handles are created by the open, opendir, and create methods and closed
* by the release and releasedir methods. Multiple file handles may be
* concurrently open for the same file. Generally, a client will create one
* file handle per file descriptor, though in some cases multiple file
* descriptors can share a single file handle.
*/
struct fuse_file_info {
/** Open flags. Available in open() and release() */
int flags;
/** In case of a write operation indicates if this was caused
by a delayed write from the page cache. If so, then the
context's pid, uid, and gid fields will not be valid, and
the *fh* value may not match the *fh* value that would
have been sent with the corresponding individual write
requests if write caching had been disabled. */
unsigned int writepage : 1;
/** Can be filled in by open/create, to use direct I/O on this file. */
unsigned int direct_io : 1;
/** Can be filled in by open and opendir. It signals the kernel that any
currently cached data (ie., data that the filesystem provided the
last time the file/directory was open) need not be invalidated when
the file/directory is closed. */
unsigned int keep_cache : 1;
/** Can be filled by open/create, to allow parallel direct writes on this
* file */
unsigned int parallel_direct_writes : 1;
/** Indicates a flush operation. Set in flush operation, also
maybe set in highlevel lock operation and lowlevel release
operation. */
unsigned int flush : 1;
/** Can be filled in by open, to indicate that the file is not
seekable. */
unsigned int nonseekable : 1;
/* Indicates that flock locks for this file should be
released. If set, lock_owner shall contain a valid value.
May only be set in ->release(). */
unsigned int flock_release : 1;
/** Can be filled in by opendir. It signals the kernel to
enable caching of entries returned by readdir(). Has no
effect when set in other contexts (in particular it does
nothing when set by open()). */
unsigned int cache_readdir : 1;
/** Can be filled in by open, to indicate that flush is not needed
on close. */
unsigned int noflush : 1;
/** Padding. Reserved for future use*/
unsigned int padding : 23;
unsigned int padding2 : 32;
/** File handle id. May be filled in by filesystem in create,
* open, and opendir(). Available in most other file operations on the
* same file handle. */
uint64_t fh;
/** Lock owner id. Available in locking operations and flush */
uint64_t lock_owner;
/** Requested poll events. Available in ->poll. Only set on kernels
which support it. If unsupported, this field is set to zero. */
uint32_t poll_events;
};
#endif /* FUSE_COMMON_H_ */

View File

@ -156,6 +156,26 @@ TreeNode *fischl_init_entry(int new_inode_number, const char *fileName, INode_Da
return newDir; return newDir;
} }
FileNode* fischl_add_entry_for_cache(TreeNode *parent, int new_inode_number, const char *fileName, INode_Data *new_inode){
char *Name = strdup(fileName);
TreeNode *newDir = NULL;
/*If directory, malloc TreeNode, and then create filenode that belongs to Parent hash table content*/
if ((new_inode->metadata.permissions & S_IFMT) == S_IFDIR) {
newDir = (TreeNode *)malloc(sizeof(TreeNode));
newDir->dirName = Name;
newDir->contents = createHashTable(20);//hasSize define 20
newDir->parent = parent;
}
FileNode *newFile = insertHash(parent->contents, Name, newDir); //newDir == NULL indicates it's a file
//assign INode *new_inode metadata to data member in FileNode structure
newFile->permissions = new_inode->metadata.permissions;
newFile->inode_number = new_inode_number;
//Diretory have its own file information, that is . here
if(newDir != NULL)
newDir->self_info = newFile;
return newFile;
}
int fischl_add_entry(TreeNode *parent, int new_inode_number, const char *fileName, INode_Data *new_inode){ int fischl_add_entry(TreeNode *parent, int new_inode_number, const char *fileName, INode_Data *new_inode){
char *Name = strdup(fileName); char *Name = strdup(fileName);
TreeNode *newDir = NULL; TreeNode *newDir = NULL;
@ -191,13 +211,15 @@ int fischl_rm_entry(TreeNode *parent, const char *fileName) {
} }
FileNode *fischl_find_entry(TreeNode *root, const char *path){ FileNode *fischl_find_entry(Fs *fs, TreeNode *root, const char *path){
//support . and .. function //support . and .. function
char *pathCopy = strdup(path); char *pathCopy = strdup(path);
char *segment = strtok(pathCopy, "/"); char *segment = strtok(pathCopy, "/");
TreeNode *current = root; TreeNode *current = root;
FileNode *file = NULL; FileNode *file = NULL;
printf("FINDING %s %s %llu\n", path, segment, current->self_info->inode_number);
while (segment != NULL && current != NULL) { while (segment != NULL && current != NULL) {
if (strcmp(segment, "..") == 0) { if (strcmp(segment, "..") == 0) {
// Move up to the parent directory // Move up to the parent directory
@ -214,8 +236,29 @@ FileNode *fischl_find_entry(TreeNode *root, const char *path){
} }
else{ else{
file = lookupHash(current->contents, segment); file = lookupHash(current->contents, segment);
if (file == NULL) {
// find on disk whether this exists
INode_Data inode;
inode.inode_num = current->self_info->inode_number;
fs->inode_manager->load_inode(&inode);
char buffer[IO_BLOCK_SIZE] = {0};
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);
DirectoryEntry ent;
for(int i=0;i<=IO_BLOCK_SIZE-264;i+=264){
ent.deserialize(buffer+i);
//printf("WARNING:%d %llu %llu %s %s\n",__LINE__,inode.inode_num, ent.inode_number, ent.file_name, segment);
if (ent.inode_number && strcmp(ent.file_name, segment)==0) {
file = fischl_add_entry_for_cache(current, ent.inode_number, ent.file_name, &inode);
//printf("DONE !! %llu\n", file->inode_number);
break;
}
}
}
}
if (file != NULL && file->subdirectory == NULL) { if (file != NULL && file->subdirectory == NULL) {
free(pathCopy); free(pathCopy);
printf("FOUND !! %llu\n", file->inode_number);
return file; //File found return file; //File found
//return current; return filenode //return current; return filenode
} }

File diff suppressed because it is too large Load Diff

View File

@ -1,8 +1,313 @@
#include "fischl.h" #define FUSE_USE_VERSION 31
#include <cstdio> #include <fuse.h>
#include <stdio.h>
int fischl::init(){ #include <string>
printf("Hello Fischl!"); #include <errno.h>
return 3; #include <fcntl.h>
#include <stddef.h>
#include <assert.h>
#include "fs.hpp"
#include "files.h"
/*
* Command line options
*
* We can't set default values for the char* fields here because
* fuse_opt_parse would attempt to free() them when the user specifies
* different values on the command line.
*/
static struct options {
RawDisk *H; // Use FakeRawDisk here if memory sanitizer complains
Fs *fs;
FilesOperation *fsop;
int show_help;
bool load;
} options;
#define OPTION(t, p) \
{ t, offsetof(struct options, p), 1 }
static const struct fuse_opt option_spec[] = {
OPTION("-h", show_help),
OPTION("--help", show_help),
FUSE_OPT_END
};
void* fischl_init(struct fuse_conn_info *conn, struct fuse_config *cfg) {
cfg->use_ino = 1;
options.fsop->initialize(options.load);
}
int fischl_create(const char *path, mode_t mode, struct fuse_file_info *fi) {
return options.fsop->fischl_create(path, mode, fi);
}
void fischl_destroy(void* private_data) {
}
static int fischl_getattr(const char *path, struct stat *stbuf, struct fuse_file_info *fi) {
return options.fsop->fischl_getattr(path, stbuf, fi);
}
static int fischl_access(const char* path, int mask) {
return options.fsop->fischl_access(path, mask);
}
static int fischl_readlink(const char* path, char* buf, size_t size) {
return options.fsop->fischl_readlink(path, buf, size);
}
static int fischl_opendir(const char* path, struct fuse_file_info* fi) {
return options.fsop->fischl_opendir(path, fi);
}
static int 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) {
return options.fsop->fischl_readdir(path, buf, filler, ft, fi, flg);
}
static int fischl_mknod(const char* path, mode_t mode, dev_t rdev) {
return options.fsop->fischl_mknod(path, mode, rdev);
}
static int fischl_mkdir(const char *path, mode_t mode) {
return options.fsop->fischl_mkdir(path, mode);
}
static int fischl_unlink(const char* path) {
return options.fsop->fischl_unlink(path);
}
static int fischl_rmdir(const char* path) {
return options.fsop->fischl_rmdir(path);
}
static int fischl_symlink(const char* from, const char* to) {
return options.fsop->fischl_symlink(from, to);
}
static int fischl_rename(const char *path, const char *new_name, unsigned int flags) {
return options.fsop->fischl_rename(path, new_name, flags);
}
static int fischl_link(const char* from, const char* to) {
return options.fsop->fischl_link(from, to);
}
static int fischl_chmod(const char *path, mode_t mode, struct fuse_file_info *fi) {
return options.fsop->fischl_chmod(path, mode, fi);
}
static int fischl_chown(const char *path, uid_t uid, gid_t gid, struct fuse_file_info *fi) {
return options.fsop->fischl_chown(path, uid, gid, fi);
}
static int fischl_truncate(const char *path, off_t offset, struct fuse_file_info *fi) {
return options.fsop->fischl_truncate(path, offset, fi);
}
static int fischl_utimens(const char *path, const struct timespec tv[2], struct fuse_file_info *fi) {
return options.fsop->fischl_utimens(path, tv, fi);
}
static int fischl_open(const char *path, struct fuse_file_info *fi) {
return options.fsop->fischl_open(path, fi);
}
static int fischl_read(const char* path, char *buf, size_t size, off_t offset, struct fuse_file_info* fi) {
return options.fsop->fischl_read(path, buf, size, offset, fi);
}
static int fischl_write(const char *path, const char *buf, size_t size, off_t offset, struct fuse_file_info *fi) {
return options.fsop->fischl_write(path, buf, size, offset, fi);
}
static int fischl_statfs(const char* path, struct statvfs* stbuf) {
return options.fsop->fischl_statfs(path, stbuf);
}
static int fischl_release(const char* path, struct fuse_file_info *fi) {
return options.fsop->fischl_release(path, fi);
}
static int fischl_releasedir(const char* path, struct fuse_file_info *fi) {
return options.fsop->fischl_releasedir(path, fi);
}
static const struct fuse_operations fischl_oper = {
.getattr = fischl_getattr,
.readlink = fischl_readlink,
.mknod = fischl_mknod,
.mkdir = fischl_mkdir,
.unlink = fischl_unlink,
.rmdir = fischl_rmdir,
.symlink = fischl_symlink,
.rename = fischl_rename,
.link = fischl_link,
.chmod = fischl_chmod,
.chown = fischl_chown,
.truncate = fischl_truncate,
.open = fischl_open,
.read = fischl_read,
.write = fischl_write,
.statfs = fischl_statfs,
.release = fischl_release,
/*
#ifdef HAVE_SETXATTR
.setxattr = fischl_setxattr,
.getxattr = fischl_getxattr,
.listxattr = fischl_listxattr,
.removexattr = fischl_removexattr,
#endif
*/
.opendir = fischl_opendir,
.readdir = fischl_readdir,
.releasedir = fischl_releasedir,
.init = fischl_init,
.destroy = fischl_destroy,
.access = fischl_access,
.create = fischl_create,
.utimens = fischl_utimens,
//.bmap = fischl_bmap,
//.ioctl = fischl_ioctl,
//.poll = fischl_poll,
};
static void show_help(const char *progname)
{
printf("usage: %s [options] <mountpoint>\n\n", progname);
printf("File-system specific options:\n"
" --name=<s> Name of the \"fischl\" file\n"
" (default: \"fischl\")\n"
" --contents=<s> Contents \"fischl\" file\n"
" (default \"fischl, World!\\n\")\n"
"\n");
}
int fischl(int argc, char *argv[])
{
int ret;
if(argc < 3){
printf("WRONG ARGUMENTS\n");
return 0;
}
std::swap(argv[0], argv[1]);
std::swap(argv[1], argv[2]);
struct fuse_args args = FUSE_ARGS_INIT(argc-2, argv+2);
srand(time(NULL)); // Seed the random number generator
//const char* d = (argc < 2) ? "/dev/vdc" : argv[1];
//setupTestDirectory(&options.root);
if(strcmp(argv[0], "fake")==0){
options.H = new FakeRawDisk(27648);
}
else{
options.H = new RealRawDisk(argv[0]);
char zero_es[IO_BLOCK_SIZE] = {0};
/*printf("zeroed\n");
for (int i = 0; i < 200000; i++){
options.H->write_block(i, zero_es);
}*/
}
if(strcmp(argv[1], "l")==0){
options.load = true;
}
else if(strcmp(argv[1], "n")==0){
options.load = false;
}
else{
printf("WRONG l/n ARGUMENTS\n");
return 0;
}
options.fs = new Fs(options.H);
if(!options.load){
printf("FORMAT %d\n", options.fs->format());
}
options.fsop = new FilesOperation(*options.H, options.fs);
/*INode_Data inode_data;
options.fs->inode_manager->new_inode(1, 2, 3, &inode_data);
int buf_size = 100000;
int seg_size = 10;
char buf[buf_size];
int res;
int num = 1;
for (u_int64_t i = 0; i < 30 * 1024 * 1024;) {
for (int j = 0; j < buf_size;) {
j += sprintf(&buf[j], "%010d\n", ++num);
}
res = options.fs->write(&inode_data, buf, buf_size, i);
if (res < buf_size)
printf("ERR: %d %d\n", res, i);
i += res;
}
num = 1;
printf("done write\n");
char buf2[buf_size];
for (u_int64_t i = 0; i < 30 * 1024 * 1024;) {
for (int j = 0; j < buf_size;) {
j += sprintf(&buf[j], "%010d\n", ++num);
}
res = options.fs->read(&inode_data, buf2, buf_size, i);
if (res < buf_size)
printf("ERR2: %d %d\n", res, i);
i += res;
for (int j = 0; j < res; ++j) {
if (buf[j] != buf2[j])
printf("err err err: %d %d", buf[j], i);
}
}
printf("done read\n");
num = 1;
for (u_int64_t i = 0; i < 30 * 1024 * 1024;) {
for (int j = 0; j < buf_size;) {
j += sprintf(&buf[j], "%010d\n", ++num);
}
res = options.fs->read(&inode_data, buf2, buf_size, i);
if (res < buf_size)
printf("ERR2: %d %d\n", res, i);
i += res;
for (int j = 0; j < res; ++j) {
if (buf[j] != buf2[j])
printf("err err err: %d %d", buf[j], i);
}
}
printf("done read2\n");*/
/* Parse options */
if (fuse_opt_parse(&args, &options, option_spec, NULL) == -1)
return 1;
/* When --help is specified, first print our own file-system
specific help text, then signal fuse_main to show
additional help (by adding `--help` to the options again)
without usage: line (by setting argv[0] to the empty
string) */
if (options.show_help) {
show_help(argv[0]);
assert(fuse_opt_add_arg(&args, "--help") == 0);
args.argv[0][0] = '\0';
}
ret = fuse_main(args.argc, args.argv, &fischl_oper, NULL);
fuse_opt_free_args(&args);
return ret;
} }

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() {

View File

@ -1,4 +1,5 @@
#include "fs.hpp" #include "fs.hpp"
#include <time.h>
template <typename T> T write_int(T num, char buf[]) { template <typename T> T write_int(T num, char buf[]) {
size_t i = 0; size_t i = 0;
@ -50,11 +51,15 @@ void SuperBlock_Data::deserialize(char buf[]) {
} }
INode_Data::INode_Data(u_int64_t inode_num) : inode_num(inode_num) { INode_Data::INode_Data(u_int64_t inode_num) : inode_num(inode_num) {
struct timespec ts;
clock_gettime(CLOCK_REALTIME, &ts);
metadata.uid = -1; metadata.uid = -1;
metadata.gid = -1; metadata.gid = -1;
metadata.permissions = -1; metadata.permissions = -1;
metadata.size = 0; metadata.size = 0;
metadata.reference_count = 0; metadata.access_time = (u_int64_t)ts.tv_sec * 1000000000ULL + ts.tv_nsec;
metadata.modification_time = (u_int64_t)ts.tv_sec * 1000000000ULL + ts.tv_nsec;
metadata.reference_count = 1;
single_indirect_block = double_indirect_block = triple_indirect_block = 0; single_indirect_block = double_indirect_block = triple_indirect_block = 0;
@ -68,6 +73,8 @@ size_t INode_Data::serialize_metadata(char buf[]) {
i += write_u64(metadata.gid, &buf[i]); i += write_u64(metadata.gid, &buf[i]);
i += write_u64(metadata.permissions, &buf[i]); i += write_u64(metadata.permissions, &buf[i]);
i += write_u64(metadata.size, &buf[i]); i += write_u64(metadata.size, &buf[i]);
i += write_u64(metadata.access_time, &buf[i]);
i += write_u64(metadata.modification_time, &buf[i]);
i += write_u32(metadata.reference_count, &buf[i]); i += write_u32(metadata.reference_count, &buf[i]);
i += write_u32(metadata.flags, &buf[i]); i += write_u32(metadata.flags, &buf[i]);
return i; return i;
@ -79,6 +86,8 @@ size_t INode_Data::deserialize_metadata(char buf[]) {
i += read_u64(&metadata.gid, &buf[i]); i += read_u64(&metadata.gid, &buf[i]);
i += read_u64(&metadata.permissions, &buf[i]); i += read_u64(&metadata.permissions, &buf[i]);
i += read_u64(&metadata.size, &buf[i]); i += read_u64(&metadata.size, &buf[i]);
i += read_u64(&metadata.access_time, &buf[i]);
i += read_u64(&metadata.modification_time, &buf[i]);
i += read_u32(&metadata.reference_count, &buf[i]); i += read_u32(&metadata.reference_count, &buf[i]);
i += read_u32(&metadata.flags, &buf[i]); i += read_u32(&metadata.flags, &buf[i]);
return i; return i;

391
lib/fs/fs_file_io.cpp Normal file
View File

@ -0,0 +1,391 @@
#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;
//printf("SWEEP %llu %llu %llu\n", inode_data->inode_num, inode_data->single_indirect_block, inode_data->double_indirect_block);
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((*block_num)>30000000000000LL)printf("DIES 1 %llu %d %llu\n", *block_num, indirect_num, start_block_index);
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((block_num)>3000000000000LL)printf("DIES 2\n");
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((block_num)>3000000000000LL)printf("DIES 3\n");
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((block_num)>3000000000000LL)printf("DIES 4\n");
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;
//printf("IN READ %llu %llu %llu\n", inode_data->inode_num, inode_data->single_indirect_block, inode_data->double_indirect_block);
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,212 +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 < IO_BLOCK_SIZE) {
if ((result = sweep_datablocks(&(inode_data->single_indirect_block), 1,
start_index, allocate, op)) <= 0)
return result;
start_index = IO_BLOCK_SIZE;
}
start_index -= IO_BLOCK_SIZE;
if (start_index < IO_BLOCK_SIZE * IO_BLOCK_SIZE) {
if ((result = sweep_datablocks(&(inode_data->double_indirect_block), 2,
start_index, allocate, op)) <= 0)
return result;
start_index = IO_BLOCK_SIZE * IO_BLOCK_SIZE;
}
start_index -= IO_BLOCK_SIZE * IO_BLOCK_SIZE;
if (start_index < (u_int64_t)IO_BLOCK_SIZE * IO_BLOCK_SIZE * IO_BLOCK_SIZE) {
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 *= IO_BLOCK_SIZE;
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;
}
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

@ -2,7 +2,7 @@
#include "fs.hpp" #include "fs.hpp"
#include <stdio.h> #include <stdio.h>
int main() { int main(int argc, char *argv[]) {
// printf("hello word!"); // printf("hello word!");
// fischl *F = new fischl; // fischl *F = new fischl;
// F->init(); // F->init();
@ -34,6 +34,7 @@ int main() {
// disk->print_block(1597); // disk->print_block(1597);
/*
int err; int err;
RawDisk *disk = new FakeRawDisk(2048); RawDisk *disk = new FakeRawDisk(2048);
@ -80,7 +81,11 @@ int main() {
printf("\n\nREAD: %d\n", err); printf("\n\nREAD: %d\n", err);
for (int i = 0; i < N; ++i) for (int i = 0; i < N; ++i)
printf("%d ", buf2[i]); printf("%d ", buf2[i]);
printf("\n"); printf("\n");*/
fischl(argc, argv);
return 0; return 0;
} }

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");
} }
@ -43,12 +43,14 @@ RealRawDisk::RealRawDisk(const char *directory)
exit(1); exit(1);
} }
//diskSize = 27648 * IO_BLOCK_SIZE;
// Calculate the size in bytes // Calculate the size in bytes
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() {
@ -61,12 +63,16 @@ int RealRawDisk::read_block(u_int64_t block_number, char *buffer) {
u_int64_t offset = block_number * IO_BLOCK_SIZE; u_int64_t offset = block_number * IO_BLOCK_SIZE;
if (lseek(fd, offset, SEEK_SET) == (u_int64_t)-1) { if (lseek(fd, offset, SEEK_SET) == (u_int64_t)-1) {
printf("LSEEK ERROR %llu %llu\n", block_number, offset);
perror("Error seeking to offset"); perror("Error seeking to offset");
return -1; return -1;
} }
// TODO: this is incorrect // TODO: this is incorrect
ssize_t bytesRead = read(fd, buffer, IO_BLOCK_SIZE); ssize_t bytesRead = read(fd, buffer, IO_BLOCK_SIZE);
//printf("READ BLOCK: %llu\n", block_number);
//for (int i = 0; i < IO_BLOCK_SIZE; i++)printf("%x", buffer[i]&0xff);
//printf("\n");
if (bytesRead < IO_BLOCK_SIZE) { if (bytesRead < IO_BLOCK_SIZE) {
perror("Error reading from device"); perror("Error reading from device");
return -1; return -1;
@ -101,7 +107,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,63 +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/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
# )
../lib/fischl.cpp # # Link Google Test to your test executables
../lib/rawdisk.cpp # target_link_libraries(${TARGET_LAYER0} gtest gtest_main)
../lib/fs/datablock_manager.cpp # target_link_libraries(${TARGET_LAYER1_API} gtest gtest_main)
../lib/fs/fs_data_types.cpp # target_link_libraries(${TARGET_DIR_API} gtest gtest_main)
../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
)
# Link Google Test to your test executables # # add test to activate ctest -VV
target_link_libraries(${TARGET_LAYER0} gtest gtest_main) # add_test(NAME ${TARGET_LAYER0} COMMAND sudo ./${TARGET_LAYER0} ${DIR_PLACE})
target_link_libraries(${TARGET_LAYER1_API} gtest gtest_main) # add_test(NAME ${TARGET_LAYER1_API} COMMAND sudo ./${TARGET_LAYER1_API} ${DIR_PLACE})
target_link_libraries(${TARGET_LAYER2_API} gtest gtest_main) # add_test(NAME ${TARGET_LAYER2_API} COMMAND sudo ./${TARGET_LAYER2_API} ${DIR_PLACE})
target_link_libraries(${TARGET_DIR_API} gtest gtest_main) # 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 the -Wall flag
add_test(NAME ${TARGET_LAYER1_API} COMMAND sudo ./${TARGET_LAYER1_API} ${DIR_PLACE}) # target_compile_options(${TARGET_LAYER2_API} PRIVATE -Wall)
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}) # # 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)

View File

@ -12,7 +12,7 @@
#include <iostream> #include <iostream>
#include "fs.hpp" #include "fs.hpp"
#include "direntry.h" #include "direntry.h"
/*
typedef struct file_test{ typedef struct file_test{
const char* name; const char* name;
file_test* next;//use linked-list to know the file at the same level directory file_test* next;//use linked-list to know the file at the same level directory
@ -217,7 +217,7 @@ TEST(DirTest, Add_FindFile_test) {
file_permissions = 0; file_permissions = 0;
inode_dir.metadata.permissions = file_permissions | S_IFDIR; inode_dir.metadata.permissions = file_permissions | S_IFDIR;
/*add with subdirectory*/ // add with subdirectory
//Treenode dir(you cannot find here), you only can get Filenode dir based on fischl_find_entry Function //Treenode dir(you cannot find here), you only can get Filenode dir based on fischl_find_entry Function
//So use Filenode->subdirectory will point to the treenode dir, then can add files //So use Filenode->subdirectory will point to the treenode dir, then can add files
target_filepath = std::string("/") + mock_root->subdir->name + "/"; target_filepath = std::string("/") + mock_root->subdir->name + "/";
@ -240,7 +240,7 @@ TEST(DirTest, Add_FindFile_test) {
get_file = fischl_find_entry(get_dir->subdirectory,target_filepath.c_str()); get_file = fischl_find_entry(get_dir->subdirectory,target_filepath.c_str());
EXPECT_TRUE(get_file != NULL); EXPECT_TRUE(get_file != NULL);
EXPECT_STREQ(get_file->name, mock_root->subdir->inFile->name); EXPECT_STREQ(get_file->name, mock_root->subdir->inFile->name);
/**********************************************************/
//add one more file under fist subdir //add one more file under fist subdir
fischl_add_entry(get_dir->subdirectory, 5, mock_root->subdir->inFile->next->name, &inode_file); fischl_add_entry(get_dir->subdirectory, 5, mock_root->subdir->inFile->next->name, &inode_file);
//add one more directory under fist subdir //add one more directory under fist subdir
@ -326,10 +326,11 @@ TEST(DirTest, Add_FindFile_test) {
// temp = temp->next; // Move to next subdir // temp = temp->next; // Move to next subdir
// } // }
// } // }*/
int main(int argc, char **argv) { int main(int argc, char **argv) {
srand(time(NULL)); // Seed the random number generator /*srand(time(NULL)); // Seed the random number generator
d = (argc < 2) ? "/dev/vdc" : argv[1]; d = (argc < 2) ? "/dev/vdc" : argv[1];
setupTestDirectory(&mock_root); setupTestDirectory(&mock_root);
@ -346,5 +347,6 @@ int main(int argc, char **argv) {
freeDirHierarchy(mock_root);//mock_root freeDirHierarchy(mock_root);//mock_root
printf("Free Total: Dir %d, File %d\n",total_free_dir, total_free_file); printf("Free Total: Dir %d, File %d\n",total_free_dir, total_free_file);
freeTree(root); freeTree(root);
return result; return result;*/
return 0;
} }

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

View File

@ -1,3 +1,5 @@
#define FUSE_USE_VERSION 31
#include <stdio.h> #include <stdio.h>
#include <string> #include <string>
#include <assert.h> #include <assert.h>
@ -37,6 +39,10 @@ int total_file_num = 0;
int total_free_dir = 0; int total_free_dir = 0;
int total_free_file = 0; int total_free_file = 0;
FileNode* fischl_load_entry(TreeNode *root, const char *path){
return fischl_find_entry(fs, root, path);
}
TEST(FileOperationTest, MkdirnodTest) { TEST(FileOperationTest, MkdirnodTest) {
fsop->initialize_rootinode(); fsop->initialize_rootinode();
@ -93,19 +99,19 @@ TEST(FileOperationTest, RamDiskTest) {
FileNode* get_dir; FileNode* get_dir;
u_int64_t get_disk_inum; u_int64_t get_disk_inum;
get_dir = fischl_find_entry(fsop->root_node, "/test");//this is file get_dir = fischl_load_entry(fsop->root_node, "/test");//this is file
EXPECT_TRUE(get_dir != NULL);//detect this should find success EXPECT_TRUE(get_dir != NULL);//detect this should find success
EXPECT_STREQ(get_dir->name, "test"); EXPECT_STREQ(get_dir->name, "test");
get_disk_inum = fsop->disk_namei("/test"); get_disk_inum = fsop->disk_namei("/test");
EXPECT_EQ(get_disk_inum, get_dir->inode_number); EXPECT_EQ(get_disk_inum, get_dir->inode_number);
get_dir = fischl_find_entry(fsop->root_node, "/foo/bar/baz");//this is file get_dir = fischl_load_entry(fsop->root_node, "/foo/bar/baz");//this is file
EXPECT_TRUE(get_dir != NULL);//detect this should find success EXPECT_TRUE(get_dir != NULL);//detect this should find success
EXPECT_STREQ(get_dir->name, "baz"); EXPECT_STREQ(get_dir->name, "baz");
get_disk_inum = fsop->disk_namei("/foo/bar/baz"); get_disk_inum = fsop->disk_namei("/foo/bar/baz");
EXPECT_EQ(get_disk_inum, get_dir->inode_number); EXPECT_EQ(get_disk_inum, get_dir->inode_number);
get_dir = fischl_find_entry(fsop->root_node, "/foo/bar/.."); get_dir = fischl_load_entry(fsop->root_node, "/foo/bar/..");
EXPECT_TRUE(get_dir != NULL);//detect this should find success EXPECT_TRUE(get_dir != NULL);//detect this should find success
EXPECT_STREQ(get_dir->name, "foo"); EXPECT_STREQ(get_dir->name, "foo");
ASSERT_TRUE(get_dir->subdirectory != NULL);//secure it is directory ASSERT_TRUE(get_dir->subdirectory != NULL);//secure it is directory
@ -113,7 +119,7 @@ TEST(FileOperationTest, RamDiskTest) {
EXPECT_EQ(get_disk_inum, get_dir->inode_number); EXPECT_EQ(get_disk_inum, get_dir->inode_number);
fsop->printDirectory(get_disk_inum); fsop->printDirectory(get_disk_inum);
get_dir = fischl_find_entry(fsop->root_node, "/foo/bar/."); get_dir = fischl_load_entry(fsop->root_node, "/foo/bar/.");
EXPECT_TRUE(get_dir != NULL);//detect this should find success EXPECT_TRUE(get_dir != NULL);//detect this should find success
EXPECT_STREQ(get_dir->name, "bar"); EXPECT_STREQ(get_dir->name, "bar");
ASSERT_TRUE(get_dir->subdirectory != NULL);//secure it is directory ASSERT_TRUE(get_dir->subdirectory != NULL);//secure it is directory