瀏覽代碼

删除文件夹时回收dentry缓存

fslongjin 2 年之前
父節點
當前提交
26eebaf03a

+ 2 - 1
.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": ""

+ 23 - 26
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
  *

+ 8 - 0
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 打开文件
  *

+ 70 - 6
kernel/filesystem/VFS/dcache.c

@@ -1,19 +1,83 @@
 #include "internal.h"
+#include <common/kfifo.h>
+#include <debug/bug.h>
 
 /**
  * @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;
 }

+ 9 - 1
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);
+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);

+ 3 - 1
kernel/filesystem/devfs/chardev.c

@@ -1,5 +1,7 @@
 #include "chardev.h"
 #include "internal.h"
+#include <filesystem/VFS/VFS.h>
+
 #include <common/mutex.h>
 #include <common/stdlib.h>
 #include <common/string.h>
@@ -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);

+ 5 - 5
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;
 

+ 4 - 9
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)
+#define __devfs_dentry_bind_parent(parent_dentry, dentry) ({                     \
+    (dentry)->parent = (parent_dentry);                                          \
+    list_append(&((parent_dentry)->subdirs_list), &((dentry)->child_node_list)); \
+})

+ 6 - 12
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;

+ 2 - 2
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);