diff options
author | J. Bruce Fields <bfields@redhat.com> | 2011-01-14 14:25:48 -0500 |
---|---|---|
committer | J. Bruce Fields <bfields@redhat.com> | 2011-01-14 14:51:31 -0500 |
commit | a8f2800b4f7b76cecb7209cb6a7d2b14904fc711 (patch) | |
tree | 29a582ee8af49577cce3e868800dfd8d8485b1e3 | |
parent | 4795bb37effb7b8fe77e2d2034545d062d3788a8 (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.c | 21 |
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); |