4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
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.
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).
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.gnu.org/licenses/gpl-2.0.html
23 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Use is subject to license terms.
26 * Copyright (c) 2012, Intel Corporation.
29 * This file is part of Lustre, http://www.lustre.org/
30 * Lustre is a trademark of Sun Microsystems, Inc.
32 * lnet/selftest/conctl.c
34 * Infrastructure of LST console
36 * Author: Liang Zhen <liangzhen@clusterfs.com>
39 #include "../../include/linux/libcfs/libcfs.h"
40 #include "../../include/linux/lnet/lib-lnet.h"
44 #define LST_NODE_STATE_COUNTER(nd, p) \
46 if ((nd)->nd_state == LST_NODE_ACTIVE) \
48 else if ((nd)->nd_state == LST_NODE_BUSY) \
50 else if ((nd)->nd_state == LST_NODE_DOWN) \
53 (p)->nle_nunknown++; \
57 struct lstcon_session console_session;
60 lstcon_node_get(struct lstcon_node *nd)
62 LASSERT(nd->nd_ref >= 1);
68 lstcon_node_find(lnet_process_id_t id, struct lstcon_node **ndpp, int create)
70 struct lstcon_ndlink *ndl;
71 unsigned int idx = LNET_NIDADDR(id.nid) % LST_GLOBAL_HASHSIZE;
73 LASSERT(id.nid != LNET_NID_ANY);
75 list_for_each_entry(ndl, &console_session.ses_ndl_hash[idx],
77 if (ndl->ndl_node->nd_id.nid != id.nid ||
78 ndl->ndl_node->nd_id.pid != id.pid)
81 lstcon_node_get(ndl->ndl_node);
82 *ndpp = ndl->ndl_node;
89 LIBCFS_ALLOC(*ndpp, sizeof(struct lstcon_node) + sizeof(struct lstcon_ndlink));
93 ndl = (struct lstcon_ndlink *)(*ndpp + 1);
95 ndl->ndl_node = *ndpp;
97 ndl->ndl_node->nd_ref = 1;
98 ndl->ndl_node->nd_id = id;
99 ndl->ndl_node->nd_stamp = cfs_time_current();
100 ndl->ndl_node->nd_state = LST_NODE_UNKNOWN;
101 ndl->ndl_node->nd_timeout = 0;
102 memset(&ndl->ndl_node->nd_ping, 0, sizeof(struct lstcon_rpc));
105 * queued in global hash & list, no refcount is taken by
106 * global hash & list, if caller release his refcount,
107 * node will be released
109 list_add_tail(&ndl->ndl_hlink, &console_session.ses_ndl_hash[idx]);
110 list_add_tail(&ndl->ndl_link, &console_session.ses_ndl_list);
116 lstcon_node_put(struct lstcon_node *nd)
118 struct lstcon_ndlink *ndl;
120 LASSERT(nd->nd_ref > 0);
122 if (--nd->nd_ref > 0)
125 ndl = (struct lstcon_ndlink *)(nd + 1);
127 LASSERT(!list_empty(&ndl->ndl_link));
128 LASSERT(!list_empty(&ndl->ndl_hlink));
130 /* remove from session */
131 list_del(&ndl->ndl_link);
132 list_del(&ndl->ndl_hlink);
134 LIBCFS_FREE(nd, sizeof(struct lstcon_node) + sizeof(struct lstcon_ndlink));
138 lstcon_ndlink_find(struct list_head *hash,
139 lnet_process_id_t id, struct lstcon_ndlink **ndlpp, int create)
141 unsigned int idx = LNET_NIDADDR(id.nid) % LST_NODE_HASHSIZE;
142 struct lstcon_ndlink *ndl;
143 struct lstcon_node *nd;
146 if (id.nid == LNET_NID_ANY)
150 list_for_each_entry(ndl, &hash[idx], ndl_hlink) {
151 if (ndl->ndl_node->nd_id.nid != id.nid ||
152 ndl->ndl_node->nd_id.pid != id.pid)
162 /* find or create in session hash */
163 rc = lstcon_node_find(id, &nd, (create == 1) ? 1 : 0);
167 LIBCFS_ALLOC(ndl, sizeof(struct lstcon_ndlink));
176 INIT_LIST_HEAD(&ndl->ndl_link);
177 list_add_tail(&ndl->ndl_hlink, &hash[idx]);
183 lstcon_ndlink_release(struct lstcon_ndlink *ndl)
185 LASSERT(list_empty(&ndl->ndl_link));
186 LASSERT(!list_empty(&ndl->ndl_hlink));
188 list_del(&ndl->ndl_hlink); /* delete from hash */
189 lstcon_node_put(ndl->ndl_node);
191 LIBCFS_FREE(ndl, sizeof(*ndl));
195 lstcon_group_alloc(char *name, struct lstcon_group **grpp)
197 struct lstcon_group *grp;
200 LIBCFS_ALLOC(grp, offsetof(struct lstcon_group,
201 grp_ndl_hash[LST_NODE_HASHSIZE]));
207 if (strlen(name) > sizeof(grp->grp_name) - 1) {
208 LIBCFS_FREE(grp, offsetof(struct lstcon_group,
209 grp_ndl_hash[LST_NODE_HASHSIZE]));
212 strncpy(grp->grp_name, name, sizeof(grp->grp_name));
215 INIT_LIST_HEAD(&grp->grp_link);
216 INIT_LIST_HEAD(&grp->grp_ndl_list);
217 INIT_LIST_HEAD(&grp->grp_trans_list);
219 for (i = 0; i < LST_NODE_HASHSIZE; i++)
220 INIT_LIST_HEAD(&grp->grp_ndl_hash[i]);
228 lstcon_group_addref(struct lstcon_group *grp)
233 static void lstcon_group_ndlink_release(struct lstcon_group *, struct lstcon_ndlink *);
236 lstcon_group_drain(struct lstcon_group *grp, int keep)
238 struct lstcon_ndlink *ndl;
239 struct lstcon_ndlink *tmp;
241 list_for_each_entry_safe(ndl, tmp, &grp->grp_ndl_list, ndl_link) {
242 if (!(ndl->ndl_node->nd_state & keep))
243 lstcon_group_ndlink_release(grp, ndl);
248 lstcon_group_decref(struct lstcon_group *grp)
252 if (--grp->grp_ref > 0)
255 if (!list_empty(&grp->grp_link))
256 list_del(&grp->grp_link);
258 lstcon_group_drain(grp, 0);
260 for (i = 0; i < LST_NODE_HASHSIZE; i++)
261 LASSERT(list_empty(&grp->grp_ndl_hash[i]));
263 LIBCFS_FREE(grp, offsetof(struct lstcon_group,
264 grp_ndl_hash[LST_NODE_HASHSIZE]));
268 lstcon_group_find(const char *name, struct lstcon_group **grpp)
270 struct lstcon_group *grp;
272 list_for_each_entry(grp, &console_session.ses_grp_list, grp_link) {
273 if (strncmp(grp->grp_name, name, LST_NAME_SIZE))
276 lstcon_group_addref(grp); /* +1 ref for caller */
285 lstcon_group_ndlink_find(struct lstcon_group *grp, lnet_process_id_t id,
286 struct lstcon_ndlink **ndlpp, int create)
290 rc = lstcon_ndlink_find(&grp->grp_ndl_hash[0], id, ndlpp, create);
294 if (!list_empty(&(*ndlpp)->ndl_link))
297 list_add_tail(&(*ndlpp)->ndl_link, &grp->grp_ndl_list);
304 lstcon_group_ndlink_release(struct lstcon_group *grp, struct lstcon_ndlink *ndl)
306 list_del_init(&ndl->ndl_link);
307 lstcon_ndlink_release(ndl);
312 lstcon_group_ndlink_move(struct lstcon_group *old,
313 struct lstcon_group *new, struct lstcon_ndlink *ndl)
315 unsigned int idx = LNET_NIDADDR(ndl->ndl_node->nd_id.nid) %
318 list_del(&ndl->ndl_hlink);
319 list_del(&ndl->ndl_link);
322 list_add_tail(&ndl->ndl_hlink, &new->grp_ndl_hash[idx]);
323 list_add_tail(&ndl->ndl_link, &new->grp_ndl_list);
328 lstcon_group_move(struct lstcon_group *old, struct lstcon_group *new)
330 struct lstcon_ndlink *ndl;
332 while (!list_empty(&old->grp_ndl_list)) {
333 ndl = list_entry(old->grp_ndl_list.next,
334 struct lstcon_ndlink, ndl_link);
335 lstcon_group_ndlink_move(old, new, ndl);
340 lstcon_sesrpc_condition(int transop, struct lstcon_node *nd, void *arg)
342 struct lstcon_group *grp = (struct lstcon_group *)arg;
345 case LST_TRANS_SESNEW:
346 if (nd->nd_state == LST_NODE_ACTIVE)
350 case LST_TRANS_SESEND:
351 if (nd->nd_state != LST_NODE_ACTIVE)
354 if (grp && nd->nd_ref > 1)
358 case LST_TRANS_SESQRY:
369 lstcon_sesrpc_readent(int transop, struct srpc_msg *msg,
370 lstcon_rpc_ent_t __user *ent_up)
372 struct srpc_debug_reply *rep;
375 case LST_TRANS_SESNEW:
376 case LST_TRANS_SESEND:
379 case LST_TRANS_SESQRY:
380 rep = &msg->msg_body.dbg_reply;
382 if (copy_to_user(&ent_up->rpe_priv[0],
383 &rep->dbg_timeout, sizeof(int)) ||
384 copy_to_user(&ent_up->rpe_payload[0],
385 &rep->dbg_name, LST_NAME_SIZE))
398 lstcon_group_nodes_add(struct lstcon_group *grp,
399 int count, lnet_process_id_t __user *ids_up,
400 unsigned *featp, struct list_head __user *result_up)
402 struct lstcon_rpc_trans *trans;
403 struct lstcon_ndlink *ndl;
404 struct lstcon_group *tmp;
405 lnet_process_id_t id;
409 rc = lstcon_group_alloc(NULL, &tmp);
411 CERROR("Out of memory\n");
415 for (i = 0 ; i < count; i++) {
416 if (copy_from_user(&id, &ids_up[i], sizeof(id))) {
421 /* skip if it's in this group already */
422 rc = lstcon_group_ndlink_find(grp, id, &ndl, 0);
426 /* add to tmp group */
427 rc = lstcon_group_ndlink_find(tmp, id, &ndl, 1);
429 CERROR("Can't create ndlink, out of memory\n");
435 lstcon_group_decref(tmp);
439 rc = lstcon_rpc_trans_ndlist(&tmp->grp_ndl_list,
440 &tmp->grp_trans_list, LST_TRANS_SESNEW,
441 tmp, lstcon_sesrpc_condition, &trans);
443 CERROR("Can't create transaction: %d\n", rc);
444 lstcon_group_decref(tmp);
449 lstcon_rpc_trans_postwait(trans, LST_TRANS_TIMEOUT);
451 rc = lstcon_rpc_trans_interpreter(trans, result_up,
452 lstcon_sesrpc_readent);
453 *featp = trans->tas_features;
455 /* destroy all RPGs */
456 lstcon_rpc_trans_destroy(trans);
458 lstcon_group_move(tmp, grp);
459 lstcon_group_decref(tmp);
465 lstcon_group_nodes_remove(struct lstcon_group *grp,
466 int count, lnet_process_id_t __user *ids_up,
467 struct list_head __user *result_up)
469 struct lstcon_rpc_trans *trans;
470 struct lstcon_ndlink *ndl;
471 struct lstcon_group *tmp;
472 lnet_process_id_t id;
476 /* End session and remove node from the group */
478 rc = lstcon_group_alloc(NULL, &tmp);
480 CERROR("Out of memory\n");
484 for (i = 0; i < count; i++) {
485 if (copy_from_user(&id, &ids_up[i], sizeof(id))) {
490 /* move node to tmp group */
491 if (!lstcon_group_ndlink_find(grp, id, &ndl, 0))
492 lstcon_group_ndlink_move(grp, tmp, ndl);
495 rc = lstcon_rpc_trans_ndlist(&tmp->grp_ndl_list,
496 &tmp->grp_trans_list, LST_TRANS_SESEND,
497 tmp, lstcon_sesrpc_condition, &trans);
499 CERROR("Can't create transaction: %d\n", rc);
503 lstcon_rpc_trans_postwait(trans, LST_TRANS_TIMEOUT);
505 rc = lstcon_rpc_trans_interpreter(trans, result_up, NULL);
507 lstcon_rpc_trans_destroy(trans);
508 /* release nodes anyway, because we can't rollback status */
509 lstcon_group_decref(tmp);
513 lstcon_group_move(tmp, grp);
514 lstcon_group_decref(tmp);
520 lstcon_group_add(char *name)
522 struct lstcon_group *grp;
525 rc = lstcon_group_find(name, &grp) ? 0 : -EEXIST;
527 /* find a group with same name */
528 lstcon_group_decref(grp);
532 rc = lstcon_group_alloc(name, &grp);
534 CERROR("Can't allocate descriptor for group %s\n", name);
538 list_add_tail(&grp->grp_link, &console_session.ses_grp_list);
544 lstcon_nodes_add(char *name, int count, lnet_process_id_t __user *ids_up,
545 unsigned *featp, struct list_head __user *result_up)
547 struct lstcon_group *grp;
553 rc = lstcon_group_find(name, &grp);
555 CDEBUG(D_NET, "Can't find group %s\n", name);
559 if (grp->grp_ref > 2) {
560 /* referred by other threads or test */
561 CDEBUG(D_NET, "Group %s is busy\n", name);
562 lstcon_group_decref(grp);
567 rc = lstcon_group_nodes_add(grp, count, ids_up, featp, result_up);
569 lstcon_group_decref(grp);
575 lstcon_group_del(char *name)
577 struct lstcon_rpc_trans *trans;
578 struct lstcon_group *grp;
581 rc = lstcon_group_find(name, &grp);
583 CDEBUG(D_NET, "Can't find group: %s\n", name);
587 if (grp->grp_ref > 2) {
588 /* referred by others threads or test */
589 CDEBUG(D_NET, "Group %s is busy\n", name);
590 lstcon_group_decref(grp);
594 rc = lstcon_rpc_trans_ndlist(&grp->grp_ndl_list,
595 &grp->grp_trans_list, LST_TRANS_SESEND,
596 grp, lstcon_sesrpc_condition, &trans);
598 CERROR("Can't create transaction: %d\n", rc);
599 lstcon_group_decref(grp);
603 lstcon_rpc_trans_postwait(trans, LST_TRANS_TIMEOUT);
605 lstcon_rpc_trans_destroy(trans);
607 lstcon_group_decref(grp);
609 * -ref for session, it's destroyed,
610 * status can't be rolled back, destroy group anyway
612 lstcon_group_decref(grp);
618 lstcon_group_clean(char *name, int args)
620 struct lstcon_group *grp = NULL;
623 rc = lstcon_group_find(name, &grp);
625 CDEBUG(D_NET, "Can't find group %s\n", name);
629 if (grp->grp_ref > 2) {
630 /* referred by test */
631 CDEBUG(D_NET, "Group %s is busy\n", name);
632 lstcon_group_decref(grp);
636 args = (LST_NODE_ACTIVE | LST_NODE_BUSY |
637 LST_NODE_DOWN | LST_NODE_UNKNOWN) & ~args;
639 lstcon_group_drain(grp, args);
641 lstcon_group_decref(grp);
642 /* release empty group */
643 if (list_empty(&grp->grp_ndl_list))
644 lstcon_group_decref(grp);
650 lstcon_nodes_remove(char *name, int count, lnet_process_id_t __user *ids_up,
651 struct list_head __user *result_up)
653 struct lstcon_group *grp = NULL;
656 rc = lstcon_group_find(name, &grp);
658 CDEBUG(D_NET, "Can't find group: %s\n", name);
662 if (grp->grp_ref > 2) {
663 /* referred by test */
664 CDEBUG(D_NET, "Group %s is busy\n", name);
665 lstcon_group_decref(grp);
669 rc = lstcon_group_nodes_remove(grp, count, ids_up, result_up);
671 lstcon_group_decref(grp);
672 /* release empty group */
673 if (list_empty(&grp->grp_ndl_list))
674 lstcon_group_decref(grp);
680 lstcon_group_refresh(char *name, struct list_head __user *result_up)
682 struct lstcon_rpc_trans *trans;
683 struct lstcon_group *grp;
686 rc = lstcon_group_find(name, &grp);
688 CDEBUG(D_NET, "Can't find group: %s\n", name);
692 if (grp->grp_ref > 2) {
693 /* referred by test */
694 CDEBUG(D_NET, "Group %s is busy\n", name);
695 lstcon_group_decref(grp);
699 /* re-invite all inactive nodes int the group */
700 rc = lstcon_rpc_trans_ndlist(&grp->grp_ndl_list,
701 &grp->grp_trans_list, LST_TRANS_SESNEW,
702 grp, lstcon_sesrpc_condition, &trans);
704 /* local error, return */
705 CDEBUG(D_NET, "Can't create transaction: %d\n", rc);
706 lstcon_group_decref(grp);
710 lstcon_rpc_trans_postwait(trans, LST_TRANS_TIMEOUT);
712 rc = lstcon_rpc_trans_interpreter(trans, result_up, NULL);
714 lstcon_rpc_trans_destroy(trans);
716 lstcon_group_decref(grp);
722 lstcon_group_list(int index, int len, char __user *name_up)
724 struct lstcon_group *grp;
729 list_for_each_entry(grp, &console_session.ses_grp_list, grp_link) {
731 return copy_to_user(name_up, grp->grp_name, len) ?
740 lstcon_nodes_getent(struct list_head *head, int *index_p,
741 int *count_p, lstcon_node_ent_t __user *dents_up)
743 struct lstcon_ndlink *ndl;
744 struct lstcon_node *nd;
748 LASSERT(index_p && count_p);
750 LASSERT(*index_p >= 0);
751 LASSERT(*count_p > 0);
753 list_for_each_entry(ndl, head, ndl_link) {
754 if (index++ < *index_p)
757 if (count >= *count_p)
761 if (copy_to_user(&dents_up[count].nde_id,
762 &nd->nd_id, sizeof(nd->nd_id)) ||
763 copy_to_user(&dents_up[count].nde_state,
764 &nd->nd_state, sizeof(nd->nd_state)))
770 if (index <= *index_p)
780 lstcon_group_info(char *name, lstcon_ndlist_ent_t __user *gents_p,
781 int *index_p, int *count_p,
782 lstcon_node_ent_t __user *dents_up)
784 lstcon_ndlist_ent_t *gentp;
785 struct lstcon_group *grp;
786 struct lstcon_ndlink *ndl;
789 rc = lstcon_group_find(name, &grp);
791 CDEBUG(D_NET, "Can't find group %s\n", name);
797 rc = lstcon_nodes_getent(&grp->grp_ndl_list,
798 index_p, count_p, dents_up);
799 lstcon_group_decref(grp);
804 /* non-verbose query */
805 LIBCFS_ALLOC(gentp, sizeof(lstcon_ndlist_ent_t));
807 CERROR("Can't allocate ndlist_ent\n");
808 lstcon_group_decref(grp);
813 list_for_each_entry(ndl, &grp->grp_ndl_list, ndl_link)
814 LST_NODE_STATE_COUNTER(ndl->ndl_node, gentp);
816 rc = copy_to_user(gents_p, gentp,
817 sizeof(lstcon_ndlist_ent_t)) ? -EFAULT : 0;
819 LIBCFS_FREE(gentp, sizeof(lstcon_ndlist_ent_t));
821 lstcon_group_decref(grp);
827 lstcon_batch_find(const char *name, struct lstcon_batch **batpp)
829 struct lstcon_batch *bat;
831 list_for_each_entry(bat, &console_session.ses_bat_list, bat_link) {
832 if (!strncmp(bat->bat_name, name, LST_NAME_SIZE)) {
842 lstcon_batch_add(char *name)
844 struct lstcon_batch *bat;
848 rc = !lstcon_batch_find(name, &bat) ? -EEXIST : 0;
850 CDEBUG(D_NET, "Batch %s already exists\n", name);
854 LIBCFS_ALLOC(bat, sizeof(struct lstcon_batch));
856 CERROR("Can't allocate descriptor for batch %s\n", name);
860 LIBCFS_ALLOC(bat->bat_cli_hash,
861 sizeof(struct list_head) * LST_NODE_HASHSIZE);
862 if (!bat->bat_cli_hash) {
863 CERROR("Can't allocate hash for batch %s\n", name);
864 LIBCFS_FREE(bat, sizeof(struct lstcon_batch));
869 LIBCFS_ALLOC(bat->bat_srv_hash,
870 sizeof(struct list_head) * LST_NODE_HASHSIZE);
871 if (!bat->bat_srv_hash) {
872 CERROR("Can't allocate hash for batch %s\n", name);
873 LIBCFS_FREE(bat->bat_cli_hash, LST_NODE_HASHSIZE);
874 LIBCFS_FREE(bat, sizeof(struct lstcon_batch));
879 if (strlen(name) > sizeof(bat->bat_name) - 1) {
880 LIBCFS_FREE(bat->bat_srv_hash, LST_NODE_HASHSIZE);
881 LIBCFS_FREE(bat->bat_cli_hash, LST_NODE_HASHSIZE);
882 LIBCFS_FREE(bat, sizeof(struct lstcon_batch));
885 strncpy(bat->bat_name, name, sizeof(bat->bat_name));
886 bat->bat_hdr.tsb_index = 0;
887 bat->bat_hdr.tsb_id.bat_id = ++console_session.ses_id_cookie;
890 bat->bat_state = LST_BATCH_IDLE;
892 INIT_LIST_HEAD(&bat->bat_cli_list);
893 INIT_LIST_HEAD(&bat->bat_srv_list);
894 INIT_LIST_HEAD(&bat->bat_test_list);
895 INIT_LIST_HEAD(&bat->bat_trans_list);
897 for (i = 0; i < LST_NODE_HASHSIZE; i++) {
898 INIT_LIST_HEAD(&bat->bat_cli_hash[i]);
899 INIT_LIST_HEAD(&bat->bat_srv_hash[i]);
902 list_add_tail(&bat->bat_link, &console_session.ses_bat_list);
908 lstcon_batch_list(int index, int len, char __user *name_up)
910 struct lstcon_batch *bat;
915 list_for_each_entry(bat, &console_session.ses_bat_list, bat_link) {
917 return copy_to_user(name_up, bat->bat_name, len) ?
926 lstcon_batch_info(char *name, lstcon_test_batch_ent_t __user *ent_up,
927 int server, int testidx, int *index_p, int *ndent_p,
928 lstcon_node_ent_t __user *dents_up)
930 lstcon_test_batch_ent_t *entp;
931 struct list_head *clilst;
932 struct list_head *srvlst;
933 struct lstcon_test *test = NULL;
934 struct lstcon_batch *bat;
935 struct lstcon_ndlink *ndl;
938 rc = lstcon_batch_find(name, &bat);
940 CDEBUG(D_NET, "Can't find batch %s\n", name);
945 /* query test, test index start from 1 */
946 list_for_each_entry(test, &bat->bat_test_list, tes_link) {
952 CDEBUG(D_NET, "Can't find specified test in batch\n");
957 clilst = !test ? &bat->bat_cli_list :
958 &test->tes_src_grp->grp_ndl_list;
959 srvlst = !test ? &bat->bat_srv_list :
960 &test->tes_dst_grp->grp_ndl_list;
963 rc = lstcon_nodes_getent((server ? srvlst : clilst),
964 index_p, ndent_p, dents_up);
968 /* non-verbose query */
969 LIBCFS_ALLOC(entp, sizeof(lstcon_test_batch_ent_t));
974 entp->u.tbe_batch.bae_ntest = bat->bat_ntest;
975 entp->u.tbe_batch.bae_state = bat->bat_state;
977 entp->u.tbe_test.tse_type = test->tes_type;
978 entp->u.tbe_test.tse_loop = test->tes_loop;
979 entp->u.tbe_test.tse_concur = test->tes_concur;
982 list_for_each_entry(ndl, clilst, ndl_link)
983 LST_NODE_STATE_COUNTER(ndl->ndl_node, &entp->tbe_cli_nle);
985 list_for_each_entry(ndl, srvlst, ndl_link)
986 LST_NODE_STATE_COUNTER(ndl->ndl_node, &entp->tbe_srv_nle);
988 rc = copy_to_user(ent_up, entp,
989 sizeof(lstcon_test_batch_ent_t)) ? -EFAULT : 0;
991 LIBCFS_FREE(entp, sizeof(lstcon_test_batch_ent_t));
997 lstcon_batrpc_condition(int transop, struct lstcon_node *nd, void *arg)
1000 case LST_TRANS_TSBRUN:
1001 if (nd->nd_state != LST_NODE_ACTIVE)
1005 case LST_TRANS_TSBSTOP:
1006 if (nd->nd_state != LST_NODE_ACTIVE)
1010 case LST_TRANS_TSBCLIQRY:
1011 case LST_TRANS_TSBSRVQRY:
1019 lstcon_batch_op(struct lstcon_batch *bat, int transop,
1020 struct list_head __user *result_up)
1022 struct lstcon_rpc_trans *trans;
1025 rc = lstcon_rpc_trans_ndlist(&bat->bat_cli_list,
1026 &bat->bat_trans_list, transop,
1027 bat, lstcon_batrpc_condition, &trans);
1029 CERROR("Can't create transaction: %d\n", rc);
1033 lstcon_rpc_trans_postwait(trans, LST_TRANS_TIMEOUT);
1035 rc = lstcon_rpc_trans_interpreter(trans, result_up, NULL);
1037 lstcon_rpc_trans_destroy(trans);
1043 lstcon_batch_run(char *name, int timeout, struct list_head __user *result_up)
1045 struct lstcon_batch *bat;
1048 if (lstcon_batch_find(name, &bat)) {
1049 CDEBUG(D_NET, "Can't find batch %s\n", name);
1053 bat->bat_arg = timeout;
1055 rc = lstcon_batch_op(bat, LST_TRANS_TSBRUN, result_up);
1057 /* mark batch as running if it's started in any node */
1058 if (lstcon_tsbop_stat_success(lstcon_trans_stat(), 0))
1059 bat->bat_state = LST_BATCH_RUNNING;
1065 lstcon_batch_stop(char *name, int force, struct list_head __user *result_up)
1067 struct lstcon_batch *bat;
1070 if (lstcon_batch_find(name, &bat)) {
1071 CDEBUG(D_NET, "Can't find batch %s\n", name);
1075 bat->bat_arg = force;
1077 rc = lstcon_batch_op(bat, LST_TRANS_TSBSTOP, result_up);
1079 /* mark batch as stopped if all RPCs finished */
1080 if (!lstcon_tsbop_stat_failure(lstcon_trans_stat(), 0))
1081 bat->bat_state = LST_BATCH_IDLE;
1087 lstcon_batch_destroy(struct lstcon_batch *bat)
1089 struct lstcon_ndlink *ndl;
1090 struct lstcon_test *test;
1093 list_del(&bat->bat_link);
1095 while (!list_empty(&bat->bat_test_list)) {
1096 test = list_entry(bat->bat_test_list.next,
1097 struct lstcon_test, tes_link);
1098 LASSERT(list_empty(&test->tes_trans_list));
1100 list_del(&test->tes_link);
1102 lstcon_group_decref(test->tes_src_grp);
1103 lstcon_group_decref(test->tes_dst_grp);
1105 LIBCFS_FREE(test, offsetof(struct lstcon_test,
1106 tes_param[test->tes_paramlen]));
1109 LASSERT(list_empty(&bat->bat_trans_list));
1111 while (!list_empty(&bat->bat_cli_list)) {
1112 ndl = list_entry(bat->bat_cli_list.next,
1113 struct lstcon_ndlink, ndl_link);
1114 list_del_init(&ndl->ndl_link);
1116 lstcon_ndlink_release(ndl);
1119 while (!list_empty(&bat->bat_srv_list)) {
1120 ndl = list_entry(bat->bat_srv_list.next,
1121 struct lstcon_ndlink, ndl_link);
1122 list_del_init(&ndl->ndl_link);
1124 lstcon_ndlink_release(ndl);
1127 for (i = 0; i < LST_NODE_HASHSIZE; i++) {
1128 LASSERT(list_empty(&bat->bat_cli_hash[i]));
1129 LASSERT(list_empty(&bat->bat_srv_hash[i]));
1132 LIBCFS_FREE(bat->bat_cli_hash,
1133 sizeof(struct list_head) * LST_NODE_HASHSIZE);
1134 LIBCFS_FREE(bat->bat_srv_hash,
1135 sizeof(struct list_head) * LST_NODE_HASHSIZE);
1136 LIBCFS_FREE(bat, sizeof(struct lstcon_batch));
1140 lstcon_testrpc_condition(int transop, struct lstcon_node *nd, void *arg)
1142 struct lstcon_test *test;
1143 struct lstcon_batch *batch;
1144 struct lstcon_ndlink *ndl;
1145 struct list_head *hash;
1146 struct list_head *head;
1148 test = (struct lstcon_test *)arg;
1151 batch = test->tes_batch;
1154 if (test->tes_oneside &&
1155 transop == LST_TRANS_TSBSRVADD)
1158 if (nd->nd_state != LST_NODE_ACTIVE)
1161 if (transop == LST_TRANS_TSBCLIADD) {
1162 hash = batch->bat_cli_hash;
1163 head = &batch->bat_cli_list;
1166 LASSERT(transop == LST_TRANS_TSBSRVADD);
1168 hash = batch->bat_srv_hash;
1169 head = &batch->bat_srv_list;
1172 LASSERT(nd->nd_id.nid != LNET_NID_ANY);
1174 if (lstcon_ndlink_find(hash, nd->nd_id, &ndl, 1))
1177 if (list_empty(&ndl->ndl_link))
1178 list_add_tail(&ndl->ndl_link, head);
1184 lstcon_test_nodes_add(struct lstcon_test *test, struct list_head __user *result_up)
1186 struct lstcon_rpc_trans *trans;
1187 struct lstcon_group *grp;
1191 LASSERT(test->tes_src_grp);
1192 LASSERT(test->tes_dst_grp);
1194 transop = LST_TRANS_TSBSRVADD;
1195 grp = test->tes_dst_grp;
1197 rc = lstcon_rpc_trans_ndlist(&grp->grp_ndl_list,
1198 &test->tes_trans_list, transop,
1199 test, lstcon_testrpc_condition, &trans);
1201 CERROR("Can't create transaction: %d\n", rc);
1205 lstcon_rpc_trans_postwait(trans, LST_TRANS_TIMEOUT);
1207 if (lstcon_trans_stat()->trs_rpc_errno ||
1208 lstcon_trans_stat()->trs_fwk_errno) {
1209 lstcon_rpc_trans_interpreter(trans, result_up, NULL);
1211 lstcon_rpc_trans_destroy(trans);
1212 /* return if any error */
1213 CDEBUG(D_NET, "Failed to add test %s, RPC error %d, framework error %d\n",
1214 transop == LST_TRANS_TSBCLIADD ? "client" : "server",
1215 lstcon_trans_stat()->trs_rpc_errno,
1216 lstcon_trans_stat()->trs_fwk_errno);
1221 lstcon_rpc_trans_destroy(trans);
1223 if (transop == LST_TRANS_TSBCLIADD)
1226 transop = LST_TRANS_TSBCLIADD;
1227 grp = test->tes_src_grp;
1228 test->tes_cliidx = 0;
1230 /* requests to test clients */
1235 lstcon_verify_batch(const char *name, struct lstcon_batch **batch)
1239 rc = lstcon_batch_find(name, batch);
1241 CDEBUG(D_NET, "Can't find batch %s\n", name);
1245 if ((*batch)->bat_state != LST_BATCH_IDLE) {
1246 CDEBUG(D_NET, "Can't change running batch %s\n", name);
1254 lstcon_verify_group(const char *name, struct lstcon_group **grp)
1257 struct lstcon_ndlink *ndl;
1259 rc = lstcon_group_find(name, grp);
1261 CDEBUG(D_NET, "can't find group %s\n", name);
1265 list_for_each_entry(ndl, &(*grp)->grp_ndl_list, ndl_link) {
1266 if (ndl->ndl_node->nd_state == LST_NODE_ACTIVE)
1270 CDEBUG(D_NET, "Group %s has no ACTIVE nodes\n", name);
1276 lstcon_test_add(char *batch_name, int type, int loop,
1277 int concur, int dist, int span,
1278 char *src_name, char *dst_name,
1279 void *param, int paramlen, int *retp,
1280 struct list_head __user *result_up)
1282 struct lstcon_test *test = NULL;
1284 struct lstcon_group *src_grp = NULL;
1285 struct lstcon_group *dst_grp = NULL;
1286 struct lstcon_batch *batch = NULL;
1289 * verify that a batch of the given name exists, and the groups
1290 * that will be part of the batch exist and have at least one
1293 rc = lstcon_verify_batch(batch_name, &batch);
1297 rc = lstcon_verify_group(src_name, &src_grp);
1301 rc = lstcon_verify_group(dst_name, &dst_grp);
1305 if (dst_grp->grp_userland)
1308 LIBCFS_ALLOC(test, offsetof(struct lstcon_test, tes_param[paramlen]));
1310 CERROR("Can't allocate test descriptor\n");
1316 test->tes_hdr.tsb_id = batch->bat_hdr.tsb_id;
1317 test->tes_batch = batch;
1318 test->tes_type = type;
1319 test->tes_oneside = 0; /* TODO */
1320 test->tes_loop = loop;
1321 test->tes_concur = concur;
1322 test->tes_stop_onerr = 1; /* TODO */
1323 test->tes_span = span;
1324 test->tes_dist = dist;
1325 test->tes_cliidx = 0; /* just used for creating RPC */
1326 test->tes_src_grp = src_grp;
1327 test->tes_dst_grp = dst_grp;
1328 INIT_LIST_HEAD(&test->tes_trans_list);
1331 test->tes_paramlen = paramlen;
1332 memcpy(&test->tes_param[0], param, paramlen);
1335 rc = lstcon_test_nodes_add(test, result_up);
1340 if (lstcon_trans_stat()->trs_rpc_errno ||
1341 lstcon_trans_stat()->trs_fwk_errno)
1342 CDEBUG(D_NET, "Failed to add test %d to batch %s\n", type,
1345 /* add to test list anyway, so user can check what's going on */
1346 list_add_tail(&test->tes_link, &batch->bat_test_list);
1349 test->tes_hdr.tsb_index = batch->bat_ntest;
1351 /* hold groups so nobody can change them */
1355 LIBCFS_FREE(test, offsetof(struct lstcon_test, tes_param[paramlen]));
1358 lstcon_group_decref(dst_grp);
1361 lstcon_group_decref(src_grp);
1367 lstcon_test_find(struct lstcon_batch *batch, int idx, struct lstcon_test **testpp)
1369 struct lstcon_test *test;
1371 list_for_each_entry(test, &batch->bat_test_list, tes_link) {
1372 if (idx == test->tes_hdr.tsb_index) {
1382 lstcon_tsbrpc_readent(int transop, struct srpc_msg *msg,
1383 lstcon_rpc_ent_t __user *ent_up)
1385 struct srpc_batch_reply *rep = &msg->msg_body.bat_reply;
1387 LASSERT(transop == LST_TRANS_TSBCLIQRY ||
1388 transop == LST_TRANS_TSBSRVQRY);
1390 /* positive errno, framework error code */
1391 if (copy_to_user(&ent_up->rpe_priv[0], &rep->bar_active,
1392 sizeof(rep->bar_active)))
1399 lstcon_test_batch_query(char *name, int testidx, int client,
1400 int timeout, struct list_head __user *result_up)
1402 struct lstcon_rpc_trans *trans;
1403 struct list_head *translist;
1404 struct list_head *ndlist;
1405 struct lstcon_tsb_hdr *hdr;
1406 struct lstcon_batch *batch;
1407 struct lstcon_test *test = NULL;
1411 rc = lstcon_batch_find(name, &batch);
1413 CDEBUG(D_NET, "Can't find batch: %s\n", name);
1418 translist = &batch->bat_trans_list;
1419 ndlist = &batch->bat_cli_list;
1420 hdr = &batch->bat_hdr;
1422 /* query specified test only */
1423 rc = lstcon_test_find(batch, testidx, &test);
1425 CDEBUG(D_NET, "Can't find test: %d\n", testidx);
1429 translist = &test->tes_trans_list;
1430 ndlist = &test->tes_src_grp->grp_ndl_list;
1431 hdr = &test->tes_hdr;
1434 transop = client ? LST_TRANS_TSBCLIQRY : LST_TRANS_TSBSRVQRY;
1436 rc = lstcon_rpc_trans_ndlist(ndlist, translist, transop, hdr,
1437 lstcon_batrpc_condition, &trans);
1439 CERROR("Can't create transaction: %d\n", rc);
1443 lstcon_rpc_trans_postwait(trans, timeout);
1445 /* query a batch, not a test */
1447 !lstcon_rpc_stat_failure(lstcon_trans_stat(), 0) &&
1448 !lstcon_tsbqry_stat_run(lstcon_trans_stat(), 0)) {
1449 /* all RPCs finished, and no active test */
1450 batch->bat_state = LST_BATCH_IDLE;
1453 rc = lstcon_rpc_trans_interpreter(trans, result_up,
1454 lstcon_tsbrpc_readent);
1455 lstcon_rpc_trans_destroy(trans);
1461 lstcon_statrpc_readent(int transop, struct srpc_msg *msg,
1462 lstcon_rpc_ent_t __user *ent_up)
1464 struct srpc_stat_reply *rep = &msg->msg_body.stat_reply;
1465 sfw_counters_t __user *sfwk_stat;
1466 srpc_counters_t __user *srpc_stat;
1467 lnet_counters_t __user *lnet_stat;
1469 if (rep->str_status)
1472 sfwk_stat = (sfw_counters_t __user *)&ent_up->rpe_payload[0];
1473 srpc_stat = (srpc_counters_t __user *)(sfwk_stat + 1);
1474 lnet_stat = (lnet_counters_t __user *)(srpc_stat + 1);
1476 if (copy_to_user(sfwk_stat, &rep->str_fw, sizeof(*sfwk_stat)) ||
1477 copy_to_user(srpc_stat, &rep->str_rpc, sizeof(*srpc_stat)) ||
1478 copy_to_user(lnet_stat, &rep->str_lnet, sizeof(*lnet_stat)))
1485 lstcon_ndlist_stat(struct list_head *ndlist,
1486 int timeout, struct list_head __user *result_up)
1488 struct list_head head;
1489 struct lstcon_rpc_trans *trans;
1492 INIT_LIST_HEAD(&head);
1494 rc = lstcon_rpc_trans_ndlist(ndlist, &head,
1495 LST_TRANS_STATQRY, NULL, NULL, &trans);
1497 CERROR("Can't create transaction: %d\n", rc);
1501 lstcon_rpc_trans_postwait(trans, LST_VALIDATE_TIMEOUT(timeout));
1503 rc = lstcon_rpc_trans_interpreter(trans, result_up,
1504 lstcon_statrpc_readent);
1505 lstcon_rpc_trans_destroy(trans);
1511 lstcon_group_stat(char *grp_name, int timeout,
1512 struct list_head __user *result_up)
1514 struct lstcon_group *grp;
1517 rc = lstcon_group_find(grp_name, &grp);
1519 CDEBUG(D_NET, "Can't find group %s\n", grp_name);
1523 rc = lstcon_ndlist_stat(&grp->grp_ndl_list, timeout, result_up);
1525 lstcon_group_decref(grp);
1531 lstcon_nodes_stat(int count, lnet_process_id_t __user *ids_up,
1532 int timeout, struct list_head __user *result_up)
1534 struct lstcon_ndlink *ndl;
1535 struct lstcon_group *tmp;
1536 lnet_process_id_t id;
1540 rc = lstcon_group_alloc(NULL, &tmp);
1542 CERROR("Out of memory\n");
1546 for (i = 0 ; i < count; i++) {
1547 if (copy_from_user(&id, &ids_up[i], sizeof(id))) {
1552 /* add to tmp group */
1553 rc = lstcon_group_ndlink_find(tmp, id, &ndl, 2);
1555 CDEBUG((rc == -ENOMEM) ? D_ERROR : D_NET,
1556 "Failed to find or create %s: %d\n",
1557 libcfs_id2str(id), rc);
1563 lstcon_group_decref(tmp);
1567 rc = lstcon_ndlist_stat(&tmp->grp_ndl_list, timeout, result_up);
1569 lstcon_group_decref(tmp);
1575 lstcon_debug_ndlist(struct list_head *ndlist,
1576 struct list_head *translist,
1577 int timeout, struct list_head __user *result_up)
1579 struct lstcon_rpc_trans *trans;
1582 rc = lstcon_rpc_trans_ndlist(ndlist, translist, LST_TRANS_SESQRY,
1583 NULL, lstcon_sesrpc_condition, &trans);
1585 CERROR("Can't create transaction: %d\n", rc);
1589 lstcon_rpc_trans_postwait(trans, LST_VALIDATE_TIMEOUT(timeout));
1591 rc = lstcon_rpc_trans_interpreter(trans, result_up,
1592 lstcon_sesrpc_readent);
1593 lstcon_rpc_trans_destroy(trans);
1599 lstcon_session_debug(int timeout, struct list_head __user *result_up)
1601 return lstcon_debug_ndlist(&console_session.ses_ndl_list,
1602 NULL, timeout, result_up);
1606 lstcon_batch_debug(int timeout, char *name,
1607 int client, struct list_head __user *result_up)
1609 struct lstcon_batch *bat;
1612 rc = lstcon_batch_find(name, &bat);
1616 rc = lstcon_debug_ndlist(client ? &bat->bat_cli_list :
1618 NULL, timeout, result_up);
1624 lstcon_group_debug(int timeout, char *name,
1625 struct list_head __user *result_up)
1627 struct lstcon_group *grp;
1630 rc = lstcon_group_find(name, &grp);
1634 rc = lstcon_debug_ndlist(&grp->grp_ndl_list, NULL,
1635 timeout, result_up);
1636 lstcon_group_decref(grp);
1642 lstcon_nodes_debug(int timeout,
1643 int count, lnet_process_id_t __user *ids_up,
1644 struct list_head __user *result_up)
1646 lnet_process_id_t id;
1647 struct lstcon_ndlink *ndl;
1648 struct lstcon_group *grp;
1652 rc = lstcon_group_alloc(NULL, &grp);
1654 CDEBUG(D_NET, "Out of memory\n");
1658 for (i = 0; i < count; i++) {
1659 if (copy_from_user(&id, &ids_up[i], sizeof(id))) {
1664 /* node is added to tmp group */
1665 rc = lstcon_group_ndlink_find(grp, id, &ndl, 1);
1667 CERROR("Can't create node link\n");
1673 lstcon_group_decref(grp);
1677 rc = lstcon_debug_ndlist(&grp->grp_ndl_list, NULL,
1678 timeout, result_up);
1680 lstcon_group_decref(grp);
1686 lstcon_session_match(lst_sid_t sid)
1688 return (console_session.ses_id.ses_nid == sid.ses_nid &&
1689 console_session.ses_id.ses_stamp == sid.ses_stamp) ? 1 : 0;
1693 lstcon_new_session_id(lst_sid_t *sid)
1695 lnet_process_id_t id;
1697 LASSERT(console_session.ses_state == LST_SESSION_NONE);
1700 sid->ses_nid = id.nid;
1701 sid->ses_stamp = cfs_time_current();
1705 lstcon_session_new(char *name, int key, unsigned feats,
1706 int timeout, int force, lst_sid_t __user *sid_up)
1711 if (console_session.ses_state != LST_SESSION_NONE) {
1712 /* session exists */
1714 CNETERR("Session %s already exists\n",
1715 console_session.ses_name);
1719 rc = lstcon_session_end();
1721 /* lstcon_session_end() only return local error */
1726 if (feats & ~LST_FEATS_MASK) {
1727 CNETERR("Unknown session features %x\n",
1728 (feats & ~LST_FEATS_MASK));
1732 for (i = 0; i < LST_GLOBAL_HASHSIZE; i++)
1733 LASSERT(list_empty(&console_session.ses_ndl_hash[i]));
1735 lstcon_new_session_id(&console_session.ses_id);
1737 console_session.ses_key = key;
1738 console_session.ses_state = LST_SESSION_ACTIVE;
1739 console_session.ses_force = !!force;
1740 console_session.ses_features = feats;
1741 console_session.ses_feats_updated = 0;
1742 console_session.ses_timeout = (timeout <= 0) ?
1743 LST_CONSOLE_TIMEOUT : timeout;
1745 if (strlen(name) > sizeof(console_session.ses_name) - 1)
1747 strlcpy(console_session.ses_name, name,
1748 sizeof(console_session.ses_name));
1750 rc = lstcon_batch_add(LST_DEFAULT_BATCH);
1754 rc = lstcon_rpc_pinger_start();
1756 struct lstcon_batch *bat = NULL;
1758 lstcon_batch_find(LST_DEFAULT_BATCH, &bat);
1759 lstcon_batch_destroy(bat);
1764 if (!copy_to_user(sid_up, &console_session.ses_id,
1768 lstcon_session_end();
1774 lstcon_session_info(lst_sid_t __user *sid_up, int __user *key_up,
1775 unsigned __user *featp,
1776 lstcon_ndlist_ent_t __user *ndinfo_up,
1777 char __user *name_up, int len)
1779 lstcon_ndlist_ent_t *entp;
1780 struct lstcon_ndlink *ndl;
1783 if (console_session.ses_state != LST_SESSION_ACTIVE)
1786 LIBCFS_ALLOC(entp, sizeof(*entp));
1790 list_for_each_entry(ndl, &console_session.ses_ndl_list, ndl_link)
1791 LST_NODE_STATE_COUNTER(ndl->ndl_node, entp);
1793 if (copy_to_user(sid_up, &console_session.ses_id,
1794 sizeof(lst_sid_t)) ||
1795 copy_to_user(key_up, &console_session.ses_key,
1797 copy_to_user(featp, &console_session.ses_features,
1799 copy_to_user(ndinfo_up, entp, sizeof(*entp)) ||
1800 copy_to_user(name_up, console_session.ses_name, len))
1803 LIBCFS_FREE(entp, sizeof(*entp));
1809 lstcon_session_end(void)
1811 struct lstcon_rpc_trans *trans;
1812 struct lstcon_group *grp;
1813 struct lstcon_batch *bat;
1816 LASSERT(console_session.ses_state == LST_SESSION_ACTIVE);
1818 rc = lstcon_rpc_trans_ndlist(&console_session.ses_ndl_list,
1819 NULL, LST_TRANS_SESEND, NULL,
1820 lstcon_sesrpc_condition, &trans);
1822 CERROR("Can't create transaction: %d\n", rc);
1826 console_session.ses_shutdown = 1;
1828 lstcon_rpc_pinger_stop();
1830 lstcon_rpc_trans_postwait(trans, LST_TRANS_TIMEOUT);
1832 lstcon_rpc_trans_destroy(trans);
1833 /* User can do nothing even rpc failed, so go on */
1835 /* waiting for orphan rpcs to die */
1836 lstcon_rpc_cleanup_wait();
1838 console_session.ses_id = LST_INVALID_SID;
1839 console_session.ses_state = LST_SESSION_NONE;
1840 console_session.ses_key = 0;
1841 console_session.ses_force = 0;
1842 console_session.ses_feats_updated = 0;
1844 /* destroy all batches */
1845 while (!list_empty(&console_session.ses_bat_list)) {
1846 bat = list_entry(console_session.ses_bat_list.next,
1847 struct lstcon_batch, bat_link);
1849 lstcon_batch_destroy(bat);
1852 /* destroy all groups */
1853 while (!list_empty(&console_session.ses_grp_list)) {
1854 grp = list_entry(console_session.ses_grp_list.next,
1855 struct lstcon_group, grp_link);
1856 LASSERT(grp->grp_ref == 1);
1858 lstcon_group_decref(grp);
1861 /* all nodes should be released */
1862 LASSERT(list_empty(&console_session.ses_ndl_list));
1864 console_session.ses_shutdown = 0;
1865 console_session.ses_expired = 0;
1871 lstcon_session_feats_check(unsigned feats)
1875 if (feats & ~LST_FEATS_MASK) {
1876 CERROR("Can't support these features: %x\n",
1877 (feats & ~LST_FEATS_MASK));
1881 spin_lock(&console_session.ses_rpc_lock);
1883 if (!console_session.ses_feats_updated) {
1884 console_session.ses_feats_updated = 1;
1885 console_session.ses_features = feats;
1888 if (console_session.ses_features != feats)
1891 spin_unlock(&console_session.ses_rpc_lock);
1894 CERROR("remote features %x do not match with session features %x of console\n",
1895 feats, console_session.ses_features);
1902 lstcon_acceptor_handle(struct srpc_server_rpc *rpc)
1904 struct srpc_msg *rep = &rpc->srpc_replymsg;
1905 struct srpc_msg *req = &rpc->srpc_reqstbuf->buf_msg;
1906 struct srpc_join_reqst *jreq = &req->msg_body.join_reqst;
1907 struct srpc_join_reply *jrep = &rep->msg_body.join_reply;
1908 struct lstcon_group *grp = NULL;
1909 struct lstcon_ndlink *ndl;
1912 sfw_unpack_message(req);
1914 mutex_lock(&console_session.ses_mutex);
1916 jrep->join_sid = console_session.ses_id;
1918 if (console_session.ses_id.ses_nid == LNET_NID_ANY) {
1919 jrep->join_status = ESRCH;
1923 if (lstcon_session_feats_check(req->msg_ses_feats)) {
1924 jrep->join_status = EPROTO;
1928 if (jreq->join_sid.ses_nid != LNET_NID_ANY &&
1929 !lstcon_session_match(jreq->join_sid)) {
1930 jrep->join_status = EBUSY;
1934 if (lstcon_group_find(jreq->join_group, &grp)) {
1935 rc = lstcon_group_alloc(jreq->join_group, &grp);
1937 CERROR("Out of memory\n");
1941 list_add_tail(&grp->grp_link,
1942 &console_session.ses_grp_list);
1943 lstcon_group_addref(grp);
1946 if (grp->grp_ref > 2) {
1947 /* Group in using */
1948 jrep->join_status = EBUSY;
1952 rc = lstcon_group_ndlink_find(grp, rpc->srpc_peer, &ndl, 0);
1954 jrep->join_status = EEXIST;
1958 rc = lstcon_group_ndlink_find(grp, rpc->srpc_peer, &ndl, 1);
1960 CERROR("Out of memory\n");
1964 ndl->ndl_node->nd_state = LST_NODE_ACTIVE;
1965 ndl->ndl_node->nd_timeout = console_session.ses_timeout;
1967 if (!grp->grp_userland)
1968 grp->grp_userland = 1;
1970 strlcpy(jrep->join_session, console_session.ses_name,
1971 sizeof(jrep->join_session));
1972 jrep->join_timeout = console_session.ses_timeout;
1973 jrep->join_status = 0;
1976 rep->msg_ses_feats = console_session.ses_features;
1978 lstcon_group_decref(grp);
1980 mutex_unlock(&console_session.ses_mutex);
1985 static struct srpc_service lstcon_acceptor_service;
1987 static void lstcon_init_acceptor_service(void)
1989 /* initialize selftest console acceptor service table */
1990 lstcon_acceptor_service.sv_name = "join session";
1991 lstcon_acceptor_service.sv_handler = lstcon_acceptor_handle;
1992 lstcon_acceptor_service.sv_id = SRPC_SERVICE_JOIN;
1993 lstcon_acceptor_service.sv_wi_total = SFW_FRWK_WI_MAX;
1996 static DECLARE_IOCTL_HANDLER(lstcon_ioctl_handler, lstcon_ioctl_entry);
1998 /* initialize console */
2000 lstcon_console_init(void)
2005 memset(&console_session, 0, sizeof(struct lstcon_session));
2007 console_session.ses_id = LST_INVALID_SID;
2008 console_session.ses_state = LST_SESSION_NONE;
2009 console_session.ses_timeout = 0;
2010 console_session.ses_force = 0;
2011 console_session.ses_expired = 0;
2012 console_session.ses_feats_updated = 0;
2013 console_session.ses_features = LST_FEATS_MASK;
2014 console_session.ses_laststamp = ktime_get_real_seconds();
2016 mutex_init(&console_session.ses_mutex);
2018 INIT_LIST_HEAD(&console_session.ses_ndl_list);
2019 INIT_LIST_HEAD(&console_session.ses_grp_list);
2020 INIT_LIST_HEAD(&console_session.ses_bat_list);
2021 INIT_LIST_HEAD(&console_session.ses_trans_list);
2023 LIBCFS_ALLOC(console_session.ses_ndl_hash,
2024 sizeof(struct list_head) * LST_GLOBAL_HASHSIZE);
2025 if (!console_session.ses_ndl_hash)
2028 for (i = 0; i < LST_GLOBAL_HASHSIZE; i++)
2029 INIT_LIST_HEAD(&console_session.ses_ndl_hash[i]);
2031 /* initialize acceptor service table */
2032 lstcon_init_acceptor_service();
2034 rc = srpc_add_service(&lstcon_acceptor_service);
2035 LASSERT(rc != -EBUSY);
2037 LIBCFS_FREE(console_session.ses_ndl_hash,
2038 sizeof(struct list_head) * LST_GLOBAL_HASHSIZE);
2042 rc = srpc_service_add_buffers(&lstcon_acceptor_service,
2043 lstcon_acceptor_service.sv_wi_total);
2049 rc = libcfs_register_ioctl(&lstcon_ioctl_handler);
2052 lstcon_rpc_module_init();
2057 srpc_shutdown_service(&lstcon_acceptor_service);
2058 srpc_remove_service(&lstcon_acceptor_service);
2060 LIBCFS_FREE(console_session.ses_ndl_hash,
2061 sizeof(struct list_head) * LST_GLOBAL_HASHSIZE);
2063 srpc_wait_service_shutdown(&lstcon_acceptor_service);
2069 lstcon_console_fini(void)
2073 libcfs_deregister_ioctl(&lstcon_ioctl_handler);
2075 mutex_lock(&console_session.ses_mutex);
2077 srpc_shutdown_service(&lstcon_acceptor_service);
2078 srpc_remove_service(&lstcon_acceptor_service);
2080 if (console_session.ses_state != LST_SESSION_NONE)
2081 lstcon_session_end();
2083 lstcon_rpc_module_fini();
2085 mutex_unlock(&console_session.ses_mutex);
2087 LASSERT(list_empty(&console_session.ses_ndl_list));
2088 LASSERT(list_empty(&console_session.ses_grp_list));
2089 LASSERT(list_empty(&console_session.ses_bat_list));
2090 LASSERT(list_empty(&console_session.ses_trans_list));
2092 for (i = 0; i < LST_NODE_HASHSIZE; i++)
2093 LASSERT(list_empty(&console_session.ses_ndl_hash[i]));
2095 LIBCFS_FREE(console_session.ses_ndl_hash,
2096 sizeof(struct list_head) * LST_GLOBAL_HASHSIZE);
2098 srpc_wait_service_shutdown(&lstcon_acceptor_service);