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