support arbitrary number of files in each folder (previously 64)

This commit is contained in:
Ziao 2023-11-18 19:25:53 -08:00
parent 1259cf5487
commit 1e735ea7d0
3 changed files with 59 additions and 29 deletions

View File

@ -14,6 +14,7 @@ class FilesOperation {
void initialize_rootinode();
void printDirectory(u_int64_t);
u_int64_t create_new_inode(u_int64_t parent_inode_number, const char* name, mode_t mode);
// int unlink_inode(u_int64_t inode_number);
u_int64_t namei(const char* path);
u_int64_t fischl_mkdir(const char*, mode_t);
u_int64_t fischl_mknod(const char*, mode_t);

View File

@ -137,6 +137,7 @@ void FilesOperation::initialize_rootinode() {
}
void FilesOperation::printDirectory(u_int64_t inode_number) {
// limit to first datablock
INode inode;
inode.inode_construct(inode_number, disk);
char buffer[IO_BLOCK_SIZE] = {0};
@ -144,7 +145,7 @@ void FilesOperation::printDirectory(u_int64_t inode_number) {
DirectoryEntry ent;
for(int i=0;i<=IO_BLOCK_SIZE-64;i+=64){
ent.deserialize(buffer+i);
printf("%d(%s)\t", i, ent.file_name);
if (ent.inode_number) printf("%s\t%llu;\t", ent.file_name, ent.inode_number);
}
printf("\n");
}
@ -161,29 +162,39 @@ u_int64_t FilesOperation::create_new_inode(u_int64_t parent_inode_number, const
printf("Parent Inode is not a directory\n");
return -1;
}
char buffer[IO_BLOCK_SIZE] = {0};
if (inode.size > 0) read_datablock(inode, 0, buffer);
// do create inode
u_int64_t new_inode_number = 0;
DirectoryEntry ent;
for(int i=0;i<=IO_BLOCK_SIZE-64;i+=64){
ent.deserialize(buffer+i);
if (ent.inode_number == 0) {
new_inode_number = inop.inode_allocate(disk);
ent.inode_number = new_inode_number;
strcpy(ent.file_name, name);
ent.serialize(buffer+i);
char rw_buffer[IO_BLOCK_SIZE] = {0};
for (u_int64_t idx=0; idx<inode.size; idx++) {
read_datablock(inode, idx, rw_buffer);
DirectoryEntry ent;
for(int i=0;i<=IO_BLOCK_SIZE-64;i+=64){
ent.deserialize(rw_buffer+i);
if (ent.inode_number == 0) {
new_inode_number = inop.inode_allocate(disk);
ent.inode_number = new_inode_number;
strcpy(ent.file_name, name);
ent.serialize(rw_buffer+i);
break;
}
}
if (new_inode_number) {
write_datablock(inode, idx, rw_buffer);
break;
}
}
if (new_inode_number == 0) {
perror("Failed to create file in directory: First datablock full");
return -1;
} else {
write_datablock(inode, 0, buffer);
if (!new_inode_number) {
char write_buffer[IO_BLOCK_SIZE] = {0};
DirectoryEntry ent;
new_inode_number = inop.inode_allocate(disk);
ent.inode_number = new_inode_number;
strcpy(ent.file_name, name);
ent.serialize(write_buffer);
write_datablock(inode, inode.size, write_buffer);
inode.inode_save(disk);
}
inode.inode_save(disk);
// initialize new file
INode *get_inode = new_inode(new_inode_number, mode);
@ -212,16 +223,20 @@ u_int64_t FilesOperation::namei(const char* path) {
printf("namei: %s is not a non-empty directory\n", current_dirname.c_str());
return -1;
}
char buffer[IO_BLOCK_SIZE] = {0};
read_datablock(inode, 0, buffer);
u_int64_t new_inode_number = 0;
DirectoryEntry ent;
for(int i=0;i<=IO_BLOCK_SIZE-64;i+=64){
ent.deserialize(buffer+i);
if (strcmp(ent.file_name, new_name.c_str()) == 0) {
new_inode_number = ent.inode_number;
break;
char buffer[IO_BLOCK_SIZE] = {0};
for(u_int64_t idx=0; idx<inode.size; idx++) {
read_datablock(inode, idx, buffer);
DirectoryEntry ent;
for(int i=0;i<=IO_BLOCK_SIZE-64;i+=64){
ent.deserialize(buffer+i);
if (strcmp(ent.file_name, new_name.c_str()) == 0) {
new_inode_number = ent.inode_number;
break;
}
}
if (new_inode_number) break;
}
if (!new_inode_number) {
printf("namei: no name matching %s under directory %s\n", new_name.c_str(), current_dirname.c_str());
@ -238,7 +253,6 @@ u_int64_t FilesOperation::namei(const char* path) {
// path = "/notnonemptydir/foo" should raise error
}
/**/
u_int64_t FilesOperation::fischl_mkdir(const char* path, mode_t mode) {
//check path
char *pathdup = strdup(path);

View File

@ -1,5 +1,5 @@
#include <stdio.h>
#include <string.h>
#include <string>
#include <assert.h>
#include "files.h"
@ -19,8 +19,10 @@ int main(int argc, char *argv[]) {
printf("/test is inode %llu, it is a file\n", file1);
u_int64_t file2 = fsop.fischl_mkdir("/foo",0);
printf("/foo is inode %llu, it is a directory\n", file2);
fsop.printDirectory(1);
u_int64_t file3 = fsop.fischl_mkdir("/foo/bar",0);
printf("/foo/bar is inode %llu, it is a directory\n", file3);
fsop.printDirectory(file2);
u_int64_t file4 = fsop.fischl_mknod("/foo/bar/baz",0);
printf("/foo/bar/baz is inode %llu, it is a file\n", file4);
// the following three testcases will fail
@ -73,4 +75,17 @@ int main(int argc, char *argv[]) {
assert(read_buffer[0] == '4');
fsop.read_datablock(inode_read, 101, read_buffer);
assert(read_buffer[0] == '5');
// pressure test create directory
printf("=== Part 5: pressure test create files ===\n");
u_int64_t file_pressure = fsop.fischl_mkdir("/pressure", 0);
u_int64_t inode_numbers[700];
std::string prefix = "/pressure/";
for(int i=0;i<700;i++){
inode_numbers[i] = fsop.fischl_mkdir((prefix+std::to_string(i)).c_str(), 0);
}
for(int i=0;i<700;i++){
u_int64_t inode_number = fsop.namei((prefix+std::to_string(i)).c_str());
assert(inode_number == inode_numbers[i]);
}
}