aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2010-07-31 14:29:06 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2010-08-03 22:06:42 -0400
commit14516c3a30e256e8d4e7a9af271c8df644ac3222 (patch)
treeed8d43d6568fca893b7b1ebd7bc38244fc37a409 /fs/nfs
parent0a8ebba943dd89bdd57c5dab5a66932f690847d9 (diff)
NFSv4.1: Handle NFS4ERR_DELAY on SEQUENCE correctly
In RFC5661, an NFS4ERR_DELAY error on a SEQUENCE operation has the special meaning that the server is not finished processing the request. In this case we want to just retry the request without touching the slot. Also fix a bug whereby we would fail to update the sequence id if the server returned any error other than NFS_OK/NFS4ERR_DELAY. Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs')
-rw-r--r--fs/nfs/nfs4proc.c92
1 files changed, 62 insertions, 30 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index d6413b48b057..cab0eb915145 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -389,11 +389,12 @@ static void nfs41_sequence_free_slot(struct nfs4_sequence_res *res)
389 res->sr_slotid = NFS4_MAX_SLOT_TABLE; 389 res->sr_slotid = NFS4_MAX_SLOT_TABLE;
390} 390}
391 391
392static void nfs41_sequence_done(struct nfs4_sequence_res *res) 392static int nfs41_sequence_done(struct rpc_task *task, struct nfs4_sequence_res *res)
393{ 393{
394 unsigned long timestamp; 394 unsigned long timestamp;
395 struct nfs4_slot_table *tbl; 395 struct nfs4_slot_table *tbl;
396 struct nfs4_slot *slot; 396 struct nfs4_slot *slot;
397 struct nfs_client *clp;
397 398
398 /* 399 /*
399 * sr_status remains 1 if an RPC level error occurred. The server 400 * sr_status remains 1 if an RPC level error occurred. The server
@@ -408,14 +409,16 @@ static void nfs41_sequence_done(struct nfs4_sequence_res *res)
408 if (res->sr_slotid == NFS4_MAX_SLOT_TABLE) 409 if (res->sr_slotid == NFS4_MAX_SLOT_TABLE)
409 goto out; 410 goto out;
410 411
412 tbl = &res->sr_session->fc_slot_table;
413 slot = tbl->slots + res->sr_slotid;
414
411 /* Check the SEQUENCE operation status */ 415 /* Check the SEQUENCE operation status */
412 if (res->sr_status == 0) { 416 switch (res->sr_status) {
413 struct nfs_client *clp = res->sr_session->clp; 417 case 0:
414 tbl = &res->sr_session->fc_slot_table;
415 slot = tbl->slots + res->sr_slotid;
416 /* Update the slot's sequence and clientid lease timer */ 418 /* Update the slot's sequence and clientid lease timer */
417 ++slot->seq_nr; 419 ++slot->seq_nr;
418 timestamp = res->sr_renewal_time; 420 timestamp = res->sr_renewal_time;
421 clp = res->sr_session->clp;
419 spin_lock(&clp->cl_lock); 422 spin_lock(&clp->cl_lock);
420 if (time_before(clp->cl_last_renewal, timestamp)) 423 if (time_before(clp->cl_last_renewal, timestamp))
421 clp->cl_last_renewal = timestamp; 424 clp->cl_last_renewal = timestamp;
@@ -423,18 +426,39 @@ static void nfs41_sequence_done(struct nfs4_sequence_res *res)
423 /* Check sequence flags */ 426 /* Check sequence flags */
424 if (atomic_read(&clp->cl_count) > 1) 427 if (atomic_read(&clp->cl_count) > 1)
425 nfs41_handle_sequence_flag_errors(clp, res->sr_status_flags); 428 nfs41_handle_sequence_flag_errors(clp, res->sr_status_flags);
429 break;
430 case -NFS4ERR_DELAY:
431 /* The server detected a resend of the RPC call and
432 * returned NFS4ERR_DELAY as per Section 2.10.6.2
433 * of RFC5661.
434 */
435 dprintk("%s: slot=%d seq=%d: Operation in progress\n",
436 __func__, res->sr_slotid, slot->seq_nr);
437 goto out_retry;
438 default:
439 /* Just update the slot sequence no. */
440 ++slot->seq_nr;
426 } 441 }
427out: 442out:
428 /* The session may be reset by one of the error handlers. */ 443 /* The session may be reset by one of the error handlers. */
429 dprintk("%s: Error %d free the slot \n", __func__, res->sr_status); 444 dprintk("%s: Error %d free the slot \n", __func__, res->sr_status);
430 nfs41_sequence_free_slot(res); 445 nfs41_sequence_free_slot(res);
446 return 1;
447out_retry:
448 rpc_restart_call(task);
449 /* FIXME: rpc_restart_call() should be made to return success/fail */
450 if (task->tk_action == NULL)
451 goto out;
452 rpc_delay(task, NFS4_POLL_RETRY_MAX);
453 return 0;
431} 454}
432 455
433static void nfs4_sequence_done(const struct nfs_server *server, 456static int nfs4_sequence_done(struct rpc_task *task,
434 struct nfs4_sequence_res *res, int rpc_status) 457 struct nfs4_sequence_res *res)
435{ 458{
436 if (res->sr_session != NULL) 459 if (res->sr_session == NULL)
437 nfs41_sequence_done(res); 460 return 1;
461 return nfs41_sequence_done(task, res);
438} 462}
439 463
440/* 464/*
@@ -592,7 +616,7 @@ static void nfs41_call_sync_done(struct rpc_task *task, void *calldata)
592{ 616{
593 struct nfs41_call_sync_data *data = calldata; 617 struct nfs41_call_sync_data *data = calldata;
594 618
595 nfs41_sequence_done(data->seq_res); 619 nfs41_sequence_done(task, data->seq_res);
596} 620}
597 621
598struct rpc_call_ops nfs41_call_sync_ops = { 622struct rpc_call_ops nfs41_call_sync_ops = {
@@ -650,9 +674,10 @@ int _nfs4_call_sync_session(struct nfs_server *server,
650} 674}
651 675
652#else 676#else
653static void nfs4_sequence_done(const struct nfs_server *server, 677static int nfs4_sequence_done(struct rpc_task *task,
654 struct nfs4_sequence_res *res, int rpc_status) 678 struct nfs4_sequence_res *res)
655{ 679{
680 return 1;
656} 681}
657#endif /* CONFIG_NFS_V4_1 */ 682#endif /* CONFIG_NFS_V4_1 */
658 683
@@ -1379,8 +1404,8 @@ static void nfs4_open_done(struct rpc_task *task, void *calldata)
1379 1404
1380 data->rpc_status = task->tk_status; 1405 data->rpc_status = task->tk_status;
1381 1406
1382 nfs4_sequence_done(data->o_arg.server, &data->o_res.seq_res, 1407 if (!nfs4_sequence_done(task, &data->o_res.seq_res))
1383 task->tk_status); 1408 return;
1384 1409
1385 if (RPC_ASSASSINATED(task)) 1410 if (RPC_ASSASSINATED(task))
1386 return; 1411 return;
@@ -1832,7 +1857,8 @@ static void nfs4_close_done(struct rpc_task *task, void *data)
1832 struct nfs4_state *state = calldata->state; 1857 struct nfs4_state *state = calldata->state;
1833 struct nfs_server *server = NFS_SERVER(calldata->inode); 1858 struct nfs_server *server = NFS_SERVER(calldata->inode);
1834 1859
1835 nfs4_sequence_done(server, &calldata->res.seq_res, task->tk_status); 1860 if (!nfs4_sequence_done(task, &calldata->res.seq_res))
1861 return;
1836 if (RPC_ASSASSINATED(task)) 1862 if (RPC_ASSASSINATED(task))
1837 return; 1863 return;
1838 /* hmm. we are done with the inode, and in the process of freeing 1864 /* hmm. we are done with the inode, and in the process of freeing
@@ -2642,7 +2668,8 @@ static int nfs4_proc_unlink_done(struct rpc_task *task, struct inode *dir)
2642{ 2668{
2643 struct nfs_removeres *res = task->tk_msg.rpc_resp; 2669 struct nfs_removeres *res = task->tk_msg.rpc_resp;
2644 2670
2645 nfs4_sequence_done(res->server, &res->seq_res, task->tk_status); 2671 if (!nfs4_sequence_done(task, &res->seq_res))
2672 return 0;
2646 if (nfs4_async_handle_error(task, res->server, NULL) == -EAGAIN) 2673 if (nfs4_async_handle_error(task, res->server, NULL) == -EAGAIN)
2647 return 0; 2674 return 0;
2648 update_changeattr(dir, &res->cinfo); 2675 update_changeattr(dir, &res->cinfo);
@@ -3087,7 +3114,8 @@ static int nfs4_read_done(struct rpc_task *task, struct nfs_read_data *data)
3087 3114
3088 dprintk("--> %s\n", __func__); 3115 dprintk("--> %s\n", __func__);
3089 3116
3090 nfs4_sequence_done(server, &data->res.seq_res, task->tk_status); 3117 if (!nfs4_sequence_done(task, &data->res.seq_res))
3118 return -EAGAIN;
3091 3119
3092 if (nfs4_async_handle_error(task, server, data->args.context->state) == -EAGAIN) { 3120 if (nfs4_async_handle_error(task, server, data->args.context->state) == -EAGAIN) {
3093 nfs_restart_rpc(task, server->nfs_client); 3121 nfs_restart_rpc(task, server->nfs_client);
@@ -3110,8 +3138,8 @@ static int nfs4_write_done(struct rpc_task *task, struct nfs_write_data *data)
3110{ 3138{
3111 struct inode *inode = data->inode; 3139 struct inode *inode = data->inode;
3112 3140
3113 nfs4_sequence_done(NFS_SERVER(inode), &data->res.seq_res, 3141 if (!nfs4_sequence_done(task, &data->res.seq_res))
3114 task->tk_status); 3142 return -EAGAIN;
3115 3143
3116 if (nfs4_async_handle_error(task, NFS_SERVER(inode), data->args.context->state) == -EAGAIN) { 3144 if (nfs4_async_handle_error(task, NFS_SERVER(inode), data->args.context->state) == -EAGAIN) {
3117 nfs_restart_rpc(task, NFS_SERVER(inode)->nfs_client); 3145 nfs_restart_rpc(task, NFS_SERVER(inode)->nfs_client);
@@ -3139,8 +3167,9 @@ static int nfs4_commit_done(struct rpc_task *task, struct nfs_write_data *data)
3139{ 3167{
3140 struct inode *inode = data->inode; 3168 struct inode *inode = data->inode;
3141 3169
3142 nfs4_sequence_done(NFS_SERVER(inode), &data->res.seq_res, 3170 if (!nfs4_sequence_done(task, &data->res.seq_res))
3143 task->tk_status); 3171 return -EAGAIN;
3172
3144 if (nfs4_async_handle_error(task, NFS_SERVER(inode), NULL) == -EAGAIN) { 3173 if (nfs4_async_handle_error(task, NFS_SERVER(inode), NULL) == -EAGAIN) {
3145 nfs_restart_rpc(task, NFS_SERVER(inode)->nfs_client); 3174 nfs_restart_rpc(task, NFS_SERVER(inode)->nfs_client);
3146 return -EAGAIN; 3175 return -EAGAIN;
@@ -3630,8 +3659,8 @@ static void nfs4_delegreturn_done(struct rpc_task *task, void *calldata)
3630{ 3659{
3631 struct nfs4_delegreturndata *data = calldata; 3660 struct nfs4_delegreturndata *data = calldata;
3632 3661
3633 nfs4_sequence_done(data->res.server, &data->res.seq_res, 3662 if (!nfs4_sequence_done(task, &data->res.seq_res))
3634 task->tk_status); 3663 return;
3635 3664
3636 switch (task->tk_status) { 3665 switch (task->tk_status) {
3637 case -NFS4ERR_STALE_STATEID: 3666 case -NFS4ERR_STALE_STATEID:
@@ -3881,8 +3910,8 @@ static void nfs4_locku_done(struct rpc_task *task, void *data)
3881{ 3910{
3882 struct nfs4_unlockdata *calldata = data; 3911 struct nfs4_unlockdata *calldata = data;
3883 3912
3884 nfs4_sequence_done(calldata->server, &calldata->res.seq_res, 3913 if (!nfs4_sequence_done(task, &calldata->res.seq_res))
3885 task->tk_status); 3914 return;
3886 if (RPC_ASSASSINATED(task)) 3915 if (RPC_ASSASSINATED(task))
3887 return; 3916 return;
3888 switch (task->tk_status) { 3917 switch (task->tk_status) {
@@ -4091,8 +4120,8 @@ static void nfs4_lock_done(struct rpc_task *task, void *calldata)
4091 4120
4092 dprintk("%s: begin!\n", __func__); 4121 dprintk("%s: begin!\n", __func__);
4093 4122
4094 nfs4_sequence_done(data->server, &data->res.seq_res, 4123 if (!nfs4_sequence_done(task, &data->res.seq_res))
4095 task->tk_status); 4124 return;
4096 4125
4097 data->rpc_status = task->tk_status; 4126 data->rpc_status = task->tk_status;
4098 if (RPC_ASSASSINATED(task)) 4127 if (RPC_ASSASSINATED(task))
@@ -4629,7 +4658,8 @@ static void nfs4_get_lease_time_done(struct rpc_task *task, void *calldata)
4629 (struct nfs4_get_lease_time_data *)calldata; 4658 (struct nfs4_get_lease_time_data *)calldata;
4630 4659
4631 dprintk("--> %s\n", __func__); 4660 dprintk("--> %s\n", __func__);
4632 nfs41_sequence_done(&data->res->lr_seq_res); 4661 if (!nfs41_sequence_done(task, &data->res->lr_seq_res))
4662 return;
4633 switch (task->tk_status) { 4663 switch (task->tk_status) {
4634 case -NFS4ERR_DELAY: 4664 case -NFS4ERR_DELAY:
4635 case -NFS4ERR_GRACE: 4665 case -NFS4ERR_GRACE:
@@ -5111,7 +5141,8 @@ static void nfs41_sequence_call_done(struct rpc_task *task, void *data)
5111 struct nfs4_sequence_data *calldata = data; 5141 struct nfs4_sequence_data *calldata = data;
5112 struct nfs_client *clp = calldata->clp; 5142 struct nfs_client *clp = calldata->clp;
5113 5143
5114 nfs41_sequence_done(task->tk_msg.rpc_resp); 5144 if (!nfs41_sequence_done(task, task->tk_msg.rpc_resp))
5145 return;
5115 5146
5116 if (task->tk_status < 0) { 5147 if (task->tk_status < 0) {
5117 dprintk("%s ERROR %d\n", __func__, task->tk_status); 5148 dprintk("%s ERROR %d\n", __func__, task->tk_status);
@@ -5255,7 +5286,8 @@ static void nfs4_reclaim_complete_done(struct rpc_task *task, void *data)
5255 struct nfs4_sequence_res *res = &calldata->res.seq_res; 5286 struct nfs4_sequence_res *res = &calldata->res.seq_res;
5256 5287
5257 dprintk("--> %s\n", __func__); 5288 dprintk("--> %s\n", __func__);
5258 nfs41_sequence_done(res); 5289 if (!nfs41_sequence_done(task, res))
5290 return;
5259 5291
5260 if (nfs41_reclaim_complete_handle_errors(task, clp) == -EAGAIN) { 5292 if (nfs41_reclaim_complete_handle_errors(task, clp) == -EAGAIN) {
5261 rpc_restart_call_prepare(task); 5293 rpc_restart_call_prepare(task);