dcache.c 3.6 KB

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