dcache.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * (C) 2001 Clemson University and The University of Chicago
  4. *
  5. * See COPYING in top-level directory.
  6. */
  7. /*
  8. * Implementation of dentry (directory cache) functions.
  9. */
  10. #include "protocol.h"
  11. #include "orangefs-kernel.h"
  12. /* Returns 1 if dentry can still be trusted, else 0. */
  13. static int orangefs_revalidate_lookup(struct dentry *dentry)
  14. {
  15. struct dentry *parent_dentry = dget_parent(dentry);
  16. struct inode *parent_inode = parent_dentry->d_inode;
  17. struct orangefs_inode_s *parent = ORANGEFS_I(parent_inode);
  18. struct inode *inode = dentry->d_inode;
  19. struct orangefs_kernel_op_s *new_op;
  20. int ret = 0;
  21. int err = 0;
  22. gossip_debug(GOSSIP_DCACHE_DEBUG, "%s: attempting lookup.\n", __func__);
  23. new_op = op_alloc(ORANGEFS_VFS_OP_LOOKUP);
  24. if (!new_op)
  25. goto out_put_parent;
  26. new_op->upcall.req.lookup.sym_follow = ORANGEFS_LOOKUP_LINK_NO_FOLLOW;
  27. new_op->upcall.req.lookup.parent_refn = parent->refn;
  28. strncpy(new_op->upcall.req.lookup.d_name,
  29. dentry->d_name.name,
  30. ORANGEFS_NAME_MAX - 1);
  31. gossip_debug(GOSSIP_DCACHE_DEBUG,
  32. "%s:%s:%d interrupt flag [%d]\n",
  33. __FILE__,
  34. __func__,
  35. __LINE__,
  36. get_interruptible_flag(parent_inode));
  37. err = service_operation(new_op, "orangefs_lookup",
  38. get_interruptible_flag(parent_inode));
  39. /* Positive dentry: reject if error or not the same inode. */
  40. if (inode) {
  41. if (err) {
  42. gossip_debug(GOSSIP_DCACHE_DEBUG,
  43. "%s:%s:%d lookup failure.\n",
  44. __FILE__, __func__, __LINE__);
  45. goto out_drop;
  46. }
  47. if (!match_handle(new_op->downcall.resp.lookup.refn.khandle,
  48. inode)) {
  49. gossip_debug(GOSSIP_DCACHE_DEBUG,
  50. "%s:%s:%d no match.\n",
  51. __FILE__, __func__, __LINE__);
  52. goto out_drop;
  53. }
  54. /* Negative dentry: reject if success or error other than ENOENT. */
  55. } else {
  56. gossip_debug(GOSSIP_DCACHE_DEBUG, "%s: negative dentry.\n",
  57. __func__);
  58. if (!err || err != -ENOENT) {
  59. if (new_op->downcall.status != 0)
  60. gossip_debug(GOSSIP_DCACHE_DEBUG,
  61. "%s:%s:%d lookup failure.\n",
  62. __FILE__, __func__, __LINE__);
  63. goto out_drop;
  64. }
  65. }
  66. orangefs_set_timeout(dentry);
  67. ret = 1;
  68. out_release_op:
  69. op_release(new_op);
  70. out_put_parent:
  71. dput(parent_dentry);
  72. return ret;
  73. out_drop:
  74. gossip_debug(GOSSIP_DCACHE_DEBUG, "%s:%s:%d revalidate failed\n",
  75. __FILE__, __func__, __LINE__);
  76. goto out_release_op;
  77. }
  78. /*
  79. * Verify that dentry is valid.
  80. *
  81. * Should return 1 if dentry can still be trusted, else 0.
  82. */
  83. static int orangefs_d_revalidate(struct dentry *dentry, unsigned int flags)
  84. {
  85. int ret;
  86. unsigned long time = (unsigned long) dentry->d_fsdata;
  87. if (time_before(jiffies, time))
  88. return 1;
  89. if (flags & LOOKUP_RCU)
  90. return -ECHILD;
  91. gossip_debug(GOSSIP_DCACHE_DEBUG, "%s: called on dentry %p.\n",
  92. __func__, dentry);
  93. /* skip root handle lookups. */
  94. if (dentry->d_inode && is_root_handle(dentry->d_inode))
  95. return 1;
  96. /*
  97. * If this passes, the positive dentry still exists or the negative
  98. * dentry still does not exist.
  99. */
  100. if (!orangefs_revalidate_lookup(dentry))
  101. return 0;
  102. /* We do not need to continue with negative dentries. */
  103. if (!dentry->d_inode) {
  104. gossip_debug(GOSSIP_DCACHE_DEBUG,
  105. "%s: negative dentry or positive dentry and inode valid.\n",
  106. __func__);
  107. return 1;
  108. }
  109. /* Now we must perform a getattr to validate the inode contents. */
  110. ret = orangefs_inode_check_changed(dentry->d_inode);
  111. if (ret < 0) {
  112. gossip_debug(GOSSIP_DCACHE_DEBUG, "%s:%s:%d getattr failure.\n",
  113. __FILE__, __func__, __LINE__);
  114. return 0;
  115. }
  116. return !ret;
  117. }
  118. const struct dentry_operations orangefs_dentry_operations = {
  119. .d_revalidate = orangefs_d_revalidate,
  120. };