summaryrefslogtreecommitdiffstats
path: root/fs/nfs
diff options
context:
space:
mode:
authorChuck Lever2012-07-11 22:30:05 +0200
committerTrond Myklebust2012-07-16 20:48:53 +0200
commiteb64cf964d453f8b559a8c0c2625952dbbcb5838 (patch)
treeb6ac6d9cfdee8d8ae1710d6f2fb25520d7d2a576 /fs/nfs
parentNFS: Don't free a state ID the server does not recognize (diff)
downloadkernel-qcow2-linux-eb64cf964d453f8b559a8c0c2625952dbbcb5838.tar.gz
kernel-qcow2-linux-eb64cf964d453f8b559a8c0c2625952dbbcb5838.tar.xz
kernel-qcow2-linux-eb64cf964d453f8b559a8c0c2625952dbbcb5838.zip
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: Chuck Lever <chuck.lever@oracle.com> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs')
-rw-r--r--fs/nfs/nfs4proc.c23
1 files changed, 12 insertions, 11 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index afd61d72837d..d1c1016cd505 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -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);
@@ -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
@@ -4690,7 +4691,7 @@ out:
#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);
@@ -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