Skip to content

Commit

Permalink
NFSv4.1: Add a helper function to deal with expired stateids
Browse files Browse the repository at this point in the history
In NFSv4.1 and newer, if the server decides to revoke some or all of
the protocol state, the client is required to iterate through all the
stateids that it holds and call TEST_STATEID to determine which stateids
still correspond to valid state, and then call FREE_STATEID on the
others.

Signed-off-by: Trond Myklebust <[email protected]>
Tested-by: Oleg Drokin <[email protected]>
Signed-off-by: Anna Schumaker <[email protected]>
  • Loading branch information
trondmypd authored and amschuma-ntap committed Sep 27, 2016
1 parent 43912bb commit 4586f6e
Showing 1 changed file with 24 additions and 21 deletions.
45 changes: 24 additions & 21 deletions fs/nfs/nfs4proc.c
Original file line number Diff line number Diff line change
Expand Up @@ -2408,6 +2408,26 @@ static int nfs40_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *st
}

#if defined(CONFIG_NFS_V4_1)
static int nfs41_test_and_free_expired_stateid(struct nfs_server *server,
nfs4_stateid *stateid,
struct rpc_cred *cred)
{
int status;

status = nfs41_test_stateid(server, stateid, cred);

switch (status) {
case -NFS4ERR_EXPIRED:
case -NFS4ERR_ADMIN_REVOKED:
case -NFS4ERR_DELEG_REVOKED:
/* Ack the revoked state to the server */
nfs41_free_stateid(server, stateid, cred);
case -NFS4ERR_BAD_STATEID:
return status;
}
return NFS_OK;
}

static void nfs41_check_delegation_stateid(struct nfs4_state *state)
{
struct nfs_server *server = NFS_SERVER(state->inode);
Expand All @@ -2432,16 +2452,10 @@ static void nfs41_check_delegation_stateid(struct nfs4_state *state)
nfs4_stateid_copy(&stateid, &delegation->stateid);
cred = get_rpccred(delegation->cred);
rcu_read_unlock();
status = nfs41_test_stateid(server, &stateid, cred);
status = nfs41_test_and_free_expired_stateid(server, &stateid, cred);
trace_nfs4_test_delegation_stateid(state, NULL, status);

if (status != NFS_OK) {
/* Free the stateid unless the server explicitly
* informs us the stateid is unrecognized. */
if (status != -NFS4ERR_BAD_STATEID)
nfs41_free_stateid(server, &stateid, cred);
if (status != NFS_OK)
nfs_finish_clear_delegation_stateid(state);
}

put_rpccred(cred);
}
Expand All @@ -2467,14 +2481,9 @@ static int nfs41_check_open_stateid(struct nfs4_state *state)
(test_bit(NFS_O_RDWR_STATE, &state->flags) == 0))
return -NFS4ERR_BAD_STATEID;

status = nfs41_test_stateid(server, stateid, cred);
status = nfs41_test_and_free_expired_stateid(server, stateid, cred);
trace_nfs4_test_open_stateid(state, NULL, status);
if (status != NFS_OK) {
/* Free the stateid unless the server explicitly
* informs us the stateid is unrecognized. */
if (status != -NFS4ERR_BAD_STATEID)
nfs41_free_stateid(server, stateid, cred);

clear_bit(NFS_O_RDONLY_STATE, &state->flags);
clear_bit(NFS_O_WRONLY_STATE, &state->flags);
clear_bit(NFS_O_RDWR_STATE, &state->flags);
Expand Down Expand Up @@ -6090,17 +6099,11 @@ static int nfs41_check_expired_locks(struct nfs4_state *state)
if (test_bit(NFS_LOCK_INITIALIZED, &lsp->ls_flags)) {
struct rpc_cred *cred = lsp->ls_state->owner->so_cred;

status = nfs41_test_stateid(server,
status = nfs41_test_and_free_expired_stateid(server,
&lsp->ls_stateid,
cred);
trace_nfs4_test_lock_stateid(state, lsp, status);
if (status != NFS_OK) {
/* Free the stateid unless the server
* informs us the stateid is unrecognized. */
if (status != -NFS4ERR_BAD_STATEID)
nfs41_free_stateid(server,
&lsp->ls_stateid,
cred);
clear_bit(NFS_LOCK_INITIALIZED, &lsp->ls_flags);
ret = status;
}
Expand Down

0 comments on commit 4586f6e

Please sign in to comment.