Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit dce2630c authored by NeilBrown's avatar NeilBrown Committed by Trond Myklebust
Browse files

NFSv4: always set NFS_LOCK_LOST when a lock is lost.



There are 2 comments in the NFSv4 code which suggest that
SIGLOST should possibly be sent to a process.  In these
cases a lock has been lost.
The current practice is to set NFS_LOCK_LOST so that
read/write returns EIO when a lock is lost.
So change these comments to code when sets NFS_LOCK_LOST.

One case is when lock recovery after apparent server restart
fails with NFS4ERR_DENIED, NFS4ERR_RECLAIM_BAD, or
NFS4ERRO_RECLAIM_CONFLICT.  The other case is when a lock
attempt as part of lease recovery fails with NFS4ERR_DENIED.

In an ideal world, these should not happen.  However I have
a packet trace showing an NFSv4.1 session getting
NFS4ERR_BADSESSION after an extended network parition.  The
NFSv4.1 client treats this like server reboot until/unless
it get NFS4ERR_NO_GRACE, in which case it switches over to
"nograce" recovery mode.  In this network trace, the client
attempts to recover a lock and the server (incorrectly)
reports NFS4ERR_DENIED rather than NFS4ERR_NO_GRACE.  This
leads to the ineffective comment and the client then
continues to write using the OPEN stateid.

Signed-off-by: default avatarNeilBrown <neilb@suse.com>
Signed-off-by: default avatarTrond Myklebust <trond.myklebust@primarydata.com>
parent aaa15008
Loading
Loading
Loading
Loading
+8 −4
Original line number Diff line number Diff line
@@ -2019,7 +2019,7 @@ static int nfs4_open_reclaim(struct nfs4_state_owner *sp, struct nfs4_state *sta
	return ret;
}

static int nfs4_handle_delegation_recall_error(struct nfs_server *server, struct nfs4_state *state, const nfs4_stateid *stateid, int err)
static int nfs4_handle_delegation_recall_error(struct nfs_server *server, struct nfs4_state *state, const nfs4_stateid *stateid, struct file_lock *fl, int err)
{
	switch (err) {
		default:
@@ -2066,7 +2066,11 @@ static int nfs4_handle_delegation_recall_error(struct nfs_server *server, struct
			return -EAGAIN;
		case -ENOMEM:
		case -NFS4ERR_DENIED:
			/* kill_proc(fl->fl_pid, SIGLOST, 1); */
			if (fl) {
				struct nfs4_lock_state *lsp = fl->fl_u.nfs4_fl.owner;
				if (lsp)
					set_bit(NFS_LOCK_LOST, &lsp->ls_flags);
			}
			return 0;
	}
	return err;
@@ -2102,7 +2106,7 @@ int nfs4_open_delegation_recall(struct nfs_open_context *ctx,
		err = nfs4_open_recover_helper(opendata, FMODE_READ);
	}
	nfs4_opendata_put(opendata);
	return nfs4_handle_delegation_recall_error(server, state, stateid, err);
	return nfs4_handle_delegation_recall_error(server, state, stateid, NULL, err);
}

static void nfs4_open_confirm_prepare(struct rpc_task *task, void *calldata)
@@ -6757,7 +6761,7 @@ int nfs4_lock_delegation_recall(struct file_lock *fl, struct nfs4_state *state,
	if (err != 0)
		return err;
	err = _nfs4_do_setlk(state, F_SETLK, fl, NFS_LOCK_NEW);
	return nfs4_handle_delegation_recall_error(server, state, stateid, err);
	return nfs4_handle_delegation_recall_error(server, state, stateid, fl, err);
}

struct nfs_release_lockowner_data {
+4 −1
Original line number Diff line number Diff line
@@ -1482,6 +1482,7 @@ static int nfs4_reclaim_locks(struct nfs4_state *state, const struct nfs4_state_
	struct inode *inode = state->inode;
	struct nfs_inode *nfsi = NFS_I(inode);
	struct file_lock *fl;
	struct nfs4_lock_state *lsp;
	int status = 0;
	struct file_lock_context *flctx = inode->i_flctx;
	struct list_head *list;
@@ -1522,7 +1523,9 @@ static int nfs4_reclaim_locks(struct nfs4_state *state, const struct nfs4_state_
		case -NFS4ERR_DENIED:
		case -NFS4ERR_RECLAIM_BAD:
		case -NFS4ERR_RECLAIM_CONFLICT:
			/* kill_proc(fl->fl_pid, SIGLOST, 1); */
			lsp = fl->fl_u.nfs4_fl.owner;
			if (lsp)
				set_bit(NFS_LOCK_LOST, &lsp->ls_flags);
			status = 0;
		}
		spin_lock(&flctx->flc_lock);