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>

+19
+19
fs/nfs/nfs4proc.c
··· 4088 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 4107 static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *fl, int recovery_type) 4092 4108 { 4093 4109 struct nfs4_lockdata *data; ··· 4142 4126 ret = nfs4_wait_for_completion_rpc_task(task); 4143 4127 if (ret == 0) { 4144 4128 ret = data->rpc_status; 4129 + if (ret) 4130 + nfs4_handle_setlk_error(data->server, data->lsp, 4131 + data->arg.new_lock_owner, ret); 4145 4132 } else 4146 4133 data->cancelled = 1; 4147 4134 rpc_put_task(task);