diff options
Diffstat (limited to 'fs/nfsd/nfs4callback.c')
-rw-r--r-- | fs/nfsd/nfs4callback.c | 52 |
1 files changed, 23 insertions, 29 deletions
diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c index cd58b7cd3f1a..4c993aaf1e6e 100644 --- a/fs/nfsd/nfs4callback.c +++ b/fs/nfsd/nfs4callback.c | |||
@@ -879,13 +879,6 @@ static void nfsd4_cb_prepare(struct rpc_task *task, void *calldata) | |||
879 | if (!nfsd41_cb_get_slot(clp, task)) | 879 | if (!nfsd41_cb_get_slot(clp, task)) |
880 | return; | 880 | return; |
881 | } | 881 | } |
882 | spin_lock(&clp->cl_lock); | ||
883 | if (list_empty(&cb->cb_per_client)) { | ||
884 | /* This is the first call, not a restart */ | ||
885 | cb->cb_done = false; | ||
886 | list_add(&cb->cb_per_client, &clp->cl_callbacks); | ||
887 | } | ||
888 | spin_unlock(&clp->cl_lock); | ||
889 | rpc_call_start(task); | 882 | rpc_call_start(task); |
890 | } | 883 | } |
891 | 884 | ||
@@ -907,16 +900,21 @@ static void nfsd4_cb_done(struct rpc_task *task, void *calldata) | |||
907 | clp->cl_cb_session->se_cb_seq_nr); | 900 | clp->cl_cb_session->se_cb_seq_nr); |
908 | } | 901 | } |
909 | 902 | ||
910 | if (clp->cl_cb_client != task->tk_client) { | 903 | /* |
911 | /* We're shutting down or changing cl_cb_client; leave | 904 | * If the backchannel connection was shut down while this |
912 | * it to nfsd4_process_cb_update to restart the call if | 905 | * task was queued, we need to resubmit it after setting up |
913 | * necessary. */ | 906 | * a new backchannel connection. |
907 | * | ||
908 | * Note that if we lost our callback connection permanently | ||
909 | * the submission code will error out, so we don't need to | ||
910 | * handle that case here. | ||
911 | */ | ||
912 | if (task->tk_flags & RPC_TASK_KILLED) { | ||
913 | task->tk_status = 0; | ||
914 | cb->cb_need_restart = true; | ||
914 | return; | 915 | return; |
915 | } | 916 | } |
916 | 917 | ||
917 | if (cb->cb_done) | ||
918 | return; | ||
919 | |||
920 | if (cb->cb_status) { | 918 | if (cb->cb_status) { |
921 | WARN_ON_ONCE(task->tk_status); | 919 | WARN_ON_ONCE(task->tk_status); |
922 | task->tk_status = cb->cb_status; | 920 | task->tk_status = cb->cb_status; |
@@ -936,21 +934,17 @@ static void nfsd4_cb_done(struct rpc_task *task, void *calldata) | |||
936 | default: | 934 | default: |
937 | BUG(); | 935 | BUG(); |
938 | } | 936 | } |
939 | cb->cb_done = true; | ||
940 | } | 937 | } |
941 | 938 | ||
942 | static void nfsd4_cb_release(void *calldata) | 939 | static void nfsd4_cb_release(void *calldata) |
943 | { | 940 | { |
944 | struct nfsd4_callback *cb = calldata; | 941 | struct nfsd4_callback *cb = calldata; |
945 | struct nfs4_client *clp = cb->cb_clp; | ||
946 | |||
947 | if (cb->cb_done) { | ||
948 | spin_lock(&clp->cl_lock); | ||
949 | list_del(&cb->cb_per_client); | ||
950 | spin_unlock(&clp->cl_lock); | ||
951 | 942 | ||
943 | if (cb->cb_need_restart) | ||
944 | nfsd4_run_cb(cb); | ||
945 | else | ||
952 | cb->cb_ops->release(cb); | 946 | cb->cb_ops->release(cb); |
953 | } | 947 | |
954 | } | 948 | } |
955 | 949 | ||
956 | static const struct rpc_call_ops nfsd4_cb_ops = { | 950 | static const struct rpc_call_ops nfsd4_cb_ops = { |
@@ -1045,9 +1039,6 @@ static void nfsd4_process_cb_update(struct nfsd4_callback *cb) | |||
1045 | nfsd4_mark_cb_down(clp, err); | 1039 | nfsd4_mark_cb_down(clp, err); |
1046 | return; | 1040 | return; |
1047 | } | 1041 | } |
1048 | /* Yay, the callback channel's back! Restart any callbacks: */ | ||
1049 | list_for_each_entry(cb, &clp->cl_callbacks, cb_per_client) | ||
1050 | queue_work(callback_wq, &cb->cb_work); | ||
1051 | } | 1042 | } |
1052 | 1043 | ||
1053 | static void | 1044 | static void |
@@ -1058,8 +1049,12 @@ nfsd4_run_cb_work(struct work_struct *work) | |||
1058 | struct nfs4_client *clp = cb->cb_clp; | 1049 | struct nfs4_client *clp = cb->cb_clp; |
1059 | struct rpc_clnt *clnt; | 1050 | struct rpc_clnt *clnt; |
1060 | 1051 | ||
1061 | if (cb->cb_ops && cb->cb_ops->prepare) | 1052 | if (cb->cb_need_restart) { |
1062 | cb->cb_ops->prepare(cb); | 1053 | cb->cb_need_restart = false; |
1054 | } else { | ||
1055 | if (cb->cb_ops && cb->cb_ops->prepare) | ||
1056 | cb->cb_ops->prepare(cb); | ||
1057 | } | ||
1063 | 1058 | ||
1064 | if (clp->cl_flags & NFSD4_CLIENT_CB_FLAG_MASK) | 1059 | if (clp->cl_flags & NFSD4_CLIENT_CB_FLAG_MASK) |
1065 | nfsd4_process_cb_update(cb); | 1060 | nfsd4_process_cb_update(cb); |
@@ -1085,9 +1080,8 @@ void nfsd4_init_cb(struct nfsd4_callback *cb, struct nfs4_client *clp, | |||
1085 | cb->cb_msg.rpc_resp = cb; | 1080 | cb->cb_msg.rpc_resp = cb; |
1086 | cb->cb_ops = ops; | 1081 | cb->cb_ops = ops; |
1087 | INIT_WORK(&cb->cb_work, nfsd4_run_cb_work); | 1082 | INIT_WORK(&cb->cb_work, nfsd4_run_cb_work); |
1088 | INIT_LIST_HEAD(&cb->cb_per_client); | ||
1089 | cb->cb_status = 0; | 1083 | cb->cb_status = 0; |
1090 | cb->cb_done = true; | 1084 | cb->cb_need_restart = false; |
1091 | } | 1085 | } |
1092 | 1086 | ||
1093 | void nfsd4_run_cb(struct nfsd4_callback *cb) | 1087 | void nfsd4_run_cb(struct nfsd4_callback *cb) |