- srpc_server_rpc_t *rpc;
- srpc_buffer_t *buf;
-
- cfs_spin_lock(&sv->sv_lock);
-
- LASSERT (sv->sv_shuttingdown); /* srpc_shutdown_service called */
-
- if (sv->sv_nposted_msg != 0 || !cfs_list_empty(&sv->sv_active_rpcq)) {
- CDEBUG (D_NET,
- "waiting for %d posted buffers to unlink and "
- "in-flight RPCs to die.\n",
- sv->sv_nposted_msg);
-
- if (!cfs_list_empty(&sv->sv_active_rpcq)) {
- rpc = cfs_list_entry(sv->sv_active_rpcq.next,
- srpc_server_rpc_t, srpc_list);
- CNETERR("Active RPC %p on shutdown: sv %s, peer %s, "
- "wi %s scheduled %d running %d, "
- "ev fired %d type %d status %d lnet %d\n",
- rpc, sv->sv_name, libcfs_id2str(rpc->srpc_peer),
- swi_state2str(rpc->srpc_wi.swi_state),
- rpc->srpc_wi.swi_workitem.wi_scheduled,
- rpc->srpc_wi.swi_workitem.wi_running,
- rpc->srpc_ev.ev_fired,
- rpc->srpc_ev.ev_type,
- rpc->srpc_ev.ev_status,
- rpc->srpc_ev.ev_lnet);
- }
-
- cfs_spin_unlock(&sv->sv_lock);
- return 0;
- }
-
- cfs_spin_unlock(&sv->sv_lock); /* no lock needed from now on */
-
- for (;;) {
- cfs_list_t *q;
-
- if (!cfs_list_empty(&sv->sv_posted_msgq))
- q = &sv->sv_posted_msgq;
- else if (!cfs_list_empty(&sv->sv_blocked_msgq))
- q = &sv->sv_blocked_msgq;
- else
- break;
-
- buf = cfs_list_entry(q->next, srpc_buffer_t, buf_list);
- cfs_list_del(&buf->buf_list);
-
- LIBCFS_FREE(buf, sizeof(*buf));
- }
-
- while (!cfs_list_empty(&sv->sv_free_rpcq)) {
- rpc = cfs_list_entry(sv->sv_free_rpcq.next,
- srpc_server_rpc_t, srpc_list);
- cfs_list_del(&rpc->srpc_list);
- LIBCFS_FREE(rpc, sizeof(*rpc));
- }
-
- return 1;
+ struct srpc_service_cd *scd;
+ struct srpc_server_rpc *rpc;
+ int i;
+
+ LASSERT(sv->sv_shuttingdown); /* srpc_shutdown_service called */
+
+ cfs_percpt_for_each(scd, i, sv->sv_cpt_data) {
+ spin_lock(&scd->scd_lock);
+ if (!swi_deschedule_workitem(&scd->scd_buf_wi)) {
+ spin_unlock(&scd->scd_lock);
+ return 0;
+ }
+
+ if (scd->scd_buf_nposted > 0) {
+ CDEBUG(D_NET, "waiting for %d posted buffers to "
+ "unlink\n", scd->scd_buf_nposted);
+ spin_unlock(&scd->scd_lock);
+ return 0;
+ }
+
+ if (list_empty(&scd->scd_rpc_active)) {
+ spin_unlock(&scd->scd_lock);
+ continue;
+ }
+
+ rpc = list_entry(scd->scd_rpc_active.next,
+ struct srpc_server_rpc, srpc_list);
+ CNETERR("Active RPC %p on shutdown: sv %s, peer %s, "
+ "wi %s scheduled %d running %d, "
+ "ev fired %d type %d status %d lnet %d\n",
+ rpc, sv->sv_name, libcfs_id2str(rpc->srpc_peer),
+ swi_state2str(rpc->srpc_wi.swi_state),
+ rpc->srpc_wi.swi_workitem.wi_scheduled,
+ rpc->srpc_wi.swi_workitem.wi_running,
+ rpc->srpc_ev.ev_fired, rpc->srpc_ev.ev_type,
+ rpc->srpc_ev.ev_status, rpc->srpc_ev.ev_lnet);
+ spin_unlock(&scd->scd_lock);
+ return 0;
+ }
+
+ /* no lock needed from now on */
+ srpc_service_fini(sv);
+ return 1;