NFS: Ensure that we handle NFS4ERR_STALE_STATEID correctly

Even if the server is crazy, we should be able to mark the stateid as being
bad, to ensure it gets recovered.

Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Reviewed-by: Chuck Lever <chuck.lever@oracle.com>

+33 -14
+1
fs/nfs/nfs4_fs.h
··· 278 278 extern void nfs4_schedule_state_recovery(struct nfs_client *); 279 279 extern void nfs4_schedule_state_manager(struct nfs_client *); 280 280 extern int nfs4_state_mark_reclaim_nograce(struct nfs_client *clp, struct nfs4_state *state); 281 + extern int nfs4_state_mark_reclaim_reboot(struct nfs_client *clp, struct nfs4_state *state); 281 282 extern void nfs41_handle_sequence_flag_errors(struct nfs_client *clp, u32 flags); 282 283 extern void nfs4_put_lock_state(struct nfs4_lock_state *lsp); 283 284 extern int nfs4_set_lock_state(struct nfs4_state *state, struct file_lock *fl);
+31 -13
fs/nfs/nfs4proc.c
··· 249 249 if (state == NULL) 250 250 break; 251 251 nfs4_state_mark_reclaim_nograce(clp, state); 252 - case -NFS4ERR_STALE_CLIENTID: 252 + goto do_state_recovery; 253 253 case -NFS4ERR_STALE_STATEID: 254 + if (state == NULL) 255 + break; 256 + nfs4_state_mark_reclaim_reboot(clp, state); 257 + case -NFS4ERR_STALE_CLIENTID: 254 258 case -NFS4ERR_EXPIRED: 255 - nfs4_schedule_state_recovery(clp); 256 - ret = nfs4_wait_clnt_recover(clp); 257 - if (ret == 0) 258 - exception->retry = 1; 259 - break; 259 + goto do_state_recovery; 260 260 #if defined(CONFIG_NFS_V4_1) 261 261 case -NFS4ERR_BADSESSION: 262 262 case -NFS4ERR_BADSLOT: ··· 289 289 } 290 290 /* We failed to handle the error */ 291 291 return nfs4_map_errors(ret); 292 + do_state_recovery: 293 + nfs4_schedule_state_recovery(clp); 294 + ret = nfs4_wait_clnt_recover(clp); 295 + if (ret == 0) 296 + exception->retry = 1; 297 + return ret; 292 298 } 293 299 294 300 ··· 3426 3420 if (state == NULL) 3427 3421 break; 3428 3422 nfs4_state_mark_reclaim_nograce(clp, state); 3429 - case -NFS4ERR_STALE_CLIENTID: 3423 + goto do_state_recovery; 3430 3424 case -NFS4ERR_STALE_STATEID: 3425 + if (state == NULL) 3426 + break; 3427 + nfs4_state_mark_reclaim_reboot(clp, state); 3428 + case -NFS4ERR_STALE_CLIENTID: 3431 3429 case -NFS4ERR_EXPIRED: 3432 - rpc_sleep_on(&clp->cl_rpcwaitq, task, NULL); 3433 - nfs4_schedule_state_recovery(clp); 3434 - if (test_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state) == 0) 3435 - rpc_wake_up_queued_task(&clp->cl_rpcwaitq, task); 3436 - task->tk_status = 0; 3437 - return -EAGAIN; 3430 + goto do_state_recovery; 3438 3431 #if defined(CONFIG_NFS_V4_1) 3439 3432 case -NFS4ERR_BADSESSION: 3440 3433 case -NFS4ERR_BADSLOT: ··· 3461 3456 } 3462 3457 task->tk_status = nfs4_map_errors(task->tk_status); 3463 3458 return 0; 3459 + do_state_recovery: 3460 + rpc_sleep_on(&clp->cl_rpcwaitq, task, NULL); 3461 + nfs4_schedule_state_recovery(clp); 3462 + if (test_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state) == 0) 3463 + rpc_wake_up_queued_task(&clp->cl_rpcwaitq, task); 3464 + task->tk_status = 0; 3465 + return -EAGAIN; 3464 3466 } 3465 3467 3466 3468 static int ··· 4110 4098 if (new_lock_owner != 0 || 4111 4099 (lsp->ls_flags & NFS_LOCK_INITIALIZED) != 0) 4112 4100 nfs4_state_mark_reclaim_nograce(clp, state); 4101 + lsp->ls_seqid.flags &= ~NFS_SEQID_CONFIRMED; 4102 + break; 4103 + case -NFS4ERR_STALE_STATEID: 4104 + if (new_lock_owner != 0 || 4105 + (lsp->ls_flags & NFS_LOCK_INITIALIZED) != 0) 4106 + nfs4_state_mark_reclaim_reboot(clp, state); 4113 4107 lsp->ls_seqid.flags &= ~NFS_SEQID_CONFIRMED; 4114 4108 }; 4115 4109 }
+1 -1
fs/nfs/nfs4state.c
··· 901 901 nfs4_schedule_state_manager(clp); 902 902 } 903 903 904 - static int nfs4_state_mark_reclaim_reboot(struct nfs_client *clp, struct nfs4_state *state) 904 + int nfs4_state_mark_reclaim_reboot(struct nfs_client *clp, struct nfs4_state *state) 905 905 { 906 906 907 907 set_bit(NFS_STATE_RECLAIM_REBOOT, &state->flags);