dcache.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. #include "internal.h"
  2. #include <common/kfifo.h>
  3. #include <debug/bug.h>
  4. /**
  5. * @brief 释放dentry,并视情况自动释放inode. 在调用该函数前,需要将dentry加锁。
  6. *
  7. * @param dentry 目标dentry
  8. *
  9. * @return 错误码
  10. * 注意,当dentry指向文件时,如果返回值为正数,则表示在释放了该dentry后,该dentry指向的inode的引用计数。
  11. */
  12. int vfs_dentry_put(struct vfs_dir_entry_t *dentry)
  13. {
  14. int retval = 0;
  15. uint64_t in_value = 0;
  16. struct kfifo_t fifo = {0};
  17. // 引用计数大于1时,尝试释放dentry的话,抛出错误信息
  18. if (unlikely(dentry->lockref.lock_count > 1))
  19. {
  20. BUG_ON(1);
  21. retval = -EBUSY;
  22. goto out;
  23. }
  24. if (D_ISDIR(dentry))
  25. {
  26. // 创建一个用来存放指向dentry的指针的fifo队列
  27. // 暂时假设队列大小为1024个元素
  28. // todo: 实现队列的自动扩容功能
  29. retval = kfifo_alloc(&fifo, 1024 * sizeof(uint64_t), 0);
  30. if (retval != 0)
  31. goto failed;
  32. // 将根dentry加入队列
  33. in_value = (uint64_t)dentry;
  34. kfifo_in(&fifo, &in_value, sizeof(uint64_t));
  35. list_del(&dentry->child_node_list); // 从父dentry中删除
  36. while (!kfifo_empty(&fifo))
  37. {
  38. // 取出队列中的下一个元素
  39. kfifo_out(&fifo, &dentry, sizeof(uint64_t));
  40. BUG_ON(dentry == NULL);
  41. struct List *list = &dentry->subdirs_list;
  42. if (!list_empty(list))
  43. {
  44. // 将当前dentry下的所有dentry加入队列
  45. do
  46. {
  47. list = list_next(list);
  48. in_value = (uint64_t)container_of(list, struct vfs_dir_entry_t, child_node_list);
  49. if (in_value != NULL)
  50. kfifo_in(&fifo, &in_value, sizeof(uint64_t));
  51. } while (list_next(list) != (&dentry->subdirs_list));
  52. }
  53. spin_lock(&dentry->lockref.lock);
  54. if(dentry->lockref.count>1)
  55. {
  56. spin_unlock(&dentry->lockref.lock);
  57. continue;
  58. }
  59. // 释放inode
  60. spin_lock(&dentry->dir_inode->lockref.lock);
  61. retval = vfs_free_inode(dentry->dir_inode);
  62. if (retval > 0) // 还有其他的dentry引用着这个inode
  63. {
  64. spin_unlock(&dentry->dir_inode->lockref.lock);
  65. retval = 0;
  66. }
  67. // 若当前dentry是否为挂载点,则umount
  68. if (is_local_mountpoint(dentry))
  69. do_umount(dentry);
  70. if (dentry->dir_ops->release != NULL)
  71. dentry->dir_ops->release(dentry);
  72. kfree(dentry);
  73. }
  74. kfifo_free_alloc(&fifo);
  75. retval = 0;
  76. goto out;
  77. }
  78. else // 是文件或设备
  79. {
  80. // 释放inode
  81. spin_lock(&dentry->dir_inode->lockref.lock);
  82. retval = vfs_free_inode(dentry->dir_inode);
  83. if (retval > 0) // 还有其他的dentry引用着这个inode
  84. spin_unlock(&dentry->dir_inode->lockref.lock);
  85. if (dentry->dir_ops->release != NULL)
  86. dentry->dir_ops->release(dentry);
  87. kfree(dentry);
  88. goto out;
  89. }
  90. failed:;
  91. if (fifo.buffer != NULL)
  92. kfifo_free_alloc(&fifo);
  93. kerror("dentry_put failed.");
  94. out:;
  95. // 在这里不用释放dentry的锁,因为dentry已经被释放掉了
  96. return retval;
  97. }
  98. /**
  99. * @brief 释放inode(要求已经对inode进行加锁后调用该函数)
  100. *
  101. * @param inode 待释放的inode
  102. * @return int 错误码
  103. * 当inode还有其他的使用者时,返回inode的使用者数量
  104. */
  105. int vfs_free_inode(struct vfs_index_node_t *inode)
  106. {
  107. --inode->lockref.count;
  108. BUG_ON(inode->lockref.count < 0);
  109. if (inode->lockref.count == 0)
  110. {
  111. kfree(inode->private_inode_info);
  112. kfree(inode);
  113. return 0;
  114. }
  115. else // 如果inode没有被释放
  116. return inode->lockref.count;
  117. }