|
@@ -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);
|
|
|
+ // 引用计数大于1时,尝试释放dentry的话,抛出错误信息
|
|
|
+ if (unlikely(dentry->lockref.lock_count > 1))
|
|
|
+ {
|
|
|
+ BUG_ON(1);
|
|
|
+ retval = -EBUSY;
|
|
|
+ spin_unlock(&dentry->lockref.lock);
|
|
|
+ goto out;
|
|
|
+ }
|
|
|
|
|
|
- if (retval != 0)
|
|
|
- goto failed;
|
|
|
+ if (D_ISDIR(dentry))
|
|
|
+ {
|
|
|
|
|
|
- // 将根dentry加入队列
|
|
|
- in_value = (uint64_t)dentry;
|
|
|
- kfifo_in(&fifo, &in_value, sizeof(uint64_t));
|
|
|
- list_del(&dentry->child_node_list); // 从父dentry中删除
|
|
|
+ // 创建一个用来存放指向dentry的指针的fifo队列
|
|
|
+ // 暂时假设队列大小为1024个元素
|
|
|
+ // todo: 实现队列的自动扩容功能
|
|
|
+ retval = kfifo_alloc(&fifo, 1024 * sizeof(uint64_t), 0);
|
|
|
|
|
|
- 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))
|
|
|
+ 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))
|
|
|
{
|
|
|
- // 将当前dentry下的所有dentry加入队列
|
|
|
- do
|
|
|
+ // 取出队列中的下一个元素
|
|
|
+ kfifo_out(&fifo, &dentry, sizeof(uint64_t));
|
|
|
+ BUG_ON(dentry == NULL);
|
|
|
+ struct List *list = &dentry->subdirs_list;
|
|
|
+ if (!list_empty(list))
|
|
|
{
|
|
|
- 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));
|
|
|
+ // 将当前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));
|
|
|
- }
|
|
|
+ } 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
|
|
|
- vfs_free_inode(dentry->dir_inode);
|
|
|
-
|
|
|
- // 若当前dentry是否为挂载点,则umount
|
|
|
- if (is_local_mountpoint(dentry))
|
|
|
- do_umount(dentry);
|
|
|
+ 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);
|
|
|
|
|
|
- dentry->dir_ops->release(dentry);
|
|
|
+ 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;
|
|
|
}
|