Merge branch 'patch-devfs-unregister-device'

This commit is contained in:
fslongjin 2022-10-06 14:49:07 +08:00
commit d7767caa7e
10 changed files with 209 additions and 66 deletions

View File

@ -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": ""

View File

@ -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))));
}
/**

View File

@ -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;
}

View File

@ -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 dentryinode
*
* @param dentry dentry
*
* @return
* dentry指向文件时dentry后dentry指向的inode的引用计数
*/
int vfs_dentry_put(struct vfs_dir_entry_t * dentry);

View File

@ -3,18 +3,32 @@
#include <debug/bug.h>
/**
* @brief dentry
* @brief dentryinode
*
* @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};
// 引用计数大于1时尝试释放dentry的话抛出错误信息
if (unlikely(dentry->lockref.lock_count > 1))
{
BUG_ON(1);
retval = -EBUSY;
spin_unlock(&dentry->lockref.lock);
goto out;
}
if (D_ISDIR(dentry))
{
// 创建一个用来存放指向dentry的指针的fifo队列
struct kfifo_t fifo;
// 暂时假设队列大小为1024个元素
// todo: 实现队列的自动扩容功能
retval = kfifo_alloc(&fifo, 1024 * sizeof(uint64_t), 0);
@ -45,39 +59,71 @@ void vfs_dentry_put(struct vfs_dir_entry_t *dentry)
} while (list_next(list) != (&dentry->subdirs_list));
}
spin_lock(&dentry->lockref.lock);
if(dentry->lockref.count>1)
{
spin_unlock(&dentry->lockref.lock);
continue;
}
// 释放inode
vfs_free_inode(dentry->dir_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);
return;
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;
}
failed:;
if (fifo.buffer != NULL)
kfifo_free_alloc(&fifo);
kerror("dentry_put failed.");
out:;
// 在这里不用释放dentry的锁因为dentry已经被释放掉了
return retval;
}
/**
* @brief inode
* @brief inodeinode进行加锁后调用该函数
*
* @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;
}
else // 如果inode没有被释放
return inode->lockref.count;
}

View File

@ -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 inodeinode进行加锁后调用该函数
*
* @param inode inode
* @return int
* inode还有其他的使用者时inode的使用者数量
*/
int vfs_free_inode(struct vfs_index_node_t * inode);

View File

@ -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
};

View File

@ -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
*

View File

@ -18,3 +18,12 @@ void devfs_init();
* @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);
/**
* @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);

View File

@ -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;
}
/**