Commit df56ddd0 authored by Trond Myklebust's avatar Trond Myklebust
Browse files

NFSv4.x: Directory delegations don't require any state recovery



The state recovery code in nfs_end_delegation_return() is intended to
allow regular files to recover cached open and lock state. It has no
function for directory delegations, and may cause corruption.

Fixes: 156b0948 ("NFS: Request a directory delegation on ACCESS, CREATE, and UNLINK")
Signed-off-by: default avatarTrond Myklebust <trond.myklebust@hammerspace.com>
parent 3f77eda5
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -581,6 +581,10 @@ static int nfs_end_delegation_return(struct inode *inode, struct nfs_delegation
	if (delegation == NULL)
		return 0;

	/* Directory delegations don't require any state recovery */
	if (!S_ISREG(inode->i_mode))
		goto out_return;

	if (!issync)
		mode |= O_NONBLOCK;
	/* Recall of any remaining application leases */
@@ -604,6 +608,7 @@ static int nfs_end_delegation_return(struct inode *inode, struct nfs_delegation
		goto out;
	}

out_return:
	err = nfs_do_return_delegation(inode, delegation, issync);
out:
	/* Refcount matched in nfs_start_delegation_return_locked() */
+5 −1
Original line number Diff line number Diff line
@@ -1445,6 +1445,8 @@ void nfs_inode_find_state_and_recover(struct inode *inode,
	struct nfs4_state *state;
	bool found = false;

	if (!S_ISREG(inode->i_mode))
		goto out;
	rcu_read_lock();
	list_for_each_entry_rcu(ctx, &nfsi->open_files, list) {
		state = ctx->state;
@@ -1466,7 +1468,7 @@ void nfs_inode_find_state_and_recover(struct inode *inode,
			found = true;
	}
	rcu_read_unlock();

out:
	nfs_inode_find_delegation_state_and_recover(inode, stateid);
	if (found)
		nfs4_schedule_state_manager(clp);
@@ -1478,6 +1480,8 @@ static void nfs4_state_mark_open_context_bad(struct nfs4_state *state, int err)
	struct nfs_inode *nfsi = NFS_I(inode);
	struct nfs_open_context *ctx;

	if (!S_ISREG(inode->i_mode))
		return;
	rcu_read_lock();
	list_for_each_entry_rcu(ctx, &nfsi->open_files, list) {
		if (ctx->state != state)