diff options
author | Chuck Lever <chuck.lever@oracle.com> | 2012-07-11 16:29:56 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2012-07-16 14:48:10 -0400 |
commit | 89af2739589365bf0dd2023c6a076b22ccd530f9 (patch) | |
tree | 91608923b32aa16c7bf013bfb25d6006266c89a1 | |
parent | 377e507d1572eca6372c862483f4ce4680ad310a (diff) |
NFS: Don't free a state ID the server does not recognize
The result of a TEST_STATEID operation can indicate a few different
things:
o If NFS_OK is returned, then the client can continue using the
state ID under test, and skip recovery.
o RFC 5661 says that if the state ID was revoked, then the client
must perform an explicit FREE_STATEID before trying to re-open.
o If the server doesn't recognize the state ID at all, then no
FREE_STATEID is needed, and the client can immediately continue
with open recovery.
Let's err on the side of caution: if the server clearly tells us the
state ID is unknown, we skip the FREE_STATEID. For any other error,
we issue a FREE_STATEID. Sometimes that FREE_STATEID will be
unnecessary, but leaving unused state IDs on the server needlessly
ties up resources.
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
-rw-r--r-- | fs/nfs/nfs4proc.c | 7 |
1 files changed, 5 insertions, 2 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index af3abf957f2c..afd61d72837d 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -1764,7 +1764,8 @@ static int nfs41_check_expired_stateid(struct nfs4_state *state, nfs4_stateid *s | |||
1764 | if (state->flags & flags) { | 1764 | if (state->flags & flags) { |
1765 | status = nfs41_test_stateid(server, stateid); | 1765 | status = nfs41_test_stateid(server, stateid); |
1766 | if (status != NFS_OK) { | 1766 | if (status != NFS_OK) { |
1767 | nfs41_free_stateid(server, stateid); | 1767 | if (status != -NFS4ERR_BAD_STATEID) |
1768 | nfs41_free_stateid(server, stateid); | ||
1768 | state->flags &= ~flags; | 1769 | state->flags &= ~flags; |
1769 | } | 1770 | } |
1770 | } | 1771 | } |
@@ -4697,7 +4698,9 @@ static int nfs41_check_expired_locks(struct nfs4_state *state) | |||
4697 | if (lsp->ls_flags & NFS_LOCK_INITIALIZED) { | 4698 | if (lsp->ls_flags & NFS_LOCK_INITIALIZED) { |
4698 | status = nfs41_test_stateid(server, &lsp->ls_stateid); | 4699 | status = nfs41_test_stateid(server, &lsp->ls_stateid); |
4699 | if (status != NFS_OK) { | 4700 | if (status != NFS_OK) { |
4700 | nfs41_free_stateid(server, &lsp->ls_stateid); | 4701 | if (status != -NFS4ERR_BAD_STATEID) |
4702 | nfs41_free_stateid(server, | ||
4703 | &lsp->ls_stateid); | ||
4701 | lsp->ls_flags &= ~NFS_LOCK_INITIALIZED; | 4704 | lsp->ls_flags &= ~NFS_LOCK_INITIALIZED; |
4702 | ret = status; | 4705 | ret = status; |
4703 | } | 4706 | } |