Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v4.9-rc8 143 lines 3.7 kB view raw
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. */ 15static 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; 78out_release_op: 79 op_release(new_op); 80out_put_parent: 81 dput(parent_dentry); 82 return ret; 83out_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 */ 94static 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 134out: 135 gossip_debug(GOSSIP_DCACHE_DEBUG, 136 "%s: negative dentry or positive dentry and inode valid.\n", 137 __func__); 138 return 1; 139} 140 141const struct dentry_operations orangefs_dentry_operations = { 142 .d_revalidate = orangefs_d_revalidate, 143};