Skip to content

Commit

Permalink
NFS: State reclaim clears OPEN and LOCK state
Browse files Browse the repository at this point in the history
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: Chuck Lever <chuck.lever@oracle.com>
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
  • Loading branch information
Chuck Lever authored and Trond Myklebust committed Jul 16, 2012
1 parent 89af273 commit eb64cf9
Showing 1 changed file with 12 additions and 11 deletions.
23 changes: 12 additions & 11 deletions fs/nfs/nfs4proc.c
Original file line number Diff line number Diff line change
Expand Up @@ -1758,8 +1758,8 @@ static int nfs4_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *sta
#if defined(CONFIG_NFS_V4_1)
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);
int status = -NFS4ERR_BAD_STATEID;

if (state->flags & flags) {
status = nfs41_test_stateid(server, stateid);
Expand All @@ -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)
{
int deleg_status, open_status;
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 status;

deleg_status = nfs41_check_expired_stateid(state, &state->stateid, deleg_flags);
open_status = nfs41_check_expired_stateid(state, &state->open_stateid, open_flags);
nfs41_check_expired_stateid(state, &state->stateid, deleg_flags);
status = nfs41_check_expired_stateid(state, &state->open_stateid,
open_flags);

if ((deleg_status == NFS_OK) && (open_status == NFS_OK))
return NFS_OK;
return nfs4_open_expired(sp, state);
if (status != NFS_OK)
status = nfs4_open_expired(sp, state);
return status;
}
#endif

Expand Down Expand Up @@ -4690,7 +4691,7 @@ static int nfs4_lock_expired(struct nfs4_state *state, struct file_lock *request
#if defined(CONFIG_NFS_V4_1)
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 nfs_server *server = NFS_SERVER(state->inode);

Expand All @@ -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))
status = nfs41_check_expired_locks(state);
if (status == NFS_OK)
return status;
return nfs4_lock_expired(state, request);
if (status != NFS_OK)
status = nfs4_lock_expired(state, request);
return status;
}
#endif

Expand Down

0 comments on commit eb64cf9

Please sign in to comment.