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 orangefs_set_timeout(dentry); 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 unsigned long time = (unsigned long) dentry->d_fsdata; 98 99 if (time_before(jiffies, time)) 100 return 1; 101 102 if (flags & LOOKUP_RCU) 103 return -ECHILD; 104 105 gossip_debug(GOSSIP_DCACHE_DEBUG, "%s: called on dentry %p.\n", 106 __func__, dentry); 107 108 /* skip root handle lookups. */ 109 if (dentry->d_inode && is_root_handle(dentry->d_inode)) 110 return 1; 111 112 /* 113 * If this passes, the positive dentry still exists or the negative 114 * dentry still does not exist. 115 */ 116 if (!orangefs_revalidate_lookup(dentry)) 117 return 0; 118 119 /* We do not need to continue with negative dentries. */ 120 if (!dentry->d_inode) 121 goto out; 122 123 /* Now we must perform a getattr to validate the inode contents. */ 124 125 ret = orangefs_inode_check_changed(dentry->d_inode); 126 if (ret < 0) { 127 gossip_debug(GOSSIP_DCACHE_DEBUG, "%s:%s:%d getattr failure.\n", 128 __FILE__, __func__, __LINE__); 129 return 0; 130 } 131 if (ret == 0) 132 return 0; 133 134 out: 135 gossip_debug(GOSSIP_DCACHE_DEBUG, 136 "%s: negative dentry or positive dentry and inode valid.\n", 137 __func__); 138 return 1; 139 } 140 141 const struct dentry_operations orangefs_dentry_operations = { 142 .d_revalidate = orangefs_d_revalidate, 143 }; 144