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, 2014, 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 <libcfs/libcfs.h>
40 #include <lnet/lib-lnet.h>
44 #define LST_NODE_STATE_COUNTER(nd, p) \
46 if ((nd)->nd_state == LST_NODE_ACTIVE) \
47 (p)->nle_nactive ++; \
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(struct lnet_process_id id, struct lstcon_node **ndpp,
71 struct lstcon_ndlink *ndl;
72 unsigned int idx = LNET_NIDADDR(id.nid) % LST_GLOBAL_HASHSIZE;
74 LASSERT(id.nid != LNET_NID_ANY);
76 list_for_each_entry(ndl, &console_session.ses_ndl_hash[idx],
78 if (ndl->ndl_node->nd_id.nid != id.nid ||
79 ndl->ndl_node->nd_id.pid != id.pid)
82 lstcon_node_get(ndl->ndl_node);
83 *ndpp = ndl->ndl_node;
90 LIBCFS_ALLOC(*ndpp, sizeof(**ndpp) + sizeof(*ndl));
94 ndl = (struct lstcon_ndlink *)(*ndpp + 1);
96 ndl->ndl_node = *ndpp;
98 ndl->ndl_node->nd_ref = 1;
99 ndl->ndl_node->nd_id = id;
100 ndl->ndl_node->nd_stamp = ktime_get();
101 ndl->ndl_node->nd_state = LST_NODE_UNKNOWN;
102 ndl->ndl_node->nd_timeout = 0;
103 memset(&ndl->ndl_node->nd_ping, 0, sizeof(ndl->ndl_node->nd_ping));
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 */
108 list_add_tail(&ndl->ndl_hlink, &console_session.ses_ndl_hash[idx]);
109 list_add_tail(&ndl->ndl_link, &console_session.ses_ndl_list);
115 lstcon_node_put(struct lstcon_node *nd)
117 struct lstcon_ndlink *ndl;
119 LASSERT(nd->nd_ref > 0);
121 if (--nd->nd_ref > 0)
124 ndl = (struct lstcon_ndlink *)(nd + 1);
126 LASSERT(!list_empty(&ndl->ndl_link));
127 LASSERT(!list_empty(&ndl->ndl_hlink));
129 /* remove from session */
130 list_del(&ndl->ndl_link);
131 list_del(&ndl->ndl_hlink);
133 LIBCFS_FREE(nd, sizeof(*nd) + sizeof(*ndl));
137 lstcon_ndlink_find(struct list_head *hash, struct lnet_process_id id,
138 struct lstcon_ndlink **ndlpp, int create)
140 unsigned int idx = LNET_NIDADDR(id.nid) % LST_NODE_HASHSIZE;
141 struct lstcon_ndlink *ndl;
142 struct lstcon_node *nd;
145 if (id.nid == LNET_NID_ANY)
149 list_for_each_entry(ndl, &hash[idx], ndl_hlink) {
150 if (ndl->ndl_node->nd_id.nid != id.nid ||
151 ndl->ndl_node->nd_id.pid != id.pid)
161 /* find or create in session hash */
162 rc = lstcon_node_find(id, &nd, (create == 1) ? 1 : 0);
166 LIBCFS_ALLOC(ndl, sizeof(*ndl));
175 INIT_LIST_HEAD(&ndl->ndl_link);
176 list_add_tail(&ndl->ndl_hlink, &hash[idx]);
182 lstcon_ndlink_release(struct lstcon_ndlink *ndl)
184 LASSERT(list_empty(&ndl->ndl_link));
185 LASSERT(!list_empty(&ndl->ndl_hlink));
187 list_del(&ndl->ndl_hlink); /* delete from hash */
188 lstcon_node_put(ndl->ndl_node);
190 LIBCFS_FREE(ndl, sizeof(*ndl));
194 lstcon_group_alloc(char *name, struct lstcon_group **grpp)
196 struct lstcon_group *grp;
199 LIBCFS_ALLOC(grp, offsetof(struct lstcon_group,
200 grp_ndl_hash[LST_NODE_HASHSIZE]));
206 if (strlen(name) > sizeof(grp->grp_name)-1) {
207 LIBCFS_FREE(grp, offsetof(struct lstcon_group,
208 grp_ndl_hash[LST_NODE_HASHSIZE]));
211 strncpy(grp->grp_name, name, sizeof(grp->grp_name));
214 INIT_LIST_HEAD(&grp->grp_link);
215 INIT_LIST_HEAD(&grp->grp_ndl_list);
216 INIT_LIST_HEAD(&grp->grp_trans_list);
218 for (i = 0; i < LST_NODE_HASHSIZE; i++)
219 INIT_LIST_HEAD(&grp->grp_ndl_hash[i]);
227 lstcon_group_addref(struct lstcon_group *grp)
232 static void lstcon_group_ndlink_release(struct lstcon_group *,
233 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) == 0)
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) != 0)
276 lstcon_group_addref(grp); /* +1 ref for caller */
285 lstcon_group_ndlink_find(struct lstcon_group *grp, struct lnet_process_id 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);
330 lstcon_group_move(struct lstcon_group *old, struct lstcon_group *new)
332 struct lstcon_ndlink *ndl;
334 while (!list_empty(&old->grp_ndl_list)) {
335 ndl = list_entry(old->grp_ndl_list.next,
336 struct lstcon_ndlink, ndl_link);
337 lstcon_group_ndlink_move(old, new, ndl);
342 lstcon_sesrpc_condition(int transop, struct lstcon_node *nd, void *arg)
344 struct lstcon_group *grp = arg;
347 case LST_TRANS_SESNEW:
348 if (nd->nd_state == LST_NODE_ACTIVE)
352 case LST_TRANS_SESEND:
353 if (nd->nd_state != LST_NODE_ACTIVE)
356 if (grp != NULL && nd->nd_ref > 1)
360 case LST_TRANS_SESQRY:
371 lstcon_sesrpc_readent(int transop, struct srpc_msg *msg,
372 struct lstcon_rpc_ent __user *ent_up)
374 struct srpc_debug_reply *rep;
377 case LST_TRANS_SESNEW:
378 case LST_TRANS_SESEND:
381 case LST_TRANS_SESQRY:
382 rep = &msg->msg_body.dbg_reply;
384 if (copy_to_user(&ent_up->rpe_priv[0],
385 &rep->dbg_timeout, sizeof(int)) ||
386 copy_to_user(&ent_up->rpe_payload[0],
387 &rep->dbg_name, LST_NAME_SIZE))
400 lstcon_group_nodes_add(struct lstcon_group *grp,
401 int count, struct lnet_process_id __user *ids_up,
403 struct list_head __user *result_up)
405 struct lstcon_rpc_trans *trans;
406 struct lstcon_ndlink *ndl;
407 struct lstcon_group *tmp;
408 struct lnet_process_id id;
412 rc = lstcon_group_alloc(NULL, &tmp);
414 CERROR("Out of memory\n");
418 for (i = 0 ; i < count; i++) {
419 if (copy_from_user(&id, &ids_up[i], sizeof(id))) {
424 /* skip if it's in this group already */
425 rc = lstcon_group_ndlink_find(grp, id, &ndl, 0);
429 /* add to tmp group */
430 rc = lstcon_group_ndlink_find(tmp, id, &ndl, 1);
432 CERROR("Can't create ndlink, out of memory\n");
438 lstcon_group_decref(tmp);
442 rc = lstcon_rpc_trans_ndlist(&tmp->grp_ndl_list,
443 &tmp->grp_trans_list, LST_TRANS_SESNEW,
444 tmp, lstcon_sesrpc_condition, &trans);
446 CERROR("Can't create transaction: %d\n", rc);
447 lstcon_group_decref(tmp);
452 lstcon_rpc_trans_postwait(trans, LST_TRANS_TIMEOUT);
454 rc = lstcon_rpc_trans_interpreter(trans, result_up,
455 lstcon_sesrpc_readent);
456 *featp = trans->tas_features;
458 /* destroy all RPGs */
459 lstcon_rpc_trans_destroy(trans);
461 lstcon_group_move(tmp, grp);
462 lstcon_group_decref(tmp);
468 lstcon_group_nodes_remove(struct lstcon_group *grp,
469 int count, struct lnet_process_id __user *ids_up,
470 struct list_head __user *result_up)
472 struct lstcon_rpc_trans *trans;
473 struct lstcon_ndlink *ndl;
474 struct lstcon_group *tmp;
475 struct lnet_process_id id;
479 /* End session and remove node from the group */
481 rc = lstcon_group_alloc(NULL, &tmp);
483 CERROR("Out of memory\n");
487 for (i = 0; i < count; i++) {
488 if (copy_from_user(&id, &ids_up[i], sizeof(id))) {
493 /* move node to tmp group */
494 if (lstcon_group_ndlink_find(grp, id, &ndl, 0) == 0)
495 lstcon_group_ndlink_move(grp, tmp, ndl);
498 rc = lstcon_rpc_trans_ndlist(&tmp->grp_ndl_list,
499 &tmp->grp_trans_list, LST_TRANS_SESEND,
500 tmp, lstcon_sesrpc_condition, &trans);
502 CERROR("Can't create transaction: %d\n", rc);
506 lstcon_rpc_trans_postwait(trans, LST_TRANS_TIMEOUT);
508 rc = lstcon_rpc_trans_interpreter(trans, result_up, NULL);
510 lstcon_rpc_trans_destroy(trans);
511 /* release nodes anyway, because we can't rollback status */
512 lstcon_group_decref(tmp);
516 lstcon_group_move(tmp, grp);
517 lstcon_group_decref(tmp);
523 lstcon_group_add(char *name)
525 struct lstcon_group *grp;
528 rc = (lstcon_group_find(name, &grp) == 0)? -EEXIST: 0;
530 /* find a group with same name */
531 lstcon_group_decref(grp);
535 rc = lstcon_group_alloc(name, &grp);
537 CERROR("Can't allocate descriptor for group %s\n", name);
541 list_add_tail(&grp->grp_link, &console_session.ses_grp_list);
547 lstcon_nodes_add(char *name, int count, struct lnet_process_id __user *ids_up,
548 unsigned *featp, struct list_head __user *result_up)
550 struct lstcon_group *grp;
554 LASSERT (ids_up != NULL);
556 rc = lstcon_group_find(name, &grp);
558 CDEBUG(D_NET, "Can't find group %s\n", name);
562 if (grp->grp_ref > 2) {
563 /* referred by other threads or test */
564 CDEBUG(D_NET, "Group %s is busy\n", name);
565 lstcon_group_decref(grp);
570 rc = lstcon_group_nodes_add(grp, count, ids_up, featp, result_up);
572 lstcon_group_decref(grp);
578 lstcon_group_del(char *name)
580 struct lstcon_rpc_trans *trans;
581 struct lstcon_group *grp;
584 rc = lstcon_group_find(name, &grp);
586 CDEBUG(D_NET, "Can't find group: %s\n", name);
590 if (grp->grp_ref > 2) {
591 /* referred by others threads or test */
592 CDEBUG(D_NET, "Group %s is busy\n", name);
593 lstcon_group_decref(grp);
597 rc = lstcon_rpc_trans_ndlist(&grp->grp_ndl_list,
598 &grp->grp_trans_list, LST_TRANS_SESEND,
599 grp, lstcon_sesrpc_condition, &trans);
601 CERROR("Can't create transaction: %d\n", rc);
602 lstcon_group_decref(grp);
606 lstcon_rpc_trans_postwait(trans, LST_TRANS_TIMEOUT);
608 lstcon_rpc_trans_destroy(trans);
610 lstcon_group_decref(grp);
611 /* -ref for session, it's destroyed,
612 * status can't be rolled back, destroy group anway */
613 lstcon_group_decref(grp);
619 lstcon_group_clean(char *name, int args)
621 struct lstcon_group *grp = NULL;
624 rc = lstcon_group_find(name, &grp);
626 CDEBUG(D_NET, "Can't find group %s\n", name);
630 if (grp->grp_ref > 2) {
631 /* referred by test */
632 CDEBUG(D_NET, "Group %s is busy\n", name);
633 lstcon_group_decref(grp);
637 args = (LST_NODE_ACTIVE | LST_NODE_BUSY |
638 LST_NODE_DOWN | LST_NODE_UNKNOWN) & ~args;
640 lstcon_group_drain(grp, args);
642 lstcon_group_decref(grp);
643 /* release empty group */
644 if (list_empty(&grp->grp_ndl_list))
645 lstcon_group_decref(grp);
651 lstcon_nodes_remove(char *name, int count,
652 struct lnet_process_id __user *ids_up,
653 struct list_head __user *result_up)
655 struct lstcon_group *grp = NULL;
658 rc = lstcon_group_find(name, &grp);
660 CDEBUG(D_NET, "Can't find group: %s\n", name);
664 if (grp->grp_ref > 2) {
665 /* referred by test */
666 CDEBUG(D_NET, "Group %s is busy\n", name);
667 lstcon_group_decref(grp);
671 rc = lstcon_group_nodes_remove(grp, count, ids_up, result_up);
673 lstcon_group_decref(grp);
674 /* release empty group */
675 if (list_empty(&grp->grp_ndl_list))
676 lstcon_group_decref(grp);
682 lstcon_group_refresh(char *name, struct list_head __user *result_up)
684 struct lstcon_rpc_trans *trans;
685 struct lstcon_group *grp;
688 rc = lstcon_group_find(name, &grp);
690 CDEBUG(D_NET, "Can't find group: %s\n", name);
694 if (grp->grp_ref > 2) {
695 /* referred by test */
696 CDEBUG(D_NET, "Group %s is busy\n", name);
697 lstcon_group_decref(grp);
701 /* re-invite all inactive nodes int the group */
702 rc = lstcon_rpc_trans_ndlist(&grp->grp_ndl_list,
703 &grp->grp_trans_list, LST_TRANS_SESNEW,
704 grp, lstcon_sesrpc_condition, &trans);
706 /* local error, return */
707 CDEBUG(D_NET, "Can't create transaction: %d\n", rc);
708 lstcon_group_decref(grp);
712 lstcon_rpc_trans_postwait(trans, LST_TRANS_TIMEOUT);
714 rc = lstcon_rpc_trans_interpreter(trans, result_up, NULL);
716 lstcon_rpc_trans_destroy(trans);
718 lstcon_group_decref(grp);
724 lstcon_group_list(int index, int len, char __user *name_up)
726 struct lstcon_group *grp;
729 LASSERT(name_up != NULL);
731 list_for_each_entry(grp, &console_session.ses_grp_list, grp_link) {
733 return copy_to_user(name_up, grp->grp_name, len) ?
742 lstcon_nodes_getent(struct list_head *head, int *index_p,
743 int *count_p, struct lstcon_node_ent __user *dents_up)
745 struct lstcon_ndlink *ndl;
746 struct lstcon_node *nd;
750 LASSERT(index_p != NULL && count_p != NULL);
751 LASSERT(dents_up != NULL);
752 LASSERT(*index_p >= 0);
753 LASSERT(*count_p > 0);
755 list_for_each_entry(ndl, head, ndl_link) {
756 if (index++ < *index_p)
759 if (count >= *count_p)
763 if (copy_to_user(&dents_up[count].nde_id,
764 &nd->nd_id, sizeof(nd->nd_id)) ||
765 copy_to_user(&dents_up[count].nde_state,
766 &nd->nd_state, sizeof(nd->nd_state)))
772 if (index <= *index_p)
782 lstcon_group_info(char *name, struct lstcon_ndlist_ent __user *gents_p,
783 int *index_p, int *count_p,
784 struct lstcon_node_ent __user *dents_up)
786 struct lstcon_ndlist_ent *gentp;
787 struct lstcon_group *grp;
788 struct lstcon_ndlink *ndl;
791 rc = lstcon_group_find(name, &grp);
793 CDEBUG(D_NET, "Can't find group %s\n", name);
797 if (dents_up != NULL) {
799 rc = lstcon_nodes_getent(&grp->grp_ndl_list,
800 index_p, count_p, dents_up);
801 lstcon_group_decref(grp);
806 /* non-verbose query */
807 LIBCFS_ALLOC(gentp, sizeof(struct lstcon_ndlist_ent));
809 CERROR("Can't allocate ndlist_ent\n");
810 lstcon_group_decref(grp);
815 list_for_each_entry(ndl, &grp->grp_ndl_list, ndl_link)
816 LST_NODE_STATE_COUNTER(ndl->ndl_node, gentp);
818 rc = copy_to_user(gents_p, gentp,
819 sizeof(struct lstcon_ndlist_ent)) ? -EFAULT : 0;
821 LIBCFS_FREE(gentp, sizeof(struct lstcon_ndlist_ent));
823 lstcon_group_decref(grp);
829 lstcon_batch_find(const char *name, struct lstcon_batch **batpp)
831 struct lstcon_batch *bat;
833 list_for_each_entry(bat, &console_session.ses_bat_list, bat_link) {
834 if (strncmp(bat->bat_name, name, LST_NAME_SIZE) == 0) {
844 lstcon_batch_add(char *name)
846 struct lstcon_batch *bat;
850 rc = (lstcon_batch_find(name, &bat) == 0)? -EEXIST: 0;
852 CDEBUG(D_NET, "Batch %s already exists\n", name);
856 LIBCFS_ALLOC(bat, sizeof(*bat));
858 CERROR("Can't allocate descriptor for batch %s\n", name);
862 LIBCFS_ALLOC(bat->bat_cli_hash,
863 sizeof(struct list_head) * LST_NODE_HASHSIZE);
864 if (bat->bat_cli_hash == NULL) {
865 CERROR("Can't allocate hash for batch %s\n", name);
866 LIBCFS_FREE(bat, sizeof(*bat));
871 LIBCFS_ALLOC(bat->bat_srv_hash,
872 sizeof(struct list_head) * LST_NODE_HASHSIZE);
873 if (bat->bat_srv_hash == NULL) {
874 CERROR("Can't allocate hash for batch %s\n", name);
875 LIBCFS_FREE(bat->bat_cli_hash, LST_NODE_HASHSIZE);
876 LIBCFS_FREE(bat, sizeof(*bat));
881 if (strlen(name) > sizeof(bat->bat_name)-1) {
882 LIBCFS_FREE(bat->bat_srv_hash, LST_NODE_HASHSIZE);
883 LIBCFS_FREE(bat->bat_cli_hash, LST_NODE_HASHSIZE);
884 LIBCFS_FREE(bat, sizeof(*bat));
887 strncpy(bat->bat_name, name, sizeof(bat->bat_name));
888 bat->bat_hdr.tsb_index = 0;
889 bat->bat_hdr.tsb_id.bat_id = ++console_session.ses_id_cookie;
892 bat->bat_state = LST_BATCH_IDLE;
894 INIT_LIST_HEAD(&bat->bat_cli_list);
895 INIT_LIST_HEAD(&bat->bat_srv_list);
896 INIT_LIST_HEAD(&bat->bat_test_list);
897 INIT_LIST_HEAD(&bat->bat_trans_list);
899 for (i = 0; i < LST_NODE_HASHSIZE; i++) {
900 INIT_LIST_HEAD(&bat->bat_cli_hash[i]);
901 INIT_LIST_HEAD(&bat->bat_srv_hash[i]);
904 list_add_tail(&bat->bat_link, &console_session.ses_bat_list);
910 lstcon_batch_list(int index, int len, char __user *name_up)
912 struct lstcon_batch *bat;
914 LASSERT(name_up != NULL);
917 list_for_each_entry(bat, &console_session.ses_bat_list, bat_link) {
919 return copy_to_user(name_up, bat->bat_name, len) ?
928 lstcon_batch_info(char *name, struct lstcon_test_batch_ent __user *ent_up,
929 int server, int testidx, int *index_p, int *ndent_p,
930 struct lstcon_node_ent __user *dents_up)
932 struct lstcon_test_batch_ent *entp;
933 struct list_head *clilst;
934 struct list_head *srvlst;
935 struct lstcon_test *test = NULL;
936 struct lstcon_batch *bat;
937 struct lstcon_ndlink *ndl;
940 rc = lstcon_batch_find(name, &bat);
942 CDEBUG(D_NET, "Can't find batch %s\n", name);
947 /* query test, test index start from 1 */
948 list_for_each_entry(test, &bat->bat_test_list, tes_link) {
954 CDEBUG(D_NET, "Can't find specified test in batch\n");
959 clilst = (test == NULL) ? &bat->bat_cli_list :
960 &test->tes_src_grp->grp_ndl_list;
961 srvlst = (test == NULL) ? &bat->bat_srv_list :
962 &test->tes_dst_grp->grp_ndl_list;
964 if (dents_up != NULL) {
965 rc = lstcon_nodes_getent((server ? srvlst: clilst),
966 index_p, ndent_p, dents_up);
970 /* non-verbose query */
971 LIBCFS_ALLOC(entp, sizeof(struct lstcon_test_batch_ent));
976 entp->u.tbe_batch.bae_ntest = bat->bat_ntest;
977 entp->u.tbe_batch.bae_state = bat->bat_state;
981 entp->u.tbe_test.tse_type = test->tes_type;
982 entp->u.tbe_test.tse_loop = test->tes_loop;
983 entp->u.tbe_test.tse_concur = test->tes_concur;
986 list_for_each_entry(ndl, clilst, ndl_link)
987 LST_NODE_STATE_COUNTER(ndl->ndl_node, &entp->tbe_cli_nle);
989 list_for_each_entry(ndl, srvlst, ndl_link)
990 LST_NODE_STATE_COUNTER(ndl->ndl_node, &entp->tbe_srv_nle);
992 rc = copy_to_user(ent_up, entp,
993 sizeof(struct lstcon_test_batch_ent)) ? -EFAULT : 0;
995 LIBCFS_FREE(entp, sizeof(struct lstcon_test_batch_ent));
1001 lstcon_batrpc_condition(int transop, struct lstcon_node *nd, void *arg)
1004 case LST_TRANS_TSBRUN:
1005 if (nd->nd_state != LST_NODE_ACTIVE)
1009 case LST_TRANS_TSBSTOP:
1010 if (nd->nd_state != LST_NODE_ACTIVE)
1014 case LST_TRANS_TSBCLIQRY:
1015 case LST_TRANS_TSBSRVQRY:
1023 lstcon_batch_op(struct lstcon_batch *bat, int transop,
1024 struct list_head __user *result_up)
1026 struct lstcon_rpc_trans *trans;
1029 rc = lstcon_rpc_trans_ndlist(&bat->bat_cli_list,
1030 &bat->bat_trans_list, transop,
1031 bat, lstcon_batrpc_condition, &trans);
1033 CERROR("Can't create transaction: %d\n", rc);
1037 lstcon_rpc_trans_postwait(trans, LST_TRANS_TIMEOUT);
1039 rc = lstcon_rpc_trans_interpreter(trans, result_up, NULL);
1041 lstcon_rpc_trans_destroy(trans);
1047 lstcon_batch_run(char *name, int timeout, struct list_head __user *result_up)
1049 struct lstcon_batch *bat;
1052 if (lstcon_batch_find(name, &bat) != 0) {
1053 CDEBUG(D_NET, "Can't find batch %s\n", name);
1057 bat->bat_arg = timeout;
1059 rc = lstcon_batch_op(bat, LST_TRANS_TSBRUN, result_up);
1061 /* mark batch as running if it's started in any node */
1062 if (lstcon_tsbop_stat_success(lstcon_trans_stat(), 0) != 0)
1063 bat->bat_state = LST_BATCH_RUNNING;
1069 lstcon_batch_stop(char *name, int force, struct list_head __user *result_up)
1071 struct lstcon_batch *bat;
1074 if (lstcon_batch_find(name, &bat) != 0) {
1075 CDEBUG(D_NET, "Can't find batch %s\n", name);
1079 bat->bat_arg = force;
1081 rc = lstcon_batch_op(bat, LST_TRANS_TSBSTOP, result_up);
1083 /* mark batch as stopped if all RPCs finished */
1084 if (lstcon_tsbop_stat_failure(lstcon_trans_stat(), 0) == 0)
1085 bat->bat_state = LST_BATCH_IDLE;
1091 lstcon_batch_destroy(struct lstcon_batch *bat)
1093 struct lstcon_ndlink *ndl;
1094 struct lstcon_test *test;
1097 list_del(&bat->bat_link);
1099 while (!list_empty(&bat->bat_test_list)) {
1100 test = list_entry(bat->bat_test_list.next,
1101 struct lstcon_test, tes_link);
1102 LASSERT(list_empty(&test->tes_trans_list));
1104 list_del(&test->tes_link);
1106 lstcon_group_decref(test->tes_src_grp);
1107 lstcon_group_decref(test->tes_dst_grp);
1109 LIBCFS_FREE(test, offsetof(struct lstcon_test,
1110 tes_param[test->tes_paramlen]));
1113 LASSERT(list_empty(&bat->bat_trans_list));
1115 while (!list_empty(&bat->bat_cli_list)) {
1116 ndl = list_entry(bat->bat_cli_list.next,
1117 struct lstcon_ndlink, ndl_link);
1118 list_del_init(&ndl->ndl_link);
1120 lstcon_ndlink_release(ndl);
1123 while (!list_empty(&bat->bat_srv_list)) {
1124 ndl = list_entry(bat->bat_srv_list.next,
1125 struct lstcon_ndlink, ndl_link);
1126 list_del_init(&ndl->ndl_link);
1128 lstcon_ndlink_release(ndl);
1131 for (i = 0; i < LST_NODE_HASHSIZE; i++) {
1132 LASSERT(list_empty(&bat->bat_cli_hash[i]));
1133 LASSERT(list_empty(&bat->bat_srv_hash[i]));
1136 LIBCFS_FREE(bat->bat_cli_hash,
1137 sizeof(struct list_head) * LST_NODE_HASHSIZE);
1138 LIBCFS_FREE(bat->bat_srv_hash,
1139 sizeof(struct list_head) * LST_NODE_HASHSIZE);
1140 LIBCFS_FREE(bat, sizeof(*bat));
1144 lstcon_testrpc_condition(int transop, struct lstcon_node *nd, void *arg)
1146 struct lstcon_test *test = arg;
1147 struct lstcon_batch *batch;
1148 struct lstcon_ndlink *ndl;
1149 struct list_head *hash;
1150 struct list_head *head;
1152 LASSERT(test != NULL);
1154 batch = test->tes_batch;
1155 LASSERT(batch != NULL);
1157 if (test->tes_oneside &&
1158 transop == LST_TRANS_TSBSRVADD)
1161 if (nd->nd_state != LST_NODE_ACTIVE)
1164 if (transop == LST_TRANS_TSBCLIADD) {
1165 hash = batch->bat_cli_hash;
1166 head = &batch->bat_cli_list;
1169 LASSERT (transop == LST_TRANS_TSBSRVADD);
1171 hash = batch->bat_srv_hash;
1172 head = &batch->bat_srv_list;
1175 LASSERT (nd->nd_id.nid != LNET_NID_ANY);
1177 if (lstcon_ndlink_find(hash, nd->nd_id, &ndl, 1) != 0)
1180 if (list_empty(&ndl->ndl_link))
1181 list_add_tail(&ndl->ndl_link, head);
1187 lstcon_test_nodes_add(struct lstcon_test *test,
1188 struct list_head __user *result_up)
1190 struct lstcon_rpc_trans *trans;
1191 struct lstcon_group *grp;
1195 LASSERT (test->tes_src_grp != NULL);
1196 LASSERT (test->tes_dst_grp != NULL);
1198 transop = LST_TRANS_TSBSRVADD;
1199 grp = test->tes_dst_grp;
1201 rc = lstcon_rpc_trans_ndlist(&grp->grp_ndl_list,
1202 &test->tes_trans_list, transop,
1203 test, lstcon_testrpc_condition, &trans);
1205 CERROR("Can't create transaction: %d\n", rc);
1209 lstcon_rpc_trans_postwait(trans, LST_TRANS_TIMEOUT);
1211 if (lstcon_trans_stat()->trs_rpc_errno != 0 ||
1212 lstcon_trans_stat()->trs_fwk_errno != 0) {
1213 lstcon_rpc_trans_interpreter(trans, result_up, NULL);
1215 lstcon_rpc_trans_destroy(trans);
1216 /* return if any error */
1217 CDEBUG(D_NET, "Failed to add test %s, "
1218 "RPC error %d, framework error %d\n",
1219 transop == LST_TRANS_TSBCLIADD ? "client" : "server",
1220 lstcon_trans_stat()->trs_rpc_errno,
1221 lstcon_trans_stat()->trs_fwk_errno);
1226 lstcon_rpc_trans_destroy(trans);
1228 if (transop == LST_TRANS_TSBCLIADD)
1231 transop = LST_TRANS_TSBCLIADD;
1232 grp = test->tes_src_grp;
1233 test->tes_cliidx = 0;
1235 /* requests to test clients */
1240 lstcon_verify_batch(const char *name, struct lstcon_batch **batch)
1244 rc = lstcon_batch_find(name, batch);
1246 CDEBUG(D_NET, "Can't find batch %s\n", name);
1250 if ((*batch)->bat_state != LST_BATCH_IDLE) {
1251 CDEBUG(D_NET, "Can't change running batch %s\n", name);
1259 lstcon_verify_group(const char *name, struct lstcon_group **grp)
1262 struct lstcon_ndlink *ndl;
1264 rc = lstcon_group_find(name, grp);
1266 CDEBUG(D_NET, "can't find group %s\n", name);
1270 list_for_each_entry(ndl, &(*grp)->grp_ndl_list, ndl_link) {
1271 if (ndl->ndl_node->nd_state == LST_NODE_ACTIVE) {
1276 CDEBUG(D_NET, "Group %s has no ACTIVE nodes\n", name);
1282 lstcon_test_add(char *batch_name, int type, int loop,
1283 int concur, int dist, int span,
1284 char *src_name, char *dst_name,
1285 void *param, int paramlen, int *retp,
1286 struct list_head __user *result_up)
1288 struct lstcon_test *test = NULL;
1290 struct lstcon_group *src_grp = NULL;
1291 struct lstcon_group *dst_grp = NULL;
1292 struct lstcon_batch *batch = NULL;
1295 * verify that a batch of the given name exists, and the groups
1296 * that will be part of the batch exist and have at least one
1299 rc = lstcon_verify_batch(batch_name, &batch);
1303 rc = lstcon_verify_group(src_name, &src_grp);
1307 rc = lstcon_verify_group(dst_name, &dst_grp);
1311 if (dst_grp->grp_userland)
1314 LIBCFS_ALLOC(test, offsetof(struct lstcon_test, tes_param[paramlen]));
1316 CERROR("Can't allocate test descriptor\n");
1322 test->tes_hdr.tsb_id = batch->bat_hdr.tsb_id;
1323 test->tes_batch = batch;
1324 test->tes_type = type;
1325 test->tes_oneside = 0; /* TODO */
1326 test->tes_loop = loop;
1327 test->tes_concur = concur;
1328 test->tes_stop_onerr = 1; /* TODO */
1329 test->tes_span = span;
1330 test->tes_dist = dist;
1331 test->tes_cliidx = 0; /* just used for creating RPC */
1332 test->tes_src_grp = src_grp;
1333 test->tes_dst_grp = dst_grp;
1334 INIT_LIST_HEAD(&test->tes_trans_list);
1336 if (param != NULL) {
1337 test->tes_paramlen = paramlen;
1338 memcpy(&test->tes_param[0], param, paramlen);
1341 rc = lstcon_test_nodes_add(test, result_up);
1346 if (lstcon_trans_stat()->trs_rpc_errno != 0 ||
1347 lstcon_trans_stat()->trs_fwk_errno != 0)
1348 CDEBUG(D_NET, "Failed to add test %d to batch %s\n", type,
1351 /* add to test list anyway, so user can check what's going on */
1352 list_add_tail(&test->tes_link, &batch->bat_test_list);
1355 test->tes_hdr.tsb_index = batch->bat_ntest;
1357 /* hold groups so nobody can change them */
1361 LIBCFS_FREE(test, offsetof(struct lstcon_test,
1362 tes_param[paramlen]));
1364 if (dst_grp != NULL)
1365 lstcon_group_decref(dst_grp);
1367 if (src_grp != NULL)
1368 lstcon_group_decref(src_grp);
1374 lstcon_test_find(struct lstcon_batch *batch, int idx,
1375 struct lstcon_test **testpp)
1377 struct lstcon_test *test;
1379 list_for_each_entry(test, &batch->bat_test_list, tes_link) {
1380 if (idx == test->tes_hdr.tsb_index) {
1390 lstcon_tsbrpc_readent(int transop, struct srpc_msg *msg,
1391 struct lstcon_rpc_ent __user *ent_up)
1393 struct srpc_batch_reply *rep = &msg->msg_body.bat_reply;
1395 LASSERT (transop == LST_TRANS_TSBCLIQRY ||
1396 transop == LST_TRANS_TSBSRVQRY);
1398 /* positive errno, framework error code */
1399 if (copy_to_user(&ent_up->rpe_priv[0],
1400 &rep->bar_active, sizeof(rep->bar_active)))
1407 lstcon_test_batch_query(char *name, int testidx, int client,
1408 int timeout, struct list_head __user *result_up)
1410 struct lstcon_rpc_trans *trans;
1411 struct list_head *translist;
1412 struct list_head *ndlist;
1413 struct lstcon_tsb_hdr *hdr;
1414 struct lstcon_batch *batch;
1415 struct lstcon_test *test = NULL;
1419 rc = lstcon_batch_find(name, &batch);
1421 CDEBUG(D_NET, "Can't find batch: %s\n", name);
1426 translist = &batch->bat_trans_list;
1427 ndlist = &batch->bat_cli_list;
1428 hdr = &batch->bat_hdr;
1431 /* query specified test only */
1432 rc = lstcon_test_find(batch, testidx, &test);
1434 CDEBUG(D_NET, "Can't find test: %d\n", testidx);
1438 translist = &test->tes_trans_list;
1439 ndlist = &test->tes_src_grp->grp_ndl_list;
1440 hdr = &test->tes_hdr;
1443 transop = client ? LST_TRANS_TSBCLIQRY : LST_TRANS_TSBSRVQRY;
1445 rc = lstcon_rpc_trans_ndlist(ndlist, translist, transop, hdr,
1446 lstcon_batrpc_condition, &trans);
1448 CERROR("Can't create transaction: %d\n", rc);
1452 lstcon_rpc_trans_postwait(trans, timeout);
1454 if (testidx == 0 && /* query a batch, not a test */
1455 lstcon_rpc_stat_failure(lstcon_trans_stat(), 0) == 0 &&
1456 lstcon_tsbqry_stat_run(lstcon_trans_stat(), 0) == 0) {
1457 /* all RPCs finished, and no active test */
1458 batch->bat_state = LST_BATCH_IDLE;
1461 rc = lstcon_rpc_trans_interpreter(trans, result_up,
1462 lstcon_tsbrpc_readent);
1463 lstcon_rpc_trans_destroy(trans);
1469 lstcon_statrpc_readent(int transop, struct srpc_msg *msg,
1470 struct lstcon_rpc_ent __user *ent_up)
1472 struct srpc_stat_reply *rep = &msg->msg_body.stat_reply;
1473 struct sfw_counters __user *sfwk_stat;
1474 struct srpc_counters __user *srpc_stat;
1475 struct lnet_counters __user *lnet_stat;
1477 if (rep->str_status != 0)
1480 sfwk_stat = (struct sfw_counters __user *)&ent_up->rpe_payload[0];
1481 srpc_stat = (struct srpc_counters __user *)
1482 ((char __user *)sfwk_stat + sizeof(*sfwk_stat));
1483 lnet_stat = (struct lnet_counters __user *)
1484 ((char __user *)srpc_stat + sizeof(*srpc_stat));
1486 if (copy_to_user(sfwk_stat, &rep->str_fw, sizeof(*sfwk_stat)) ||
1487 copy_to_user(srpc_stat, &rep->str_rpc, sizeof(*srpc_stat)) ||
1488 copy_to_user(lnet_stat, &rep->str_lnet, sizeof(*lnet_stat)))
1495 lstcon_ndlist_stat(struct list_head *ndlist,
1496 int timeout, struct list_head __user *result_up)
1498 struct list_head head;
1499 struct lstcon_rpc_trans *trans;
1502 INIT_LIST_HEAD(&head);
1504 rc = lstcon_rpc_trans_ndlist(ndlist, &head,
1505 LST_TRANS_STATQRY, NULL, NULL, &trans);
1507 CERROR("Can't create transaction: %d\n", rc);
1511 lstcon_rpc_trans_postwait(trans, LST_VALIDATE_TIMEOUT(timeout));
1513 rc = lstcon_rpc_trans_interpreter(trans, result_up,
1514 lstcon_statrpc_readent);
1515 lstcon_rpc_trans_destroy(trans);
1521 lstcon_group_stat(char *grp_name, int timeout,
1522 struct list_head __user *result_up)
1524 struct lstcon_group *grp;
1527 rc = lstcon_group_find(grp_name, &grp);
1529 CDEBUG(D_NET, "Can't find group %s\n", grp_name);
1533 rc = lstcon_ndlist_stat(&grp->grp_ndl_list, timeout, result_up);
1535 lstcon_group_decref(grp);
1541 lstcon_nodes_stat(int count, struct lnet_process_id __user *ids_up,
1542 int timeout, struct list_head __user *result_up)
1544 struct lstcon_ndlink *ndl;
1545 struct lstcon_group *tmp;
1546 struct lnet_process_id id;
1550 rc = lstcon_group_alloc(NULL, &tmp);
1552 CERROR("Out of memory\n");
1556 for (i = 0 ; i < count; i++) {
1557 if (copy_from_user(&id, &ids_up[i], sizeof(id))) {
1562 /* add to tmp group */
1563 rc = lstcon_group_ndlink_find(tmp, id, &ndl, 2);
1565 CDEBUG((rc == -ENOMEM) ? D_ERROR : D_NET,
1566 "Failed to find or create %s: %d\n",
1567 libcfs_id2str(id), rc);
1573 lstcon_group_decref(tmp);
1577 rc = lstcon_ndlist_stat(&tmp->grp_ndl_list, timeout, result_up);
1579 lstcon_group_decref(tmp);
1585 lstcon_debug_ndlist(struct list_head *ndlist,
1586 struct list_head *translist,
1587 int timeout, struct list_head __user *result_up)
1589 struct lstcon_rpc_trans *trans;
1592 rc = lstcon_rpc_trans_ndlist(ndlist, translist, LST_TRANS_SESQRY,
1593 NULL, lstcon_sesrpc_condition, &trans);
1595 CERROR("Can't create transaction: %d\n", rc);
1599 lstcon_rpc_trans_postwait(trans, LST_VALIDATE_TIMEOUT(timeout));
1601 rc = lstcon_rpc_trans_interpreter(trans, result_up,
1602 lstcon_sesrpc_readent);
1603 lstcon_rpc_trans_destroy(trans);
1609 lstcon_session_debug(int timeout, struct list_head __user *result_up)
1611 return lstcon_debug_ndlist(&console_session.ses_ndl_list,
1612 NULL, timeout, result_up);
1616 lstcon_batch_debug(int timeout, char *name,
1617 int client, struct list_head __user *result_up)
1619 struct lstcon_batch *bat;
1622 rc = lstcon_batch_find(name, &bat);
1626 rc = lstcon_debug_ndlist(client ? &bat->bat_cli_list :
1628 NULL, timeout, result_up);
1634 lstcon_group_debug(int timeout, char *name,
1635 struct list_head __user *result_up)
1637 struct lstcon_group *grp;
1640 rc = lstcon_group_find(name, &grp);
1644 rc = lstcon_debug_ndlist(&grp->grp_ndl_list, NULL,
1645 timeout, result_up);
1646 lstcon_group_decref(grp);
1652 lstcon_nodes_debug(int timeout, int count,
1653 struct lnet_process_id __user *ids_up,
1654 struct list_head __user *result_up)
1656 struct lnet_process_id id;
1657 struct lstcon_ndlink *ndl;
1658 struct lstcon_group *grp;
1662 rc = lstcon_group_alloc(NULL, &grp);
1664 CDEBUG(D_NET, "Out of memory\n");
1668 for (i = 0; i < count; i++) {
1669 if (copy_from_user(&id, &ids_up[i], sizeof(id))) {
1674 /* node is added to tmp group */
1675 rc = lstcon_group_ndlink_find(grp, id, &ndl, 1);
1677 CERROR("Can't create node link\n");
1683 lstcon_group_decref(grp);
1687 rc = lstcon_debug_ndlist(&grp->grp_ndl_list, NULL,
1688 timeout, result_up);
1690 lstcon_group_decref(grp);
1696 lstcon_session_match(struct lst_sid sid)
1698 return (console_session.ses_id.ses_nid == sid.ses_nid &&
1699 console_session.ses_id.ses_stamp == sid.ses_stamp) ? 1: 0;
1703 lstcon_new_session_id(struct lst_sid *sid)
1705 struct lnet_process_id id;
1707 LASSERT(console_session.ses_state == LST_SESSION_NONE);
1710 sid->ses_nid = id.nid;
1711 sid->ses_stamp = ktime_get_ns() / NSEC_PER_MSEC;
1715 lstcon_session_new(char *name, int key, unsigned feats,
1716 int timeout, int force, struct lst_sid __user *sid_up)
1721 if (console_session.ses_state != LST_SESSION_NONE) {
1722 /* session exists */
1724 CNETERR("Session %s already exists\n",
1725 console_session.ses_name);
1729 rc = lstcon_session_end();
1731 /* lstcon_session_end() only return local error */
1736 if ((feats & ~LST_FEATS_MASK) != 0) {
1737 CNETERR("Unknown session features %x\n",
1738 (feats & ~LST_FEATS_MASK));
1742 for (i = 0; i < LST_GLOBAL_HASHSIZE; i++)
1743 LASSERT(list_empty(&console_session.ses_ndl_hash[i]));
1745 lstcon_new_session_id(&console_session.ses_id);
1747 console_session.ses_key = key;
1748 console_session.ses_state = LST_SESSION_ACTIVE;
1749 console_session.ses_force = !!force;
1750 console_session.ses_features = feats;
1751 console_session.ses_feats_updated = 0;
1752 console_session.ses_timeout = (timeout <= 0) ?
1753 LST_CONSOLE_TIMEOUT : timeout;
1755 if (strlen(name) > sizeof(console_session.ses_name)-1)
1757 strlcpy(console_session.ses_name, name,
1758 sizeof(console_session.ses_name));
1760 rc = lstcon_batch_add(LST_DEFAULT_BATCH);
1764 rc = lstcon_rpc_pinger_start();
1766 struct lstcon_batch *bat = NULL;
1768 lstcon_batch_find(LST_DEFAULT_BATCH, &bat);
1769 lstcon_batch_destroy(bat);
1774 if (copy_to_user(sid_up, &console_session.ses_id,
1775 sizeof(struct lst_sid)) == 0)
1778 lstcon_session_end();
1784 lstcon_session_info(struct lst_sid __user *sid_up, int __user *key_up,
1785 unsigned __user *featp,
1786 struct lstcon_ndlist_ent __user *ndinfo_up,
1787 char __user *name_up, int len)
1789 struct lstcon_ndlist_ent *entp;
1790 struct lstcon_ndlink *ndl;
1793 if (console_session.ses_state != LST_SESSION_ACTIVE)
1796 LIBCFS_ALLOC(entp, sizeof(*entp));
1800 list_for_each_entry(ndl, &console_session.ses_ndl_list, ndl_link)
1801 LST_NODE_STATE_COUNTER(ndl->ndl_node, entp);
1803 if (copy_to_user(sid_up, &console_session.ses_id,
1804 sizeof(struct lst_sid)) ||
1805 copy_to_user(key_up, &console_session.ses_key,
1807 copy_to_user(featp, &console_session.ses_features,
1809 copy_to_user(ndinfo_up, entp, sizeof(*entp)) ||
1810 copy_to_user(name_up, console_session.ses_name, len))
1813 LIBCFS_FREE(entp, sizeof(*entp));
1819 lstcon_session_end()
1821 struct lstcon_rpc_trans *trans;
1822 struct lstcon_group *grp;
1823 struct lstcon_batch *bat;
1826 LASSERT (console_session.ses_state == LST_SESSION_ACTIVE);
1828 rc = lstcon_rpc_trans_ndlist(&console_session.ses_ndl_list,
1829 NULL, LST_TRANS_SESEND, NULL,
1830 lstcon_sesrpc_condition, &trans);
1832 CERROR("Can't create transaction: %d\n", rc);
1836 console_session.ses_shutdown = 1;
1838 lstcon_rpc_pinger_stop();
1840 lstcon_rpc_trans_postwait(trans, LST_TRANS_TIMEOUT);
1842 lstcon_rpc_trans_destroy(trans);
1843 /* User can do nothing even rpc failed, so go on */
1845 /* waiting for orphan rpcs to die */
1846 lstcon_rpc_cleanup_wait();
1848 console_session.ses_id = LST_INVALID_SID;
1849 console_session.ses_state = LST_SESSION_NONE;
1850 console_session.ses_key = 0;
1851 console_session.ses_force = 0;
1852 console_session.ses_feats_updated = 0;
1854 /* destroy all batches */
1855 while (!list_empty(&console_session.ses_bat_list)) {
1856 bat = list_entry(console_session.ses_bat_list.next,
1857 struct lstcon_batch, bat_link);
1859 lstcon_batch_destroy(bat);
1862 /* destroy all groups */
1863 while (!list_empty(&console_session.ses_grp_list)) {
1864 grp = list_entry(console_session.ses_grp_list.next,
1865 struct lstcon_group, grp_link);
1866 LASSERT(grp->grp_ref == 1);
1868 lstcon_group_decref(grp);
1871 /* all nodes should be released */
1872 LASSERT(list_empty(&console_session.ses_ndl_list));
1874 console_session.ses_shutdown = 0;
1875 console_session.ses_expired = 0;
1881 lstcon_session_feats_check(unsigned feats)
1885 if ((feats & ~LST_FEATS_MASK) != 0) {
1886 CERROR("Can't support these features: %x\n",
1887 (feats & ~LST_FEATS_MASK));
1891 spin_lock(&console_session.ses_rpc_lock);
1893 if (!console_session.ses_feats_updated) {
1894 console_session.ses_feats_updated = 1;
1895 console_session.ses_features = feats;
1898 if (console_session.ses_features != feats)
1901 spin_unlock(&console_session.ses_rpc_lock);
1904 CERROR("remote features %x do not match with "
1905 "session features %x of console\n",
1906 feats, console_session.ses_features);
1913 lstcon_acceptor_handle(struct srpc_server_rpc *rpc)
1915 struct srpc_msg *rep = &rpc->srpc_replymsg;
1916 struct srpc_msg *req = &rpc->srpc_reqstbuf->buf_msg;
1917 struct srpc_join_reqst *jreq = &req->msg_body.join_reqst;
1918 struct srpc_join_reply *jrep = &rep->msg_body.join_reply;
1919 struct lstcon_group *grp = NULL;
1920 struct lstcon_ndlink *ndl;
1923 sfw_unpack_message(req);
1925 mutex_lock(&console_session.ses_mutex);
1927 jrep->join_sid = console_session.ses_id;
1929 if (console_session.ses_id.ses_nid == LNET_NID_ANY) {
1930 jrep->join_status = ESRCH;
1934 if (lstcon_session_feats_check(req->msg_ses_feats) != 0) {
1935 jrep->join_status = EPROTO;
1939 if (jreq->join_sid.ses_nid != LNET_NID_ANY &&
1940 !lstcon_session_match(jreq->join_sid)) {
1941 jrep->join_status = EBUSY;
1945 if (lstcon_group_find(jreq->join_group, &grp) != 0) {
1946 rc = lstcon_group_alloc(jreq->join_group, &grp);
1948 CERROR("Out of memory\n");
1952 list_add_tail(&grp->grp_link,
1953 &console_session.ses_grp_list);
1954 lstcon_group_addref(grp);
1957 if (grp->grp_ref > 2) {
1958 /* Group in using */
1959 jrep->join_status = EBUSY;
1963 rc = lstcon_group_ndlink_find(grp, rpc->srpc_peer, &ndl, 0);
1965 jrep->join_status = EEXIST;
1969 rc = lstcon_group_ndlink_find(grp, rpc->srpc_peer, &ndl, 1);
1971 CERROR("Out of memory\n");
1975 ndl->ndl_node->nd_state = LST_NODE_ACTIVE;
1976 ndl->ndl_node->nd_timeout = console_session.ses_timeout;
1978 if (grp->grp_userland == 0)
1979 grp->grp_userland = 1;
1981 strlcpy(jrep->join_session, console_session.ses_name,
1982 sizeof(jrep->join_session));
1983 jrep->join_timeout = console_session.ses_timeout;
1984 jrep->join_status = 0;
1987 rep->msg_ses_feats = console_session.ses_features;
1989 lstcon_group_decref(grp);
1991 mutex_unlock(&console_session.ses_mutex);
1996 static struct srpc_service lstcon_acceptor_service;
1998 static void lstcon_init_acceptor_service(void)
2000 /* initialize selftest console acceptor service table */
2001 lstcon_acceptor_service.sv_name = "join session";
2002 lstcon_acceptor_service.sv_handler = lstcon_acceptor_handle;
2003 lstcon_acceptor_service.sv_id = SRPC_SERVICE_JOIN;
2004 lstcon_acceptor_service.sv_wi_total = SFW_FRWK_WI_MAX;
2007 int lstcon_ioctl_entry(unsigned int cmd, struct libcfs_ioctl_hdr *hdr);
2009 DECLARE_IOCTL_HANDLER(lstcon_ioctl_handler, lstcon_ioctl_entry);
2011 /* initialize console */
2013 lstcon_console_init(void)
2018 console_session.ses_id = LST_INVALID_SID;
2019 console_session.ses_state = LST_SESSION_NONE;
2020 console_session.ses_timeout = 0;
2021 console_session.ses_force = 0;
2022 console_session.ses_expired = 0;
2023 console_session.ses_feats_updated = 0;
2024 console_session.ses_features = LST_FEATS_MASK;
2025 console_session.ses_laststamp = ktime_get_real_seconds();
2027 mutex_init(&console_session.ses_mutex);
2029 INIT_LIST_HEAD(&console_session.ses_ndl_list);
2030 INIT_LIST_HEAD(&console_session.ses_grp_list);
2031 INIT_LIST_HEAD(&console_session.ses_bat_list);
2032 INIT_LIST_HEAD(&console_session.ses_trans_list);
2034 LIBCFS_ALLOC(console_session.ses_ndl_hash,
2035 sizeof(struct list_head) * LST_GLOBAL_HASHSIZE);
2036 if (console_session.ses_ndl_hash == NULL)
2039 for (i = 0; i < LST_GLOBAL_HASHSIZE; i++)
2040 INIT_LIST_HEAD(&console_session.ses_ndl_hash[i]);
2043 /* initialize acceptor service table */
2044 lstcon_init_acceptor_service();
2046 rc = srpc_add_service(&lstcon_acceptor_service);
2047 LASSERT(rc != -EBUSY);
2049 LIBCFS_FREE(console_session.ses_ndl_hash,
2050 sizeof(struct list_head) * LST_GLOBAL_HASHSIZE);
2054 rc = srpc_service_add_buffers(&lstcon_acceptor_service,
2055 lstcon_acceptor_service.sv_wi_total);
2061 rc = libcfs_register_ioctl(&lstcon_ioctl_handler);
2064 lstcon_rpc_module_init();
2069 srpc_shutdown_service(&lstcon_acceptor_service);
2070 srpc_remove_service(&lstcon_acceptor_service);
2072 LIBCFS_FREE(console_session.ses_ndl_hash,
2073 sizeof(struct list_head) * LST_GLOBAL_HASHSIZE);
2075 srpc_wait_service_shutdown(&lstcon_acceptor_service);
2081 lstcon_console_fini(void)
2085 libcfs_deregister_ioctl(&lstcon_ioctl_handler);
2087 mutex_lock(&console_session.ses_mutex);
2089 srpc_shutdown_service(&lstcon_acceptor_service);
2090 srpc_remove_service(&lstcon_acceptor_service);
2092 if (console_session.ses_state != LST_SESSION_NONE)
2093 lstcon_session_end();
2095 lstcon_rpc_module_fini();
2097 mutex_unlock(&console_session.ses_mutex);
2099 LASSERT(list_empty(&console_session.ses_ndl_list));
2100 LASSERT(list_empty(&console_session.ses_grp_list));
2101 LASSERT(list_empty(&console_session.ses_bat_list));
2102 LASSERT(list_empty(&console_session.ses_trans_list));
2104 for (i = 0; i < LST_NODE_HASHSIZE; i++)
2105 LASSERT(list_empty(&console_session.ses_ndl_hash[i]));
2107 LIBCFS_FREE(console_session.ses_ndl_hash,
2108 sizeof(struct list_head) * LST_GLOBAL_HASHSIZE);
2110 srpc_wait_service_shutdown(&lstcon_acceptor_service);