dcache.c 4.0 KB

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