staging: lustre: align all code properly for LNet core
[deliverable/linux.git] / drivers / staging / lustre / lnet / selftest / conrpc.c
CommitLineData
d7e09d03
PT
1/*
2 * GPL HEADER START
3 *
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 only,
8 * as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License version 2 for more details (a copy is included
14 * in the LICENSE file that accompanied this code).
15 *
16 * You should have received a copy of the GNU General Public License
17 * version 2 along with this program; If not, see
18 * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
19 *
20 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
21 * CA 95054 USA or visit www.sun.com if you need additional information or
22 * have any questions.
23 *
24 * GPL HEADER END
25 */
26/*
27 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
28 * Use is subject to license terms.
29 *
30 * Copyright (c) 2011, 2012, Intel Corporation.
31 */
32/*
33 * This file is part of Lustre, http://www.lustre.org/
34 * Lustre is a trademark of Sun Microsystems, Inc.
35 *
36 * lnet/selftest/conctl.c
37 *
38 * Console framework rpcs
39 *
40 * Author: Liang Zhen <liang@whamcloud.com>
41 */
42
9fdaf8c0
GKH
43#include "../../include/linux/libcfs/libcfs.h"
44#include "../../include/linux/lnet/lib-lnet.h"
d7e09d03
PT
45#include "timer.h"
46#include "conrpc.h"
47#include "console.h"
48
49void lstcon_rpc_stat_reply(lstcon_rpc_trans_t *, srpc_msg_t *,
50 lstcon_node_t *, lstcon_trans_stat_t *);
51
52static void
53lstcon_rpc_done(srpc_client_rpc_t *rpc)
54{
55 lstcon_rpc_t *crpc = (lstcon_rpc_t *)rpc->crpc_priv;
56
57 LASSERT(crpc != NULL && rpc == crpc->crp_rpc);
58 LASSERT(crpc->crp_posted && !crpc->crp_finished);
59
60 spin_lock(&rpc->crpc_lock);
61
62 if (crpc->crp_trans == NULL) {
4420cfd3
JS
63 /*
64 * Orphan RPC is not in any transaction,
65 * I'm just a poor body and nobody loves me
66 */
d7e09d03
PT
67 spin_unlock(&rpc->crpc_lock);
68
69 /* release it */
70 lstcon_rpc_put(crpc);
71 return;
72 }
73
74 /* not an orphan RPC */
75 crpc->crp_finished = 1;
76
77 if (crpc->crp_stamp == 0) {
78 /* not aborted */
4d72b5af 79 LASSERT(crpc->crp_status == 0);
d7e09d03
PT
80
81 crpc->crp_stamp = cfs_time_current();
82 crpc->crp_status = rpc->crpc_status;
83 }
84
85 /* wakeup (transaction)thread if I'm the last RPC in the transaction */
86 if (atomic_dec_and_test(&crpc->crp_trans->tas_remaining))
87 wake_up(&crpc->crp_trans->tas_waitq);
88
89 spin_unlock(&rpc->crpc_lock);
90}
91
8d94b6d2 92static int
d7e09d03
PT
93lstcon_rpc_init(lstcon_node_t *nd, int service, unsigned feats,
94 int bulk_npg, int bulk_len, int embedded, lstcon_rpc_t *crpc)
95{
96 crpc->crp_rpc = sfw_create_rpc(nd->nd_id, service,
97 feats, bulk_npg, bulk_len,
98 lstcon_rpc_done, (void *)crpc);
99 if (crpc->crp_rpc == NULL)
100 return -ENOMEM;
101
102 crpc->crp_trans = NULL;
103 crpc->crp_node = nd;
104 crpc->crp_posted = 0;
105 crpc->crp_finished = 0;
106 crpc->crp_unpacked = 0;
107 crpc->crp_status = 0;
108 crpc->crp_stamp = 0;
109 crpc->crp_embedded = embedded;
110 INIT_LIST_HEAD(&crpc->crp_link);
111
112 atomic_inc(&console_session.ses_rpc_counter);
113
114 return 0;
115}
116
8d94b6d2 117static int
d7e09d03
PT
118lstcon_rpc_prep(lstcon_node_t *nd, int service, unsigned feats,
119 int bulk_npg, int bulk_len, lstcon_rpc_t **crpcpp)
120{
74d68011
MS
121 lstcon_rpc_t *crpc = NULL;
122 int rc;
d7e09d03
PT
123
124 spin_lock(&console_session.ses_rpc_lock);
125
126 if (!list_empty(&console_session.ses_rpc_freelist)) {
127 crpc = list_entry(console_session.ses_rpc_freelist.next,
c314c319 128 lstcon_rpc_t, crp_link);
d7e09d03
PT
129 list_del_init(&crpc->crp_link);
130 }
131
132 spin_unlock(&console_session.ses_rpc_lock);
133
134 if (crpc == NULL) {
135 LIBCFS_ALLOC(crpc, sizeof(*crpc));
136 if (crpc == NULL)
137 return -ENOMEM;
138 }
139
140 rc = lstcon_rpc_init(nd, service, feats, bulk_npg, bulk_len, 0, crpc);
141 if (rc == 0) {
142 *crpcpp = crpc;
143 return 0;
144 }
145
146 LIBCFS_FREE(crpc, sizeof(*crpc));
147
148 return rc;
149}
150
151void
152lstcon_rpc_put(lstcon_rpc_t *crpc)
153{
154 srpc_bulk_t *bulk = &crpc->crp_rpc->crpc_bulk;
74d68011 155 int i;
d7e09d03 156
4d72b5af 157 LASSERT(list_empty(&crpc->crp_link));
d7e09d03
PT
158
159 for (i = 0; i < bulk->bk_niov; i++) {
160 if (bulk->bk_iovs[i].kiov_page == NULL)
161 continue;
162
163 __free_page(bulk->bk_iovs[i].kiov_page);
164 }
165
166 srpc_client_rpc_decref(crpc->crp_rpc);
167
168 if (crpc->crp_embedded) {
169 /* embedded RPC, don't recycle it */
170 memset(crpc, 0, sizeof(*crpc));
171 crpc->crp_embedded = 1;
172
173 } else {
174 spin_lock(&console_session.ses_rpc_lock);
175
176 list_add(&crpc->crp_link,
c314c319 177 &console_session.ses_rpc_freelist);
d7e09d03
PT
178
179 spin_unlock(&console_session.ses_rpc_lock);
180 }
181
182 /* RPC is not alive now */
183 atomic_dec(&console_session.ses_rpc_counter);
184}
185
8d94b6d2 186static void
d7e09d03
PT
187lstcon_rpc_post(lstcon_rpc_t *crpc)
188{
189 lstcon_rpc_trans_t *trans = crpc->crp_trans;
190
4d72b5af 191 LASSERT(trans != NULL);
d7e09d03
PT
192
193 atomic_inc(&trans->tas_remaining);
194 crpc->crp_posted = 1;
195
196 sfw_post_rpc(crpc->crp_rpc);
197}
198
199static char *
200lstcon_rpc_trans_name(int transop)
201{
202 if (transop == LST_TRANS_SESNEW)
203 return "SESNEW";
204
205 if (transop == LST_TRANS_SESEND)
206 return "SESEND";
207
208 if (transop == LST_TRANS_SESQRY)
209 return "SESQRY";
210
211 if (transop == LST_TRANS_SESPING)
212 return "SESPING";
213
214 if (transop == LST_TRANS_TSBCLIADD)
215 return "TSBCLIADD";
216
217 if (transop == LST_TRANS_TSBSRVADD)
218 return "TSBSRVADD";
219
220 if (transop == LST_TRANS_TSBRUN)
221 return "TSBRUN";
222
223 if (transop == LST_TRANS_TSBSTOP)
224 return "TSBSTOP";
225
226 if (transop == LST_TRANS_TSBCLIQRY)
227 return "TSBCLIQRY";
228
229 if (transop == LST_TRANS_TSBSRVQRY)
230 return "TSBSRVQRY";
231
232 if (transop == LST_TRANS_STATQRY)
233 return "STATQRY";
234
235 return "Unknown";
236}
237
238int
239lstcon_rpc_trans_prep(struct list_head *translist,
240 int transop, lstcon_rpc_trans_t **transpp)
241{
242 lstcon_rpc_trans_t *trans;
243
244 if (translist != NULL) {
245 list_for_each_entry(trans, translist, tas_link) {
4420cfd3
JS
246 /*
247 * Can't enqueue two private transaction on
248 * the same object
249 */
d7e09d03
PT
250 if ((trans->tas_opc & transop) == LST_TRANS_PRIVATE)
251 return -EPERM;
252 }
253 }
254
255 /* create a trans group */
256 LIBCFS_ALLOC(trans, sizeof(*trans));
257 if (trans == NULL)
258 return -ENOMEM;
259
260 trans->tas_opc = transop;
261
262 if (translist == NULL)
263 INIT_LIST_HEAD(&trans->tas_olink);
264 else
265 list_add_tail(&trans->tas_olink, translist);
266
267 list_add_tail(&trans->tas_link, &console_session.ses_trans_list);
268
269 INIT_LIST_HEAD(&trans->tas_rpcs_list);
270 atomic_set(&trans->tas_remaining, 0);
271 init_waitqueue_head(&trans->tas_waitq);
272
273 spin_lock(&console_session.ses_rpc_lock);
274 trans->tas_features = console_session.ses_features;
275 spin_unlock(&console_session.ses_rpc_lock);
276
277 *transpp = trans;
278 return 0;
279}
280
281void
282lstcon_rpc_trans_addreq(lstcon_rpc_trans_t *trans, lstcon_rpc_t *crpc)
283{
284 list_add_tail(&crpc->crp_link, &trans->tas_rpcs_list);
285 crpc->crp_trans = trans;
286}
287
288void
289lstcon_rpc_trans_abort(lstcon_rpc_trans_t *trans, int error)
290{
291 srpc_client_rpc_t *rpc;
292 lstcon_rpc_t *crpc;
293 lstcon_node_t *nd;
294
4d72b5af 295 list_for_each_entry(crpc, &trans->tas_rpcs_list, crp_link) {
d7e09d03
PT
296 rpc = crpc->crp_rpc;
297
298 spin_lock(&rpc->crpc_lock);
299
300 if (!crpc->crp_posted || /* not posted */
301 crpc->crp_stamp != 0) { /* rpc done or aborted already */
302 if (crpc->crp_stamp == 0) {
303 crpc->crp_stamp = cfs_time_current();
304 crpc->crp_status = -EINTR;
305 }
306 spin_unlock(&rpc->crpc_lock);
307 continue;
308 }
309
310 crpc->crp_stamp = cfs_time_current();
311 crpc->crp_status = error;
312
313 spin_unlock(&rpc->crpc_lock);
314
315 sfw_abort_rpc(rpc);
316
f02e0156 317 if (error != ETIMEDOUT)
d7e09d03
PT
318 continue;
319
320 nd = crpc->crp_node;
321 if (cfs_time_after(nd->nd_stamp, crpc->crp_stamp))
322 continue;
323
324 nd->nd_stamp = crpc->crp_stamp;
325 nd->nd_state = LST_NODE_DOWN;
326 }
327}
328
329static int
330lstcon_rpc_trans_check(lstcon_rpc_trans_t *trans)
331{
332 if (console_session.ses_shutdown &&
333 !list_empty(&trans->tas_olink)) /* Not an end session RPC */
334 return 1;
335
98d1bbdd 336 return (atomic_read(&trans->tas_remaining) == 0) ? 1 : 0;
d7e09d03
PT
337}
338
339int
340lstcon_rpc_trans_postwait(lstcon_rpc_trans_t *trans, int timeout)
341{
74d68011
MS
342 lstcon_rpc_t *crpc;
343 int rc;
d7e09d03
PT
344
345 if (list_empty(&trans->tas_rpcs_list))
346 return 0;
347
348 if (timeout < LST_TRANS_MIN_TIMEOUT)
349 timeout = LST_TRANS_MIN_TIMEOUT;
350
351 CDEBUG(D_NET, "Transaction %s started\n",
352 lstcon_rpc_trans_name(trans->tas_opc));
353
354 /* post all requests */
4d72b5af
RK
355 list_for_each_entry(crpc, &trans->tas_rpcs_list, crp_link) {
356 LASSERT(!crpc->crp_posted);
d7e09d03
PT
357
358 lstcon_rpc_post(crpc);
359 }
360
361 mutex_unlock(&console_session.ses_mutex);
362
363 rc = wait_event_interruptible_timeout(trans->tas_waitq,
364 lstcon_rpc_trans_check(trans),
365 cfs_time_seconds(timeout));
366 rc = (rc > 0) ? 0 : ((rc < 0) ? -EINTR : -ETIMEDOUT);
367
368 mutex_lock(&console_session.ses_mutex);
369
370 if (console_session.ses_shutdown)
371 rc = -ESHUTDOWN;
372
373 if (rc != 0 || atomic_read(&trans->tas_remaining) != 0) {
374 /* treat short timeout as canceled */
375 if (rc == -ETIMEDOUT && timeout < LST_TRANS_MIN_TIMEOUT * 2)
376 rc = -EINTR;
377
378 lstcon_rpc_trans_abort(trans, rc);
379 }
380
381 CDEBUG(D_NET, "Transaction %s stopped: %d\n",
382 lstcon_rpc_trans_name(trans->tas_opc), rc);
383
384 lstcon_rpc_trans_stat(trans, lstcon_trans_stat());
385
386 return rc;
387}
388
8d94b6d2 389static int
d7e09d03
PT
390lstcon_rpc_get_reply(lstcon_rpc_t *crpc, srpc_msg_t **msgpp)
391{
74d68011
MS
392 lstcon_node_t *nd = crpc->crp_node;
393 srpc_client_rpc_t *rpc = crpc->crp_rpc;
d7e09d03
PT
394 srpc_generic_reply_t *rep;
395
4d72b5af
RK
396 LASSERT(nd != NULL && rpc != NULL);
397 LASSERT(crpc->crp_stamp != 0);
d7e09d03
PT
398
399 if (crpc->crp_status != 0) {
400 *msgpp = NULL;
401 return crpc->crp_status;
402 }
403
404 *msgpp = &rpc->crpc_replymsg;
405 if (!crpc->crp_unpacked) {
406 sfw_unpack_message(*msgpp);
407 crpc->crp_unpacked = 1;
408 }
409
410 if (cfs_time_after(nd->nd_stamp, crpc->crp_stamp))
411 return 0;
412
413 nd->nd_stamp = crpc->crp_stamp;
414 rep = &(*msgpp)->msg_body.reply;
415
416 if (rep->sid.ses_nid == LNET_NID_ANY)
417 nd->nd_state = LST_NODE_UNKNOWN;
418 else if (lstcon_session_match(rep->sid))
419 nd->nd_state = LST_NODE_ACTIVE;
420 else
421 nd->nd_state = LST_NODE_BUSY;
422
423 return 0;
424}
425
426void
427lstcon_rpc_trans_stat(lstcon_rpc_trans_t *trans, lstcon_trans_stat_t *stat)
428{
74d68011
MS
429 lstcon_rpc_t *crpc;
430 srpc_msg_t *rep;
431 int error;
d7e09d03 432
4d72b5af 433 LASSERT(stat != NULL);
d7e09d03
PT
434
435 memset(stat, 0, sizeof(*stat));
436
437 list_for_each_entry(crpc, &trans->tas_rpcs_list, crp_link) {
438 lstcon_rpc_stat_total(stat, 1);
439
4d72b5af 440 LASSERT(crpc->crp_stamp != 0);
d7e09d03
PT
441
442 error = lstcon_rpc_get_reply(crpc, &rep);
443 if (error != 0) {
444 lstcon_rpc_stat_failure(stat, 1);
445 if (stat->trs_rpc_errno == 0)
446 stat->trs_rpc_errno = -error;
447
448 continue;
449 }
450
451 lstcon_rpc_stat_success(stat, 1);
452
453 lstcon_rpc_stat_reply(trans, rep, crpc->crp_node, stat);
454 }
455
456 if (trans->tas_opc == LST_TRANS_SESNEW && stat->trs_fwk_errno == 0) {
457 stat->trs_fwk_errno =
458 lstcon_session_feats_check(trans->tas_features);
459 }
460
eac2e8c6 461 CDEBUG(D_NET, "transaction %s : success %d, failure %d, total %d, RPC error(%d), Framework error(%d)\n",
d7e09d03
PT
462 lstcon_rpc_trans_name(trans->tas_opc),
463 lstcon_rpc_stat_success(stat, 0),
464 lstcon_rpc_stat_failure(stat, 0),
465 lstcon_rpc_stat_total(stat, 0),
466 stat->trs_rpc_errno, stat->trs_fwk_errno);
467
468 return;
469}
470
471int
472lstcon_rpc_trans_interpreter(lstcon_rpc_trans_t *trans,
08816b2e 473 struct list_head __user *head_up,
d7e09d03
PT
474 lstcon_rpc_readent_func_t readent)
475{
74d68011 476 struct list_head tmp;
08816b2e 477 struct list_head __user *next;
74d68011 478 lstcon_rpc_ent_t *ent;
d7e09d03 479 srpc_generic_reply_t *rep;
74d68011
MS
480 lstcon_rpc_t *crpc;
481 srpc_msg_t *msg;
482 lstcon_node_t *nd;
483 long dur;
484 struct timeval tv;
485 int error;
d7e09d03 486
4d72b5af 487 LASSERT(head_up != NULL);
d7e09d03
PT
488
489 next = head_up;
490
491 list_for_each_entry(crpc, &trans->tas_rpcs_list, crp_link) {
492 if (copy_from_user(&tmp, next,
c314c319 493 sizeof(struct list_head)))
d7e09d03
PT
494 return -EFAULT;
495
496 if (tmp.next == head_up)
497 return 0;
498
499 next = tmp.next;
500
501 ent = list_entry(next, lstcon_rpc_ent_t, rpe_link);
502
4d72b5af 503 LASSERT(crpc->crp_stamp != 0);
d7e09d03
PT
504
505 error = lstcon_rpc_get_reply(crpc, &msg);
506
507 nd = crpc->crp_node;
508
b2d201bd 509 dur = (long)cfs_time_sub(crpc->crp_stamp,
a649ad1d 510 (unsigned long)console_session.ses_id.ses_stamp);
70513c5d 511 jiffies_to_timeval(dur, &tv);
d7e09d03 512
c314c319
JS
513 if (copy_to_user(&ent->rpe_peer, &nd->nd_id,
514 sizeof(lnet_process_id_t)) ||
d7e09d03 515 copy_to_user(&ent->rpe_stamp, &tv, sizeof(tv)) ||
c314c319
JS
516 copy_to_user(&ent->rpe_state, &nd->nd_state,
517 sizeof(nd->nd_state)) ||
d7e09d03 518 copy_to_user(&ent->rpe_rpc_errno, &error,
c314c319 519 sizeof(error)))
d7e09d03
PT
520 return -EFAULT;
521
522 if (error != 0)
523 continue;
524
525 /* RPC is done */
526 rep = (srpc_generic_reply_t *)&msg->msg_body.reply;
527
c314c319
JS
528 if (copy_to_user(&ent->rpe_sid, &rep->sid, sizeof(lst_sid_t)) ||
529 copy_to_user(&ent->rpe_fwk_errno, &rep->status,
530 sizeof(rep->status)))
d7e09d03
PT
531 return -EFAULT;
532
533 if (readent == NULL)
534 continue;
535
b0834c87
RK
536 error = readent(trans->tas_opc, msg, ent);
537
538 if (error != 0)
d7e09d03
PT
539 return error;
540 }
541
542 return 0;
543}
544
545void
546lstcon_rpc_trans_destroy(lstcon_rpc_trans_t *trans)
547{
548 srpc_client_rpc_t *rpc;
74d68011
MS
549 lstcon_rpc_t *crpc;
550 lstcon_rpc_t *tmp;
551 int count = 0;
d7e09d03
PT
552
553 list_for_each_entry_safe(crpc, tmp, &trans->tas_rpcs_list,
554 crp_link) {
555 rpc = crpc->crp_rpc;
556
557 spin_lock(&rpc->crpc_lock);
558
559 /* free it if not posted or finished already */
560 if (!crpc->crp_posted || crpc->crp_finished) {
561 spin_unlock(&rpc->crpc_lock);
562
563 list_del_init(&crpc->crp_link);
564 lstcon_rpc_put(crpc);
565
566 continue;
567 }
568
4420cfd3
JS
569 /*
570 * rpcs can be still not callbacked (even LNetMDUnlink is called)
d7e09d03
PT
571 * because huge timeout for inaccessible network, don't make
572 * user wait for them, just abandon them, they will be recycled
4420cfd3
JS
573 * in callback
574 */
4d72b5af 575 LASSERT(crpc->crp_status != 0);
d7e09d03
PT
576
577 crpc->crp_node = NULL;
578 crpc->crp_trans = NULL;
579 list_del_init(&crpc->crp_link);
fc831a90 580 count++;
d7e09d03
PT
581
582 spin_unlock(&rpc->crpc_lock);
583
584 atomic_dec(&trans->tas_remaining);
585 }
586
4d72b5af 587 LASSERT(atomic_read(&trans->tas_remaining) == 0);
d7e09d03
PT
588
589 list_del(&trans->tas_link);
590 if (!list_empty(&trans->tas_olink))
591 list_del(&trans->tas_olink);
592
593 CDEBUG(D_NET, "Transaction %s destroyed with %d pending RPCs\n",
594 lstcon_rpc_trans_name(trans->tas_opc), count);
595
596 LIBCFS_FREE(trans, sizeof(*trans));
597
598 return;
599}
600
601int
602lstcon_sesrpc_prep(lstcon_node_t *nd, int transop,
603 unsigned feats, lstcon_rpc_t **crpc)
604{
605 srpc_mksn_reqst_t *msrq;
606 srpc_rmsn_reqst_t *rsrq;
74d68011 607 int rc;
d7e09d03
PT
608
609 switch (transop) {
610 case LST_TRANS_SESNEW:
611 rc = lstcon_rpc_prep(nd, SRPC_SERVICE_MAKE_SESSION,
612 feats, 0, 0, crpc);
613 if (rc != 0)
614 return rc;
615
616 msrq = &(*crpc)->crp_rpc->crpc_reqstmsg.msg_body.mksn_reqst;
617 msrq->mksn_sid = console_session.ses_id;
618 msrq->mksn_force = console_session.ses_force;
9563fe8a
DE
619 strlcpy(msrq->mksn_name, console_session.ses_name,
620 sizeof(msrq->mksn_name));
d7e09d03
PT
621 break;
622
623 case LST_TRANS_SESEND:
624 rc = lstcon_rpc_prep(nd, SRPC_SERVICE_REMOVE_SESSION,
625 feats, 0, 0, crpc);
626 if (rc != 0)
627 return rc;
628
629 rsrq = &(*crpc)->crp_rpc->crpc_reqstmsg.msg_body.rmsn_reqst;
630 rsrq->rmsn_sid = console_session.ses_id;
631 break;
632
633 default:
634 LBUG();
635 }
636
637 return 0;
638}
639
640int
641lstcon_dbgrpc_prep(lstcon_node_t *nd, unsigned feats, lstcon_rpc_t **crpc)
642{
643 srpc_debug_reqst_t *drq;
74d68011 644 int rc;
d7e09d03
PT
645
646 rc = lstcon_rpc_prep(nd, SRPC_SERVICE_DEBUG, feats, 0, 0, crpc);
647 if (rc != 0)
648 return rc;
649
650 drq = &(*crpc)->crp_rpc->crpc_reqstmsg.msg_body.dbg_reqst;
651
652 drq->dbg_sid = console_session.ses_id;
653 drq->dbg_flags = 0;
654
655 return rc;
656}
657
658int
659lstcon_batrpc_prep(lstcon_node_t *nd, int transop, unsigned feats,
660 lstcon_tsb_hdr_t *tsb, lstcon_rpc_t **crpc)
661{
662 lstcon_batch_t *batch;
663 srpc_batch_reqst_t *brq;
664 int rc;
665
666 rc = lstcon_rpc_prep(nd, SRPC_SERVICE_BATCH, feats, 0, 0, crpc);
667 if (rc != 0)
668 return rc;
669
670 brq = &(*crpc)->crp_rpc->crpc_reqstmsg.msg_body.bat_reqst;
671
672 brq->bar_sid = console_session.ses_id;
673 brq->bar_bid = tsb->tsb_id;
674 brq->bar_testidx = tsb->tsb_index;
675 brq->bar_opc = transop == LST_TRANS_TSBRUN ? SRPC_BATCH_OPC_RUN :
98d1bbdd 676 (transop == LST_TRANS_TSBSTOP ? SRPC_BATCH_OPC_STOP :
d7e09d03
PT
677 SRPC_BATCH_OPC_QUERY);
678
679 if (transop != LST_TRANS_TSBRUN &&
680 transop != LST_TRANS_TSBSTOP)
681 return 0;
682
4d72b5af 683 LASSERT(tsb->tsb_index == 0);
d7e09d03
PT
684
685 batch = (lstcon_batch_t *)tsb;
686 brq->bar_arg = batch->bat_arg;
687
688 return 0;
689}
690
691int
692lstcon_statrpc_prep(lstcon_node_t *nd, unsigned feats, lstcon_rpc_t **crpc)
693{
694 srpc_stat_reqst_t *srq;
695 int rc;
696
697 rc = lstcon_rpc_prep(nd, SRPC_SERVICE_QUERY_STAT, feats, 0, 0, crpc);
698 if (rc != 0)
699 return rc;
700
701 srq = &(*crpc)->crp_rpc->crpc_reqstmsg.msg_body.stat_reqst;
702
703 srq->str_sid = console_session.ses_id;
704 srq->str_type = 0; /* XXX remove it */
705
706 return 0;
707}
708
f3731cdb 709static lnet_process_id_packed_t *
d7e09d03
PT
710lstcon_next_id(int idx, int nkiov, lnet_kiov_t *kiov)
711{
712 lnet_process_id_packed_t *pid;
74d68011 713 int i;
d7e09d03
PT
714
715 i = idx / SFW_ID_PER_PAGE;
716
4d72b5af 717 LASSERT(i < nkiov);
d7e09d03
PT
718
719 pid = (lnet_process_id_packed_t *)page_address(kiov[i].kiov_page);
720
721 return &pid[idx % SFW_ID_PER_PAGE];
722}
723
8d94b6d2 724static int
d7e09d03
PT
725lstcon_dstnodes_prep(lstcon_group_t *grp, int idx,
726 int dist, int span, int nkiov, lnet_kiov_t *kiov)
727{
728 lnet_process_id_packed_t *pid;
74d68011
MS
729 lstcon_ndlink_t *ndl;
730 lstcon_node_t *nd;
731 int start;
732 int end;
733 int i = 0;
d7e09d03 734
4d72b5af
RK
735 LASSERT(dist >= 1);
736 LASSERT(span >= 1);
737 LASSERT(grp->grp_nnode >= 1);
d7e09d03
PT
738
739 if (span > grp->grp_nnode)
740 return -EINVAL;
741
742 start = ((idx / dist) * span) % grp->grp_nnode;
743 end = ((idx / dist) * span + span - 1) % grp->grp_nnode;
744
745 list_for_each_entry(ndl, &grp->grp_ndl_list, ndl_link) {
746 nd = ndl->ndl_node;
747 if (i < start) {
fc831a90 748 i++;
d7e09d03
PT
749 continue;
750 }
751
98d1bbdd 752 if (i > (end >= start ? end : grp->grp_nnode))
d7e09d03
PT
753 break;
754
755 pid = lstcon_next_id((i - start), nkiov, kiov);
756 pid->nid = nd->nd_id.nid;
757 pid->pid = nd->nd_id.pid;
758 i++;
759 }
760
761 if (start <= end) /* done */
762 return 0;
763
764 list_for_each_entry(ndl, &grp->grp_ndl_list, ndl_link) {
765 if (i > grp->grp_nnode + end)
766 break;
767
768 nd = ndl->ndl_node;
769 pid = lstcon_next_id((i - start), nkiov, kiov);
770 pid->nid = nd->nd_id.nid;
771 pid->pid = nd->nd_id.pid;
772 i++;
773 }
774
775 return 0;
776}
777
8d94b6d2 778static int
d7e09d03
PT
779lstcon_pingrpc_prep(lst_test_ping_param_t *param, srpc_test_reqst_t *req)
780{
781 test_ping_req_t *prq = &req->tsr_u.ping;
782
74d68011
MS
783 prq->png_size = param->png_size;
784 prq->png_flags = param->png_flags;
d7e09d03
PT
785 /* TODO dest */
786 return 0;
787}
788
8d94b6d2 789static int
d7e09d03
PT
790lstcon_bulkrpc_v0_prep(lst_test_bulk_param_t *param, srpc_test_reqst_t *req)
791{
792 test_bulk_req_t *brq = &req->tsr_u.bulk_v0;
793
74d68011
MS
794 brq->blk_opc = param->blk_opc;
795 brq->blk_npg = (param->blk_size + PAGE_CACHE_SIZE - 1) /
796 PAGE_CACHE_SIZE;
797 brq->blk_flags = param->blk_flags;
d7e09d03
PT
798
799 return 0;
800}
801
8d94b6d2 802static int
d7e09d03
PT
803lstcon_bulkrpc_v1_prep(lst_test_bulk_param_t *param, srpc_test_reqst_t *req)
804{
805 test_bulk_req_v1_t *brq = &req->tsr_u.bulk_v1;
806
807 brq->blk_opc = param->blk_opc;
808 brq->blk_flags = param->blk_flags;
809 brq->blk_len = param->blk_size;
810 brq->blk_offset = 0; /* reserved */
811
812 return 0;
813}
814
815int
816lstcon_testrpc_prep(lstcon_node_t *nd, int transop, unsigned feats,
817 lstcon_test_t *test, lstcon_rpc_t **crpc)
818{
819 lstcon_group_t *sgrp = test->tes_src_grp;
820 lstcon_group_t *dgrp = test->tes_dst_grp;
821 srpc_test_reqst_t *trq;
822 srpc_bulk_t *bulk;
74d68011 823 int i;
d7e09d03
PT
824 int npg = 0;
825 int nob = 0;
826 int rc = 0;
827
828 if (transop == LST_TRANS_TSBCLIADD) {
829 npg = sfw_id_pages(test->tes_span);
830 nob = (feats & LST_FEAT_BULK_LEN) == 0 ?
831 npg * PAGE_CACHE_SIZE :
832 sizeof(lnet_process_id_packed_t) * test->tes_span;
833 }
834
835 rc = lstcon_rpc_prep(nd, SRPC_SERVICE_TEST, feats, npg, nob, crpc);
836 if (rc != 0)
837 return rc;
838
839 trq = &(*crpc)->crp_rpc->crpc_reqstmsg.msg_body.tes_reqst;
840
841 if (transop == LST_TRANS_TSBSRVADD) {
74d68011
MS
842 int ndist = (sgrp->grp_nnode + test->tes_dist - 1) /
843 test->tes_dist;
844 int nspan = (dgrp->grp_nnode + test->tes_span - 1) /
845 test->tes_span;
d7e09d03
PT
846 int nmax = (ndist + nspan - 1) / nspan;
847
848 trq->tsr_ndest = 0;
849 trq->tsr_loop = nmax * test->tes_dist * test->tes_concur;
850
851 } else {
852 bulk = &(*crpc)->crp_rpc->crpc_bulk;
853
854 for (i = 0; i < npg; i++) {
855 int len;
856
857 LASSERT(nob > 0);
858
859 len = (feats & LST_FEAT_BULK_LEN) == 0 ?
74d68011
MS
860 PAGE_CACHE_SIZE :
861 min_t(int, nob, PAGE_CACHE_SIZE);
d7e09d03
PT
862 nob -= len;
863
864 bulk->bk_iovs[i].kiov_offset = 0;
865 bulk->bk_iovs[i].kiov_len = len;
866 bulk->bk_iovs[i].kiov_page =
40113370 867 alloc_page(GFP_KERNEL);
d7e09d03
PT
868
869 if (bulk->bk_iovs[i].kiov_page == NULL) {
870 lstcon_rpc_put(*crpc);
871 return -ENOMEM;
872 }
873 }
874
875 bulk->bk_sink = 0;
876
4d72b5af 877 LASSERT(transop == LST_TRANS_TSBCLIADD);
d7e09d03
PT
878
879 rc = lstcon_dstnodes_prep(test->tes_dst_grp,
880 test->tes_cliidx++,
881 test->tes_dist,
882 test->tes_span,
883 npg, &bulk->bk_iovs[0]);
884 if (rc != 0) {
885 lstcon_rpc_put(*crpc);
886 return rc;
887 }
888
889 trq->tsr_ndest = test->tes_span;
890 trq->tsr_loop = test->tes_loop;
891 }
892
74d68011
MS
893 trq->tsr_sid = console_session.ses_id;
894 trq->tsr_bid = test->tes_hdr.tsb_id;
d7e09d03
PT
895 trq->tsr_concur = test->tes_concur;
896 trq->tsr_is_client = (transop == LST_TRANS_TSBCLIADD) ? 1 : 0;
897 trq->tsr_stop_onerr = !!test->tes_stop_onerr;
898
899 switch (test->tes_type) {
900 case LST_TEST_PING:
901 trq->tsr_service = SRPC_SERVICE_PING;
902 rc = lstcon_pingrpc_prep((lst_test_ping_param_t *)
903 &test->tes_param[0], trq);
904 break;
905
906 case LST_TEST_BULK:
907 trq->tsr_service = SRPC_SERVICE_BRW;
908 if ((feats & LST_FEAT_BULK_LEN) == 0) {
909 rc = lstcon_bulkrpc_v0_prep((lst_test_bulk_param_t *)
910 &test->tes_param[0], trq);
911 } else {
912 rc = lstcon_bulkrpc_v1_prep((lst_test_bulk_param_t *)
913 &test->tes_param[0], trq);
914 }
915
916 break;
917 default:
918 LBUG();
919 break;
920 }
921
922 return rc;
923}
924
8d94b6d2 925static int
d7e09d03
PT
926lstcon_sesnew_stat_reply(lstcon_rpc_trans_t *trans,
927 lstcon_node_t *nd, srpc_msg_t *reply)
928{
929 srpc_mksn_reply_t *mksn_rep = &reply->msg_body.mksn_reply;
930 int status = mksn_rep->mksn_status;
931
932 if (status == 0 &&
933 (reply->msg_ses_feats & ~LST_FEATS_MASK) != 0) {
934 mksn_rep->mksn_status = EPROTO;
935 status = EPROTO;
936 }
937
938 if (status == EPROTO) {
939 CNETERR("session protocol error from %s: %u\n",
940 libcfs_nid2str(nd->nd_id.nid),
941 reply->msg_ses_feats);
942 }
943
944 if (status != 0)
945 return status;
946
947 if (!trans->tas_feats_updated) {
948 trans->tas_feats_updated = 1;
949 trans->tas_features = reply->msg_ses_feats;
950 }
951
952 if (reply->msg_ses_feats != trans->tas_features) {
eac2e8c6 953 CNETERR("Framework features %x from %s is different with features on this transaction: %x\n",
c314c319
JS
954 reply->msg_ses_feats, libcfs_nid2str(nd->nd_id.nid),
955 trans->tas_features);
d7e09d03
PT
956 status = mksn_rep->mksn_status = EPROTO;
957 }
958
959 if (status == 0) {
960 /* session timeout on remote node */
961 nd->nd_timeout = mksn_rep->mksn_timeout;
962 }
963
964 return status;
965}
966
967void
968lstcon_rpc_stat_reply(lstcon_rpc_trans_t *trans, srpc_msg_t *msg,
969 lstcon_node_t *nd, lstcon_trans_stat_t *stat)
970{
971 srpc_rmsn_reply_t *rmsn_rep;
972 srpc_debug_reply_t *dbg_rep;
973 srpc_batch_reply_t *bat_rep;
974 srpc_test_reply_t *test_rep;
975 srpc_stat_reply_t *stat_rep;
74d68011 976 int rc = 0;
d7e09d03
PT
977
978 switch (trans->tas_opc) {
979 case LST_TRANS_SESNEW:
980 rc = lstcon_sesnew_stat_reply(trans, nd, msg);
981 if (rc == 0) {
982 lstcon_sesop_stat_success(stat, 1);
983 return;
984 }
985
986 lstcon_sesop_stat_failure(stat, 1);
987 break;
988
989 case LST_TRANS_SESEND:
990 rmsn_rep = &msg->msg_body.rmsn_reply;
991 /* ESRCH is not an error for end session */
992 if (rmsn_rep->rmsn_status == 0 ||
993 rmsn_rep->rmsn_status == ESRCH) {
994 lstcon_sesop_stat_success(stat, 1);
995 return;
996 }
997
998 lstcon_sesop_stat_failure(stat, 1);
999 rc = rmsn_rep->rmsn_status;
1000 break;
1001
1002 case LST_TRANS_SESQRY:
1003 case LST_TRANS_SESPING:
1004 dbg_rep = &msg->msg_body.dbg_reply;
1005
1006 if (dbg_rep->dbg_status == ESRCH) {
1007 lstcon_sesqry_stat_unknown(stat, 1);
1008 return;
1009 }
1010
1011 if (lstcon_session_match(dbg_rep->dbg_sid))
1012 lstcon_sesqry_stat_active(stat, 1);
1013 else
1014 lstcon_sesqry_stat_busy(stat, 1);
1015 return;
1016
1017 case LST_TRANS_TSBRUN:
1018 case LST_TRANS_TSBSTOP:
1019 bat_rep = &msg->msg_body.bat_reply;
1020
1021 if (bat_rep->bar_status == 0) {
1022 lstcon_tsbop_stat_success(stat, 1);
1023 return;
1024 }
1025
1026 if (bat_rep->bar_status == EPERM &&
1027 trans->tas_opc == LST_TRANS_TSBSTOP) {
1028 lstcon_tsbop_stat_success(stat, 1);
1029 return;
1030 }
1031
1032 lstcon_tsbop_stat_failure(stat, 1);
1033 rc = bat_rep->bar_status;
1034 break;
1035
1036 case LST_TRANS_TSBCLIQRY:
1037 case LST_TRANS_TSBSRVQRY:
1038 bat_rep = &msg->msg_body.bat_reply;
1039
1040 if (bat_rep->bar_active != 0)
1041 lstcon_tsbqry_stat_run(stat, 1);
1042 else
1043 lstcon_tsbqry_stat_idle(stat, 1);
1044
1045 if (bat_rep->bar_status == 0)
1046 return;
1047
1048 lstcon_tsbqry_stat_failure(stat, 1);
1049 rc = bat_rep->bar_status;
1050 break;
1051
1052 case LST_TRANS_TSBCLIADD:
1053 case LST_TRANS_TSBSRVADD:
1054 test_rep = &msg->msg_body.tes_reply;
1055
1056 if (test_rep->tsr_status == 0) {
1057 lstcon_tsbop_stat_success(stat, 1);
1058 return;
1059 }
1060
1061 lstcon_tsbop_stat_failure(stat, 1);
1062 rc = test_rep->tsr_status;
1063 break;
1064
1065 case LST_TRANS_STATQRY:
1066 stat_rep = &msg->msg_body.stat_reply;
1067
1068 if (stat_rep->str_status == 0) {
1069 lstcon_statqry_stat_success(stat, 1);
1070 return;
1071 }
1072
1073 lstcon_statqry_stat_failure(stat, 1);
1074 rc = stat_rep->str_status;
1075 break;
1076
1077 default:
1078 LBUG();
1079 }
1080
1081 if (stat->trs_fwk_errno == 0)
1082 stat->trs_fwk_errno = rc;
1083
1084 return;
1085}
1086
1087int
1088lstcon_rpc_trans_ndlist(struct list_head *ndlist,
1089 struct list_head *translist, int transop,
1090 void *arg, lstcon_rpc_cond_func_t condition,
1091 lstcon_rpc_trans_t **transpp)
1092{
1093 lstcon_rpc_trans_t *trans;
74d68011
MS
1094 lstcon_ndlink_t *ndl;
1095 lstcon_node_t *nd;
1096 lstcon_rpc_t *rpc;
1097 unsigned feats;
1098 int rc;
d7e09d03
PT
1099
1100 /* Creating session RPG for list of nodes */
1101
1102 rc = lstcon_rpc_trans_prep(translist, transop, &trans);
1103 if (rc != 0) {
1104 CERROR("Can't create transaction %d: %d\n", transop, rc);
1105 return rc;
1106 }
1107
1108 feats = trans->tas_features;
1109 list_for_each_entry(ndl, ndlist, ndl_link) {
1110 rc = condition == NULL ? 1 :
1111 condition(transop, ndl->ndl_node, arg);
1112
1113 if (rc == 0)
1114 continue;
1115
1116 if (rc < 0) {
eac2e8c6 1117 CDEBUG(D_NET, "Condition error while creating RPC for transaction %d: %d\n",
c314c319 1118 transop, rc);
d7e09d03
PT
1119 break;
1120 }
1121
1122 nd = ndl->ndl_node;
1123
1124 switch (transop) {
1125 case LST_TRANS_SESNEW:
1126 case LST_TRANS_SESEND:
1127 rc = lstcon_sesrpc_prep(nd, transop, feats, &rpc);
1128 break;
1129 case LST_TRANS_SESQRY:
1130 case LST_TRANS_SESPING:
1131 rc = lstcon_dbgrpc_prep(nd, feats, &rpc);
1132 break;
1133 case LST_TRANS_TSBCLIADD:
1134 case LST_TRANS_TSBSRVADD:
1135 rc = lstcon_testrpc_prep(nd, transop, feats,
1136 (lstcon_test_t *)arg, &rpc);
1137 break;
1138 case LST_TRANS_TSBRUN:
1139 case LST_TRANS_TSBSTOP:
1140 case LST_TRANS_TSBCLIQRY:
1141 case LST_TRANS_TSBSRVQRY:
1142 rc = lstcon_batrpc_prep(nd, transop, feats,
1143 (lstcon_tsb_hdr_t *)arg, &rpc);
1144 break;
1145 case LST_TRANS_STATQRY:
1146 rc = lstcon_statrpc_prep(nd, feats, &rpc);
1147 break;
1148 default:
1149 rc = -EINVAL;
1150 break;
1151 }
1152
1153 if (rc != 0) {
1154 CERROR("Failed to create RPC for transaction %s: %d\n",
1155 lstcon_rpc_trans_name(transop), rc);
1156 break;
1157 }
1158
1159 lstcon_rpc_trans_addreq(trans, rpc);
1160 }
1161
1162 if (rc == 0) {
1163 *transpp = trans;
1164 return 0;
1165 }
1166
1167 lstcon_rpc_trans_destroy(trans);
1168
1169 return rc;
1170}
1171
8d94b6d2 1172static void
d7e09d03
PT
1173lstcon_rpc_pinger(void *arg)
1174{
74d68011 1175 stt_timer_t *ptimer = (stt_timer_t *)arg;
d7e09d03 1176 lstcon_rpc_trans_t *trans;
74d68011
MS
1177 lstcon_rpc_t *crpc;
1178 srpc_msg_t *rep;
d7e09d03 1179 srpc_debug_reqst_t *drq;
74d68011
MS
1180 lstcon_ndlink_t *ndl;
1181 lstcon_node_t *nd;
d9f79e6b 1182 int intv;
74d68011
MS
1183 int count = 0;
1184 int rc;
d7e09d03
PT
1185
1186 /* RPC pinger is a special case of transaction,
1187 * it's called by timer at 8 seconds interval.
1188 */
1189 mutex_lock(&console_session.ses_mutex);
1190
1191 if (console_session.ses_shutdown || console_session.ses_expired) {
1192 mutex_unlock(&console_session.ses_mutex);
1193 return;
1194 }
1195
1196 if (!console_session.ses_expired &&
d9f79e6b
AB
1197 ktime_get_real_seconds() - console_session.ses_laststamp >
1198 (time64_t)console_session.ses_timeout)
d7e09d03
PT
1199 console_session.ses_expired = 1;
1200
1201 trans = console_session.ses_ping;
1202
4d72b5af 1203 LASSERT(trans != NULL);
d7e09d03
PT
1204
1205 list_for_each_entry(ndl, &console_session.ses_ndl_list, ndl_link) {
1206 nd = ndl->ndl_node;
1207
1208 if (console_session.ses_expired) {
1209 /* idle console, end session on all nodes */
1210 if (nd->nd_state != LST_NODE_ACTIVE)
1211 continue;
1212
1213 rc = lstcon_sesrpc_prep(nd, LST_TRANS_SESEND,
1214 trans->tas_features, &crpc);
1215 if (rc != 0) {
1216 CERROR("Out of memory\n");
1217 break;
1218 }
1219
1220 lstcon_rpc_trans_addreq(trans, crpc);
1221 lstcon_rpc_post(crpc);
1222
1223 continue;
1224 }
1225
1226 crpc = &nd->nd_ping;
1227
1228 if (crpc->crp_rpc != NULL) {
4d72b5af
RK
1229 LASSERT(crpc->crp_trans == trans);
1230 LASSERT(!list_empty(&crpc->crp_link));
d7e09d03
PT
1231
1232 spin_lock(&crpc->crp_rpc->crpc_lock);
1233
1234 LASSERT(crpc->crp_posted);
1235
1236 if (!crpc->crp_finished) {
1237 /* in flight */
1238 spin_unlock(&crpc->crp_rpc->crpc_lock);
1239 continue;
1240 }
1241
1242 spin_unlock(&crpc->crp_rpc->crpc_lock);
1243
1244 lstcon_rpc_get_reply(crpc, &rep);
1245
1246 list_del_init(&crpc->crp_link);
1247
1248 lstcon_rpc_put(crpc);
1249 }
1250
1251 if (nd->nd_state != LST_NODE_ACTIVE)
1252 continue;
1253
d9f79e6b
AB
1254 intv = (jiffies - nd->nd_stamp) / HZ;
1255 if (intv < nd->nd_timeout / 2)
d7e09d03
PT
1256 continue;
1257
1258 rc = lstcon_rpc_init(nd, SRPC_SERVICE_DEBUG,
1259 trans->tas_features, 0, 0, 1, crpc);
1260 if (rc != 0) {
1261 CERROR("Out of memory\n");
1262 break;
1263 }
1264
1265 drq = &crpc->crp_rpc->crpc_reqstmsg.msg_body.dbg_reqst;
1266
1267 drq->dbg_sid = console_session.ses_id;
1268 drq->dbg_flags = 0;
1269
1270 lstcon_rpc_trans_addreq(trans, crpc);
1271 lstcon_rpc_post(crpc);
1272
fc831a90 1273 count++;
d7e09d03
PT
1274 }
1275
1276 if (console_session.ses_expired) {
1277 mutex_unlock(&console_session.ses_mutex);
1278 return;
1279 }
1280
1281 CDEBUG(D_NET, "Ping %d nodes in session\n", count);
1282
d9f79e6b 1283 ptimer->stt_expires = ktime_get_real_seconds() + LST_PING_INTERVAL;
d7e09d03
PT
1284 stt_add_timer(ptimer);
1285
1286 mutex_unlock(&console_session.ses_mutex);
1287}
1288
1289int
1290lstcon_rpc_pinger_start(void)
1291{
74d68011
MS
1292 stt_timer_t *ptimer;
1293 int rc;
d7e09d03 1294
4d72b5af
RK
1295 LASSERT(list_empty(&console_session.ses_rpc_freelist));
1296 LASSERT(atomic_read(&console_session.ses_rpc_counter) == 0);
d7e09d03
PT
1297
1298 rc = lstcon_rpc_trans_prep(NULL, LST_TRANS_SESPING,
1299 &console_session.ses_ping);
1300 if (rc != 0) {
1301 CERROR("Failed to create console pinger\n");
1302 return rc;
1303 }
1304
1305 ptimer = &console_session.ses_ping_timer;
d9f79e6b 1306 ptimer->stt_expires = ktime_get_real_seconds() + LST_PING_INTERVAL;
d7e09d03
PT
1307
1308 stt_add_timer(ptimer);
1309
1310 return 0;
1311}
1312
1313void
1314lstcon_rpc_pinger_stop(void)
1315{
4d72b5af 1316 LASSERT(console_session.ses_shutdown);
d7e09d03
PT
1317
1318 stt_del_timer(&console_session.ses_ping_timer);
1319
1320 lstcon_rpc_trans_abort(console_session.ses_ping, -ESHUTDOWN);
1321 lstcon_rpc_trans_stat(console_session.ses_ping, lstcon_trans_stat());
1322 lstcon_rpc_trans_destroy(console_session.ses_ping);
1323
1324 memset(lstcon_trans_stat(), 0, sizeof(lstcon_trans_stat_t));
1325
1326 console_session.ses_ping = NULL;
1327}
1328
1329void
1330lstcon_rpc_cleanup_wait(void)
1331{
1332 lstcon_rpc_trans_t *trans;
74d68011
MS
1333 lstcon_rpc_t *crpc;
1334 struct list_head *pacer;
1335 struct list_head zlist;
d7e09d03
PT
1336
1337 /* Called with hold of global mutex */
1338
4d72b5af 1339 LASSERT(console_session.ses_shutdown);
d7e09d03
PT
1340
1341 while (!list_empty(&console_session.ses_trans_list)) {
1342 list_for_each(pacer, &console_session.ses_trans_list) {
1343 trans = list_entry(pacer, lstcon_rpc_trans_t,
c314c319 1344 tas_link);
d7e09d03
PT
1345
1346 CDEBUG(D_NET, "Session closed, wakeup transaction %s\n",
1347 lstcon_rpc_trans_name(trans->tas_opc));
1348
1349 wake_up(&trans->tas_waitq);
1350 }
1351
1352 mutex_unlock(&console_session.ses_mutex);
1353
eac2e8c6 1354 CWARN("Session is shutting down, waiting for termination of transactions\n");
d3caf4d5
PT
1355 set_current_state(TASK_UNINTERRUPTIBLE);
1356 schedule_timeout(cfs_time_seconds(1));
d7e09d03
PT
1357
1358 mutex_lock(&console_session.ses_mutex);
1359 }
1360
1361 spin_lock(&console_session.ses_rpc_lock);
1362
1363 lst_wait_until((atomic_read(&console_session.ses_rpc_counter) == 0),
1364 console_session.ses_rpc_lock,
eac2e8c6 1365 "Network is not accessible or target is down, waiting for %d console RPCs to being recycled\n",
d7e09d03
PT
1366 atomic_read(&console_session.ses_rpc_counter));
1367
1368 list_add(&zlist, &console_session.ses_rpc_freelist);
1369 list_del_init(&console_session.ses_rpc_freelist);
1370
1371 spin_unlock(&console_session.ses_rpc_lock);
1372
1373 while (!list_empty(&zlist)) {
1374 crpc = list_entry(zlist.next, lstcon_rpc_t, crp_link);
1375
1376 list_del(&crpc->crp_link);
1377 LIBCFS_FREE(crpc, sizeof(lstcon_rpc_t));
1378 }
1379}
1380
1381int
1382lstcon_rpc_module_init(void)
1383{
1384 INIT_LIST_HEAD(&console_session.ses_ping_timer.stt_list);
1385 console_session.ses_ping_timer.stt_func = lstcon_rpc_pinger;
1386 console_session.ses_ping_timer.stt_data = &console_session.ses_ping_timer;
1387
1388 console_session.ses_ping = NULL;
1389
1390 spin_lock_init(&console_session.ses_rpc_lock);
1391 atomic_set(&console_session.ses_rpc_counter, 0);
1392 INIT_LIST_HEAD(&console_session.ses_rpc_freelist);
1393
1394 return 0;
1395}
1396
1397void
1398lstcon_rpc_module_fini(void)
1399{
4d72b5af
RK
1400 LASSERT(list_empty(&console_session.ses_rpc_freelist));
1401 LASSERT(atomic_read(&console_session.ses_rpc_counter) == 0);
d7e09d03 1402}
This page took 0.435125 seconds and 5 git commands to generate.