@@ -826,6 +826,31 @@ static int max_cb_time(struct net *net)
826
826
return max (nn -> nfsd4_lease /10 , (time_t )1 ) * HZ ;
827
827
}
828
828
829
+ static struct workqueue_struct * callback_wq ;
830
+
831
+ static bool nfsd4_queue_cb (struct nfsd4_callback * cb )
832
+ {
833
+ return queue_work (callback_wq , & cb -> cb_work );
834
+ }
835
+
836
+ static void nfsd41_cb_inflight_begin (struct nfs4_client * clp )
837
+ {
838
+ atomic_inc (& clp -> cl_cb_inflight );
839
+ }
840
+
841
+ static void nfsd41_cb_inflight_end (struct nfs4_client * clp )
842
+ {
843
+
844
+ if (atomic_dec_and_test (& clp -> cl_cb_inflight ))
845
+ wake_up_var (& clp -> cl_cb_inflight );
846
+ }
847
+
848
+ static void nfsd41_cb_inflight_wait_complete (struct nfs4_client * clp )
849
+ {
850
+ wait_var_event (& clp -> cl_cb_inflight ,
851
+ !atomic_read (& clp -> cl_cb_inflight ));
852
+ }
853
+
829
854
static const struct cred * get_backchannel_cred (struct nfs4_client * clp , struct rpc_clnt * client , struct nfsd4_session * ses )
830
855
{
831
856
if (clp -> cl_minorversion == 0 ) {
@@ -937,14 +962,21 @@ static void nfsd4_cb_probe_done(struct rpc_task *task, void *calldata)
937
962
clp -> cl_cb_state = NFSD4_CB_UP ;
938
963
}
939
964
965
+ static void nfsd4_cb_probe_release (void * calldata )
966
+ {
967
+ struct nfs4_client * clp = container_of (calldata , struct nfs4_client , cl_cb_null );
968
+
969
+ nfsd41_cb_inflight_end (clp );
970
+
971
+ }
972
+
940
973
static const struct rpc_call_ops nfsd4_cb_probe_ops = {
941
974
/* XXX: release method to ensure we set the cb channel down if
942
975
* necessary on early failure? */
943
976
.rpc_call_done = nfsd4_cb_probe_done ,
977
+ .rpc_release = nfsd4_cb_probe_release ,
944
978
};
945
979
946
- static struct workqueue_struct * callback_wq ;
947
-
948
980
/*
949
981
* Poke the callback thread to process any updates to the callback
950
982
* parameters, and send a null probe.
@@ -1004,6 +1036,16 @@ static void nfsd41_cb_release_slot(struct nfsd4_callback *cb)
1004
1036
}
1005
1037
}
1006
1038
1039
+ static void nfsd41_destroy_cb (struct nfsd4_callback * cb )
1040
+ {
1041
+ struct nfs4_client * clp = cb -> cb_clp ;
1042
+
1043
+ nfsd41_cb_release_slot (cb );
1044
+ if (cb -> cb_ops && cb -> cb_ops -> release )
1045
+ cb -> cb_ops -> release (cb );
1046
+ nfsd41_cb_inflight_end (clp );
1047
+ }
1048
+
1007
1049
/*
1008
1050
* TODO: cb_sequence should support referring call lists, cachethis, multiple
1009
1051
* slots, and mark callback channel down on communication errors.
@@ -1101,8 +1143,10 @@ static bool nfsd4_cb_sequence_done(struct rpc_task *task, struct nfsd4_callback
1101
1143
ret = false;
1102
1144
goto out ;
1103
1145
need_restart :
1104
- task -> tk_status = 0 ;
1105
- cb -> cb_need_restart = true;
1146
+ if (!test_bit (NFSD4_CLIENT_CB_KILL , & clp -> cl_flags )) {
1147
+ task -> tk_status = 0 ;
1148
+ cb -> cb_need_restart = true;
1149
+ }
1106
1150
return false;
1107
1151
}
1108
1152
@@ -1144,9 +1188,9 @@ static void nfsd4_cb_release(void *calldata)
1144
1188
struct nfsd4_callback * cb = calldata ;
1145
1189
1146
1190
if (cb -> cb_need_restart )
1147
- nfsd4_run_cb (cb );
1191
+ nfsd4_queue_cb (cb );
1148
1192
else
1149
- cb -> cb_ops -> release (cb );
1193
+ nfsd41_destroy_cb (cb );
1150
1194
1151
1195
}
1152
1196
@@ -1180,6 +1224,7 @@ void nfsd4_shutdown_callback(struct nfs4_client *clp)
1180
1224
*/
1181
1225
nfsd4_run_cb (& clp -> cl_cb_null );
1182
1226
flush_workqueue (callback_wq );
1227
+ nfsd41_cb_inflight_wait_complete (clp );
1183
1228
}
1184
1229
1185
1230
/* requires cl_lock: */
@@ -1265,8 +1310,7 @@ nfsd4_run_cb_work(struct work_struct *work)
1265
1310
clnt = clp -> cl_cb_client ;
1266
1311
if (!clnt ) {
1267
1312
/* Callback channel broken, or client killed; give up: */
1268
- if (cb -> cb_ops && cb -> cb_ops -> release )
1269
- cb -> cb_ops -> release (cb );
1313
+ nfsd41_destroy_cb (cb );
1270
1314
return ;
1271
1315
}
1272
1316
@@ -1275,6 +1319,7 @@ nfsd4_run_cb_work(struct work_struct *work)
1275
1319
*/
1276
1320
if (!cb -> cb_ops && clp -> cl_minorversion ) {
1277
1321
clp -> cl_cb_state = NFSD4_CB_UP ;
1322
+ nfsd41_destroy_cb (cb );
1278
1323
return ;
1279
1324
}
1280
1325
@@ -1300,5 +1345,9 @@ void nfsd4_init_cb(struct nfsd4_callback *cb, struct nfs4_client *clp,
1300
1345
1301
1346
void nfsd4_run_cb (struct nfsd4_callback * cb )
1302
1347
{
1303
- queue_work (callback_wq , & cb -> cb_work );
1348
+ struct nfs4_client * clp = cb -> cb_clp ;
1349
+
1350
+ nfsd41_cb_inflight_begin (clp );
1351
+ if (!nfsd4_queue_cb (cb ))
1352
+ nfsd41_cb_inflight_end (clp );
1304
1353
}
0 commit comments