diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2010-01-26 15:42:21 -0500 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2010-01-26 15:42:21 -0500 |
commit | 2bee72a6aa1e6d0a4f5da56217f0d0bbbdd0d9a3 (patch) | |
tree | 62a943e0bfb1cff52ac9e54ef5d8a5cea3fbfa35 /fs | |
parent | b0706ca415b188ed58788420de4d5c9972b2afb2 (diff) |
NFSv4: Ensure that the NFSv4 locking can recover from stateid errors
In most cases, we just want to mark the lock_stateid sequence id as being
uninitialised.
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Cc: stable@kernel.org
Reviewed-by: Chuck Lever <chuck.lever@oracle.com>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/nfs/nfs4proc.c | 19 |
1 files changed, 19 insertions, 0 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 198d51d17c13..0b68238ed0c8 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -4088,6 +4088,22 @@ static const struct rpc_call_ops nfs4_recover_lock_ops = { | |||
4088 | .rpc_release = nfs4_lock_release, | 4088 | .rpc_release = nfs4_lock_release, |
4089 | }; | 4089 | }; |
4090 | 4090 | ||
4091 | static void nfs4_handle_setlk_error(struct nfs_server *server, struct nfs4_lock_state *lsp, int new_lock_owner, int error) | ||
4092 | { | ||
4093 | struct nfs_client *clp = server->nfs_client; | ||
4094 | struct nfs4_state *state = lsp->ls_state; | ||
4095 | |||
4096 | switch (error) { | ||
4097 | case -NFS4ERR_ADMIN_REVOKED: | ||
4098 | case -NFS4ERR_BAD_STATEID: | ||
4099 | case -NFS4ERR_EXPIRED: | ||
4100 | if (new_lock_owner != 0 || | ||
4101 | (lsp->ls_flags & NFS_LOCK_INITIALIZED) != 0) | ||
4102 | nfs4_state_mark_reclaim_nograce(clp, state); | ||
4103 | lsp->ls_seqid.flags &= ~NFS_SEQID_CONFIRMED; | ||
4104 | }; | ||
4105 | } | ||
4106 | |||
4091 | static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *fl, int recovery_type) | 4107 | static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *fl, int recovery_type) |
4092 | { | 4108 | { |
4093 | struct nfs4_lockdata *data; | 4109 | struct nfs4_lockdata *data; |
@@ -4126,6 +4142,9 @@ static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *f | |||
4126 | ret = nfs4_wait_for_completion_rpc_task(task); | 4142 | ret = nfs4_wait_for_completion_rpc_task(task); |
4127 | if (ret == 0) { | 4143 | if (ret == 0) { |
4128 | ret = data->rpc_status; | 4144 | ret = data->rpc_status; |
4145 | if (ret) | ||
4146 | nfs4_handle_setlk_error(data->server, data->lsp, | ||
4147 | data->arg.new_lock_owner, ret); | ||
4129 | } else | 4148 | } else |
4130 | data->cancelled = 1; | 4149 | data->cancelled = 1; |
4131 | rpc_put_task(task); | 4150 | rpc_put_task(task); |