Compare commits
2 Commits
bc9a7d0b3c
...
f05cf635da
Author | SHA1 | Date | |
---|---|---|---|
![]() |
f05cf635da | ||
![]() |
26b44b20ba |
@ -24,6 +24,7 @@ public:
|
|||||||
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);
|
||||||
|
bool dir_empty(u_int64_t inode_number);
|
||||||
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_access(const char* path, int mask);
|
||||||
|
@ -12,7 +12,7 @@ class DatablockOperation;
|
|||||||
|
|
||||||
class Fs {
|
class Fs {
|
||||||
public:
|
public:
|
||||||
Fs(RawDisk *disk);
|
Fs(RawDisk *disk, bool load, u_int64_t user_inode_blocks = 0);
|
||||||
~Fs();
|
~Fs();
|
||||||
|
|
||||||
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);
|
||||||
@ -35,6 +35,8 @@ 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);
|
||||||
|
void update_num_used_inodes(int delta);
|
||||||
|
void update_num_used_datablocks(int delta);
|
||||||
|
|
||||||
int sweep_inode_datablocks(INode_Data *inode_data,
|
int sweep_inode_datablocks(INode_Data *inode_data,
|
||||||
u_int64_t start_block_index, bool allocate,
|
u_int64_t start_block_index, bool allocate,
|
||||||
|
@ -15,6 +15,10 @@ class SuperBlock_Data {
|
|||||||
public:
|
public:
|
||||||
u_int64_t free_list_head;
|
u_int64_t free_list_head;
|
||||||
u_int64_t inode_list_head;
|
u_int64_t inode_list_head;
|
||||||
|
u_int64_t num_inode_blocks;
|
||||||
|
u_int64_t num_used_inodes;
|
||||||
|
u_int64_t num_data_blocks;
|
||||||
|
u_int64_t num_used_data_blocks;
|
||||||
SuperBlock_Data();
|
SuperBlock_Data();
|
||||||
void serialize(char buf[]);
|
void serialize(char buf[]);
|
||||||
void deserialize(char buf[]);
|
void deserialize(char buf[]);
|
||||||
|
@ -501,6 +501,25 @@ int FilesOperation::fischl_readdir(const char *path, void *buf,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool FilesOperation::dir_empty(u_int64_t inode_number) {
|
||||||
|
INode_Data inode;
|
||||||
|
inode.inode_num = 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);
|
||||||
|
if (ent.inode_number && strcmp(ent.file_name, ".") &&
|
||||||
|
strcmp(ent.file_name, "..")) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
int FilesOperation::fischl_releasedir(const char *path,
|
int FilesOperation::fischl_releasedir(const char *path,
|
||||||
struct fuse_file_info *fi) {
|
struct fuse_file_info *fi) {
|
||||||
if (fischl_load_entry(root_node, path) == NULL)
|
if (fischl_load_entry(root_node, path) == NULL)
|
||||||
@ -559,6 +578,16 @@ int FilesOperation::fischl_opendir(const char *path,
|
|||||||
}
|
}
|
||||||
|
|
||||||
int FilesOperation::fischl_rmdir(const char *path) {
|
int FilesOperation::fischl_rmdir(const char *path) {
|
||||||
|
u_int64_t fh = namei(path);
|
||||||
|
if (fh == -1) {
|
||||||
|
return -ENOENT;
|
||||||
|
}
|
||||||
|
printf("in rmdir\n");
|
||||||
|
if(!dir_empty(fh)){
|
||||||
|
return -ENOTEMPTY;
|
||||||
|
}
|
||||||
|
printf("rmdir: not empty\n");
|
||||||
|
|
||||||
char *pathdup = strdup(path);
|
char *pathdup = strdup(path);
|
||||||
char *lastSlash = strrchr(pathdup, '/');
|
char *lastSlash = strrchr(pathdup, '/');
|
||||||
*lastSlash = '\0';
|
*lastSlash = '\0';
|
||||||
@ -1324,10 +1353,11 @@ int FilesOperation::fischl_utimens(const char *path,
|
|||||||
|
|
||||||
int FilesOperation::fischl_statfs(const char *path, struct statvfs *stbuf) {
|
int FilesOperation::fischl_statfs(const char *path, struct statvfs *stbuf) {
|
||||||
stbuf->f_bsize = 4096;
|
stbuf->f_bsize = 4096;
|
||||||
stbuf->f_blocks = 0;
|
stbuf->f_frsize = IO_BLOCK_SIZE;
|
||||||
stbuf->f_bfree = 0;
|
stbuf->f_blocks = fs->superblock.num_data_blocks;
|
||||||
stbuf->f_files = 0;
|
stbuf->f_bfree = fs->superblock.num_data_blocks - fs->superblock.num_used_data_blocks;
|
||||||
stbuf->f_ffree = 0;
|
stbuf->f_files = fs->superblock.num_inode_blocks * 8;
|
||||||
|
stbuf->f_ffree = fs->superblock.num_inode_blocks * 8 - fs->superblock.num_used_inodes;
|
||||||
stbuf->f_namemax = 256;
|
stbuf->f_namemax = 256;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -226,8 +226,21 @@ int fischl(int argc, char *argv[])
|
|||||||
printf("WRONG l/n ARGUMENTS\n");
|
printf("WRONG l/n ARGUMENTS\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
options.fs = new Fs(options.H);
|
if(options.load){
|
||||||
if(!options.load){
|
options.fs = new Fs(options.H, true);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
uint64_t total_blocks = options.H->diskSize / IO_BLOCK_SIZE;
|
||||||
|
uint64_t max_inode_blocks = options.H->diskSize / IO_BLOCK_SIZE - 2 - DATABLOCKS_PER_BITMAP_BLOCK;
|
||||||
|
printf("The block device contains %llu blocks\n", total_blocks);
|
||||||
|
printf("Choose the number of blocks to store inodes: 1 ~ %llu\n", max_inode_blocks);
|
||||||
|
uint64_t user_inode_blocks;
|
||||||
|
scanf("%llu", &user_inode_blocks);
|
||||||
|
if (user_inode_blocks < 1 || user_inode_blocks > max_inode_blocks) {
|
||||||
|
printf("Invalid number of blocks to store inodes\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
options.fs = new Fs(options.H, false, user_inode_blocks);
|
||||||
printf("FORMAT %d\n", options.fs->format());
|
printf("FORMAT %d\n", options.fs->format());
|
||||||
}
|
}
|
||||||
options.fsop = new FilesOperation(*options.H, options.fs);
|
options.fsop = new FilesOperation(*options.H, options.fs);
|
||||||
@ -311,4 +324,4 @@ int fischl(int argc, char *argv[])
|
|||||||
ret = fuse_main(args.argc, args.argv, &fischl_oper, NULL);
|
ret = fuse_main(args.argc, args.argv, &fischl_oper, NULL);
|
||||||
fuse_opt_free_args(&args);
|
fuse_opt_free_args(&args);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -88,6 +88,8 @@ int DataBlock_Manager_Bitmap::new_datablock(u_int64_t *block_num) {
|
|||||||
return err;
|
return err;
|
||||||
|
|
||||||
(*block_num) = block_num_;
|
(*block_num) = block_num_;
|
||||||
|
fs->update_num_used_datablocks(1);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -119,6 +121,7 @@ int DataBlock_Manager_Bitmap::free_datablock(u_int64_t block_num) {
|
|||||||
if ((err = fs->save_free_list_head(bitmap_block_num)) < 0)
|
if ((err = fs->save_free_list_head(bitmap_block_num)) < 0)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
|
fs->update_num_used_datablocks(-1);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
// placing almost full bitmaps back at start of freelist is slow
|
// placing almost full bitmaps back at start of freelist is slow
|
||||||
|
@ -1,13 +1,25 @@
|
|||||||
#include "fs.hpp"
|
#include "fs.hpp"
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
Fs::Fs(RawDisk *disk) : disk(disk) {
|
Fs::Fs(RawDisk *disk, bool load, uint64_t user_inode_blocks) : 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);
|
// Determine the num inode blocks
|
||||||
|
uint64_t num_inode_blocks = 0; // The superblock is not loaded from disk here; it is done in FilesOperation::initialize called by fischl_init
|
||||||
|
if(load) {
|
||||||
|
load_superblock();
|
||||||
|
num_inode_blocks = superblock.num_inode_blocks;
|
||||||
|
} else {
|
||||||
|
num_inode_blocks = user_inode_blocks;
|
||||||
|
superblock.num_inode_blocks = num_inode_blocks;
|
||||||
|
superblock.num_used_inodes = 0;
|
||||||
|
superblock.num_data_blocks = disk->diskSize / IO_BLOCK_SIZE - 1 - num_inode_blocks;
|
||||||
|
superblock.num_used_data_blocks = 0;
|
||||||
|
}
|
||||||
|
assert((disk->diskSize / IO_BLOCK_SIZE) >
|
||||||
|
2 + num_inode_blocks + DATABLOCKS_PER_BITMAP_BLOCK);
|
||||||
|
inode_manager = new INode_Manager_Freelist(this, 1, 1 + num_inode_blocks);
|
||||||
datablock_manager = new DataBlock_Manager_Bitmap(
|
datablock_manager = 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() {
|
||||||
@ -68,4 +80,12 @@ int Fs::save_inode_list_head(u_int64_t new_inode_list_head) {
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Fs::update_num_used_inodes(int delta) {
|
||||||
|
superblock.num_used_inodes += delta;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Fs::update_num_used_datablocks(int delta) {
|
||||||
|
superblock.num_used_data_blocks += delta;
|
||||||
}
|
}
|
@ -36,18 +36,27 @@ size_t read_u32(u_int32_t *num, char buf[]) {
|
|||||||
SuperBlock_Data::SuperBlock_Data() {
|
SuperBlock_Data::SuperBlock_Data() {
|
||||||
free_list_head = 0;
|
free_list_head = 0;
|
||||||
inode_list_head = 0;
|
inode_list_head = 0;
|
||||||
|
num_inode_blocks = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SuperBlock_Data::serialize(char buf[]) {
|
void SuperBlock_Data::serialize(char buf[]) {
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
i += write_u64(free_list_head, &buf[i]);
|
i += write_u64(free_list_head, &buf[i]);
|
||||||
i += write_u64(inode_list_head, &buf[i]);
|
i += write_u64(inode_list_head, &buf[i]);
|
||||||
|
i += write_u64(num_inode_blocks, &buf[i]);
|
||||||
|
i += write_u64(num_used_inodes, &buf[i]);
|
||||||
|
i += write_u64(num_data_blocks, &buf[i]);
|
||||||
|
i += write_u64(num_used_data_blocks, &buf[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SuperBlock_Data::deserialize(char buf[]) {
|
void SuperBlock_Data::deserialize(char buf[]) {
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
i += read_u64(&free_list_head, &buf[i]);
|
i += read_u64(&free_list_head, &buf[i]);
|
||||||
i += read_u64(&inode_list_head, &buf[i]);
|
i += read_u64(&inode_list_head, &buf[i]);
|
||||||
|
i += read_u64(&num_inode_blocks, &buf[i]);
|
||||||
|
i += read_u64(&num_used_inodes, &buf[i]);
|
||||||
|
i += read_u64(&num_data_blocks, &buf[i]);
|
||||||
|
i += read_u64(&num_used_data_blocks, &buf[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
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) {
|
||||||
|
@ -88,6 +88,7 @@ int INode_Manager_Freelist::new_inode(u_int64_t uid, u_int64_t gid,
|
|||||||
inode_data->inode_num = 0xFFFFFFFFFFFFFFFF;
|
inode_data->inode_num = 0xFFFFFFFFFFFFFFFF;
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
fs->update_num_used_inodes(1);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -111,6 +112,7 @@ int INode_Manager_Freelist::free_inode(INode_Data *inode_data) {
|
|||||||
|
|
||||||
if ((err = fs->save_inode_list_head(inode_data->inode_num)) < 0)
|
if ((err = fs->save_inode_list_head(inode_data->inode_num)) < 0)
|
||||||
return err;
|
return err;
|
||||||
|
fs->update_num_used_inodes(-1);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user