mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-09 07:06:47 +00:00
Merge branch 'patch-devfs-unregister-device'
This commit is contained in:
commit
d7767caa7e
4
.vscode/settings.json
vendored
4
.vscode/settings.json
vendored
@ -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": ""
|
||||
|
@ -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))));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include <common/glib.h>
|
||||
#include <common/fcntl.h>
|
||||
#include <common/blk_types.h>
|
||||
#include <common/lockref.h>
|
||||
#include <mm/slab.h>
|
||||
|
||||
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);
|
@ -3,81 +3,127 @@
|
||||
#include <debug/bug.h>
|
||||
|
||||
/**
|
||||
* @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;
|
||||
}
|
@ -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);
|
@ -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
|
||||
};
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include <common/string.h>
|
||||
#include <mm/slab.h>
|
||||
#include <common/spinlock.h>
|
||||
#include <debug/bug.h>
|
||||
|
||||
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
|
||||
*
|
||||
|
@ -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);
|
||||
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);
|
@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
x
Reference in New Issue
Block a user