new: devfs设备卸载

This commit is contained in:
fslongjin
2022-10-06 14:48:44 +08:00
parent 85719d938d
commit 7e0835c92f
10 changed files with 209 additions and 66 deletions

View File

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