From 26eebaf03a5fc393fb48ac9497fc092d5fb5f374 Mon Sep 17 00:00:00 2001 From: fslongjin Date: Tue, 13 Sep 2022 16:17:35 +0800 Subject: [PATCH] =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=96=87=E4=BB=B6=E5=A4=B9?= =?UTF-8?q?=E6=97=B6=E5=9B=9E=E6=94=B6dentry=E7=BC=93=E5=AD=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .vscode/settings.json | 3 +- kernel/filesystem/VFS/VFS.c | 49 +++++++++---------- kernel/filesystem/VFS/VFS.h | 8 ++++ kernel/filesystem/VFS/dcache.c | 76 +++++++++++++++++++++++++++--- kernel/filesystem/VFS/internal.h | 10 +++- kernel/filesystem/devfs/chardev.c | 4 +- kernel/filesystem/devfs/devfs.c | 10 ++-- kernel/filesystem/devfs/internal.h | 13 ++--- kernel/filesystem/fat32/fat32.c | 18 +++---- user/apps/shell/cmd.c | 4 +- 10 files changed, 132 insertions(+), 63 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index e95ee48f..9e952d3a 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -136,7 +136,8 @@ "mount.h": "c", "internal.h": "c", "devfs.h": "c", - "devfs-types.h": "c" + "devfs-types.h": "c", + "chardev.h": "c" }, "C_Cpp.errorSquiggles": "Enabled", "esbonio.sphinx.confDir": "" diff --git a/kernel/filesystem/VFS/VFS.c b/kernel/filesystem/VFS/VFS.c index 205efc4f..78d36a03 100644 --- a/kernel/filesystem/VFS/VFS.c +++ b/kernel/filesystem/VFS/VFS.c @@ -155,18 +155,19 @@ struct vfs_dir_entry_t *vfs_path_walk(const char *path, uint64_t flags) while (true) { // 提取出下一级待搜索的目录名或文件名,并保存在dEntry_name中 - char *tmp_path = path; + const char *tmp_path = path; while ((*path && *path != '\0') && (*path != '/')) ++path; int tmp_path_len = path - tmp_path; // 搜索是否有dentry缓存 { - char bk = *(tmp_path + tmp_path_len); - *(tmp_path + tmp_path_len) = '\0'; - // kdebug("to search:%s", tmp_path); - dentry = vfs_search_dentry_list(parent, tmp_path); - // kdebug("search done, dentry=%#018lx", dentry); - *(tmp_path + tmp_path_len) = bk; + char *tmpname = kzalloc(tmp_path_len + 1, 0); + strncpy(tmpname, tmp_path, tmp_path_len); + tmpname[tmp_path_len] = '\0'; + + dentry = vfs_search_dentry_list(parent, tmpname); + + kfree(tmpname); } // 如果没有找到dentry缓存,则申请新的dentry @@ -301,8 +302,8 @@ int64_t vfs_mkdir(const char *path, mode_t mode, bool from_userland) return -EEXIST; } - struct vfs_dir_entry_t *subdir_dentry = (struct vfs_dir_entry_t *)kmalloc(sizeof(struct vfs_dir_entry_t), 0); - memset((void *)subdir_dentry, 0, sizeof(struct vfs_dir_entry_t)); + struct vfs_dir_entry_t *subdir_dentry = (struct vfs_dir_entry_t *)kzalloc(sizeof(struct vfs_dir_entry_t), 0); + list_init(&subdir_dentry->subdirs_list); list_init(&subdir_dentry->child_node_list); if (path[pathlen - 1] == '/') @@ -450,23 +451,6 @@ uint64_t do_open(const char *filename, int flags) if ((flags & O_DIRECTORY) && (dentry->dir_inode->attribute != VFS_IF_DIR)) return -ENOTDIR; - // // 要找的目标是文件夹 - // if ((flags & O_DIRECTORY) && dentry->dir_inode->attribute == VFS_IF_DIR) - // return -EISDIR; - - // // todo: 引入devfs后删除这段代码 - // // 暂时遇到设备文件的话,就将其first clus设置为特定值 - // if (path_len >= 5 && filename[0] == '/' && filename[1] == 'd' && filename[2] == 'e' && filename[3] == 'v' && filename[4] == '/') - // { - // if (dentry->dir_inode->attribute & VFS_IF_FILE) - // { - // // 对于fat32文件系统上面的设备文件,设置其起始扇区 - // ((struct fat32_inode_info_t *)(dentry->dir_inode->private_inode_info))->first_clus |= 0xf0000000; - // dentry->dir_inode->sb->sb_ops->write_inode(dentry->dir_inode); - // dentry->dir_inode->attribute |= VFS_IF_DEVICE; - // } - // } - // 创建文件描述符 struct vfs_file_t *file_ptr = (struct vfs_file_t *)kzalloc(sizeof(struct vfs_file_t), 0); @@ -662,6 +646,19 @@ uint64_t sys_rmdir(struct pt_regs *regs) else return vfs_rmdir((char *)regs->r8, false); } + +/** + * @brief 分配inode并将引用计数初始化为1 + * + * @return struct vfs_index_node_t * 分配得到的inode + */ +struct vfs_index_node_t *vfs_alloc_inode() +{ + struct vfs_index_node_t *inode = kzalloc(sizeof(struct vfs_index_node_t), 0); + inode->ref_count = 1; // 初始化引用计数为1 + return inode; +} + /** * @brief 初始化vfs * diff --git a/kernel/filesystem/VFS/VFS.h b/kernel/filesystem/VFS/VFS.h index dfbba17f..d3a6b655 100644 --- a/kernel/filesystem/VFS/VFS.h +++ b/kernel/filesystem/VFS/VFS.h @@ -75,6 +75,7 @@ struct vfs_index_node_t uint64_t file_size; // 文件大小 uint64_t blocks; // 占用的扇区数 uint64_t attribute; + int32_t ref_count; // 引用计数 struct vfs_superblock_t *sb; struct vfs_file_operations_t *file_ops; @@ -220,6 +221,13 @@ int vfs_init(); */ struct vfs_dir_entry_t *vfs_alloc_dentry(const int name_size); +/** + * @brief 分配inode并将引用计数初始化为1 + * + * @return struct vfs_index_node_t * 分配得到的inode + */ +struct vfs_index_node_t * vfs_alloc_inode(); + /** * @brief 打开文件 * diff --git a/kernel/filesystem/VFS/dcache.c b/kernel/filesystem/VFS/dcache.c index 452d583f..d5c43d82 100644 --- a/kernel/filesystem/VFS/dcache.c +++ b/kernel/filesystem/VFS/dcache.c @@ -1,19 +1,83 @@ #include "internal.h" +#include +#include /** * @brief 释放dentry - * + * * @param dentry 目标dentry */ -void vfs_dentry_put(struct vfs_dir_entry_t * dentry) +void vfs_dentry_put(struct vfs_dir_entry_t *dentry) { + int retval = 0; + uint64_t in_value = 0; // todo: 加锁、放锁 - list_del(&dentry->child_node_list);// 从父dentry中删除 + // 创建一个用来存放指向dentry的指针的fifo队列 + struct kfifo_t fifo; + // 暂时假设队列大小为1024个元素 + // todo: 实现队列的自动扩容功能 + retval = kfifo_alloc(&fifo, 1024 * sizeof(uint64_t), 0); - // todo: 清除子目录的dentry + if (retval != 0) + goto failed; - dentry->dir_ops->release(dentry); + // 将根dentry加入队列 + in_value = (uint64_t)dentry; + kfifo_in(&fifo, &in_value, sizeof(uint64_t)); + list_del(&dentry->child_node_list); // 从父dentry中删除 - kfree(dentry); + while (!kfifo_empty(&fifo)) + { + // 取出队列中的下一个元素 + kfifo_out(&fifo, &dentry, sizeof(uint64_t)); + BUG_ON(dentry == NULL); + struct List *list = &dentry->subdirs_list; + if (!list_empty(list)) + { + // 将当前dentry下的所有dentry加入队列 + do + { + list = list_next(list); + in_value = (uint64_t)container_of(list, struct vfs_dir_entry_t, child_node_list); + if (in_value != NULL) + kfifo_in(&fifo, &in_value, sizeof(uint64_t)); + + } while (list_next(list) != (&dentry->subdirs_list)); + } + + // 释放inode + vfs_free_inode(dentry->dir_inode); + + // 若当前dentry是否为挂载点,则umount + if (is_local_mountpoint(dentry)) + do_umount(dentry); + + dentry->dir_ops->release(dentry); + kfree(dentry); + } + kfifo_free_alloc(&fifo); + return; +failed:; + if (fifo.buffer != NULL) + kfifo_free_alloc(&fifo); + kerror("dentry_put failed."); +} + +/** + * @brief 释放inode + * + * @param inode 待释放的inode + * @return int 错误码 + */ +int vfs_free_inode(struct vfs_index_node_t *inode) +{ + --inode->ref_count; + BUG_ON(inode->ref_count < 0); + if (inode->ref_count == 0) + { + kfree(inode->private_inode_info); + kfree(inode); + } + return 0; } \ No newline at end of file diff --git a/kernel/filesystem/VFS/internal.h b/kernel/filesystem/VFS/internal.h index 0c807024..eb100ece 100644 --- a/kernel/filesystem/VFS/internal.h +++ b/kernel/filesystem/VFS/internal.h @@ -38,4 +38,12 @@ static inline bool is_local_mountpoint(struct vfs_dir_entry_t *dentry) * * @param dentry 目标dentry */ -void vfs_dentry_put(struct vfs_dir_entry_t * dentry); \ No newline at end of file +void vfs_dentry_put(struct vfs_dir_entry_t * dentry); + +/** + * @brief 释放inode + * + * @param inode 待释放的inode + * @return int 错误码 + */ +int vfs_free_inode(struct vfs_index_node_t * inode); \ No newline at end of file diff --git a/kernel/filesystem/devfs/chardev.c b/kernel/filesystem/devfs/chardev.c index 786ea745..cdda059d 100644 --- a/kernel/filesystem/devfs/chardev.c +++ b/kernel/filesystem/devfs/chardev.c @@ -1,5 +1,7 @@ #include "chardev.h" #include "internal.h" +#include + #include #include #include @@ -55,7 +57,7 @@ int __devfs_chardev_register(struct devfs_private_inode_info_t *private_info, st struct vfs_dir_entry_t *dentry = vfs_alloc_dentry(namelen + 1); __devfs_fill_dentry(dentry, devname); - __devfs_fill_inode(dentry, __devfs_alloc_inode(), VFS_IF_DEVICE, private_info); + __devfs_fill_inode(dentry, vfs_alloc_inode(), VFS_IF_DEVICE, private_info); // 将dentry挂载到char文件夹下 __devfs_dentry_bind_parent(chardev_folder_dentry, dentry); diff --git a/kernel/filesystem/devfs/devfs.c b/kernel/filesystem/devfs/devfs.c index 19be1711..0add5bd1 100644 --- a/kernel/filesystem/devfs/devfs.c +++ b/kernel/filesystem/devfs/devfs.c @@ -33,11 +33,11 @@ struct vfs_superblock_t *devfs_read_superblock(struct block_device *blk) return &devfs_sb; } -static void devfs_write_superblock(struct vfs_superblock_t *sb) {return 0; } +static void devfs_write_superblock(struct vfs_superblock_t *sb) {return ; } -static void devfs_put_superblock(struct vfs_superblock_t *sb) {return 0; } +static void devfs_put_superblock(struct vfs_superblock_t *sb) {return ; } -static void devfs_write_inode(struct vfs_index_node_t *inode) {return 0; } +static void devfs_write_inode(struct vfs_index_node_t *inode) {return ; } struct vfs_super_block_operations_t devfs_sb_ops = { .write_superblock = &devfs_write_superblock, @@ -146,7 +146,7 @@ static struct vfs_dir_entry_t *devfs_lookup(struct vfs_index_node_t *parent_inod */ static long devfs_mkdir(struct vfs_index_node_t *inode, struct vfs_dir_entry_t *dEntry, int mode) { - dEntry->dir_inode = (struct vfs_index_node_t *)kzalloc(sizeof(struct vfs_index_node_t), 0); + dEntry->dir_inode = vfs_alloc_inode(); dEntry->dir_inode->file_ops = &devfs_file_ops; dEntry->dir_inode->inode_ops = &devfs_inode_ops; dEntry->dir_ops = &devfs_dentry_ops; @@ -181,7 +181,7 @@ struct vfs_filesystem_type_t devfs_fs_type = static __always_inline void __devfs_init_root_inode() { - devfs_root_dentry->dir_inode = (struct vfs_index_node_t *)kzalloc(sizeof(struct vfs_index_node_t), 0); + devfs_root_dentry->dir_inode = vfs_alloc_inode(); devfs_root_dentry->dir_inode->file_ops = &devfs_file_ops; devfs_root_dentry->dir_inode->inode_ops = &devfs_inode_ops; diff --git a/kernel/filesystem/devfs/internal.h b/kernel/filesystem/devfs/internal.h index 98a8e5d3..1bd1beb7 100644 --- a/kernel/filesystem/devfs/internal.h +++ b/kernel/filesystem/devfs/internal.h @@ -9,9 +9,6 @@ extern struct vfs_file_operations_t devfs_file_ops; extern struct vfs_inode_operations_t devfs_inode_ops; extern struct vfs_superblock_t devfs_sb; -// 分配inode -#define __devfs_alloc_inode() ((struct vfs_index_node_t *)kzalloc(sizeof(struct vfs_index_node_t), 0)) - /** * @brief 在devfs中注册字符设备(该函数只应被devfs调用) * @@ -101,9 +98,7 @@ static inline void __devfs_fill_dentry(struct vfs_dir_entry_t *dentry, const cha * @param parent 父目录项 * @param dentry 子目录项 */ -#define __devfs_dentry_bind_parent(parent_dentry, dentry) \ - do \ - { \ - (dentry)->parent = (parent_dentry); \ - list_append(&((parent_dentry)->subdirs_list), &((dentry)->child_node_list)); \ - } while (0) \ No newline at end of file +#define __devfs_dentry_bind_parent(parent_dentry, dentry) ({ \ + (dentry)->parent = (parent_dentry); \ + list_append(&((parent_dentry)->subdirs_list), &((dentry)->child_node_list)); \ +}) diff --git a/kernel/filesystem/fat32/fat32.c b/kernel/filesystem/fat32/fat32.c index 528ceedb..68b31fed 100644 --- a/kernel/filesystem/fat32/fat32.c +++ b/kernel/filesystem/fat32/fat32.c @@ -287,8 +287,7 @@ struct vfs_dir_entry_t *fat32_lookup(struct vfs_index_node_t *parent_inode, stru } } find_lookup_success:; // 找到目标dentry - struct vfs_index_node_t *p = (struct vfs_index_node_t *)kmalloc(sizeof(struct vfs_index_node_t), 0); - memset(p, 0, sizeof(struct vfs_index_node_t)); + struct vfs_index_node_t *p = vfs_alloc_inode(); p->file_size = tmp_dEntry->DIR_FileSize; // 计算文件占用的扇区数, 由于最小存储单位是簇,因此需要按照簇的大小来对齐扇区 @@ -299,8 +298,7 @@ find_lookup_success:; // 找到目标dentry p->inode_ops = &fat32_inode_ops; // 为inode的与文件系统相关的信息结构体分配空间 - p->private_inode_info = (void *)kmalloc(sizeof(fat32_inode_info_t), 0); - memset(p->private_inode_info, 0, sizeof(fat32_inode_info_t)); + p->private_inode_info = (void *)kzalloc(sizeof(fat32_inode_info_t), 0); finode = (fat32_inode_info_t *)p->private_inode_info; finode->first_clus = ((tmp_dEntry->DIR_FstClusHI << 16) | tmp_dEntry->DIR_FstClusLO) & 0x0fffffff; @@ -387,8 +385,7 @@ struct vfs_superblock_t *fat32_read_superblock(struct block_device *blk) sb_ptr->root->name_length = 1; // 为root目录项分配index node - sb_ptr->root->dir_inode = (struct vfs_index_node_t *)kmalloc(sizeof(struct vfs_index_node_t), 0); - memset(sb_ptr->root->dir_inode, 0, sizeof(struct vfs_index_node_t)); + sb_ptr->root->dir_inode = vfs_alloc_inode(); sb_ptr->root->dir_inode->inode_ops = &fat32_inode_ops; sb_ptr->root->dir_inode->file_ops = &fat32_file_ops; sb_ptr->root->dir_inode->file_size = 0; @@ -819,13 +816,11 @@ long fat32_create(struct vfs_index_node_t *parent_inode, struct vfs_dir_entry_t if (dest_dEntry->dir_inode != NULL) return -EEXIST; - struct vfs_index_node_t *inode = (struct vfs_index_node_t *)kmalloc(sizeof(struct vfs_index_node_t), 0); - memset((void *)inode, 0, sizeof(struct vfs_index_node_t)); + struct vfs_index_node_t *inode = vfs_alloc_inode(); dest_dEntry->dir_inode = inode; dest_dEntry->dir_ops = &fat32_dEntry_ops; - struct fat32_inode_info_t *finode = (struct fat32_inode_info_t *)kmalloc(sizeof(struct fat32_inode_info_t), 0); - memset((void *)finode, 0, sizeof(struct fat32_inode_info_t)); + struct fat32_inode_info_t *finode = (struct fat32_inode_info_t *)kzalloc(sizeof(struct fat32_inode_info_t), 0); inode->attribute = VFS_IF_FILE; inode->file_ops = &fat32_file_ops; inode->file_size = 0; @@ -931,8 +926,7 @@ int64_t fat32_mkdir(struct vfs_index_node_t *parent_inode, struct vfs_dir_entry_ struct fat32_Directory_t *empty_fat32_dentry = fat32_find_empty_dentry(parent_inode, cnt_longname + 1, 0, &tmp_dentry_sector, &tmp_parent_dentry_clus, &tmp_dentry_clus_buf_addr); // ====== 初始化inode ======= - struct vfs_index_node_t *inode = (struct vfs_index_node_t *)kmalloc(sizeof(struct vfs_index_node_t), 0); - memset(inode, 0, sizeof(struct vfs_index_node_t)); + struct vfs_index_node_t *inode = vfs_alloc_inode(); inode->attribute = VFS_IF_DIR; inode->blocks = fsbi->sec_per_clus; inode->file_ops = &fat32_file_ops; diff --git a/user/apps/shell/cmd.c b/user/apps/shell/cmd.c index 6b5d6d1f..5828c7da 100644 --- a/user/apps/shell/cmd.c +++ b/user/apps/shell/cmd.c @@ -388,7 +388,7 @@ int shell_cmd_mkdir(int argc, char **argv) { full_path = get_target_filepath(argv[1], &result_path_len); } - printf("mkdir: full_path = %s\n", full_path); + // printf("mkdir: full_path = %s\n", full_path); int retval = mkdir(full_path, 0); if (argv != NULL) @@ -414,7 +414,7 @@ int shell_cmd_rmdir(int argc, char **argv) else full_path = get_target_filepath(argv[1], &result_path_len); int retval = rmdir(full_path); - printf("rmdir: path=%s, retval=%d", full_path, retval); + // printf("rmdir: path=%s, retval=%d\n", full_path, retval); if (argv != NULL) free(argv);