dcache.c 3.5 KB
Newer Older
M
Mike Marshall 已提交
1 2 3 4 5 6 7 8 9 10 11
/*
 * (C) 2001 Clemson University and The University of Chicago
 *
 * See COPYING in top-level directory.
 */

/*
 *  Implementation of dentry (directory cache) functions.
 */

#include "protocol.h"
12
#include "orangefs-kernel.h"
M
Mike Marshall 已提交
13 14

/* Returns 1 if dentry can still be trusted, else 0. */
15
static int orangefs_revalidate_lookup(struct dentry *dentry)
M
Mike Marshall 已提交
16 17 18
{
	struct dentry *parent_dentry = dget_parent(dentry);
	struct inode *parent_inode = parent_dentry->d_inode;
19
	struct orangefs_inode_s *parent = ORANGEFS_I(parent_inode);
M
Mike Marshall 已提交
20
	struct inode *inode = dentry->d_inode;
21
	struct orangefs_kernel_op_s *new_op;
M
Mike Marshall 已提交
22 23 24 25 26
	int ret = 0;
	int err = 0;

	gossip_debug(GOSSIP_DCACHE_DEBUG, "%s: attempting lookup.\n", __func__);

27
	new_op = op_alloc(ORANGEFS_VFS_OP_LOOKUP);
M
Mike Marshall 已提交
28 29 30
	if (!new_op)
		goto out_put_parent;

31
	new_op->upcall.req.lookup.sym_follow = ORANGEFS_LOOKUP_LINK_NO_FOLLOW;
M
Mike Marshall 已提交
32 33 34
	new_op->upcall.req.lookup.parent_refn = parent->refn;
	strncpy(new_op->upcall.req.lookup.d_name,
		dentry->d_name.name,
35
		ORANGEFS_NAME_MAX);
M
Mike Marshall 已提交
36 37 38 39 40 41 42 43

	gossip_debug(GOSSIP_DCACHE_DEBUG,
		     "%s:%s:%d interrupt flag [%d]\n",
		     __FILE__,
		     __func__,
		     __LINE__,
		     get_interruptible_flag(parent_inode));

44
	err = service_operation(new_op, "orangefs_lookup",
M
Mike Marshall 已提交
45
			get_interruptible_flag(parent_inode));
M
Martin Brandenburg 已提交
46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73

	/* Positive dentry: reject if error or not the same inode. */
	if (inode) {
		if (err) {
			gossip_debug(GOSSIP_DCACHE_DEBUG,
			    "%s:%s:%d lookup failure.\n",
			    __FILE__, __func__, __LINE__);
			goto out_drop;
		}
		if (!match_handle(new_op->downcall.resp.lookup.refn.khandle,
		    inode)) {
			gossip_debug(GOSSIP_DCACHE_DEBUG,
			    "%s:%s:%d no match.\n",
			    __FILE__, __func__, __LINE__);
			goto out_drop;
		}

	/* Negative dentry: reject if success or error other than ENOENT. */
	} else {
		gossip_debug(GOSSIP_DCACHE_DEBUG, "%s: negative dentry.\n",
		    __func__);
		if (!err || err != -ENOENT) {
			if (new_op->downcall.status != 0)
				gossip_debug(GOSSIP_DCACHE_DEBUG,
				    "%s:%s:%d lookup failure.\n",
				    __FILE__, __func__, __LINE__);
			goto out_drop;
		}
M
Mike Marshall 已提交
74 75 76 77 78 79 80 81 82
	}

	ret = 1;
out_release_op:
	op_release(new_op);
out_put_parent:
	dput(parent_dentry);
	return ret;
out_drop:
M
Martin Brandenburg 已提交
83 84
	gossip_debug(GOSSIP_DCACHE_DEBUG, "%s:%s:%d revalidate failed\n",
	    __FILE__, __func__, __LINE__);
M
Mike Marshall 已提交
85 86 87 88 89 90
	goto out_release_op;
}

/*
 * Verify that dentry is valid.
 *
91
 * Should return 1 if dentry can still be trusted, else 0.
M
Mike Marshall 已提交
92
 */
93
static int orangefs_d_revalidate(struct dentry *dentry, unsigned int flags)
M
Mike Marshall 已提交
94
{
M
Martin Brandenburg 已提交
95
	int ret;
M
Mike Marshall 已提交
96 97 98 99 100 101 102

	if (flags & LOOKUP_RCU)
		return -ECHILD;

	gossip_debug(GOSSIP_DCACHE_DEBUG, "%s: called on dentry %p.\n",
		     __func__, dentry);

M
Martin Brandenburg 已提交
103 104 105 106 107 108 109 110
	/* skip root handle lookups. */
	if (dentry->d_inode && is_root_handle(dentry->d_inode))
		return 1;

	/*
	 * If this passes, the positive dentry still exists or the negative
	 * dentry still does not exist.
	 */
111
	if (!orangefs_revalidate_lookup(dentry))
M
Martin Brandenburg 已提交
112
		return 0;
M
Mike Marshall 已提交
113

M
Martin Brandenburg 已提交
114 115
	/* We do not need to continue with negative dentries. */
	if (!dentry->d_inode)
116
		goto out;
M
Mike Marshall 已提交
117

M
Martin Brandenburg 已提交
118
	/* Now we must perform a getattr to validate the inode contents. */
119

120
	ret = orangefs_inode_old_getattr(dentry->d_inode,
121
	    ORANGEFS_ATTR_SYS_TYPE|ORANGEFS_ATTR_SYS_LNK_TARGET, 1);
M
Martin Brandenburg 已提交
122 123 124 125 126
	if (ret < 0) {
		gossip_debug(GOSSIP_DCACHE_DEBUG, "%s:%s:%d getattr failure.\n",
		    __FILE__, __func__, __LINE__);
		return 0;
	}
127
	if (ret == 0)
M
Martin Brandenburg 已提交
128
		return 0;
129 130

out:
M
Martin Brandenburg 已提交
131 132 133 134
	gossip_debug(GOSSIP_DCACHE_DEBUG,
	    "%s: negative dentry or positive dentry and inode valid.\n",
	    __func__);
	return 1;
M
Mike Marshall 已提交
135 136
}

137 138
const struct dentry_operations orangefs_dentry_operations = {
	.d_revalidate = orangefs_d_revalidate,
M
Mike Marshall 已提交
139
};