aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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);