diff --git a/.vscode/settings.json b/.vscode/settings.json index b8d1b20e..5ea0ca16 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -140,7 +140,9 @@ "chardev.h": "c", "rootfs.h": "c", "tty.h": "c", - "kthread.h": "c" + "kthread.h": "c", + "lockref.h": "c", + "compiler_attributes.h": "c" }, "C_Cpp.errorSquiggles": "Enabled", "esbonio.sphinx.confDir": "" diff --git a/kernel/driver/usb/xhci/xhci.c b/kernel/driver/usb/xhci/xhci.c index ecc88268..f9f0c929 100644 --- a/kernel/driver/usb/xhci/xhci.c +++ b/kernel/driver/usb/xhci/xhci.c @@ -207,7 +207,7 @@ static __always_inline void __xhci_write_trb(struct xhci_ep_info_t *ep_info, str */ static __always_inline uint64_t xhci_get_device_context_vaddr(const int id, const int port_id) { - return phys_2_virt(__read8b(xhci_hc[id].dcbaap_vaddr + (xhci_hc[id].ports[port_id].slot_id * sizeof(uint64_t)))); + return (uint64_t)phys_2_virt(__read8b(xhci_hc[id].dcbaap_vaddr + (xhci_hc[id].ports[port_id].slot_id * sizeof(uint64_t)))); } /** diff --git a/kernel/filesystem/VFS/VFS.c b/kernel/filesystem/VFS/VFS.c index 40ada56f..30412ec9 100644 --- a/kernel/filesystem/VFS/VFS.c +++ b/kernel/filesystem/VFS/VFS.c @@ -514,6 +514,11 @@ struct vfs_dir_entry_t *vfs_alloc_dentry(const int name_size) if (unlikely(dentry == NULL)) return NULL; dentry->name = (char *)kzalloc(name_size, 0); + + // 初始化lockref + spin_init(&dentry->lockref.lock); + dentry->lockref.count = 1; + // 初始化链表 list_init(&dentry->child_node_list); list_init(&dentry->subdirs_list); return dentry; @@ -604,6 +609,7 @@ int64_t vfs_rmdir(const char *path, bool from_userland) if (retval != 0) return retval; // todo: 对dentry和inode加锁 + spin_lock(&dentry->lockref.lock); retval = -EBUSY; if (is_local_mountpoint(dentry)) goto out; @@ -616,8 +622,11 @@ int64_t vfs_rmdir(const char *path, bool from_userland) dont_mount(dentry); // 将当前dentry标记为不可被挂载 detach_mounts(dentry); // 清理同样挂载在该路径的所有挂载点的挂载树 - vfs_dentry_put(dentry); // 释放dentry + if (vfs_dentry_put(dentry) != 0) + goto out; // 释放dentry + return retval; out:; + spin_unlock(&dentry->lockref.lock); // todo: 对dentry和inode放锁 return retval; } @@ -644,7 +653,8 @@ uint64_t sys_rmdir(struct pt_regs *regs) 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 + spin_init(&inode->lockref.lock); + inode->lockref.count = 1; // 初始化引用计数为1 return inode; } diff --git a/kernel/filesystem/VFS/VFS.h b/kernel/filesystem/VFS/VFS.h index 8c427434..f82e7cf5 100644 --- a/kernel/filesystem/VFS/VFS.h +++ b/kernel/filesystem/VFS/VFS.h @@ -14,6 +14,7 @@ #include #include #include +#include #include extern struct vfs_superblock_t *vfs_root_sb; @@ -32,7 +33,7 @@ extern struct vfs_superblock_t *vfs_root_sb; * */ #define VFS_IF_FILE (1UL << 0) -#define VFS_IF_DIR (1UL << 1) +#define VFS_IF_DIR (1UL << 1) // 文件夹 #define VFS_IF_DEVICE (1UL << 2) #define VFS_IF_DEAD (1UL << 3) /* removed, but still open directory */ @@ -52,6 +53,7 @@ struct vfs_dir_entry_t struct List child_node_list; struct List subdirs_list; + struct lockref lockref; // 该lockref包含了dentry的自旋锁以及引用计数 struct vfs_index_node_t *dir_inode; struct vfs_dir_entry_t *parent; struct vfs_dir_entry_operations_t *dir_ops; @@ -75,7 +77,7 @@ struct vfs_index_node_t uint64_t file_size; // 文件大小 uint64_t blocks; // 占用的扇区数 uint64_t attribute; - int32_t ref_count; // 引用计数 + struct lockref lockref; // 自旋锁与引用计数 struct vfs_superblock_t *sb; struct vfs_file_operations_t *file_ops; @@ -267,3 +269,13 @@ int64_t vfs_mkdir(const char *path, mode_t mode, bool from_userland); * @return int64_t 错误码 */ int64_t vfs_rmdir(const char *path, bool from_userland); + +/** + * @brief 释放dentry,并视情况自动释放inode + * + * @param dentry 目标dentry + * + * @return 错误码 + * 注意,当dentry指向文件时,如果返回值为正数,则表示在释放了该dentry后,该dentry指向的inode的引用计数。 + */ +int vfs_dentry_put(struct vfs_dir_entry_t * dentry); \ No newline at end of file diff --git a/kernel/filesystem/VFS/dcache.c b/kernel/filesystem/VFS/dcache.c index d5c43d82..e2f4b046 100644 --- a/kernel/filesystem/VFS/dcache.c +++ b/kernel/filesystem/VFS/dcache.c @@ -3,81 +3,127 @@ #include /** - * @brief 释放dentry + * @brief 释放dentry,并视情况自动释放inode * * @param dentry 目标dentry + * + * @return 错误码 + * 注意,当dentry指向文件时,如果返回值为正数,则表示在释放了该dentry后,该dentry指向的inode的引用计数。 */ -void vfs_dentry_put(struct vfs_dir_entry_t *dentry) +int vfs_dentry_put(struct vfs_dir_entry_t *dentry) { int retval = 0; uint64_t in_value = 0; - // todo: 加锁、放锁 + struct kfifo_t fifo = {0}; - // 创建一个用来存放指向dentry的指针的fifo队列 - struct kfifo_t fifo; - // 暂时假设队列大小为1024个元素 - // todo: 实现队列的自动扩容功能 - retval = kfifo_alloc(&fifo, 1024 * sizeof(uint64_t), 0); - - if (retval != 0) - goto failed; - - // 将根dentry加入队列 - in_value = (uint64_t)dentry; - kfifo_in(&fifo, &in_value, sizeof(uint64_t)); - list_del(&dentry->child_node_list); // 从父dentry中删除 - - while (!kfifo_empty(&fifo)) + // 引用计数大于1时,尝试释放dentry的话,抛出错误信息 + if (unlikely(dentry->lockref.lock_count > 1)) { - // 取出队列中的下一个元素 - 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); + BUG_ON(1); + retval = -EBUSY; + spin_unlock(&dentry->lockref.lock); + goto out; + } + + if (D_ISDIR(dentry)) + { + + // 创建一个用来存放指向dentry的指针的fifo队列 + // 暂时假设队列大小为1024个元素 + // todo: 实现队列的自动扩容功能 + retval = kfifo_alloc(&fifo, 1024 * sizeof(uint64_t), 0); + + if (retval != 0) + goto failed; + + // 将根dentry加入队列 + in_value = (uint64_t)dentry; + kfifo_in(&fifo, &in_value, sizeof(uint64_t)); + list_del(&dentry->child_node_list); // 从父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)); + } + spin_lock(&dentry->lockref.lock); + if(dentry->lockref.count>1) + { + spin_unlock(&dentry->lockref.lock); + continue; + } + // 释放inode + spin_lock(&dentry->dir_inode->lockref.lock); + retval = vfs_free_inode(dentry->dir_inode); + if (retval > 0) // 还有其他的dentry引用着这个inode + { + spin_unlock(&dentry->dir_inode->lockref.lock); + retval = 0; + } + + // 若当前dentry是否为挂载点,则umount + if (is_local_mountpoint(dentry)) + do_umount(dentry); + if (dentry->dir_ops->release != NULL) + dentry->dir_ops->release(dentry); + kfree(dentry); + } + kfifo_free_alloc(&fifo); + retval = 0; + goto out; + } + else // 是文件或设备 + { + // 释放inode + spin_lock(&dentry->dir_inode->lockref.lock); + retval = vfs_free_inode(dentry->dir_inode); + if (retval > 0) // 还有其他的dentry引用着这个inode + spin_unlock(&dentry->dir_inode->lockref.lock); + + if (dentry->dir_ops->release != NULL) + dentry->dir_ops->release(dentry); + kfree(dentry); + goto out; } - kfifo_free_alloc(&fifo); - return; failed:; if (fifo.buffer != NULL) kfifo_free_alloc(&fifo); kerror("dentry_put failed."); +out:; + // 在这里不用释放dentry的锁,因为dentry已经被释放掉了 + return retval; } /** - * @brief 释放inode + * @brief 释放inode(要求已经对inode进行加锁后调用该函数) * * @param inode 待释放的inode * @return int 错误码 + * 当inode还有其他的使用者时,返回inode的使用者数量 */ int vfs_free_inode(struct vfs_index_node_t *inode) { - --inode->ref_count; - BUG_ON(inode->ref_count < 0); - if (inode->ref_count == 0) + --inode->lockref.count; + BUG_ON(inode->lockref.count < 0); + if (inode->lockref.count == 0) { kfree(inode->private_inode_info); kfree(inode); + return 0; } - return 0; + else // 如果inode没有被释放 + return inode->lockref.count; } \ No newline at end of file diff --git a/kernel/filesystem/VFS/internal.h b/kernel/filesystem/VFS/internal.h index eb100ece..500f50a6 100644 --- a/kernel/filesystem/VFS/internal.h +++ b/kernel/filesystem/VFS/internal.h @@ -33,17 +33,13 @@ static inline bool is_local_mountpoint(struct vfs_dir_entry_t *dentry) return false; } -/** - * @brief 释放dentry - * - * @param dentry 目标dentry - */ -void vfs_dentry_put(struct vfs_dir_entry_t * dentry); + /** - * @brief 释放inode - * + * @brief 释放inode(要求已经对inode进行加锁后调用该函数) + * * @param inode 待释放的inode * @return int 错误码 + * 当inode还有其他的使用者时,返回inode的使用者数量 */ int vfs_free_inode(struct vfs_index_node_t * inode); \ No newline at end of file diff --git a/kernel/filesystem/devfs/devfs-types.h b/kernel/filesystem/devfs/devfs-types.h index d28c6493..8d87f54e 100644 --- a/kernel/filesystem/devfs/devfs-types.h +++ b/kernel/filesystem/devfs/devfs-types.h @@ -43,4 +43,5 @@ struct devfs_private_inode_info_t uint16_t sub_type; // 设备子类型 struct vfs_file_operations_t *f_ops; uint64_t uuid; + struct vfs_index_node_t * inode; // 当前私有信息所绑定的inode }; diff --git a/kernel/filesystem/devfs/devfs.c b/kernel/filesystem/devfs/devfs.c index dbbd8cf7..f21b38dd 100644 --- a/kernel/filesystem/devfs/devfs.c +++ b/kernel/filesystem/devfs/devfs.c @@ -5,6 +5,7 @@ #include #include #include +#include struct vfs_super_block_operations_t devfs_sb_ops; struct vfs_dir_entry_operations_t devfs_dentry_ops; @@ -257,6 +258,70 @@ failed:; return retval; } +/** + * @brief 卸载设备 + * + * @param private_inode_info 待卸载的设备的inode私有信息 + * @param put_private_info 设备被卸载后,执行的函数 + * @return int 错误码 + */ +int devfs_unregister_device(struct devfs_private_inode_info_t *private_inode_info) +{ + int retval = 0; + spin_lock(&devfs_global_lock); + struct vfs_dir_entry_t *base_dentry = NULL; + struct vfs_dir_entry_t *target_dentry = NULL; + + // 找到父目录的dentry + { + + char base_path[64] = {0}; + switch (private_inode_info->type) + { + case DEV_TYPE_CHAR: + strcpy(base_path, "/dev/char"); + break; + default: + retval = -ENOTSUP; + goto out; + break; + } + + base_dentry = vfs_path_walk(base_path, 0); + // bug + if (unlikely(base_dentry == NULL)) + { + BUG_ON(1); + retval = -ENODEV; + goto out; + } + } + + // 遍历子目录,寻找拥有指定inode的dentry(暂时不支持一个inode对应多个dentry的情况) + // todo: 支持链接文件的卸载 + struct List *tmp_list = NULL, *target_list = NULL; + list_for_each_safe(target_list, tmp_list, &base_dentry->subdirs_list) + { + target_dentry = list_entry(target_list, struct vfs_dir_entry_t, child_node_list); + if (target_dentry->dir_inode == private_inode_info->inode) + { + spin_lock(&target_dentry->lockref.lock); + retval = vfs_dentry_put(target_dentry); + if (retval < 0) + { + kerror("Error when try to unregister device"); + spin_unlock(&target_dentry->lockref.lock); + } + else if (retval == 0) // 该设备的所有dentry均被卸载完成,不必继续迭代 + break; + } + } + retval = 0; +out:; + spin_unlock(&devfs_global_lock); + return retval; +} + /** * @brief 初始化devfs * diff --git a/kernel/filesystem/devfs/devfs.h b/kernel/filesystem/devfs/devfs.h index b68f30a0..a2c68f5f 100644 --- a/kernel/filesystem/devfs/devfs.h +++ b/kernel/filesystem/devfs/devfs.h @@ -17,4 +17,13 @@ void devfs_init(); * @param ret_private_inode_info_ptr 返回的指向inode私有信息结构体的指针 * @return int 错误码 */ -int devfs_register_device(uint16_t device_type, uint16_t sub_type, struct vfs_file_operations_t *file_ops, struct devfs_private_inode_info_t **ret_private_inode_info_ptr); \ No newline at end of file +int devfs_register_device(uint16_t device_type, uint16_t sub_type, struct vfs_file_operations_t *file_ops, struct devfs_private_inode_info_t **ret_private_inode_info_ptr); + +/** + * @brief 卸载设备 + * + * @param private_inode_info 待卸载的设备的inode私有信息 + * @param put_private_info 设备被卸载后,执行的函数 + * @return int 错误码 + */ +int devfs_unregister_device(struct devfs_private_inode_info_t * private_inode_info); \ No newline at end of file diff --git a/kernel/filesystem/devfs/internal.h b/kernel/filesystem/devfs/internal.h index 1bd1beb7..015272b7 100644 --- a/kernel/filesystem/devfs/internal.h +++ b/kernel/filesystem/devfs/internal.h @@ -78,6 +78,8 @@ static inline void __devfs_fill_inode(struct vfs_dir_entry_t *dentry, struct vfs dentry->dir_inode->private_inode_info = private_inode_data; dentry->dir_inode->sb = &devfs_sb; dentry->dir_inode->attribute = inode_attr; + // 反向绑定inode + private_inode_data->inode = dentry->dir_inode; } /**