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>
40 #include <libcfs/libcfs.h>
41 #include <lnet/lib-lnet.h>
45 #define LST_NODE_STATE_COUNTER(nd, p) \
47 if ((nd)->nd_state == LST_NODE_ACTIVE) \
48 (p)->nle_nactive ++; \
49 else if ((nd)->nd_state == LST_NODE_BUSY) \
51 else if ((nd)->nd_state == LST_NODE_DOWN) \
54 (p)->nle_nunknown ++; \
58 struct lstcon_session console_session;
61 lstcon_node_get(struct lstcon_node *nd)
63 LASSERT (nd->nd_ref >= 1);
69 lstcon_node_find(struct lnet_process_id id, struct lstcon_node **ndpp,
72 struct lstcon_ndlink *ndl;
73 unsigned int idx = LNET_NIDADDR(id.nid) % LST_GLOBAL_HASHSIZE;
75 LASSERT(id.nid != LNET_NID_ANY);
77 list_for_each_entry(ndl, &console_session.ses_ndl_hash[idx],
79 if (ndl->ndl_node->nd_id.nid != id.nid ||
80 ndl->ndl_node->nd_id.pid != id.pid)
83 lstcon_node_get(ndl->ndl_node);
84 *ndpp = ndl->ndl_node;
91 LIBCFS_ALLOC(*ndpp, sizeof(**ndpp) + sizeof(*ndl));
95 ndl = (struct lstcon_ndlink *)(*ndpp + 1);
97 ndl->ndl_node = *ndpp;
99 ndl->ndl_node->nd_ref = 1;
100 ndl->ndl_node->nd_id = id;
101 ndl->ndl_node->nd_stamp = cfs_time_current();
102 ndl->ndl_node->nd_state = LST_NODE_UNKNOWN;
103 ndl->ndl_node->nd_timeout = 0;
104 memset(&ndl->ndl_node->nd_ping, 0, sizeof(ndl->ndl_node->nd_ping));
106 /* queued in global hash & list, no refcount is taken by
107 * global hash & list, if caller release his refcount,
108 * 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(*nd) + sizeof(*ndl));
138 lstcon_ndlink_find(struct list_head *hash, struct lnet_process_id id,
139 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(*ndl));
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 *,
234 struct lstcon_ndlink *);
237 lstcon_group_drain(struct lstcon_group *grp, int keep)
239 struct lstcon_ndlink *ndl;
240 struct lstcon_ndlink *tmp;
242 list_for_each_entry_safe(ndl, tmp, &grp->grp_ndl_list, ndl_link) {
243 if ((ndl->ndl_node->nd_state & keep) == 0)
244 lstcon_group_ndlink_release(grp, ndl);
249 lstcon_group_decref(struct lstcon_group *grp)
253 if (--grp->grp_ref > 0)
256 if (!list_empty(&grp->grp_link))
257 list_del(&grp->grp_link);
259 lstcon_group_drain(grp, 0);
261 for (i = 0; i < LST_NODE_HASHSIZE; i++)
262 LASSERT(list_empty(&grp->grp_ndl_hash[i]));
264 LIBCFS_FREE(grp, offsetof(struct lstcon_group,
265 grp_ndl_hash[LST_NODE_HASHSIZE]));
269 lstcon_group_find(const char *name, struct lstcon_group **grpp)
271 struct lstcon_group *grp;
273 list_for_each_entry(grp, &console_session.ses_grp_list, grp_link) {
274 if (strncmp(grp->grp_name, name, LST_NAME_SIZE) != 0)
277 lstcon_group_addref(grp); /* +1 ref for caller */
286 lstcon_group_ndlink_find(struct lstcon_group *grp, struct lnet_process_id id,
287 struct lstcon_ndlink **ndlpp, int create)
291 rc = lstcon_ndlink_find(&grp->grp_ndl_hash[0], id, ndlpp, create);
295 if (!list_empty(&(*ndlpp)->ndl_link))
298 list_add_tail(&(*ndlpp)->ndl_link, &grp->grp_ndl_list);
305 lstcon_group_ndlink_release(struct lstcon_group *grp, struct lstcon_ndlink *ndl)
307 list_del_init(&ndl->ndl_link);
308 lstcon_ndlink_release(ndl);
313 lstcon_group_ndlink_move(struct lstcon_group *old,
314 struct lstcon_group *new, struct lstcon_ndlink *ndl)
316 unsigned int idx = LNET_NIDADDR(ndl->ndl_node->nd_id.nid) %
319 list_del(&ndl->ndl_hlink);
320 list_del(&ndl->ndl_link);
323 list_add_tail(&ndl->ndl_hlink, &new->grp_ndl_hash[idx]);
324 list_add_tail(&ndl->ndl_link, &new->grp_ndl_list);
331 lstcon_group_move(struct lstcon_group *old, struct lstcon_group *new)
333 struct lstcon_ndlink *ndl;
335 while (!list_empty(&old->grp_ndl_list)) {
336 ndl = list_entry(old->grp_ndl_list.next,
337 struct lstcon_ndlink, ndl_link);
338 lstcon_group_ndlink_move(old, new, ndl);
343 lstcon_sesrpc_condition(int transop, struct lstcon_node *nd, void *arg)
345 struct lstcon_group *grp = arg;
348 case LST_TRANS_SESNEW:
349 if (nd->nd_state == LST_NODE_ACTIVE)
353 case LST_TRANS_SESEND:
354 if (nd->nd_state != LST_NODE_ACTIVE)
357 if (grp != NULL && nd->nd_ref > 1)
361 case LST_TRANS_SESQRY:
372 lstcon_sesrpc_readent(int transop, struct srpc_msg *msg,
373 struct lstcon_rpc_ent __user *ent_up)
375 struct srpc_debug_reply *rep;
378 case LST_TRANS_SESNEW:
379 case LST_TRANS_SESEND:
382 case LST_TRANS_SESQRY:
383 rep = &msg->msg_body.dbg_reply;
385 if (copy_to_user(&ent_up->rpe_priv[0],
386 &rep->dbg_timeout, sizeof(int)) ||
387 copy_to_user(&ent_up->rpe_payload[0],
388 &rep->dbg_name, LST_NAME_SIZE))
401 lstcon_group_nodes_add(struct lstcon_group *grp,
402 int count, struct lnet_process_id __user *ids_up,
404 struct list_head __user *result_up)
406 struct lstcon_rpc_trans *trans;
407 struct lstcon_ndlink *ndl;
408 struct lstcon_group *tmp;
409 struct lnet_process_id id;
413 rc = lstcon_group_alloc(NULL, &tmp);
415 CERROR("Out of memory\n");
419 for (i = 0 ; i < count; i++) {
420 if (copy_from_user(&id, &ids_up[i], sizeof(id))) {
425 /* skip if it's in this group already */
426 rc = lstcon_group_ndlink_find(grp, id, &ndl, 0);
430 /* add to tmp group */
431 rc = lstcon_group_ndlink_find(tmp, id, &ndl, 1);
433 CERROR("Can't create ndlink, out of memory\n");
439 lstcon_group_decref(tmp);
443 rc = lstcon_rpc_trans_ndlist(&tmp->grp_ndl_list,
444 &tmp->grp_trans_list, LST_TRANS_SESNEW,
445 tmp, lstcon_sesrpc_condition, &trans);
447 CERROR("Can't create transaction: %d\n", rc);
448 lstcon_group_decref(tmp);
453 lstcon_rpc_trans_postwait(trans, LST_TRANS_TIMEOUT);
455 rc = lstcon_rpc_trans_interpreter(trans, result_up,
456 lstcon_sesrpc_readent);
457 *featp = trans->tas_features;
459 /* destroy all RPGs */
460 lstcon_rpc_trans_destroy(trans);
462 lstcon_group_move(tmp, grp);
463 lstcon_group_decref(tmp);
469 lstcon_group_nodes_remove(struct lstcon_group *grp,
470 int count, struct lnet_process_id __user *ids_up,
471 struct list_head __user *result_up)
473 struct lstcon_rpc_trans *trans;
474 struct lstcon_ndlink *ndl;
475 struct lstcon_group *tmp;
476 struct lnet_process_id id;
480 /* End session and remove node from the group */
482 rc = lstcon_group_alloc(NULL, &tmp);
484 CERROR("Out of memory\n");
488 for (i = 0; i < count; i++) {
489 if (copy_from_user(&id, &ids_up[i], sizeof(id))) {
494 /* move node to tmp group */
495 if (lstcon_group_ndlink_find(grp, id, &ndl, 0) == 0)
496 lstcon_group_ndlink_move(grp, tmp, ndl);
499 rc = lstcon_rpc_trans_ndlist(&tmp->grp_ndl_list,
500 &tmp->grp_trans_list, LST_TRANS_SESEND,
501 tmp, lstcon_sesrpc_condition, &trans);
503 CERROR("Can't create transaction: %d\n", rc);
507 lstcon_rpc_trans_postwait(trans, LST_TRANS_TIMEOUT);
509 rc = lstcon_rpc_trans_interpreter(trans, result_up, NULL);
511 lstcon_rpc_trans_destroy(trans);
512 /* release nodes anyway, because we can't rollback status */
513 lstcon_group_decref(tmp);
517 lstcon_group_move(tmp, grp);
518 lstcon_group_decref(tmp);
524 lstcon_group_add(char *name)
526 struct lstcon_group *grp;
529 rc = (lstcon_group_find(name, &grp) == 0)? -EEXIST: 0;
531 /* find a group with same name */
532 lstcon_group_decref(grp);
536 rc = lstcon_group_alloc(name, &grp);
538 CERROR("Can't allocate descriptor for group %s\n", name);
542 list_add_tail(&grp->grp_link, &console_session.ses_grp_list);
548 lstcon_nodes_add(char *name, int count, struct lnet_process_id __user *ids_up,
549 unsigned *featp, struct list_head __user *result_up)
551 struct lstcon_group *grp;
555 LASSERT (ids_up != NULL);
557 rc = lstcon_group_find(name, &grp);
559 CDEBUG(D_NET, "Can't find group %s\n", name);
563 if (grp->grp_ref > 2) {
564 /* referred by other threads or test */
565 CDEBUG(D_NET, "Group %s is busy\n", name);
566 lstcon_group_decref(grp);
571 rc = lstcon_group_nodes_add(grp, count, ids_up, featp, result_up);
573 lstcon_group_decref(grp);
579 lstcon_group_del(char *name)
581 struct lstcon_rpc_trans *trans;
582 struct lstcon_group *grp;
585 rc = lstcon_group_find(name, &grp);
587 CDEBUG(D_NET, "Can't find group: %s\n", name);
591 if (grp->grp_ref > 2) {
592 /* referred by others threads or test */
593 CDEBUG(D_NET, "Group %s is busy\n", name);
594 lstcon_group_decref(grp);
598 rc = lstcon_rpc_trans_ndlist(&grp->grp_ndl_list,
599 &grp->grp_trans_list, LST_TRANS_SESEND,
600 grp, lstcon_sesrpc_condition, &trans);
602 CERROR("Can't create transaction: %d\n", rc);
603 lstcon_group_decref(grp);
607 lstcon_rpc_trans_postwait(trans, LST_TRANS_TIMEOUT);
609 lstcon_rpc_trans_destroy(trans);
611 lstcon_group_decref(grp);
612 /* -ref for session, it's destroyed,
613 * status can't be rolled back, destroy group anway */
614 lstcon_group_decref(grp);
620 lstcon_group_clean(char *name, int args)
622 struct lstcon_group *grp = NULL;
625 rc = lstcon_group_find(name, &grp);
627 CDEBUG(D_NET, "Can't find group %s\n", name);
631 if (grp->grp_ref > 2) {
632 /* referred by test */
633 CDEBUG(D_NET, "Group %s is busy\n", name);
634 lstcon_group_decref(grp);
638 args = (LST_NODE_ACTIVE | LST_NODE_BUSY |
639 LST_NODE_DOWN | LST_NODE_UNKNOWN) & ~args;
641 lstcon_group_drain(grp, args);
643 lstcon_group_decref(grp);
644 /* release empty group */
645 if (list_empty(&grp->grp_ndl_list))
646 lstcon_group_decref(grp);
652 lstcon_nodes_remove(char *name, int count,
653 struct lnet_process_id __user *ids_up,
654 struct list_head __user *result_up)
656 struct lstcon_group *grp = NULL;
659 rc = lstcon_group_find(name, &grp);
661 CDEBUG(D_NET, "Can't find group: %s\n", name);
665 if (grp->grp_ref > 2) {
666 /* referred by test */
667 CDEBUG(D_NET, "Group %s is busy\n", name);
668 lstcon_group_decref(grp);
672 rc = lstcon_group_nodes_remove(grp, count, ids_up, result_up);
674 lstcon_group_decref(grp);
675 /* release empty group */
676 if (list_empty(&grp->grp_ndl_list))
677 lstcon_group_decref(grp);
683 lstcon_group_refresh(char *name, struct list_head __user *result_up)
685 struct lstcon_rpc_trans *trans;
686 struct lstcon_group *grp;
689 rc = lstcon_group_find(name, &grp);
691 CDEBUG(D_NET, "Can't find group: %s\n", name);
695 if (grp->grp_ref > 2) {
696 /* referred by test */
697 CDEBUG(D_NET, "Group %s is busy\n", name);
698 lstcon_group_decref(grp);
702 /* re-invite all inactive nodes int the group */
703 rc = lstcon_rpc_trans_ndlist(&grp->grp_ndl_list,
704 &grp->grp_trans_list, LST_TRANS_SESNEW,
705 grp, lstcon_sesrpc_condition, &trans);
707 /* local error, return */
708 CDEBUG(D_NET, "Can't create transaction: %d\n", rc);
709 lstcon_group_decref(grp);
713 lstcon_rpc_trans_postwait(trans, LST_TRANS_TIMEOUT);
715 rc = lstcon_rpc_trans_interpreter(trans, result_up, NULL);
717 lstcon_rpc_trans_destroy(trans);
719 lstcon_group_decref(grp);
725 lstcon_group_list(int index, int len, char __user *name_up)
727 struct lstcon_group *grp;
730 LASSERT(name_up != NULL);
732 list_for_each_entry(grp, &console_session.ses_grp_list, grp_link) {
734 return copy_to_user(name_up, grp->grp_name, len) ?
743 lstcon_nodes_getent(struct list_head *head, int *index_p,
744 int *count_p, struct lstcon_node_ent __user *dents_up)
746 struct lstcon_ndlink *ndl;
747 struct lstcon_node *nd;
751 LASSERT(index_p != NULL && count_p != NULL);
752 LASSERT(dents_up != NULL);
753 LASSERT(*index_p >= 0);
754 LASSERT(*count_p > 0);
756 list_for_each_entry(ndl, head, ndl_link) {
757 if (index++ < *index_p)
760 if (count >= *count_p)
764 if (copy_to_user(&dents_up[count].nde_id,
765 &nd->nd_id, sizeof(nd->nd_id)) ||
766 copy_to_user(&dents_up[count].nde_state,
767 &nd->nd_state, sizeof(nd->nd_state)))
773 if (index <= *index_p)
783 lstcon_group_info(char *name, struct lstcon_ndlist_ent __user *gents_p,
784 int *index_p, int *count_p,
785 struct lstcon_node_ent __user *dents_up)
787 struct lstcon_ndlist_ent *gentp;
788 struct lstcon_group *grp;
789 struct lstcon_ndlink *ndl;
792 rc = lstcon_group_find(name, &grp);
794 CDEBUG(D_NET, "Can't find group %s\n", name);
798 if (dents_up != NULL) {
800 rc = lstcon_nodes_getent(&grp->grp_ndl_list,
801 index_p, count_p, dents_up);
802 lstcon_group_decref(grp);
807 /* non-verbose query */
808 LIBCFS_ALLOC(gentp, sizeof(struct lstcon_ndlist_ent));
810 CERROR("Can't allocate ndlist_ent\n");
811 lstcon_group_decref(grp);
816 list_for_each_entry(ndl, &grp->grp_ndl_list, ndl_link)
817 LST_NODE_STATE_COUNTER(ndl->ndl_node, gentp);
819 rc = copy_to_user(gents_p, gentp,
820 sizeof(struct lstcon_ndlist_ent)) ? -EFAULT : 0;
822 LIBCFS_FREE(gentp, sizeof(struct lstcon_ndlist_ent));
824 lstcon_group_decref(grp);
830 lstcon_batch_find(const char *name, struct lstcon_batch **batpp)
832 struct lstcon_batch *bat;
834 list_for_each_entry(bat, &console_session.ses_bat_list, bat_link) {
835 if (strncmp(bat->bat_name, name, LST_NAME_SIZE) == 0) {
845 lstcon_batch_add(char *name)
847 struct lstcon_batch *bat;
851 rc = (lstcon_batch_find(name, &bat) == 0)? -EEXIST: 0;
853 CDEBUG(D_NET, "Batch %s already exists\n", name);
857 LIBCFS_ALLOC(bat, sizeof(*bat));
859 CERROR("Can't allocate descriptor for batch %s\n", name);
863 LIBCFS_ALLOC(bat->bat_cli_hash,
864 sizeof(struct list_head) * LST_NODE_HASHSIZE);
865 if (bat->bat_cli_hash == NULL) {
866 CERROR("Can't allocate hash for batch %s\n", name);
867 LIBCFS_FREE(bat, sizeof(*bat));
872 LIBCFS_ALLOC(bat->bat_srv_hash,
873 sizeof(struct list_head) * LST_NODE_HASHSIZE);
874 if (bat->bat_srv_hash == NULL) {
875 CERROR("Can't allocate hash for batch %s\n", name);
876 LIBCFS_FREE(bat->bat_cli_hash, LST_NODE_HASHSIZE);
877 LIBCFS_FREE(bat, sizeof(*bat));
882 if (strlen(name) > sizeof(bat->bat_name)-1) {
883 LIBCFS_FREE(bat->bat_srv_hash, LST_NODE_HASHSIZE);
884 LIBCFS_FREE(bat->bat_cli_hash, LST_NODE_HASHSIZE);
885 LIBCFS_FREE(bat, sizeof(*bat));
888 strncpy(bat->bat_name, name, sizeof(bat->bat_name));
889 bat->bat_hdr.tsb_index = 0;
890 bat->bat_hdr.tsb_id.bat_id = ++console_session.ses_id_cookie;
893 bat->bat_state = LST_BATCH_IDLE;
895 INIT_LIST_HEAD(&bat->bat_cli_list);
896 INIT_LIST_HEAD(&bat->bat_srv_list);
897 INIT_LIST_HEAD(&bat->bat_test_list);
898 INIT_LIST_HEAD(&bat->bat_trans_list);
900 for (i = 0; i < LST_NODE_HASHSIZE; i++) {
901 INIT_LIST_HEAD(&bat->bat_cli_hash[i]);
902 INIT_LIST_HEAD(&bat->bat_srv_hash[i]);
905 list_add_tail(&bat->bat_link, &console_session.ses_bat_list);
911 lstcon_batch_list(int index, int len, char __user *name_up)
913 struct lstcon_batch *bat;
915 LASSERT(name_up != NULL);
918 list_for_each_entry(bat, &console_session.ses_bat_list, bat_link) {
920 return copy_to_user(name_up, bat->bat_name, len) ?
929 lstcon_batch_info(char *name, struct lstcon_test_batch_ent __user *ent_up,
930 int server, int testidx, int *index_p, int *ndent_p,
931 struct lstcon_node_ent __user *dents_up)
933 struct lstcon_test_batch_ent *entp;
934 struct list_head *clilst;
935 struct list_head *srvlst;
936 struct lstcon_test *test = NULL;
937 struct lstcon_batch *bat;
938 struct lstcon_ndlink *ndl;
941 rc = lstcon_batch_find(name, &bat);
943 CDEBUG(D_NET, "Can't find batch %s\n", name);
948 /* query test, test index start from 1 */
949 list_for_each_entry(test, &bat->bat_test_list, tes_link) {
955 CDEBUG(D_NET, "Can't find specified test in batch\n");
960 clilst = (test == NULL) ? &bat->bat_cli_list :
961 &test->tes_src_grp->grp_ndl_list;
962 srvlst = (test == NULL) ? &bat->bat_srv_list :
963 &test->tes_dst_grp->grp_ndl_list;
965 if (dents_up != NULL) {
966 rc = lstcon_nodes_getent((server ? srvlst: clilst),
967 index_p, ndent_p, dents_up);
971 /* non-verbose query */
972 LIBCFS_ALLOC(entp, sizeof(struct lstcon_test_batch_ent));
977 entp->u.tbe_batch.bae_ntest = bat->bat_ntest;
978 entp->u.tbe_batch.bae_state = bat->bat_state;
982 entp->u.tbe_test.tse_type = test->tes_type;
983 entp->u.tbe_test.tse_loop = test->tes_loop;
984 entp->u.tbe_test.tse_concur = test->tes_concur;
987 list_for_each_entry(ndl, clilst, ndl_link)
988 LST_NODE_STATE_COUNTER(ndl->ndl_node, &entp->tbe_cli_nle);
990 list_for_each_entry(ndl, srvlst, ndl_link)
991 LST_NODE_STATE_COUNTER(ndl->ndl_node, &entp->tbe_srv_nle);
993 rc = copy_to_user(ent_up, entp,
994 sizeof(struct lstcon_test_batch_ent)) ? -EFAULT : 0;
996 LIBCFS_FREE(entp, sizeof(struct lstcon_test_batch_ent));
1002 lstcon_batrpc_condition(int transop, struct lstcon_node *nd, void *arg)
1005 case LST_TRANS_TSBRUN:
1006 if (nd->nd_state != LST_NODE_ACTIVE)
1010 case LST_TRANS_TSBSTOP:
1011 if (nd->nd_state != LST_NODE_ACTIVE)
1015 case LST_TRANS_TSBCLIQRY:
1016 case LST_TRANS_TSBSRVQRY:
1024 lstcon_batch_op(struct lstcon_batch *bat, int transop,
1025 struct list_head __user *result_up)
1027 struct lstcon_rpc_trans *trans;
1030 rc = lstcon_rpc_trans_ndlist(&bat->bat_cli_list,
1031 &bat->bat_trans_list, transop,
1032 bat, lstcon_batrpc_condition, &trans);
1034 CERROR("Can't create transaction: %d\n", rc);
1038 lstcon_rpc_trans_postwait(trans, LST_TRANS_TIMEOUT);
1040 rc = lstcon_rpc_trans_interpreter(trans, result_up, NULL);
1042 lstcon_rpc_trans_destroy(trans);
1048 lstcon_batch_run(char *name, int timeout, struct list_head __user *result_up)
1050 struct lstcon_batch *bat;
1053 if (lstcon_batch_find(name, &bat) != 0) {
1054 CDEBUG(D_NET, "Can't find batch %s\n", name);
1058 bat->bat_arg = timeout;
1060 rc = lstcon_batch_op(bat, LST_TRANS_TSBRUN, result_up);
1062 /* mark batch as running if it's started in any node */
1063 if (lstcon_tsbop_stat_success(lstcon_trans_stat(), 0) != 0)
1064 bat->bat_state = LST_BATCH_RUNNING;
1070 lstcon_batch_stop(char *name, int force, struct list_head __user *result_up)
1072 struct lstcon_batch *bat;
1075 if (lstcon_batch_find(name, &bat) != 0) {
1076 CDEBUG(D_NET, "Can't find batch %s\n", name);
1080 bat->bat_arg = force;
1082 rc = lstcon_batch_op(bat, LST_TRANS_TSBSTOP, result_up);
1084 /* mark batch as stopped if all RPCs finished */
1085 if (lstcon_tsbop_stat_failure(lstcon_trans_stat(), 0) == 0)
1086 bat->bat_state = LST_BATCH_IDLE;
1092 lstcon_batch_destroy(struct lstcon_batch *bat)
1094 struct lstcon_ndlink *ndl;
1095 struct lstcon_test *test;
1098 list_del(&bat->bat_link);
1100 while (!list_empty(&bat->bat_test_list)) {
1101 test = list_entry(bat->bat_test_list.next,
1102 struct lstcon_test, tes_link);
1103 LASSERT(list_empty(&test->tes_trans_list));
1105 list_del(&test->tes_link);
1107 lstcon_group_decref(test->tes_src_grp);
1108 lstcon_group_decref(test->tes_dst_grp);
1110 LIBCFS_FREE(test, offsetof(struct lstcon_test,
1111 tes_param[test->tes_paramlen]));
1114 LASSERT(list_empty(&bat->bat_trans_list));
1116 while (!list_empty(&bat->bat_cli_list)) {
1117 ndl = list_entry(bat->bat_cli_list.next,
1118 struct lstcon_ndlink, ndl_link);
1119 list_del_init(&ndl->ndl_link);
1121 lstcon_ndlink_release(ndl);
1124 while (!list_empty(&bat->bat_srv_list)) {
1125 ndl = list_entry(bat->bat_srv_list.next,
1126 struct lstcon_ndlink, ndl_link);
1127 list_del_init(&ndl->ndl_link);
1129 lstcon_ndlink_release(ndl);
1132 for (i = 0; i < LST_NODE_HASHSIZE; i++) {
1133 LASSERT(list_empty(&bat->bat_cli_hash[i]));
1134 LASSERT(list_empty(&bat->bat_srv_hash[i]));
1137 LIBCFS_FREE(bat->bat_cli_hash,
1138 sizeof(struct list_head) * LST_NODE_HASHSIZE);
1139 LIBCFS_FREE(bat->bat_srv_hash,
1140 sizeof(struct list_head) * LST_NODE_HASHSIZE);
1141 LIBCFS_FREE(bat, sizeof(*bat));
1145 lstcon_testrpc_condition(int transop, struct lstcon_node *nd, void *arg)
1147 struct lstcon_test *test = arg;
1148 struct lstcon_batch *batch;
1149 struct lstcon_ndlink *ndl;
1150 struct list_head *hash;
1151 struct list_head *head;
1153 LASSERT(test != NULL);
1155 batch = test->tes_batch;
1156 LASSERT(batch != NULL);
1158 if (test->tes_oneside &&
1159 transop == LST_TRANS_TSBSRVADD)
1162 if (nd->nd_state != LST_NODE_ACTIVE)
1165 if (transop == LST_TRANS_TSBCLIADD) {
1166 hash = batch->bat_cli_hash;
1167 head = &batch->bat_cli_list;
1170 LASSERT (transop == LST_TRANS_TSBSRVADD);
1172 hash = batch->bat_srv_hash;
1173 head = &batch->bat_srv_list;
1176 LASSERT (nd->nd_id.nid != LNET_NID_ANY);
1178 if (lstcon_ndlink_find(hash, nd->nd_id, &ndl, 1) != 0)
1181 if (list_empty(&ndl->ndl_link))
1182 list_add_tail(&ndl->ndl_link, head);
1188 lstcon_test_nodes_add(struct lstcon_test *test,
1189 struct list_head __user *result_up)
1191 struct lstcon_rpc_trans *trans;
1192 struct lstcon_group *grp;
1196 LASSERT (test->tes_src_grp != NULL);
1197 LASSERT (test->tes_dst_grp != NULL);
1199 transop = LST_TRANS_TSBSRVADD;
1200 grp = test->tes_dst_grp;
1202 rc = lstcon_rpc_trans_ndlist(&grp->grp_ndl_list,
1203 &test->tes_trans_list, transop,
1204 test, lstcon_testrpc_condition, &trans);
1206 CERROR("Can't create transaction: %d\n", rc);
1210 lstcon_rpc_trans_postwait(trans, LST_TRANS_TIMEOUT);
1212 if (lstcon_trans_stat()->trs_rpc_errno != 0 ||
1213 lstcon_trans_stat()->trs_fwk_errno != 0) {
1214 lstcon_rpc_trans_interpreter(trans, result_up, NULL);
1216 lstcon_rpc_trans_destroy(trans);
1217 /* return if any error */
1218 CDEBUG(D_NET, "Failed to add test %s, "
1219 "RPC error %d, framework error %d\n",
1220 transop == LST_TRANS_TSBCLIADD ? "client" : "server",
1221 lstcon_trans_stat()->trs_rpc_errno,
1222 lstcon_trans_stat()->trs_fwk_errno);
1227 lstcon_rpc_trans_destroy(trans);
1229 if (transop == LST_TRANS_TSBCLIADD)
1232 transop = LST_TRANS_TSBCLIADD;
1233 grp = test->tes_src_grp;
1234 test->tes_cliidx = 0;
1236 /* requests to test clients */
1241 lstcon_verify_batch(const char *name, struct lstcon_batch **batch)
1245 rc = lstcon_batch_find(name, batch);
1247 CDEBUG(D_NET, "Can't find batch %s\n", name);
1251 if ((*batch)->bat_state != LST_BATCH_IDLE) {
1252 CDEBUG(D_NET, "Can't change running batch %s\n", name);
1260 lstcon_verify_group(const char *name, struct lstcon_group **grp)
1263 struct lstcon_ndlink *ndl;
1265 rc = lstcon_group_find(name, grp);
1267 CDEBUG(D_NET, "can't find group %s\n", name);
1271 list_for_each_entry(ndl, &(*grp)->grp_ndl_list, ndl_link) {
1272 if (ndl->ndl_node->nd_state == LST_NODE_ACTIVE) {
1277 CDEBUG(D_NET, "Group %s has no ACTIVE nodes\n", name);
1283 lstcon_test_add(char *batch_name, int type, int loop,
1284 int concur, int dist, int span,
1285 char *src_name, char *dst_name,
1286 void *param, int paramlen, int *retp,
1287 struct list_head __user *result_up)
1289 struct lstcon_test *test = NULL;
1291 struct lstcon_group *src_grp = NULL;
1292 struct lstcon_group *dst_grp = NULL;
1293 struct lstcon_batch *batch = NULL;
1296 * verify that a batch of the given name exists, and the groups
1297 * that will be part of the batch exist and have at least one
1300 rc = lstcon_verify_batch(batch_name, &batch);
1304 rc = lstcon_verify_group(src_name, &src_grp);
1308 rc = lstcon_verify_group(dst_name, &dst_grp);
1312 if (dst_grp->grp_userland)
1315 LIBCFS_ALLOC(test, offsetof(struct lstcon_test, tes_param[paramlen]));
1317 CERROR("Can't allocate test descriptor\n");
1323 test->tes_hdr.tsb_id = batch->bat_hdr.tsb_id;
1324 test->tes_batch = batch;
1325 test->tes_type = type;
1326 test->tes_oneside = 0; /* TODO */
1327 test->tes_loop = loop;
1328 test->tes_concur = concur;
1329 test->tes_stop_onerr = 1; /* TODO */
1330 test->tes_span = span;
1331 test->tes_dist = dist;
1332 test->tes_cliidx = 0; /* just used for creating RPC */
1333 test->tes_src_grp = src_grp;
1334 test->tes_dst_grp = dst_grp;
1335 INIT_LIST_HEAD(&test->tes_trans_list);
1337 if (param != NULL) {
1338 test->tes_paramlen = paramlen;
1339 memcpy(&test->tes_param[0], param, paramlen);
1342 rc = lstcon_test_nodes_add(test, result_up);
1347 if (lstcon_trans_stat()->trs_rpc_errno != 0 ||
1348 lstcon_trans_stat()->trs_fwk_errno != 0)
1349 CDEBUG(D_NET, "Failed to add test %d to batch %s\n", type,
1352 /* add to test list anyway, so user can check what's going on */
1353 list_add_tail(&test->tes_link, &batch->bat_test_list);
1356 test->tes_hdr.tsb_index = batch->bat_ntest;
1358 /* hold groups so nobody can change them */
1362 LIBCFS_FREE(test, offsetof(struct lstcon_test,
1363 tes_param[paramlen]));
1365 if (dst_grp != NULL)
1366 lstcon_group_decref(dst_grp);
1368 if (src_grp != NULL)
1369 lstcon_group_decref(src_grp);
1375 lstcon_test_find(struct lstcon_batch *batch, int idx,
1376 struct lstcon_test **testpp)
1378 struct lstcon_test *test;
1380 list_for_each_entry(test, &batch->bat_test_list, tes_link) {
1381 if (idx == test->tes_hdr.tsb_index) {
1391 lstcon_tsbrpc_readent(int transop, struct srpc_msg *msg,
1392 struct lstcon_rpc_ent __user *ent_up)
1394 struct srpc_batch_reply *rep = &msg->msg_body.bat_reply;
1396 LASSERT (transop == LST_TRANS_TSBCLIQRY ||
1397 transop == LST_TRANS_TSBSRVQRY);
1399 /* positive errno, framework error code */
1400 if (copy_to_user(&ent_up->rpe_priv[0],
1401 &rep->bar_active, sizeof(rep->bar_active)))
1408 lstcon_test_batch_query(char *name, int testidx, int client,
1409 int timeout, struct list_head __user *result_up)
1411 struct lstcon_rpc_trans *trans;
1412 struct list_head *translist;
1413 struct list_head *ndlist;
1414 struct lstcon_tsb_hdr *hdr;
1415 struct lstcon_batch *batch;
1416 struct lstcon_test *test = NULL;
1420 rc = lstcon_batch_find(name, &batch);
1422 CDEBUG(D_NET, "Can't find batch: %s\n", name);
1427 translist = &batch->bat_trans_list;
1428 ndlist = &batch->bat_cli_list;
1429 hdr = &batch->bat_hdr;
1432 /* query specified test only */
1433 rc = lstcon_test_find(batch, testidx, &test);
1435 CDEBUG(D_NET, "Can't find test: %d\n", testidx);
1439 translist = &test->tes_trans_list;
1440 ndlist = &test->tes_src_grp->grp_ndl_list;
1441 hdr = &test->tes_hdr;
1444 transop = client ? LST_TRANS_TSBCLIQRY : LST_TRANS_TSBSRVQRY;
1446 rc = lstcon_rpc_trans_ndlist(ndlist, translist, transop, hdr,
1447 lstcon_batrpc_condition, &trans);
1449 CERROR("Can't create transaction: %d\n", rc);
1453 lstcon_rpc_trans_postwait(trans, timeout);
1455 if (testidx == 0 && /* query a batch, not a test */
1456 lstcon_rpc_stat_failure(lstcon_trans_stat(), 0) == 0 &&
1457 lstcon_tsbqry_stat_run(lstcon_trans_stat(), 0) == 0) {
1458 /* all RPCs finished, and no active test */
1459 batch->bat_state = LST_BATCH_IDLE;
1462 rc = lstcon_rpc_trans_interpreter(trans, result_up,
1463 lstcon_tsbrpc_readent);
1464 lstcon_rpc_trans_destroy(trans);
1470 lstcon_statrpc_readent(int transop, struct srpc_msg *msg,
1471 struct lstcon_rpc_ent __user *ent_up)
1473 struct srpc_stat_reply *rep = &msg->msg_body.stat_reply;
1474 struct sfw_counters __user *sfwk_stat;
1475 struct srpc_counters __user *srpc_stat;
1476 struct lnet_counters __user *lnet_stat;
1478 if (rep->str_status != 0)
1481 sfwk_stat = (struct sfw_counters __user *)&ent_up->rpe_payload[0];
1482 srpc_stat = (struct srpc_counters __user *)
1483 ((char __user *)sfwk_stat + sizeof(*sfwk_stat));
1484 lnet_stat = (struct lnet_counters __user *)
1485 ((char __user *)srpc_stat + sizeof(*srpc_stat));
1487 if (copy_to_user(sfwk_stat, &rep->str_fw, sizeof(*sfwk_stat)) ||
1488 copy_to_user(srpc_stat, &rep->str_rpc, sizeof(*srpc_stat)) ||
1489 copy_to_user(lnet_stat, &rep->str_lnet, sizeof(*lnet_stat)))
1496 lstcon_ndlist_stat(struct list_head *ndlist,
1497 int timeout, struct list_head __user *result_up)
1499 struct list_head head;
1500 struct lstcon_rpc_trans *trans;
1503 INIT_LIST_HEAD(&head);
1505 rc = lstcon_rpc_trans_ndlist(ndlist, &head,
1506 LST_TRANS_STATQRY, NULL, NULL, &trans);
1508 CERROR("Can't create transaction: %d\n", rc);
1512 lstcon_rpc_trans_postwait(trans, LST_VALIDATE_TIMEOUT(timeout));
1514 rc = lstcon_rpc_trans_interpreter(trans, result_up,
1515 lstcon_statrpc_readent);
1516 lstcon_rpc_trans_destroy(trans);
1522 lstcon_group_stat(char *grp_name, int timeout,
1523 struct list_head __user *result_up)
1525 struct lstcon_group *grp;
1528 rc = lstcon_group_find(grp_name, &grp);
1530 CDEBUG(D_NET, "Can't find group %s\n", grp_name);
1534 rc = lstcon_ndlist_stat(&grp->grp_ndl_list, timeout, result_up);
1536 lstcon_group_decref(grp);
1542 lstcon_nodes_stat(int count, struct lnet_process_id __user *ids_up,
1543 int timeout, struct list_head __user *result_up)
1545 struct lstcon_ndlink *ndl;
1546 struct lstcon_group *tmp;
1547 struct lnet_process_id id;
1551 rc = lstcon_group_alloc(NULL, &tmp);
1553 CERROR("Out of memory\n");
1557 for (i = 0 ; i < count; i++) {
1558 if (copy_from_user(&id, &ids_up[i], sizeof(id))) {
1563 /* add to tmp group */
1564 rc = lstcon_group_ndlink_find(tmp, id, &ndl, 2);
1566 CDEBUG((rc == -ENOMEM) ? D_ERROR : D_NET,
1567 "Failed to find or create %s: %d\n",
1568 libcfs_id2str(id), rc);
1574 lstcon_group_decref(tmp);
1578 rc = lstcon_ndlist_stat(&tmp->grp_ndl_list, timeout, result_up);
1580 lstcon_group_decref(tmp);
1586 lstcon_debug_ndlist(struct list_head *ndlist,
1587 struct list_head *translist,
1588 int timeout, struct list_head __user *result_up)
1590 struct lstcon_rpc_trans *trans;
1593 rc = lstcon_rpc_trans_ndlist(ndlist, translist, LST_TRANS_SESQRY,
1594 NULL, lstcon_sesrpc_condition, &trans);
1596 CERROR("Can't create transaction: %d\n", rc);
1600 lstcon_rpc_trans_postwait(trans, LST_VALIDATE_TIMEOUT(timeout));
1602 rc = lstcon_rpc_trans_interpreter(trans, result_up,
1603 lstcon_sesrpc_readent);
1604 lstcon_rpc_trans_destroy(trans);
1610 lstcon_session_debug(int timeout, struct list_head __user *result_up)
1612 return lstcon_debug_ndlist(&console_session.ses_ndl_list,
1613 NULL, timeout, result_up);
1617 lstcon_batch_debug(int timeout, char *name,
1618 int client, struct list_head __user *result_up)
1620 struct lstcon_batch *bat;
1623 rc = lstcon_batch_find(name, &bat);
1627 rc = lstcon_debug_ndlist(client ? &bat->bat_cli_list :
1629 NULL, timeout, result_up);
1635 lstcon_group_debug(int timeout, char *name,
1636 struct list_head __user *result_up)
1638 struct lstcon_group *grp;
1641 rc = lstcon_group_find(name, &grp);
1645 rc = lstcon_debug_ndlist(&grp->grp_ndl_list, NULL,
1646 timeout, result_up);
1647 lstcon_group_decref(grp);
1653 lstcon_nodes_debug(int timeout, int count,
1654 struct lnet_process_id __user *ids_up,
1655 struct list_head __user *result_up)
1657 struct lnet_process_id id;
1658 struct lstcon_ndlink *ndl;
1659 struct lstcon_group *grp;
1663 rc = lstcon_group_alloc(NULL, &grp);
1665 CDEBUG(D_NET, "Out of memory\n");
1669 for (i = 0; i < count; i++) {
1670 if (copy_from_user(&id, &ids_up[i], sizeof(id))) {
1675 /* node is added to tmp group */
1676 rc = lstcon_group_ndlink_find(grp, id, &ndl, 1);
1678 CERROR("Can't create node link\n");
1684 lstcon_group_decref(grp);
1688 rc = lstcon_debug_ndlist(&grp->grp_ndl_list, NULL,
1689 timeout, result_up);
1691 lstcon_group_decref(grp);
1697 lstcon_session_match(struct lst_sid sid)
1699 return (console_session.ses_id.ses_nid == sid.ses_nid &&
1700 console_session.ses_id.ses_stamp == sid.ses_stamp) ? 1: 0;
1704 lstcon_new_session_id(struct lst_sid *sid)
1706 struct lnet_process_id id;
1708 LASSERT (console_session.ses_state == LST_SESSION_NONE);
1711 sid->ses_nid = id.nid;
1712 sid->ses_stamp = cfs_time_current();
1716 lstcon_session_new(char *name, int key, unsigned feats,
1717 int timeout, int force, struct lst_sid __user *sid_up)
1722 if (console_session.ses_state != LST_SESSION_NONE) {
1723 /* session exists */
1725 CNETERR("Session %s already exists\n",
1726 console_session.ses_name);
1730 rc = lstcon_session_end();
1732 /* lstcon_session_end() only return local error */
1737 if ((feats & ~LST_FEATS_MASK) != 0) {
1738 CNETERR("Unknown session features %x\n",
1739 (feats & ~LST_FEATS_MASK));
1743 for (i = 0; i < LST_GLOBAL_HASHSIZE; i++)
1744 LASSERT(list_empty(&console_session.ses_ndl_hash[i]));
1746 lstcon_new_session_id(&console_session.ses_id);
1748 console_session.ses_key = key;
1749 console_session.ses_state = LST_SESSION_ACTIVE;
1750 console_session.ses_force = !!force;
1751 console_session.ses_features = feats;
1752 console_session.ses_feats_updated = 0;
1753 console_session.ses_timeout = (timeout <= 0) ?
1754 LST_CONSOLE_TIMEOUT : timeout;
1756 if (strlen(name) > sizeof(console_session.ses_name)-1)
1758 strlcpy(console_session.ses_name, name,
1759 sizeof(console_session.ses_name));
1761 rc = lstcon_batch_add(LST_DEFAULT_BATCH);
1765 rc = lstcon_rpc_pinger_start();
1767 struct lstcon_batch *bat = NULL;
1769 lstcon_batch_find(LST_DEFAULT_BATCH, &bat);
1770 lstcon_batch_destroy(bat);
1775 if (copy_to_user(sid_up, &console_session.ses_id,
1776 sizeof(struct lst_sid)) == 0)
1779 lstcon_session_end();
1785 lstcon_session_info(struct lst_sid __user *sid_up, int __user *key_up,
1786 unsigned __user *featp,
1787 struct lstcon_ndlist_ent __user *ndinfo_up,
1788 char __user *name_up, int len)
1790 struct lstcon_ndlist_ent *entp;
1791 struct lstcon_ndlink *ndl;
1794 if (console_session.ses_state != LST_SESSION_ACTIVE)
1797 LIBCFS_ALLOC(entp, sizeof(*entp));
1801 list_for_each_entry(ndl, &console_session.ses_ndl_list, ndl_link)
1802 LST_NODE_STATE_COUNTER(ndl->ndl_node, entp);
1804 if (copy_to_user(sid_up, &console_session.ses_id,
1805 sizeof(struct lst_sid)) ||
1806 copy_to_user(key_up, &console_session.ses_key,
1808 copy_to_user(featp, &console_session.ses_features,
1810 copy_to_user(ndinfo_up, entp, sizeof(*entp)) ||
1811 copy_to_user(name_up, console_session.ses_name, len))
1814 LIBCFS_FREE(entp, sizeof(*entp));
1820 lstcon_session_end()
1822 struct lstcon_rpc_trans *trans;
1823 struct lstcon_group *grp;
1824 struct lstcon_batch *bat;
1827 LASSERT (console_session.ses_state == LST_SESSION_ACTIVE);
1829 rc = lstcon_rpc_trans_ndlist(&console_session.ses_ndl_list,
1830 NULL, LST_TRANS_SESEND, NULL,
1831 lstcon_sesrpc_condition, &trans);
1833 CERROR("Can't create transaction: %d\n", rc);
1837 console_session.ses_shutdown = 1;
1839 lstcon_rpc_pinger_stop();
1841 lstcon_rpc_trans_postwait(trans, LST_TRANS_TIMEOUT);
1843 lstcon_rpc_trans_destroy(trans);
1844 /* User can do nothing even rpc failed, so go on */
1846 /* waiting for orphan rpcs to die */
1847 lstcon_rpc_cleanup_wait();
1849 console_session.ses_id = LST_INVALID_SID;
1850 console_session.ses_state = LST_SESSION_NONE;
1851 console_session.ses_key = 0;
1852 console_session.ses_force = 0;
1853 console_session.ses_feats_updated = 0;
1855 /* destroy all batches */
1856 while (!list_empty(&console_session.ses_bat_list)) {
1857 bat = list_entry(console_session.ses_bat_list.next,
1858 struct lstcon_batch, bat_link);
1860 lstcon_batch_destroy(bat);
1863 /* destroy all groups */
1864 while (!list_empty(&console_session.ses_grp_list)) {
1865 grp = list_entry(console_session.ses_grp_list.next,
1866 struct lstcon_group, grp_link);
1867 LASSERT(grp->grp_ref == 1);
1869 lstcon_group_decref(grp);
1872 /* all nodes should be released */
1873 LASSERT(list_empty(&console_session.ses_ndl_list));
1875 console_session.ses_shutdown = 0;
1876 console_session.ses_expired = 0;
1882 lstcon_session_feats_check(unsigned feats)
1886 if ((feats & ~LST_FEATS_MASK) != 0) {
1887 CERROR("Can't support these features: %x\n",
1888 (feats & ~LST_FEATS_MASK));
1892 spin_lock(&console_session.ses_rpc_lock);
1894 if (!console_session.ses_feats_updated) {
1895 console_session.ses_feats_updated = 1;
1896 console_session.ses_features = feats;
1899 if (console_session.ses_features != feats)
1902 spin_unlock(&console_session.ses_rpc_lock);
1905 CERROR("remote features %x do not match with "
1906 "session features %x of console\n",
1907 feats, console_session.ses_features);
1914 lstcon_acceptor_handle(struct srpc_server_rpc *rpc)
1916 struct srpc_msg *rep = &rpc->srpc_replymsg;
1917 struct srpc_msg *req = &rpc->srpc_reqstbuf->buf_msg;
1918 struct srpc_join_reqst *jreq = &req->msg_body.join_reqst;
1919 struct srpc_join_reply *jrep = &rep->msg_body.join_reply;
1920 struct lstcon_group *grp = NULL;
1921 struct lstcon_ndlink *ndl;
1924 sfw_unpack_message(req);
1926 mutex_lock(&console_session.ses_mutex);
1928 jrep->join_sid = console_session.ses_id;
1930 if (console_session.ses_id.ses_nid == LNET_NID_ANY) {
1931 jrep->join_status = ESRCH;
1935 if (lstcon_session_feats_check(req->msg_ses_feats) != 0) {
1936 jrep->join_status = EPROTO;
1940 if (jreq->join_sid.ses_nid != LNET_NID_ANY &&
1941 !lstcon_session_match(jreq->join_sid)) {
1942 jrep->join_status = EBUSY;
1946 if (lstcon_group_find(jreq->join_group, &grp) != 0) {
1947 rc = lstcon_group_alloc(jreq->join_group, &grp);
1949 CERROR("Out of memory\n");
1953 list_add_tail(&grp->grp_link,
1954 &console_session.ses_grp_list);
1955 lstcon_group_addref(grp);
1958 if (grp->grp_ref > 2) {
1959 /* Group in using */
1960 jrep->join_status = EBUSY;
1964 rc = lstcon_group_ndlink_find(grp, rpc->srpc_peer, &ndl, 0);
1966 jrep->join_status = EEXIST;
1970 rc = lstcon_group_ndlink_find(grp, rpc->srpc_peer, &ndl, 1);
1972 CERROR("Out of memory\n");
1976 ndl->ndl_node->nd_state = LST_NODE_ACTIVE;
1977 ndl->ndl_node->nd_timeout = console_session.ses_timeout;
1979 if (grp->grp_userland == 0)
1980 grp->grp_userland = 1;
1982 strlcpy(jrep->join_session, console_session.ses_name,
1983 sizeof(jrep->join_session));
1984 jrep->join_timeout = console_session.ses_timeout;
1985 jrep->join_status = 0;
1988 rep->msg_ses_feats = console_session.ses_features;
1990 lstcon_group_decref(grp);
1992 mutex_unlock(&console_session.ses_mutex);
1997 static struct srpc_service lstcon_acceptor_service;
1999 static void lstcon_init_acceptor_service(void)
2001 /* initialize selftest console acceptor service table */
2002 lstcon_acceptor_service.sv_name = "join session";
2003 lstcon_acceptor_service.sv_handler = lstcon_acceptor_handle;
2004 lstcon_acceptor_service.sv_id = SRPC_SERVICE_JOIN;
2005 lstcon_acceptor_service.sv_wi_total = SFW_FRWK_WI_MAX;
2008 int lstcon_ioctl_entry(unsigned int cmd, struct libcfs_ioctl_hdr *hdr);
2010 DECLARE_IOCTL_HANDLER(lstcon_ioctl_handler, lstcon_ioctl_entry);
2012 /* initialize console */
2014 lstcon_console_init(void)
2019 console_session.ses_id = LST_INVALID_SID;
2020 console_session.ses_state = LST_SESSION_NONE;
2021 console_session.ses_timeout = 0;
2022 console_session.ses_force = 0;
2023 console_session.ses_expired = 0;
2024 console_session.ses_feats_updated = 0;
2025 console_session.ses_features = LST_FEATS_MASK;
2026 console_session.ses_laststamp = ktime_get_real_seconds();
2028 mutex_init(&console_session.ses_mutex);
2030 INIT_LIST_HEAD(&console_session.ses_ndl_list);
2031 INIT_LIST_HEAD(&console_session.ses_grp_list);
2032 INIT_LIST_HEAD(&console_session.ses_bat_list);
2033 INIT_LIST_HEAD(&console_session.ses_trans_list);
2035 LIBCFS_ALLOC(console_session.ses_ndl_hash,
2036 sizeof(struct list_head) * LST_GLOBAL_HASHSIZE);
2037 if (console_session.ses_ndl_hash == NULL)
2040 for (i = 0; i < LST_GLOBAL_HASHSIZE; i++)
2041 INIT_LIST_HEAD(&console_session.ses_ndl_hash[i]);
2044 /* initialize acceptor service table */
2045 lstcon_init_acceptor_service();
2047 rc = srpc_add_service(&lstcon_acceptor_service);
2048 LASSERT(rc != -EBUSY);
2050 LIBCFS_FREE(console_session.ses_ndl_hash,
2051 sizeof(struct list_head) * LST_GLOBAL_HASHSIZE);
2055 rc = srpc_service_add_buffers(&lstcon_acceptor_service,
2056 lstcon_acceptor_service.sv_wi_total);
2062 rc = libcfs_register_ioctl(&lstcon_ioctl_handler);
2065 lstcon_rpc_module_init();
2070 srpc_shutdown_service(&lstcon_acceptor_service);
2071 srpc_remove_service(&lstcon_acceptor_service);
2073 LIBCFS_FREE(console_session.ses_ndl_hash,
2074 sizeof(struct list_head) * LST_GLOBAL_HASHSIZE);
2076 srpc_wait_service_shutdown(&lstcon_acceptor_service);
2082 lstcon_console_fini(void)
2086 libcfs_deregister_ioctl(&lstcon_ioctl_handler);
2088 mutex_lock(&console_session.ses_mutex);
2090 srpc_shutdown_service(&lstcon_acceptor_service);
2091 srpc_remove_service(&lstcon_acceptor_service);
2093 if (console_session.ses_state != LST_SESSION_NONE)
2094 lstcon_session_end();
2096 lstcon_rpc_module_fini();
2098 mutex_unlock(&console_session.ses_mutex);
2100 LASSERT(list_empty(&console_session.ses_ndl_list));
2101 LASSERT(list_empty(&console_session.ses_grp_list));
2102 LASSERT(list_empty(&console_session.ses_bat_list));
2103 LASSERT(list_empty(&console_session.ses_trans_list));
2105 for (i = 0; i < LST_NODE_HASHSIZE; i++)
2106 LASSERT(list_empty(&console_session.ses_ndl_hash[i]));
2108 LIBCFS_FREE(console_session.ses_ndl_hash,
2109 sizeof(struct list_head) * LST_GLOBAL_HASHSIZE);
2111 srpc_wait_service_shutdown(&lstcon_acceptor_service);