aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJ. Bruce Fields <bfields@redhat.com>2011-01-14 14:25:48 -0500
committerJ. Bruce Fields <bfields@redhat.com>2011-01-14 14:51:31 -0500
commita8f2800b4f7b76cecb7209cb6a7d2b14904fc711 (patch)
tree29a582ee8af49577cce3e868800dfd8d8485b1e3
parent4795bb37effb7b8fe77e2d2034545d062d3788a8 (diff)
nfsd4: fix callback restarting
Ensure a new callback is added to the client's list of callbacks at most once. Signed-off-by: J. Bruce Fields <bfields@redhat.com>
-rw-r--r--fs/nfsd/nfs4callback.c21
1 files changed, 9 insertions, 12 deletions
diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
index 209e186386a0..ae93c5c83e87 100644
--- a/fs/nfsd/nfs4callback.c
+++ b/fs/nfsd/nfs4callback.c
@@ -639,9 +639,12 @@ static void nfsd4_cb_prepare(struct rpc_task *task, void *calldata)
639 if (!nfsd41_cb_get_slot(clp, task)) 639 if (!nfsd41_cb_get_slot(clp, task))
640 return; 640 return;
641 } 641 }
642 cb->cb_done = false;
643 spin_lock(&clp->cl_lock); 642 spin_lock(&clp->cl_lock);
644 list_add(&cb->cb_per_client, &clp->cl_callbacks); 643 if (list_empty(&cb->cb_per_client)) {
644 /* This is the first call, not a restart */
645 cb->cb_done = false;
646 list_add(&cb->cb_per_client, &clp->cl_callbacks);
647 }
645 spin_unlock(&clp->cl_lock); 648 spin_unlock(&clp->cl_lock);
646 rpc_call_start(task); 649 rpc_call_start(task);
647} 650}
@@ -678,10 +681,10 @@ static void nfsd4_cb_recall_done(struct rpc_task *task, void *calldata)
678 681
679 nfsd4_cb_done(task, calldata); 682 nfsd4_cb_done(task, calldata);
680 683
681 if (current_rpc_client == NULL) { 684 if (current_rpc_client != task->tk_client) {
682 /* We're shutting down; give up. */ 685 /* We're shutting down or changing cl_cb_client; leave
683 /* XXX: err, or is it ok just to fall through 686 * it to nfsd4_process_cb_update to restart the call if
684 * and rpc_restart_call? */ 687 * necessary. */
685 return; 688 return;
686 } 689 }
687 690
@@ -699,12 +702,6 @@ static void nfsd4_cb_recall_done(struct rpc_task *task, void *calldata)
699 default: 702 default:
700 /* Network partition? */ 703 /* Network partition? */
701 nfsd4_mark_cb_down(clp, task->tk_status); 704 nfsd4_mark_cb_down(clp, task->tk_status);
702 if (current_rpc_client != task->tk_client) {
703 /* queue a callback on the new connection: */
704 atomic_inc(&dp->dl_count);
705 run_nfsd4_cb(&dp->dl_recall);
706 return;
707 }
708 } 705 }
709 if (dp->dl_retries--) { 706 if (dp->dl_retries--) {
710 rpc_delay(task, 2*HZ); 707 rpc_delay(task, 2*HZ);