Commit eb64cf96 authored by Chuck Lever's avatar Chuck Lever Committed by Trond Myklebust

NFS: State reclaim clears OPEN and LOCK state

The "state->flags & flags" test in nfs41_check_expired_stateid()
allows the state manager to squelch a TEST_STATEID operation when
it is known for sure that a state ID is no longer valid.  If the
lease was purged, for example, the client already knows that state
ID is now defunct.

But open recovery is still needed for that inode.

To force a call to nfs4_open_expired(), change the default return
value for nfs41_check_expired_stateid() to force open recovery, and
the default return value for nfs41_check_locks() to force lock
recovery, if the requested flags are clear.  Fix suggested by Bryan
Schumaker.

Also, the presence of a delegation state ID must not prevent normal
open recovery.  The delegation state ID must be cleared if it was
revoked, but once cleared I don't think it's presence or absence has
any bearing on whether open recovery is still needed.  So the logic
is adjusted to ignore the TEST_STATEID result for the delegation
state ID.
Signed-off-by: default avatarChuck Lever <chuck.lever@oracle.com>
Signed-off-by: default avatarTrond Myklebust <Trond.Myklebust@netapp.com>
parent 89af2739
...@@ -1758,8 +1758,8 @@ static int nfs4_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *sta ...@@ -1758,8 +1758,8 @@ static int nfs4_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *sta
#if defined(CONFIG_NFS_V4_1) #if defined(CONFIG_NFS_V4_1)
static int nfs41_check_expired_stateid(struct nfs4_state *state, nfs4_stateid *stateid, unsigned int flags) static int nfs41_check_expired_stateid(struct nfs4_state *state, nfs4_stateid *stateid, unsigned int flags)
{ {
int status = NFS_OK;
struct nfs_server *server = NFS_SERVER(state->inode); struct nfs_server *server = NFS_SERVER(state->inode);
int status = -NFS4ERR_BAD_STATEID;
if (state->flags & flags) { if (state->flags & flags) {
status = nfs41_test_stateid(server, stateid); status = nfs41_test_stateid(server, stateid);
...@@ -1774,16 +1774,17 @@ static int nfs41_check_expired_stateid(struct nfs4_state *state, nfs4_stateid *s ...@@ -1774,16 +1774,17 @@ static int nfs41_check_expired_stateid(struct nfs4_state *state, nfs4_stateid *s
static int nfs41_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *state) static int nfs41_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *state)
{ {
int deleg_status, open_status;
int deleg_flags = 1 << NFS_DELEGATED_STATE; int deleg_flags = 1 << NFS_DELEGATED_STATE;
int open_flags = (1 << NFS_O_RDONLY_STATE) | (1 << NFS_O_WRONLY_STATE) | (1 << NFS_O_RDWR_STATE); int open_flags = (1 << NFS_O_RDONLY_STATE) | (1 << NFS_O_WRONLY_STATE) | (1 << NFS_O_RDWR_STATE);
int status;
deleg_status = nfs41_check_expired_stateid(state, &state->stateid, deleg_flags); nfs41_check_expired_stateid(state, &state->stateid, deleg_flags);
open_status = nfs41_check_expired_stateid(state, &state->open_stateid, open_flags); status = nfs41_check_expired_stateid(state, &state->open_stateid,
open_flags);
if ((deleg_status == NFS_OK) && (open_status == NFS_OK)) if (status != NFS_OK)
return NFS_OK; status = nfs4_open_expired(sp, state);
return nfs4_open_expired(sp, state); return status;
} }
#endif #endif
...@@ -4690,7 +4691,7 @@ static int nfs4_lock_expired(struct nfs4_state *state, struct file_lock *request ...@@ -4690,7 +4691,7 @@ static int nfs4_lock_expired(struct nfs4_state *state, struct file_lock *request
#if defined(CONFIG_NFS_V4_1) #if defined(CONFIG_NFS_V4_1)
static int nfs41_check_expired_locks(struct nfs4_state *state) static int nfs41_check_expired_locks(struct nfs4_state *state)
{ {
int status, ret = NFS_OK; int status, ret = -NFS4ERR_BAD_STATEID;
struct nfs4_lock_state *lsp; struct nfs4_lock_state *lsp;
struct nfs_server *server = NFS_SERVER(state->inode); struct nfs_server *server = NFS_SERVER(state->inode);
...@@ -4716,9 +4717,9 @@ static int nfs41_lock_expired(struct nfs4_state *state, struct file_lock *reques ...@@ -4716,9 +4717,9 @@ static int nfs41_lock_expired(struct nfs4_state *state, struct file_lock *reques
if (test_bit(LK_STATE_IN_USE, &state->flags)) if (test_bit(LK_STATE_IN_USE, &state->flags))
status = nfs41_check_expired_locks(state); status = nfs41_check_expired_locks(state);
if (status == NFS_OK) if (status != NFS_OK)
return status; status = nfs4_lock_expired(state, request);
return nfs4_lock_expired(state, request); return status;
} }
#endif #endif
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment