]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blame - drivers/staging/lustre/lnet/selftest/conrpc.c
staging: rtl8723au: hal: Remove useless return variables
[mirror_ubuntu-jammy-kernel.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
06ace26e 57 LASSERT(crpc && rpc == crpc->crp_rpc);
d7e09d03
PT
58 LASSERT(crpc->crp_posted && !crpc->crp_finished);
59
60 spin_lock(&rpc->crpc_lock);
61
06ace26e 62 if (!crpc->crp_trans) {
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
5fd88337 77 if (!crpc->crp_stamp) {
d7e09d03 78 /* not aborted */
5fd88337 79 LASSERT(!crpc->crp_status);
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);
06ace26e 99 if (!crpc->crp_rpc)
d7e09d03
PT
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
06ace26e 134 if (!crpc) {
d7e09d03 135 LIBCFS_ALLOC(crpc, sizeof(*crpc));
06ace26e 136 if (!crpc)
d7e09d03
PT
137 return -ENOMEM;
138 }
139
140 rc = lstcon_rpc_init(nd, service, feats, bulk_npg, bulk_len, 0, crpc);
5fd88337 141 if (!rc) {
d7e09d03
PT
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++) {
06ace26e 160 if (!bulk->bk_iovs[i].kiov_page)
d7e09d03
PT
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
06ace26e 191 LASSERT(trans);
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
06ace26e 244 if (translist) {
d7e09d03 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));
06ace26e 257 if (!trans)
d7e09d03
PT
258 return -ENOMEM;
259
260 trans->tas_opc = transop;
261
06ace26e 262 if (!translist)
d7e09d03
PT
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 */
5fd88337
JS
301 crpc->crp_stamp) { /* rpc done or aborted already */
302 if (!crpc->crp_stamp) {
d7e09d03
PT
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
5fd88337 336 return !atomic_read(&trans->tas_remaining) ? 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
5fd88337 373 if (rc || atomic_read(&trans->tas_remaining)) {
d7e09d03
PT
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
06ace26e 396 LASSERT(nd && rpc);
5fd88337 397 LASSERT(crpc->crp_stamp);
d7e09d03 398
5fd88337 399 if (crpc->crp_status) {
d7e09d03
PT
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
06ace26e 433 LASSERT(stat);
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
5fd88337 440 LASSERT(crpc->crp_stamp);
d7e09d03
PT
441
442 error = lstcon_rpc_get_reply(crpc, &rep);
5fd88337 443 if (error) {
d7e09d03 444 lstcon_rpc_stat_failure(stat, 1);
5fd88337 445 if (!stat->trs_rpc_errno)
d7e09d03
PT
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
5fd88337 456 if (trans->tas_opc == LST_TRANS_SESNEW && !stat->trs_fwk_errno) {
d7e09d03
PT
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
06ace26e 487 LASSERT(head_up);
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
5fd88337 503 LASSERT(crpc->crp_stamp);
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
5fd88337 522 if (error)
d7e09d03
PT
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
06ace26e 533 if (!readent)
d7e09d03
PT
534 continue;
535
b0834c87
RK
536 error = readent(trans->tas_opc, msg, ent);
537
5fd88337 538 if (error)
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 */
5fd88337 575 LASSERT(crpc->crp_status);
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
5fd88337 587 LASSERT(!atomic_read(&trans->tas_remaining));
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);
5fd88337 613 if (rc)
d7e09d03
PT
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);
5fd88337 626 if (rc)
d7e09d03
PT
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);
5fd88337 647 if (rc)
d7e09d03
PT
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);
5fd88337 667 if (rc)
d7e09d03
PT
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
5fd88337 683 LASSERT(!tsb->tsb_index);
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);
5fd88337 698 if (rc)
d7e09d03
PT
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);
5fd88337 830 nob = !(feats & LST_FEAT_BULK_LEN) ?
d7e09d03
PT
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);
5fd88337 836 if (rc)
d7e09d03
PT
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
5fd88337 859 len = !(feats & LST_FEAT_BULK_LEN) ?
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 868
06ace26e 869 if (!bulk->bk_iovs[i].kiov_page) {
d7e09d03
PT
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]);
5fd88337 884 if (rc) {
d7e09d03
PT
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;
5fd88337 908 if (!(feats & LST_FEAT_BULK_LEN)) {
d7e09d03
PT
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
5fd88337
JS
932 if (!status &&
933 (reply->msg_ses_feats & ~LST_FEATS_MASK)) {
d7e09d03
PT
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
5fd88337 944 if (status)
d7e09d03
PT
945 return status;
946
947 if (!trans->tas_feats_updated) {
c206f8bc
SB
948 spin_lock(&console_session.ses_rpc_lock);
949 if (!trans->tas_feats_updated) { /* recheck with lock */
950 trans->tas_feats_updated = 1;
951 trans->tas_features = reply->msg_ses_feats;
952 }
953 spin_unlock(&console_session.ses_rpc_lock);
d7e09d03
PT
954 }
955
956 if (reply->msg_ses_feats != trans->tas_features) {
eac2e8c6 957 CNETERR("Framework features %x from %s is different with features on this transaction: %x\n",
c314c319
JS
958 reply->msg_ses_feats, libcfs_nid2str(nd->nd_id.nid),
959 trans->tas_features);
d3d3d37a
JS
960 mksn_rep->mksn_status = EPROTO;
961 status = EPROTO;
d7e09d03
PT
962 }
963
5fd88337 964 if (!status) {
d7e09d03
PT
965 /* session timeout on remote node */
966 nd->nd_timeout = mksn_rep->mksn_timeout;
967 }
968
969 return status;
970}
971
972void
973lstcon_rpc_stat_reply(lstcon_rpc_trans_t *trans, srpc_msg_t *msg,
974 lstcon_node_t *nd, lstcon_trans_stat_t *stat)
975{
976 srpc_rmsn_reply_t *rmsn_rep;
977 srpc_debug_reply_t *dbg_rep;
978 srpc_batch_reply_t *bat_rep;
979 srpc_test_reply_t *test_rep;
980 srpc_stat_reply_t *stat_rep;
74d68011 981 int rc = 0;
d7e09d03
PT
982
983 switch (trans->tas_opc) {
984 case LST_TRANS_SESNEW:
985 rc = lstcon_sesnew_stat_reply(trans, nd, msg);
5fd88337 986 if (!rc) {
d7e09d03
PT
987 lstcon_sesop_stat_success(stat, 1);
988 return;
989 }
990
991 lstcon_sesop_stat_failure(stat, 1);
992 break;
993
994 case LST_TRANS_SESEND:
995 rmsn_rep = &msg->msg_body.rmsn_reply;
996 /* ESRCH is not an error for end session */
5fd88337 997 if (!rmsn_rep->rmsn_status ||
d7e09d03
PT
998 rmsn_rep->rmsn_status == ESRCH) {
999 lstcon_sesop_stat_success(stat, 1);
1000 return;
1001 }
1002
1003 lstcon_sesop_stat_failure(stat, 1);
1004 rc = rmsn_rep->rmsn_status;
1005 break;
1006
1007 case LST_TRANS_SESQRY:
1008 case LST_TRANS_SESPING:
1009 dbg_rep = &msg->msg_body.dbg_reply;
1010
1011 if (dbg_rep->dbg_status == ESRCH) {
1012 lstcon_sesqry_stat_unknown(stat, 1);
1013 return;
1014 }
1015
1016 if (lstcon_session_match(dbg_rep->dbg_sid))
1017 lstcon_sesqry_stat_active(stat, 1);
1018 else
1019 lstcon_sesqry_stat_busy(stat, 1);
1020 return;
1021
1022 case LST_TRANS_TSBRUN:
1023 case LST_TRANS_TSBSTOP:
1024 bat_rep = &msg->msg_body.bat_reply;
1025
5fd88337 1026 if (!bat_rep->bar_status) {
d7e09d03
PT
1027 lstcon_tsbop_stat_success(stat, 1);
1028 return;
1029 }
1030
1031 if (bat_rep->bar_status == EPERM &&
1032 trans->tas_opc == LST_TRANS_TSBSTOP) {
1033 lstcon_tsbop_stat_success(stat, 1);
1034 return;
1035 }
1036
1037 lstcon_tsbop_stat_failure(stat, 1);
1038 rc = bat_rep->bar_status;
1039 break;
1040
1041 case LST_TRANS_TSBCLIQRY:
1042 case LST_TRANS_TSBSRVQRY:
1043 bat_rep = &msg->msg_body.bat_reply;
1044
5fd88337 1045 if (bat_rep->bar_active)
d7e09d03
PT
1046 lstcon_tsbqry_stat_run(stat, 1);
1047 else
1048 lstcon_tsbqry_stat_idle(stat, 1);
1049
5fd88337 1050 if (!bat_rep->bar_status)
d7e09d03
PT
1051 return;
1052
1053 lstcon_tsbqry_stat_failure(stat, 1);
1054 rc = bat_rep->bar_status;
1055 break;
1056
1057 case LST_TRANS_TSBCLIADD:
1058 case LST_TRANS_TSBSRVADD:
1059 test_rep = &msg->msg_body.tes_reply;
1060
5fd88337 1061 if (!test_rep->tsr_status) {
d7e09d03
PT
1062 lstcon_tsbop_stat_success(stat, 1);
1063 return;
1064 }
1065
1066 lstcon_tsbop_stat_failure(stat, 1);
1067 rc = test_rep->tsr_status;
1068 break;
1069
1070 case LST_TRANS_STATQRY:
1071 stat_rep = &msg->msg_body.stat_reply;
1072
5fd88337 1073 if (!stat_rep->str_status) {
d7e09d03
PT
1074 lstcon_statqry_stat_success(stat, 1);
1075 return;
1076 }
1077
1078 lstcon_statqry_stat_failure(stat, 1);
1079 rc = stat_rep->str_status;
1080 break;
1081
1082 default:
1083 LBUG();
1084 }
1085
5fd88337 1086 if (!stat->trs_fwk_errno)
d7e09d03
PT
1087 stat->trs_fwk_errno = rc;
1088
1089 return;
1090}
1091
1092int
1093lstcon_rpc_trans_ndlist(struct list_head *ndlist,
1094 struct list_head *translist, int transop,
1095 void *arg, lstcon_rpc_cond_func_t condition,
1096 lstcon_rpc_trans_t **transpp)
1097{
1098 lstcon_rpc_trans_t *trans;
74d68011
MS
1099 lstcon_ndlink_t *ndl;
1100 lstcon_node_t *nd;
1101 lstcon_rpc_t *rpc;
1102 unsigned feats;
1103 int rc;
d7e09d03
PT
1104
1105 /* Creating session RPG for list of nodes */
1106
1107 rc = lstcon_rpc_trans_prep(translist, transop, &trans);
5fd88337 1108 if (rc) {
d7e09d03
PT
1109 CERROR("Can't create transaction %d: %d\n", transop, rc);
1110 return rc;
1111 }
1112
1113 feats = trans->tas_features;
1114 list_for_each_entry(ndl, ndlist, ndl_link) {
06ace26e 1115 rc = !condition ? 1 :
d7e09d03
PT
1116 condition(transop, ndl->ndl_node, arg);
1117
5fd88337 1118 if (!rc)
d7e09d03
PT
1119 continue;
1120
1121 if (rc < 0) {
eac2e8c6 1122 CDEBUG(D_NET, "Condition error while creating RPC for transaction %d: %d\n",
c314c319 1123 transop, rc);
d7e09d03
PT
1124 break;
1125 }
1126
1127 nd = ndl->ndl_node;
1128
1129 switch (transop) {
1130 case LST_TRANS_SESNEW:
1131 case LST_TRANS_SESEND:
1132 rc = lstcon_sesrpc_prep(nd, transop, feats, &rpc);
1133 break;
1134 case LST_TRANS_SESQRY:
1135 case LST_TRANS_SESPING:
1136 rc = lstcon_dbgrpc_prep(nd, feats, &rpc);
1137 break;
1138 case LST_TRANS_TSBCLIADD:
1139 case LST_TRANS_TSBSRVADD:
1140 rc = lstcon_testrpc_prep(nd, transop, feats,
1141 (lstcon_test_t *)arg, &rpc);
1142 break;
1143 case LST_TRANS_TSBRUN:
1144 case LST_TRANS_TSBSTOP:
1145 case LST_TRANS_TSBCLIQRY:
1146 case LST_TRANS_TSBSRVQRY:
1147 rc = lstcon_batrpc_prep(nd, transop, feats,
1148 (lstcon_tsb_hdr_t *)arg, &rpc);
1149 break;
1150 case LST_TRANS_STATQRY:
1151 rc = lstcon_statrpc_prep(nd, feats, &rpc);
1152 break;
1153 default:
1154 rc = -EINVAL;
1155 break;
1156 }
1157
5fd88337 1158 if (rc) {
d7e09d03
PT
1159 CERROR("Failed to create RPC for transaction %s: %d\n",
1160 lstcon_rpc_trans_name(transop), rc);
1161 break;
1162 }
1163
1164 lstcon_rpc_trans_addreq(trans, rpc);
1165 }
1166
5fd88337 1167 if (!rc) {
d7e09d03
PT
1168 *transpp = trans;
1169 return 0;
1170 }
1171
1172 lstcon_rpc_trans_destroy(trans);
1173
1174 return rc;
1175}
1176
8d94b6d2 1177static void
d7e09d03
PT
1178lstcon_rpc_pinger(void *arg)
1179{
27f9aea3 1180 struct stt_timer *ptimer = (struct stt_timer *)arg;
d7e09d03 1181 lstcon_rpc_trans_t *trans;
74d68011
MS
1182 lstcon_rpc_t *crpc;
1183 srpc_msg_t *rep;
d7e09d03 1184 srpc_debug_reqst_t *drq;
74d68011
MS
1185 lstcon_ndlink_t *ndl;
1186 lstcon_node_t *nd;
d9f79e6b 1187 int intv;
74d68011
MS
1188 int count = 0;
1189 int rc;
d7e09d03
PT
1190
1191 /* RPC pinger is a special case of transaction,
1192 * it's called by timer at 8 seconds interval.
1193 */
1194 mutex_lock(&console_session.ses_mutex);
1195
1196 if (console_session.ses_shutdown || console_session.ses_expired) {
1197 mutex_unlock(&console_session.ses_mutex);
1198 return;
1199 }
1200
1201 if (!console_session.ses_expired &&
d9f79e6b
AB
1202 ktime_get_real_seconds() - console_session.ses_laststamp >
1203 (time64_t)console_session.ses_timeout)
d7e09d03
PT
1204 console_session.ses_expired = 1;
1205
1206 trans = console_session.ses_ping;
1207
06ace26e 1208 LASSERT(trans);
d7e09d03
PT
1209
1210 list_for_each_entry(ndl, &console_session.ses_ndl_list, ndl_link) {
1211 nd = ndl->ndl_node;
1212
1213 if (console_session.ses_expired) {
1214 /* idle console, end session on all nodes */
1215 if (nd->nd_state != LST_NODE_ACTIVE)
1216 continue;
1217
1218 rc = lstcon_sesrpc_prep(nd, LST_TRANS_SESEND,
1219 trans->tas_features, &crpc);
5fd88337 1220 if (rc) {
d7e09d03
PT
1221 CERROR("Out of memory\n");
1222 break;
1223 }
1224
1225 lstcon_rpc_trans_addreq(trans, crpc);
1226 lstcon_rpc_post(crpc);
1227
1228 continue;
1229 }
1230
1231 crpc = &nd->nd_ping;
1232
06ace26e 1233 if (crpc->crp_rpc) {
4d72b5af
RK
1234 LASSERT(crpc->crp_trans == trans);
1235 LASSERT(!list_empty(&crpc->crp_link));
d7e09d03
PT
1236
1237 spin_lock(&crpc->crp_rpc->crpc_lock);
1238
1239 LASSERT(crpc->crp_posted);
1240
1241 if (!crpc->crp_finished) {
1242 /* in flight */
1243 spin_unlock(&crpc->crp_rpc->crpc_lock);
1244 continue;
1245 }
1246
1247 spin_unlock(&crpc->crp_rpc->crpc_lock);
1248
1249 lstcon_rpc_get_reply(crpc, &rep);
1250
1251 list_del_init(&crpc->crp_link);
1252
1253 lstcon_rpc_put(crpc);
1254 }
1255
1256 if (nd->nd_state != LST_NODE_ACTIVE)
1257 continue;
1258
27d81ace 1259 intv = (jiffies - nd->nd_stamp) / msecs_to_jiffies(MSEC_PER_SEC);
d9f79e6b 1260 if (intv < nd->nd_timeout / 2)
d7e09d03
PT
1261 continue;
1262
1263 rc = lstcon_rpc_init(nd, SRPC_SERVICE_DEBUG,
1264 trans->tas_features, 0, 0, 1, crpc);
5fd88337 1265 if (rc) {
d7e09d03
PT
1266 CERROR("Out of memory\n");
1267 break;
1268 }
1269
1270 drq = &crpc->crp_rpc->crpc_reqstmsg.msg_body.dbg_reqst;
1271
1272 drq->dbg_sid = console_session.ses_id;
1273 drq->dbg_flags = 0;
1274
1275 lstcon_rpc_trans_addreq(trans, crpc);
1276 lstcon_rpc_post(crpc);
1277
fc831a90 1278 count++;
d7e09d03
PT
1279 }
1280
1281 if (console_session.ses_expired) {
1282 mutex_unlock(&console_session.ses_mutex);
1283 return;
1284 }
1285
1286 CDEBUG(D_NET, "Ping %d nodes in session\n", count);
1287
d9f79e6b 1288 ptimer->stt_expires = ktime_get_real_seconds() + LST_PING_INTERVAL;
d7e09d03
PT
1289 stt_add_timer(ptimer);
1290
1291 mutex_unlock(&console_session.ses_mutex);
1292}
1293
1294int
1295lstcon_rpc_pinger_start(void)
1296{
27f9aea3 1297 struct stt_timer *ptimer;
74d68011 1298 int rc;
d7e09d03 1299
4d72b5af 1300 LASSERT(list_empty(&console_session.ses_rpc_freelist));
5fd88337 1301 LASSERT(!atomic_read(&console_session.ses_rpc_counter));
d7e09d03
PT
1302
1303 rc = lstcon_rpc_trans_prep(NULL, LST_TRANS_SESPING,
1304 &console_session.ses_ping);
5fd88337 1305 if (rc) {
d7e09d03
PT
1306 CERROR("Failed to create console pinger\n");
1307 return rc;
1308 }
1309
1310 ptimer = &console_session.ses_ping_timer;
d9f79e6b 1311 ptimer->stt_expires = ktime_get_real_seconds() + LST_PING_INTERVAL;
d7e09d03
PT
1312
1313 stt_add_timer(ptimer);
1314
1315 return 0;
1316}
1317
1318void
1319lstcon_rpc_pinger_stop(void)
1320{
4d72b5af 1321 LASSERT(console_session.ses_shutdown);
d7e09d03
PT
1322
1323 stt_del_timer(&console_session.ses_ping_timer);
1324
1325 lstcon_rpc_trans_abort(console_session.ses_ping, -ESHUTDOWN);
1326 lstcon_rpc_trans_stat(console_session.ses_ping, lstcon_trans_stat());
1327 lstcon_rpc_trans_destroy(console_session.ses_ping);
1328
1329 memset(lstcon_trans_stat(), 0, sizeof(lstcon_trans_stat_t));
1330
1331 console_session.ses_ping = NULL;
1332}
1333
1334void
1335lstcon_rpc_cleanup_wait(void)
1336{
1337 lstcon_rpc_trans_t *trans;
74d68011
MS
1338 lstcon_rpc_t *crpc;
1339 struct list_head *pacer;
1340 struct list_head zlist;
d7e09d03
PT
1341
1342 /* Called with hold of global mutex */
1343
4d72b5af 1344 LASSERT(console_session.ses_shutdown);
d7e09d03
PT
1345
1346 while (!list_empty(&console_session.ses_trans_list)) {
1347 list_for_each(pacer, &console_session.ses_trans_list) {
1348 trans = list_entry(pacer, lstcon_rpc_trans_t,
c314c319 1349 tas_link);
d7e09d03
PT
1350
1351 CDEBUG(D_NET, "Session closed, wakeup transaction %s\n",
1352 lstcon_rpc_trans_name(trans->tas_opc));
1353
1354 wake_up(&trans->tas_waitq);
1355 }
1356
1357 mutex_unlock(&console_session.ses_mutex);
1358
eac2e8c6 1359 CWARN("Session is shutting down, waiting for termination of transactions\n");
d3caf4d5
PT
1360 set_current_state(TASK_UNINTERRUPTIBLE);
1361 schedule_timeout(cfs_time_seconds(1));
d7e09d03
PT
1362
1363 mutex_lock(&console_session.ses_mutex);
1364 }
1365
1366 spin_lock(&console_session.ses_rpc_lock);
1367
5fd88337 1368 lst_wait_until(!atomic_read(&console_session.ses_rpc_counter),
d7e09d03 1369 console_session.ses_rpc_lock,
eac2e8c6 1370 "Network is not accessible or target is down, waiting for %d console RPCs to being recycled\n",
d7e09d03
PT
1371 atomic_read(&console_session.ses_rpc_counter));
1372
1373 list_add(&zlist, &console_session.ses_rpc_freelist);
1374 list_del_init(&console_session.ses_rpc_freelist);
1375
1376 spin_unlock(&console_session.ses_rpc_lock);
1377
1378 while (!list_empty(&zlist)) {
1379 crpc = list_entry(zlist.next, lstcon_rpc_t, crp_link);
1380
1381 list_del(&crpc->crp_link);
1382 LIBCFS_FREE(crpc, sizeof(lstcon_rpc_t));
1383 }
1384}
1385
1386int
1387lstcon_rpc_module_init(void)
1388{
1389 INIT_LIST_HEAD(&console_session.ses_ping_timer.stt_list);
1390 console_session.ses_ping_timer.stt_func = lstcon_rpc_pinger;
1391 console_session.ses_ping_timer.stt_data = &console_session.ses_ping_timer;
1392
1393 console_session.ses_ping = NULL;
1394
1395 spin_lock_init(&console_session.ses_rpc_lock);
1396 atomic_set(&console_session.ses_rpc_counter, 0);
1397 INIT_LIST_HEAD(&console_session.ses_rpc_freelist);
1398
1399 return 0;
1400}
1401
1402void
1403lstcon_rpc_module_fini(void)
1404{
4d72b5af 1405 LASSERT(list_empty(&console_session.ses_rpc_freelist));
5fd88337 1406 LASSERT(!atomic_read(&console_session.ses_rpc_counter));
d7e09d03 1407}