Commit f7b37b8b authored by Trond Myklebust's avatar Trond Myklebust Committed by Anna Schumaker
Browse files

NFS: Add softreval behaviour to nfs_lookup_revalidate()



If the server is unavaliable, we want to allow the revalidating
lookup to time out, and to default to validating the cached dentry
if the 'softreval' mount option is set.

Signed-off-by: default avatarTrond Myklebust <trond.myklebust@hammerspace.com>
Signed-off-by: default avatarAnna Schumaker <Anna.Schumaker@Netapp.com>
parent fe1e8dbe
Loading
Loading
Loading
Loading
+11 −4
Original line number Diff line number Diff line
@@ -1142,10 +1142,17 @@ nfs_lookup_revalidate_dentry(struct inode *dir, struct dentry *dentry,
	if (fhandle == NULL || fattr == NULL || IS_ERR(label))
		goto out;

	ret = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle, fattr, label);
	ret = NFS_PROTO(dir)->lookup(dir, dentry, fhandle, fattr, label);
	if (ret < 0) {
		if (ret == -ESTALE || ret == -ENOENT)
		switch (ret) {
		case -ESTALE:
		case -ENOENT:
			ret = 0;
			break;
		case -ETIMEDOUT:
			if (NFS_SERVER(inode)->flags & NFS_MOUNT_SOFTREVAL)
				ret = 1;
		}
		goto out;
	}
	ret = 0;
@@ -1408,7 +1415,7 @@ struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, unsigned in
		goto out;

	trace_nfs_lookup_enter(dir, dentry, flags);
	error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle, fattr, label);
	error = NFS_PROTO(dir)->lookup(dir, dentry, fhandle, fattr, label);
	if (error == -ENOENT)
		goto no_entry;
	if (error < 0) {
@@ -1683,7 +1690,7 @@ nfs_add_or_obtain(struct dentry *dentry, struct nfs_fh *fhandle,
	d_drop(dentry);

	if (fhandle->size == 0) {
		error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle, fattr, NULL);
		error = NFS_PROTO(dir)->lookup(dir, dentry, fhandle, fattr, NULL);
		if (error)
			goto out_error;
	}
+9 −0
Original line number Diff line number Diff line
@@ -33,6 +33,15 @@ static inline int nfs_attr_use_mounted_on_fileid(struct nfs_fattr *fattr)
	return 1;
}

static inline bool nfs_lookup_is_soft_revalidate(const struct dentry *dentry)
{
	if (!(NFS_SB(dentry->d_sb)->flags & NFS_MOUNT_SOFTREVAL))
		return false;
	if (!d_is_positive(dentry) || !NFS_FH(d_inode(dentry))->size)
		return false;
	return true;
}

/*
 * Note: RFC 1813 doesn't limit the number of auth flavors that
 * a server can return, so make something up.
+1 −1
Original line number Diff line number Diff line
@@ -301,7 +301,7 @@ int nfs_submount(struct fs_context *fc, struct nfs_server *server)
	int err;

	/* Look it up again to get its attributes */
	err = server->nfs_client->rpc_ops->lookup(d_inode(parent), &dentry->d_name,
	err = server->nfs_client->rpc_ops->lookup(d_inode(parent), dentry,
						  ctx->mntfh, ctx->clone_data.fattr,
						  NULL);
	dput(parent);
+11 −6
Original line number Diff line number Diff line
@@ -154,14 +154,14 @@ nfs3_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr,
}

static int
nfs3_proc_lookup(struct inode *dir, const struct qstr *name,
nfs3_proc_lookup(struct inode *dir, struct dentry *dentry,
		 struct nfs_fh *fhandle, struct nfs_fattr *fattr,
		 struct nfs4_label *label)
{
	struct nfs3_diropargs	arg = {
		.fh		= NFS_FH(dir),
		.name		= name->name,
		.len		= name->len
		.name		= dentry->d_name.name,
		.len		= dentry->d_name.len
	};
	struct nfs3_diropres	res = {
		.fh		= fhandle,
@@ -173,20 +173,25 @@ nfs3_proc_lookup(struct inode *dir, const struct qstr *name,
		.rpc_resp	= &res,
	};
	int			status;
	unsigned short task_flags = 0;

	/* Is this is an attribute revalidation, subject to softreval? */
	if (nfs_lookup_is_soft_revalidate(dentry))
		task_flags |= RPC_TASK_TIMEOUT;

	dprintk("NFS call  lookup %pd2\n", dentry);
	res.dir_attr = nfs_alloc_fattr();
	if (res.dir_attr == NULL)
		return -ENOMEM;

	dprintk("NFS call  lookup %s\n", name->name);
	nfs_fattr_init(fattr);
	status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
	status = rpc_call_sync(NFS_CLIENT(dir), &msg, task_flags);
	nfs_refresh_inode(dir, res.dir_attr);
	if (status >= 0 && !(fattr->valid & NFS_ATTR_FATTR)) {
		msg.rpc_proc = &nfs3_procedures[NFS3PROC_GETATTR];
		msg.rpc_argp = fhandle;
		msg.rpc_resp = fattr;
		status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
		status = rpc_call_sync(NFS_CLIENT(dir), &msg, task_flags);
	}
	nfs_free_fattr(res.dir_attr);
	dprintk("NFS reply lookup: %d\n", status);
+4 −2
Original line number Diff line number Diff line
@@ -302,8 +302,10 @@ extern int nfs4_proc_fs_locations(struct rpc_clnt *, struct inode *, const struc
extern int nfs4_proc_get_locations(struct inode *, struct nfs4_fs_locations *,
		struct page *page, const struct cred *);
extern int nfs4_proc_fsid_present(struct inode *, const struct cred *);
extern struct rpc_clnt *nfs4_proc_lookup_mountpoint(struct inode *, const struct qstr *,
			    struct nfs_fh *, struct nfs_fattr *);
extern struct rpc_clnt *nfs4_proc_lookup_mountpoint(struct inode *,
						    struct dentry *,
						    struct nfs_fh *,
						    struct nfs_fattr *);
extern int nfs4_proc_secinfo(struct inode *, const struct qstr *, struct nfs4_secinfo_flavors *);
extern const struct xattr_handler *nfs4_xattr_handlers[];
extern int nfs4_set_rw_stateid(nfs4_stateid *stateid,
Loading