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.sun.com/software/products/lustre/docs/GPLv2.pdf
20 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
21 * CA 95054 USA or visit www.sun.com if you need additional information or
27 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
28 * Use is subject to license terms.
30 * Copyright (c) 2012, Intel Corporation.
33 * This file is part of Lustre, http://www.lustre.org/
34 * Lustre is a trademark of Sun Microsystems, Inc.
36 * lnet/selftest/conctl.c
38 * Infrastructure of LST console
40 * Author: Liang Zhen <liangzhen@clusterfs.com>
43 #include "../../include/linux/libcfs/libcfs.h"
44 #include "../../include/linux/lnet/lib-lnet.h"
48 #define LST_NODE_STATE_COUNTER(nd, p) \
50 if ((nd)->nd_state == LST_NODE_ACTIVE) \
52 else if ((nd)->nd_state == LST_NODE_BUSY) \
54 else if ((nd)->nd_state == LST_NODE_DOWN) \
57 (p)->nle_nunknown++; \
61 lstcon_session_t console_session;
64 lstcon_node_get(lstcon_node_t *nd)
66 LASSERT(nd->nd_ref >= 1);
72 lstcon_node_find(lnet_process_id_t id, lstcon_node_t **ndpp, int create)
75 unsigned int idx = LNET_NIDADDR(id.nid) % LST_GLOBAL_HASHSIZE;
77 LASSERT(id.nid != LNET_NID_ANY);
79 list_for_each_entry(ndl, &console_session.ses_ndl_hash[idx], ndl_hlink) {
80 if (ndl->ndl_node->nd_id.nid != id.nid ||
81 ndl->ndl_node->nd_id.pid != id.pid)
84 lstcon_node_get(ndl->ndl_node);
85 *ndpp = ndl->ndl_node;
92 LIBCFS_ALLOC(*ndpp, sizeof(lstcon_node_t) + sizeof(lstcon_ndlink_t));
96 ndl = (lstcon_ndlink_t *)(*ndpp + 1);
98 ndl->ndl_node = *ndpp;
100 ndl->ndl_node->nd_ref = 1;
101 ndl->ndl_node->nd_id = id;
102 ndl->ndl_node->nd_stamp = cfs_time_current();
103 ndl->ndl_node->nd_state = LST_NODE_UNKNOWN;
104 ndl->ndl_node->nd_timeout = 0;
105 memset(&ndl->ndl_node->nd_ping, 0, sizeof(lstcon_rpc_t));
107 /* queued in global hash & list, no refcount is taken by
108 * global hash & list, if caller release his refcount,
109 * node will be released */
110 list_add_tail(&ndl->ndl_hlink, &console_session.ses_ndl_hash[idx]);
111 list_add_tail(&ndl->ndl_link, &console_session.ses_ndl_list);
117 lstcon_node_put(lstcon_node_t *nd)
119 lstcon_ndlink_t *ndl;
121 LASSERT(nd->nd_ref > 0);
123 if (--nd->nd_ref > 0)
126 ndl = (lstcon_ndlink_t *)(nd + 1);
128 LASSERT(!list_empty(&ndl->ndl_link));
129 LASSERT(!list_empty(&ndl->ndl_hlink));
131 /* remove from session */
132 list_del(&ndl->ndl_link);
133 list_del(&ndl->ndl_hlink);
135 LIBCFS_FREE(nd, sizeof(lstcon_node_t) + sizeof(lstcon_ndlink_t));
139 lstcon_ndlink_find(struct list_head *hash,
140 lnet_process_id_t id, lstcon_ndlink_t **ndlpp, int create)
142 unsigned int idx = LNET_NIDADDR(id.nid) % LST_NODE_HASHSIZE;
143 lstcon_ndlink_t *ndl;
147 if (id.nid == LNET_NID_ANY)
151 list_for_each_entry(ndl, &hash[idx], ndl_hlink) {
152 if (ndl->ndl_node->nd_id.nid != id.nid ||
153 ndl->ndl_node->nd_id.pid != id.pid)
163 /* find or create in session hash */
164 rc = lstcon_node_find(id, &nd, (create == 1) ? 1 : 0);
168 LIBCFS_ALLOC(ndl, sizeof(lstcon_ndlink_t));
177 INIT_LIST_HEAD(&ndl->ndl_link);
178 list_add_tail(&ndl->ndl_hlink, &hash[idx]);
184 lstcon_ndlink_release(lstcon_ndlink_t *ndl)
186 LASSERT(list_empty(&ndl->ndl_link));
187 LASSERT(!list_empty(&ndl->ndl_hlink));
189 list_del(&ndl->ndl_hlink); /* delete from hash */
190 lstcon_node_put(ndl->ndl_node);
192 LIBCFS_FREE(ndl, sizeof(*ndl));
196 lstcon_group_alloc(char *name, lstcon_group_t **grpp)
201 LIBCFS_ALLOC(grp, offsetof(lstcon_group_t,
202 grp_ndl_hash[LST_NODE_HASHSIZE]));
208 strcpy(grp->grp_name, name);
210 INIT_LIST_HEAD(&grp->grp_link);
211 INIT_LIST_HEAD(&grp->grp_ndl_list);
212 INIT_LIST_HEAD(&grp->grp_trans_list);
214 for (i = 0; i < LST_NODE_HASHSIZE; i++)
215 INIT_LIST_HEAD(&grp->grp_ndl_hash[i]);
223 lstcon_group_addref(lstcon_group_t *grp)
228 static void lstcon_group_ndlink_release(lstcon_group_t *, lstcon_ndlink_t *);
231 lstcon_group_drain(lstcon_group_t *grp, int keep)
233 lstcon_ndlink_t *ndl;
234 lstcon_ndlink_t *tmp;
236 list_for_each_entry_safe(ndl, tmp, &grp->grp_ndl_list, ndl_link) {
237 if ((ndl->ndl_node->nd_state & keep) == 0)
238 lstcon_group_ndlink_release(grp, ndl);
243 lstcon_group_decref(lstcon_group_t *grp)
247 if (--grp->grp_ref > 0)
250 if (!list_empty(&grp->grp_link))
251 list_del(&grp->grp_link);
253 lstcon_group_drain(grp, 0);
255 for (i = 0; i < LST_NODE_HASHSIZE; i++) {
256 LASSERT(list_empty(&grp->grp_ndl_hash[i]));
259 LIBCFS_FREE(grp, offsetof(lstcon_group_t,
260 grp_ndl_hash[LST_NODE_HASHSIZE]));
264 lstcon_group_find(const char *name, lstcon_group_t **grpp)
268 list_for_each_entry(grp, &console_session.ses_grp_list, grp_link) {
269 if (strncmp(grp->grp_name, name, LST_NAME_SIZE) != 0)
272 lstcon_group_addref(grp); /* +1 ref for caller */
281 lstcon_group_put(lstcon_group_t *grp)
283 lstcon_group_decref(grp);
287 lstcon_group_ndlink_find(lstcon_group_t *grp, lnet_process_id_t id,
288 lstcon_ndlink_t **ndlpp, int create)
292 rc = lstcon_ndlink_find(&grp->grp_ndl_hash[0], id, ndlpp, create);
296 if (!list_empty(&(*ndlpp)->ndl_link))
299 list_add_tail(&(*ndlpp)->ndl_link, &grp->grp_ndl_list);
306 lstcon_group_ndlink_release(lstcon_group_t *grp, lstcon_ndlink_t *ndl)
308 list_del_init(&ndl->ndl_link);
309 lstcon_ndlink_release(ndl);
314 lstcon_group_ndlink_move(lstcon_group_t *old,
315 lstcon_group_t *new, lstcon_ndlink_t *ndl)
317 unsigned int idx = LNET_NIDADDR(ndl->ndl_node->nd_id.nid) %
320 list_del(&ndl->ndl_hlink);
321 list_del(&ndl->ndl_link);
324 list_add_tail(&ndl->ndl_hlink, &new->grp_ndl_hash[idx]);
325 list_add_tail(&ndl->ndl_link, &new->grp_ndl_list);
332 lstcon_group_move(lstcon_group_t *old, lstcon_group_t *new)
334 lstcon_ndlink_t *ndl;
336 while (!list_empty(&old->grp_ndl_list)) {
337 ndl = list_entry(old->grp_ndl_list.next,
338 lstcon_ndlink_t, ndl_link);
339 lstcon_group_ndlink_move(old, new, ndl);
344 lstcon_sesrpc_condition(int transop, lstcon_node_t *nd, void *arg)
346 lstcon_group_t *grp = (lstcon_group_t *)arg;
349 case LST_TRANS_SESNEW:
350 if (nd->nd_state == LST_NODE_ACTIVE)
354 case LST_TRANS_SESEND:
355 if (nd->nd_state != LST_NODE_ACTIVE)
358 if (grp != NULL && nd->nd_ref > 1)
362 case LST_TRANS_SESQRY:
373 lstcon_sesrpc_readent(int transop, srpc_msg_t *msg,
374 lstcon_rpc_ent_t *ent_up)
376 srpc_debug_reply_t *rep;
379 case LST_TRANS_SESNEW:
380 case LST_TRANS_SESEND:
383 case LST_TRANS_SESQRY:
384 rep = &msg->msg_body.dbg_reply;
386 if (copy_to_user(&ent_up->rpe_priv[0],
387 &rep->dbg_timeout, sizeof(int)) ||
388 copy_to_user(&ent_up->rpe_payload[0],
389 &rep->dbg_name, LST_NAME_SIZE))
402 lstcon_group_nodes_add(lstcon_group_t *grp,
403 int count, lnet_process_id_t *ids_up,
404 unsigned *featp, struct list_head *result_up)
406 lstcon_rpc_trans_t *trans;
407 lstcon_ndlink_t *ndl;
409 lnet_process_id_t 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_put(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_put(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_put(tmp);
469 lstcon_group_nodes_remove(lstcon_group_t *grp,
470 int count, lnet_process_id_t *ids_up,
471 struct list_head *result_up)
473 lstcon_rpc_trans_t *trans;
474 lstcon_ndlink_t *ndl;
476 lnet_process_id_t 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_put(tmp);
517 lstcon_group_move(tmp, grp);
518 lstcon_group_put(tmp);
524 lstcon_group_add(char *name)
529 rc = (lstcon_group_find(name, &grp) == 0) ? -EEXIST : 0;
531 /* find a group with same name */
532 lstcon_group_put(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, lnet_process_id_t *ids_up,
549 unsigned *featp, struct list_head *result_up)
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_put(grp);
571 rc = lstcon_group_nodes_add(grp, count, ids_up, featp, result_up);
573 lstcon_group_put(grp);
579 lstcon_group_del(char *name)
581 lstcon_rpc_trans_t *trans;
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_put(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_put(grp);
607 lstcon_rpc_trans_postwait(trans, LST_TRANS_TIMEOUT);
609 lstcon_rpc_trans_destroy(trans);
611 lstcon_group_put(grp);
612 /* -ref for session, it's destroyed,
613 * status can't be rolled back, destroy group anyway */
614 lstcon_group_put(grp);
620 lstcon_group_clean(char *name, int args)
622 lstcon_group_t *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_put(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_put(grp);
644 /* release empty group */
645 if (list_empty(&grp->grp_ndl_list))
646 lstcon_group_put(grp);
652 lstcon_nodes_remove(char *name, int count,
653 lnet_process_id_t *ids_up, struct list_head *result_up)
655 lstcon_group_t *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_put(grp);
671 rc = lstcon_group_nodes_remove(grp, count, ids_up, result_up);
673 lstcon_group_put(grp);
674 /* release empty group */
675 if (list_empty(&grp->grp_ndl_list))
676 lstcon_group_put(grp);
682 lstcon_group_refresh(char *name, struct list_head *result_up)
684 lstcon_rpc_trans_t *trans;
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_put(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_put(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_put(grp);
724 lstcon_group_list(int index, int len, char *name_up)
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, lstcon_node_ent_t *dents_up)
745 lstcon_ndlink_t *ndl;
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, lstcon_ndlist_ent_t *gents_p,
783 int *index_p, int *count_p, lstcon_node_ent_t *dents_up)
785 lstcon_ndlist_ent_t *gentp;
787 lstcon_ndlink_t *ndl;
790 rc = lstcon_group_find(name, &grp);
792 CDEBUG(D_NET, "Can't find group %s\n", name);
798 rc = lstcon_nodes_getent(&grp->grp_ndl_list,
799 index_p, count_p, dents_up);
800 lstcon_group_put(grp);
805 /* non-verbose query */
806 LIBCFS_ALLOC(gentp, sizeof(lstcon_ndlist_ent_t));
808 CERROR("Can't allocate ndlist_ent\n");
809 lstcon_group_put(grp);
814 list_for_each_entry(ndl, &grp->grp_ndl_list, ndl_link)
815 LST_NODE_STATE_COUNTER(ndl->ndl_node, gentp);
817 rc = copy_to_user(gents_p, gentp,
818 sizeof(lstcon_ndlist_ent_t)) ? -EFAULT : 0;
820 LIBCFS_FREE(gentp, sizeof(lstcon_ndlist_ent_t));
822 lstcon_group_put(grp);
828 lstcon_batch_find(const char *name, lstcon_batch_t **batpp)
832 list_for_each_entry(bat, &console_session.ses_bat_list, bat_link) {
833 if (strncmp(bat->bat_name, name, LST_NAME_SIZE) == 0) {
843 lstcon_batch_add(char *name)
849 rc = (lstcon_batch_find(name, &bat) == 0) ? -EEXIST : 0;
851 CDEBUG(D_NET, "Batch %s already exists\n", name);
855 LIBCFS_ALLOC(bat, sizeof(lstcon_batch_t));
857 CERROR("Can't allocate descriptor for batch %s\n", name);
861 LIBCFS_ALLOC(bat->bat_cli_hash,
862 sizeof(struct list_head) * LST_NODE_HASHSIZE);
863 if (bat->bat_cli_hash == NULL) {
864 CERROR("Can't allocate hash for batch %s\n", name);
865 LIBCFS_FREE(bat, sizeof(lstcon_batch_t));
870 LIBCFS_ALLOC(bat->bat_srv_hash,
871 sizeof(struct list_head) * LST_NODE_HASHSIZE);
872 if (bat->bat_srv_hash == NULL) {
873 CERROR("Can't allocate hash for batch %s\n", name);
874 LIBCFS_FREE(bat->bat_cli_hash, LST_NODE_HASHSIZE);
875 LIBCFS_FREE(bat, sizeof(lstcon_batch_t));
880 strcpy(bat->bat_name, name);
881 bat->bat_hdr.tsb_index = 0;
882 bat->bat_hdr.tsb_id.bat_id = ++console_session.ses_id_cookie;
885 bat->bat_state = LST_BATCH_IDLE;
887 INIT_LIST_HEAD(&bat->bat_cli_list);
888 INIT_LIST_HEAD(&bat->bat_srv_list);
889 INIT_LIST_HEAD(&bat->bat_test_list);
890 INIT_LIST_HEAD(&bat->bat_trans_list);
892 for (i = 0; i < LST_NODE_HASHSIZE; i++) {
893 INIT_LIST_HEAD(&bat->bat_cli_hash[i]);
894 INIT_LIST_HEAD(&bat->bat_srv_hash[i]);
897 list_add_tail(&bat->bat_link, &console_session.ses_bat_list);
903 lstcon_batch_list(int index, int len, char *name_up)
907 LASSERT(name_up != NULL);
910 list_for_each_entry(bat, &console_session.ses_bat_list, bat_link) {
912 return copy_to_user(name_up, bat->bat_name, len) ?
921 lstcon_batch_info(char *name, lstcon_test_batch_ent_t *ent_up, int server,
922 int testidx, int *index_p, int *ndent_p,
923 lstcon_node_ent_t *dents_up)
925 lstcon_test_batch_ent_t *entp;
926 struct list_head *clilst;
927 struct list_head *srvlst;
928 lstcon_test_t *test = NULL;
930 lstcon_ndlink_t *ndl;
933 rc = lstcon_batch_find(name, &bat);
935 CDEBUG(D_NET, "Can't find batch %s\n", name);
940 /* query test, test index start from 1 */
941 list_for_each_entry(test, &bat->bat_test_list, tes_link) {
947 CDEBUG(D_NET, "Can't find specified test in batch\n");
952 clilst = (test == NULL) ? &bat->bat_cli_list :
953 &test->tes_src_grp->grp_ndl_list;
954 srvlst = (test == NULL) ? &bat->bat_srv_list :
955 &test->tes_dst_grp->grp_ndl_list;
957 if (dents_up != NULL) {
958 rc = lstcon_nodes_getent((server ? srvlst : clilst),
959 index_p, ndent_p, dents_up);
963 /* non-verbose query */
964 LIBCFS_ALLOC(entp, sizeof(lstcon_test_batch_ent_t));
969 entp->u.tbe_batch.bae_ntest = bat->bat_ntest;
970 entp->u.tbe_batch.bae_state = bat->bat_state;
974 entp->u.tbe_test.tse_type = test->tes_type;
975 entp->u.tbe_test.tse_loop = test->tes_loop;
976 entp->u.tbe_test.tse_concur = test->tes_concur;
979 list_for_each_entry(ndl, clilst, ndl_link)
980 LST_NODE_STATE_COUNTER(ndl->ndl_node, &entp->tbe_cli_nle);
982 list_for_each_entry(ndl, srvlst, ndl_link)
983 LST_NODE_STATE_COUNTER(ndl->ndl_node, &entp->tbe_srv_nle);
985 rc = copy_to_user(ent_up, entp,
986 sizeof(lstcon_test_batch_ent_t)) ? -EFAULT : 0;
988 LIBCFS_FREE(entp, sizeof(lstcon_test_batch_ent_t));
994 lstcon_batrpc_condition(int transop, lstcon_node_t *nd, void *arg)
997 case LST_TRANS_TSBRUN:
998 if (nd->nd_state != LST_NODE_ACTIVE)
1002 case LST_TRANS_TSBSTOP:
1003 if (nd->nd_state != LST_NODE_ACTIVE)
1007 case LST_TRANS_TSBCLIQRY:
1008 case LST_TRANS_TSBSRVQRY:
1016 lstcon_batch_op(lstcon_batch_t *bat, int transop,
1017 struct list_head *result_up)
1019 lstcon_rpc_trans_t *trans;
1022 rc = lstcon_rpc_trans_ndlist(&bat->bat_cli_list,
1023 &bat->bat_trans_list, transop,
1024 bat, lstcon_batrpc_condition, &trans);
1026 CERROR("Can't create transaction: %d\n", rc);
1030 lstcon_rpc_trans_postwait(trans, LST_TRANS_TIMEOUT);
1032 rc = lstcon_rpc_trans_interpreter(trans, result_up, NULL);
1034 lstcon_rpc_trans_destroy(trans);
1040 lstcon_batch_run(char *name, int timeout, struct list_head *result_up)
1042 lstcon_batch_t *bat;
1045 if (lstcon_batch_find(name, &bat) != 0) {
1046 CDEBUG(D_NET, "Can't find batch %s\n", name);
1050 bat->bat_arg = timeout;
1052 rc = lstcon_batch_op(bat, LST_TRANS_TSBRUN, result_up);
1054 /* mark batch as running if it's started in any node */
1055 if (lstcon_tsbop_stat_success(lstcon_trans_stat(), 0) != 0)
1056 bat->bat_state = LST_BATCH_RUNNING;
1062 lstcon_batch_stop(char *name, int force, struct list_head *result_up)
1064 lstcon_batch_t *bat;
1067 if (lstcon_batch_find(name, &bat) != 0) {
1068 CDEBUG(D_NET, "Can't find batch %s\n", name);
1072 bat->bat_arg = force;
1074 rc = lstcon_batch_op(bat, LST_TRANS_TSBSTOP, result_up);
1076 /* mark batch as stopped if all RPCs finished */
1077 if (lstcon_tsbop_stat_failure(lstcon_trans_stat(), 0) == 0)
1078 bat->bat_state = LST_BATCH_IDLE;
1084 lstcon_batch_destroy(lstcon_batch_t *bat)
1086 lstcon_ndlink_t *ndl;
1087 lstcon_test_t *test;
1090 list_del(&bat->bat_link);
1092 while (!list_empty(&bat->bat_test_list)) {
1093 test = list_entry(bat->bat_test_list.next,
1094 lstcon_test_t, tes_link);
1095 LASSERT(list_empty(&test->tes_trans_list));
1097 list_del(&test->tes_link);
1099 lstcon_group_put(test->tes_src_grp);
1100 lstcon_group_put(test->tes_dst_grp);
1102 LIBCFS_FREE(test, offsetof(lstcon_test_t,
1103 tes_param[test->tes_paramlen]));
1106 LASSERT(list_empty(&bat->bat_trans_list));
1108 while (!list_empty(&bat->bat_cli_list)) {
1109 ndl = list_entry(bat->bat_cli_list.next,
1110 lstcon_ndlink_t, ndl_link);
1111 list_del_init(&ndl->ndl_link);
1113 lstcon_ndlink_release(ndl);
1116 while (!list_empty(&bat->bat_srv_list)) {
1117 ndl = list_entry(bat->bat_srv_list.next,
1118 lstcon_ndlink_t, ndl_link);
1119 list_del_init(&ndl->ndl_link);
1121 lstcon_ndlink_release(ndl);
1124 for (i = 0; i < LST_NODE_HASHSIZE; i++) {
1125 LASSERT(list_empty(&bat->bat_cli_hash[i]));
1126 LASSERT(list_empty(&bat->bat_srv_hash[i]));
1129 LIBCFS_FREE(bat->bat_cli_hash,
1130 sizeof(struct list_head) * LST_NODE_HASHSIZE);
1131 LIBCFS_FREE(bat->bat_srv_hash,
1132 sizeof(struct list_head) * LST_NODE_HASHSIZE);
1133 LIBCFS_FREE(bat, sizeof(lstcon_batch_t));
1137 lstcon_testrpc_condition(int transop, lstcon_node_t *nd, void *arg)
1139 lstcon_test_t *test;
1140 lstcon_batch_t *batch;
1141 lstcon_ndlink_t *ndl;
1142 struct list_head *hash;
1143 struct list_head *head;
1145 test = (lstcon_test_t *)arg;
1146 LASSERT(test != NULL);
1148 batch = test->tes_batch;
1149 LASSERT(batch != NULL);
1151 if (test->tes_oneside &&
1152 transop == LST_TRANS_TSBSRVADD)
1155 if (nd->nd_state != LST_NODE_ACTIVE)
1158 if (transop == LST_TRANS_TSBCLIADD) {
1159 hash = batch->bat_cli_hash;
1160 head = &batch->bat_cli_list;
1163 LASSERT(transop == LST_TRANS_TSBSRVADD);
1165 hash = batch->bat_srv_hash;
1166 head = &batch->bat_srv_list;
1169 LASSERT(nd->nd_id.nid != LNET_NID_ANY);
1171 if (lstcon_ndlink_find(hash, nd->nd_id, &ndl, 1) != 0)
1174 if (list_empty(&ndl->ndl_link))
1175 list_add_tail(&ndl->ndl_link, head);
1181 lstcon_test_nodes_add(lstcon_test_t *test, struct list_head *result_up)
1183 lstcon_rpc_trans_t *trans;
1184 lstcon_group_t *grp;
1188 LASSERT(test->tes_src_grp != NULL);
1189 LASSERT(test->tes_dst_grp != NULL);
1191 transop = LST_TRANS_TSBSRVADD;
1192 grp = test->tes_dst_grp;
1194 rc = lstcon_rpc_trans_ndlist(&grp->grp_ndl_list,
1195 &test->tes_trans_list, transop,
1196 test, lstcon_testrpc_condition, &trans);
1198 CERROR("Can't create transaction: %d\n", rc);
1202 lstcon_rpc_trans_postwait(trans, LST_TRANS_TIMEOUT);
1204 if (lstcon_trans_stat()->trs_rpc_errno != 0 ||
1205 lstcon_trans_stat()->trs_fwk_errno != 0) {
1206 lstcon_rpc_trans_interpreter(trans, result_up, NULL);
1208 lstcon_rpc_trans_destroy(trans);
1209 /* return if any error */
1210 CDEBUG(D_NET, "Failed to add test %s, RPC error %d, framework error %d\n",
1211 transop == LST_TRANS_TSBCLIADD ? "client" : "server",
1212 lstcon_trans_stat()->trs_rpc_errno,
1213 lstcon_trans_stat()->trs_fwk_errno);
1218 lstcon_rpc_trans_destroy(trans);
1220 if (transop == LST_TRANS_TSBCLIADD)
1223 transop = LST_TRANS_TSBCLIADD;
1224 grp = test->tes_src_grp;
1225 test->tes_cliidx = 0;
1227 /* requests to test clients */
1232 lstcon_verify_batch(const char *name, lstcon_batch_t **batch)
1236 rc = lstcon_batch_find(name, batch);
1238 CDEBUG(D_NET, "Can't find batch %s\n", name);
1242 if ((*batch)->bat_state != LST_BATCH_IDLE) {
1243 CDEBUG(D_NET, "Can't change running batch %s\n", name);
1251 lstcon_verify_group(const char *name, lstcon_group_t **grp)
1254 lstcon_ndlink_t *ndl;
1256 rc = lstcon_group_find(name, grp);
1258 CDEBUG(D_NET, "can't find group %s\n", name);
1262 list_for_each_entry(ndl, &(*grp)->grp_ndl_list, ndl_link) {
1263 if (ndl->ndl_node->nd_state == LST_NODE_ACTIVE)
1267 CDEBUG(D_NET, "Group %s has no ACTIVE nodes\n", name);
1273 lstcon_test_add(char *batch_name, int type, int loop,
1274 int concur, int dist, int span,
1275 char *src_name, char *dst_name,
1276 void *param, int paramlen, int *retp,
1277 struct list_head *result_up)
1279 lstcon_test_t *test = NULL;
1281 lstcon_group_t *src_grp = NULL;
1282 lstcon_group_t *dst_grp = NULL;
1283 lstcon_batch_t *batch = NULL;
1286 * verify that a batch of the given name exists, and the groups
1287 * that will be part of the batch exist and have at least one
1290 rc = lstcon_verify_batch(batch_name, &batch);
1294 rc = lstcon_verify_group(src_name, &src_grp);
1298 rc = lstcon_verify_group(dst_name, &dst_grp);
1302 if (dst_grp->grp_userland)
1305 LIBCFS_ALLOC(test, offsetof(lstcon_test_t, tes_param[paramlen]));
1307 CERROR("Can't allocate test descriptor\n");
1313 test->tes_hdr.tsb_id = batch->bat_hdr.tsb_id;
1314 test->tes_batch = batch;
1315 test->tes_type = type;
1316 test->tes_oneside = 0; /* TODO */
1317 test->tes_loop = loop;
1318 test->tes_concur = concur;
1319 test->tes_stop_onerr = 1; /* TODO */
1320 test->tes_span = span;
1321 test->tes_dist = dist;
1322 test->tes_cliidx = 0; /* just used for creating RPC */
1323 test->tes_src_grp = src_grp;
1324 test->tes_dst_grp = dst_grp;
1325 INIT_LIST_HEAD(&test->tes_trans_list);
1327 if (param != NULL) {
1328 test->tes_paramlen = paramlen;
1329 memcpy(&test->tes_param[0], param, paramlen);
1332 rc = lstcon_test_nodes_add(test, result_up);
1337 if (lstcon_trans_stat()->trs_rpc_errno != 0 ||
1338 lstcon_trans_stat()->trs_fwk_errno != 0)
1339 CDEBUG(D_NET, "Failed to add test %d to batch %s\n", type,
1342 /* add to test list anyway, so user can check what's going on */
1343 list_add_tail(&test->tes_link, &batch->bat_test_list);
1346 test->tes_hdr.tsb_index = batch->bat_ntest;
1348 /* hold groups so nobody can change them */
1352 LIBCFS_FREE(test, offsetof(lstcon_test_t, tes_param[paramlen]));
1354 if (dst_grp != NULL)
1355 lstcon_group_put(dst_grp);
1357 if (src_grp != NULL)
1358 lstcon_group_put(src_grp);
1364 lstcon_test_find(lstcon_batch_t *batch, int idx, lstcon_test_t **testpp)
1366 lstcon_test_t *test;
1368 list_for_each_entry(test, &batch->bat_test_list, tes_link) {
1369 if (idx == test->tes_hdr.tsb_index) {
1379 lstcon_tsbrpc_readent(int transop, srpc_msg_t *msg,
1380 lstcon_rpc_ent_t *ent_up)
1382 srpc_batch_reply_t *rep = &msg->msg_body.bat_reply;
1384 LASSERT(transop == LST_TRANS_TSBCLIQRY ||
1385 transop == LST_TRANS_TSBSRVQRY);
1387 /* positive errno, framework error code */
1388 if (copy_to_user(&ent_up->rpe_priv[0],
1389 &rep->bar_active, sizeof(rep->bar_active)))
1396 lstcon_test_batch_query(char *name, int testidx, int client,
1397 int timeout, struct list_head *result_up)
1399 lstcon_rpc_trans_t *trans;
1400 struct list_head *translist;
1401 struct list_head *ndlist;
1402 lstcon_tsb_hdr_t *hdr;
1403 lstcon_batch_t *batch;
1404 lstcon_test_t *test = NULL;
1408 rc = lstcon_batch_find(name, &batch);
1410 CDEBUG(D_NET, "Can't find batch: %s\n", name);
1415 translist = &batch->bat_trans_list;
1416 ndlist = &batch->bat_cli_list;
1417 hdr = &batch->bat_hdr;
1420 /* query specified test only */
1421 rc = lstcon_test_find(batch, testidx, &test);
1423 CDEBUG(D_NET, "Can't find test: %d\n", testidx);
1427 translist = &test->tes_trans_list;
1428 ndlist = &test->tes_src_grp->grp_ndl_list;
1429 hdr = &test->tes_hdr;
1432 transop = client ? LST_TRANS_TSBCLIQRY : LST_TRANS_TSBSRVQRY;
1434 rc = lstcon_rpc_trans_ndlist(ndlist, translist, transop, hdr,
1435 lstcon_batrpc_condition, &trans);
1437 CERROR("Can't create transaction: %d\n", rc);
1441 lstcon_rpc_trans_postwait(trans, timeout);
1443 if (testidx == 0 && /* query a batch, not a test */
1444 lstcon_rpc_stat_failure(lstcon_trans_stat(), 0) == 0 &&
1445 lstcon_tsbqry_stat_run(lstcon_trans_stat(), 0) == 0) {
1446 /* all RPCs finished, and no active test */
1447 batch->bat_state = LST_BATCH_IDLE;
1450 rc = lstcon_rpc_trans_interpreter(trans, result_up,
1451 lstcon_tsbrpc_readent);
1452 lstcon_rpc_trans_destroy(trans);
1458 lstcon_statrpc_readent(int transop, srpc_msg_t *msg,
1459 lstcon_rpc_ent_t *ent_up)
1461 srpc_stat_reply_t *rep = &msg->msg_body.stat_reply;
1462 sfw_counters_t *sfwk_stat;
1463 srpc_counters_t *srpc_stat;
1464 lnet_counters_t *lnet_stat;
1466 if (rep->str_status != 0)
1469 sfwk_stat = (sfw_counters_t *)&ent_up->rpe_payload[0];
1470 srpc_stat = (srpc_counters_t *)((char *)sfwk_stat + sizeof(*sfwk_stat));
1471 lnet_stat = (lnet_counters_t *)((char *)srpc_stat + sizeof(*srpc_stat));
1473 if (copy_to_user(sfwk_stat, &rep->str_fw, sizeof(*sfwk_stat)) ||
1474 copy_to_user(srpc_stat, &rep->str_rpc, sizeof(*srpc_stat)) ||
1475 copy_to_user(lnet_stat, &rep->str_lnet, sizeof(*lnet_stat)))
1482 lstcon_ndlist_stat(struct list_head *ndlist,
1483 int timeout, struct list_head *result_up)
1485 struct list_head head;
1486 lstcon_rpc_trans_t *trans;
1489 INIT_LIST_HEAD(&head);
1491 rc = lstcon_rpc_trans_ndlist(ndlist, &head,
1492 LST_TRANS_STATQRY, NULL, NULL, &trans);
1494 CERROR("Can't create transaction: %d\n", rc);
1498 lstcon_rpc_trans_postwait(trans, LST_VALIDATE_TIMEOUT(timeout));
1500 rc = lstcon_rpc_trans_interpreter(trans, result_up,
1501 lstcon_statrpc_readent);
1502 lstcon_rpc_trans_destroy(trans);
1508 lstcon_group_stat(char *grp_name, int timeout, struct list_head *result_up)
1510 lstcon_group_t *grp;
1513 rc = lstcon_group_find(grp_name, &grp);
1515 CDEBUG(D_NET, "Can't find group %s\n", grp_name);
1519 rc = lstcon_ndlist_stat(&grp->grp_ndl_list, timeout, result_up);
1521 lstcon_group_put(grp);
1527 lstcon_nodes_stat(int count, lnet_process_id_t *ids_up,
1528 int timeout, struct list_head *result_up)
1530 lstcon_ndlink_t *ndl;
1531 lstcon_group_t *tmp;
1532 lnet_process_id_t id;
1536 rc = lstcon_group_alloc(NULL, &tmp);
1538 CERROR("Out of memory\n");
1542 for (i = 0 ; i < count; i++) {
1543 if (copy_from_user(&id, &ids_up[i], sizeof(id))) {
1548 /* add to tmp group */
1549 rc = lstcon_group_ndlink_find(tmp, id, &ndl, 2);
1551 CDEBUG((rc == -ENOMEM) ? D_ERROR : D_NET,
1552 "Failed to find or create %s: %d\n",
1553 libcfs_id2str(id), rc);
1559 lstcon_group_put(tmp);
1563 rc = lstcon_ndlist_stat(&tmp->grp_ndl_list, timeout, result_up);
1565 lstcon_group_put(tmp);
1571 lstcon_debug_ndlist(struct list_head *ndlist,
1572 struct list_head *translist,
1573 int timeout, struct list_head *result_up)
1575 lstcon_rpc_trans_t *trans;
1578 rc = lstcon_rpc_trans_ndlist(ndlist, translist, LST_TRANS_SESQRY,
1579 NULL, lstcon_sesrpc_condition, &trans);
1581 CERROR("Can't create transaction: %d\n", rc);
1585 lstcon_rpc_trans_postwait(trans, LST_VALIDATE_TIMEOUT(timeout));
1587 rc = lstcon_rpc_trans_interpreter(trans, result_up,
1588 lstcon_sesrpc_readent);
1589 lstcon_rpc_trans_destroy(trans);
1595 lstcon_session_debug(int timeout, struct list_head *result_up)
1597 return lstcon_debug_ndlist(&console_session.ses_ndl_list,
1598 NULL, timeout, result_up);
1602 lstcon_batch_debug(int timeout, char *name,
1603 int client, struct list_head *result_up)
1605 lstcon_batch_t *bat;
1608 rc = lstcon_batch_find(name, &bat);
1612 rc = lstcon_debug_ndlist(client ? &bat->bat_cli_list :
1614 NULL, timeout, result_up);
1620 lstcon_group_debug(int timeout, char *name,
1621 struct list_head *result_up)
1623 lstcon_group_t *grp;
1626 rc = lstcon_group_find(name, &grp);
1630 rc = lstcon_debug_ndlist(&grp->grp_ndl_list, NULL,
1631 timeout, result_up);
1632 lstcon_group_put(grp);
1638 lstcon_nodes_debug(int timeout,
1639 int count, lnet_process_id_t *ids_up,
1640 struct list_head *result_up)
1642 lnet_process_id_t id;
1643 lstcon_ndlink_t *ndl;
1644 lstcon_group_t *grp;
1648 rc = lstcon_group_alloc(NULL, &grp);
1650 CDEBUG(D_NET, "Out of memory\n");
1654 for (i = 0; i < count; i++) {
1655 if (copy_from_user(&id, &ids_up[i], sizeof(id))) {
1660 /* node is added to tmp group */
1661 rc = lstcon_group_ndlink_find(grp, id, &ndl, 1);
1663 CERROR("Can't create node link\n");
1669 lstcon_group_put(grp);
1673 rc = lstcon_debug_ndlist(&grp->grp_ndl_list, NULL,
1674 timeout, result_up);
1676 lstcon_group_put(grp);
1682 lstcon_session_match(lst_sid_t sid)
1684 return (console_session.ses_id.ses_nid == sid.ses_nid &&
1685 console_session.ses_id.ses_stamp == sid.ses_stamp) ? 1 : 0;
1689 lstcon_new_session_id(lst_sid_t *sid)
1691 lnet_process_id_t id;
1693 LASSERT(console_session.ses_state == LST_SESSION_NONE);
1696 sid->ses_nid = id.nid;
1697 sid->ses_stamp = cfs_time_current();
1700 extern srpc_service_t lstcon_acceptor_service;
1703 lstcon_session_new(char *name, int key, unsigned feats,
1704 int timeout, int force, lst_sid_t *sid_up)
1709 if (console_session.ses_state != LST_SESSION_NONE) {
1710 /* session exists */
1712 CNETERR("Session %s already exists\n",
1713 console_session.ses_name);
1717 rc = lstcon_session_end();
1719 /* lstcon_session_end() only return local error */
1724 if ((feats & ~LST_FEATS_MASK) != 0) {
1725 CNETERR("Unknown session features %x\n",
1726 (feats & ~LST_FEATS_MASK));
1730 for (i = 0; i < LST_GLOBAL_HASHSIZE; i++)
1731 LASSERT(list_empty(&console_session.ses_ndl_hash[i]));
1733 lstcon_new_session_id(&console_session.ses_id);
1735 console_session.ses_key = key;
1736 console_session.ses_state = LST_SESSION_ACTIVE;
1737 console_session.ses_force = !!force;
1738 console_session.ses_features = feats;
1739 console_session.ses_feats_updated = 0;
1740 console_session.ses_timeout = (timeout <= 0) ?
1741 LST_CONSOLE_TIMEOUT : timeout;
1742 strcpy(console_session.ses_name, name);
1744 rc = lstcon_batch_add(LST_DEFAULT_BATCH);
1748 rc = lstcon_rpc_pinger_start();
1750 lstcon_batch_t *bat = NULL;
1752 lstcon_batch_find(LST_DEFAULT_BATCH, &bat);
1753 lstcon_batch_destroy(bat);
1758 if (copy_to_user(sid_up, &console_session.ses_id,
1759 sizeof(lst_sid_t)) == 0)
1762 lstcon_session_end();
1768 lstcon_session_info(lst_sid_t *sid_up, int *key_up, unsigned *featp,
1769 lstcon_ndlist_ent_t *ndinfo_up, char *name_up, int len)
1771 lstcon_ndlist_ent_t *entp;
1772 lstcon_ndlink_t *ndl;
1775 if (console_session.ses_state != LST_SESSION_ACTIVE)
1778 LIBCFS_ALLOC(entp, sizeof(*entp));
1782 list_for_each_entry(ndl, &console_session.ses_ndl_list, ndl_link)
1783 LST_NODE_STATE_COUNTER(ndl->ndl_node, entp);
1785 if (copy_to_user(sid_up, &console_session.ses_id,
1786 sizeof(lst_sid_t)) ||
1787 copy_to_user(key_up, &console_session.ses_key,
1789 copy_to_user(featp, &console_session.ses_features,
1791 copy_to_user(ndinfo_up, entp, sizeof(*entp)) ||
1792 copy_to_user(name_up, console_session.ses_name, len))
1795 LIBCFS_FREE(entp, sizeof(*entp));
1801 lstcon_session_end(void)
1803 lstcon_rpc_trans_t *trans;
1804 lstcon_group_t *grp;
1805 lstcon_batch_t *bat;
1808 LASSERT(console_session.ses_state == LST_SESSION_ACTIVE);
1810 rc = lstcon_rpc_trans_ndlist(&console_session.ses_ndl_list,
1811 NULL, LST_TRANS_SESEND, NULL,
1812 lstcon_sesrpc_condition, &trans);
1814 CERROR("Can't create transaction: %d\n", rc);
1818 console_session.ses_shutdown = 1;
1820 lstcon_rpc_pinger_stop();
1822 lstcon_rpc_trans_postwait(trans, LST_TRANS_TIMEOUT);
1824 lstcon_rpc_trans_destroy(trans);
1825 /* User can do nothing even rpc failed, so go on */
1827 /* waiting for orphan rpcs to die */
1828 lstcon_rpc_cleanup_wait();
1830 console_session.ses_id = LST_INVALID_SID;
1831 console_session.ses_state = LST_SESSION_NONE;
1832 console_session.ses_key = 0;
1833 console_session.ses_force = 0;
1834 console_session.ses_feats_updated = 0;
1836 /* destroy all batches */
1837 while (!list_empty(&console_session.ses_bat_list)) {
1838 bat = list_entry(console_session.ses_bat_list.next,
1839 lstcon_batch_t, bat_link);
1841 lstcon_batch_destroy(bat);
1844 /* destroy all groups */
1845 while (!list_empty(&console_session.ses_grp_list)) {
1846 grp = list_entry(console_session.ses_grp_list.next,
1847 lstcon_group_t, grp_link);
1848 LASSERT(grp->grp_ref == 1);
1850 lstcon_group_put(grp);
1853 /* all nodes should be released */
1854 LASSERT(list_empty(&console_session.ses_ndl_list));
1856 console_session.ses_shutdown = 0;
1857 console_session.ses_expired = 0;
1863 lstcon_session_feats_check(unsigned feats)
1867 if ((feats & ~LST_FEATS_MASK) != 0) {
1868 CERROR("Can't support these features: %x\n",
1869 (feats & ~LST_FEATS_MASK));
1873 spin_lock(&console_session.ses_rpc_lock);
1875 if (!console_session.ses_feats_updated) {
1876 console_session.ses_feats_updated = 1;
1877 console_session.ses_features = feats;
1880 if (console_session.ses_features != feats)
1883 spin_unlock(&console_session.ses_rpc_lock);
1886 CERROR("remote features %x do not match with session features %x of console\n",
1887 feats, console_session.ses_features);
1894 lstcon_acceptor_handle(srpc_server_rpc_t *rpc)
1896 srpc_msg_t *rep = &rpc->srpc_replymsg;
1897 srpc_msg_t *req = &rpc->srpc_reqstbuf->buf_msg;
1898 srpc_join_reqst_t *jreq = &req->msg_body.join_reqst;
1899 srpc_join_reply_t *jrep = &rep->msg_body.join_reply;
1900 lstcon_group_t *grp = NULL;
1901 lstcon_ndlink_t *ndl;
1904 sfw_unpack_message(req);
1906 mutex_lock(&console_session.ses_mutex);
1908 jrep->join_sid = console_session.ses_id;
1910 if (console_session.ses_id.ses_nid == LNET_NID_ANY) {
1911 jrep->join_status = ESRCH;
1915 if (lstcon_session_feats_check(req->msg_ses_feats) != 0) {
1916 jrep->join_status = EPROTO;
1920 if (jreq->join_sid.ses_nid != LNET_NID_ANY &&
1921 !lstcon_session_match(jreq->join_sid)) {
1922 jrep->join_status = EBUSY;
1926 if (lstcon_group_find(jreq->join_group, &grp) != 0) {
1927 rc = lstcon_group_alloc(jreq->join_group, &grp);
1929 CERROR("Out of memory\n");
1933 list_add_tail(&grp->grp_link,
1934 &console_session.ses_grp_list);
1935 lstcon_group_addref(grp);
1938 if (grp->grp_ref > 2) {
1939 /* Group in using */
1940 jrep->join_status = EBUSY;
1944 rc = lstcon_group_ndlink_find(grp, rpc->srpc_peer, &ndl, 0);
1946 jrep->join_status = EEXIST;
1950 rc = lstcon_group_ndlink_find(grp, rpc->srpc_peer, &ndl, 1);
1952 CERROR("Out of memory\n");
1956 ndl->ndl_node->nd_state = LST_NODE_ACTIVE;
1957 ndl->ndl_node->nd_timeout = console_session.ses_timeout;
1959 if (grp->grp_userland == 0)
1960 grp->grp_userland = 1;
1962 strcpy(jrep->join_session, console_session.ses_name);
1963 jrep->join_timeout = console_session.ses_timeout;
1964 jrep->join_status = 0;
1967 rep->msg_ses_feats = console_session.ses_features;
1969 lstcon_group_put(grp);
1971 mutex_unlock(&console_session.ses_mutex);
1976 srpc_service_t lstcon_acceptor_service;
1977 static void lstcon_init_acceptor_service(void)
1979 /* initialize selftest console acceptor service table */
1980 lstcon_acceptor_service.sv_name = "join session";
1981 lstcon_acceptor_service.sv_handler = lstcon_acceptor_handle;
1982 lstcon_acceptor_service.sv_id = SRPC_SERVICE_JOIN;
1983 lstcon_acceptor_service.sv_wi_total = SFW_FRWK_WI_MAX;
1986 extern int lstcon_ioctl_entry(unsigned int cmd, struct libcfs_ioctl_data *data);
1988 static DECLARE_IOCTL_HANDLER(lstcon_ioctl_handler, lstcon_ioctl_entry);
1990 /* initialize console */
1992 lstcon_console_init(void)
1997 memset(&console_session, 0, sizeof(lstcon_session_t));
1999 console_session.ses_id = LST_INVALID_SID;
2000 console_session.ses_state = LST_SESSION_NONE;
2001 console_session.ses_timeout = 0;
2002 console_session.ses_force = 0;
2003 console_session.ses_expired = 0;
2004 console_session.ses_feats_updated = 0;
2005 console_session.ses_features = LST_FEATS_MASK;
2006 console_session.ses_laststamp = ktime_get_real_seconds();
2008 mutex_init(&console_session.ses_mutex);
2010 INIT_LIST_HEAD(&console_session.ses_ndl_list);
2011 INIT_LIST_HEAD(&console_session.ses_grp_list);
2012 INIT_LIST_HEAD(&console_session.ses_bat_list);
2013 INIT_LIST_HEAD(&console_session.ses_trans_list);
2015 LIBCFS_ALLOC(console_session.ses_ndl_hash,
2016 sizeof(struct list_head) * LST_GLOBAL_HASHSIZE);
2017 if (console_session.ses_ndl_hash == NULL)
2020 for (i = 0; i < LST_GLOBAL_HASHSIZE; i++)
2021 INIT_LIST_HEAD(&console_session.ses_ndl_hash[i]);
2023 /* initialize acceptor service table */
2024 lstcon_init_acceptor_service();
2026 rc = srpc_add_service(&lstcon_acceptor_service);
2027 LASSERT(rc != -EBUSY);
2029 LIBCFS_FREE(console_session.ses_ndl_hash,
2030 sizeof(struct list_head) * LST_GLOBAL_HASHSIZE);
2034 rc = srpc_service_add_buffers(&lstcon_acceptor_service,
2035 lstcon_acceptor_service.sv_wi_total);
2041 rc = libcfs_register_ioctl(&lstcon_ioctl_handler);
2044 lstcon_rpc_module_init();
2049 srpc_shutdown_service(&lstcon_acceptor_service);
2050 srpc_remove_service(&lstcon_acceptor_service);
2052 LIBCFS_FREE(console_session.ses_ndl_hash,
2053 sizeof(struct list_head) * LST_GLOBAL_HASHSIZE);
2055 srpc_wait_service_shutdown(&lstcon_acceptor_service);
2061 lstcon_console_fini(void)
2065 libcfs_deregister_ioctl(&lstcon_ioctl_handler);
2067 mutex_lock(&console_session.ses_mutex);
2069 srpc_shutdown_service(&lstcon_acceptor_service);
2070 srpc_remove_service(&lstcon_acceptor_service);
2072 if (console_session.ses_state != LST_SESSION_NONE)
2073 lstcon_session_end();
2075 lstcon_rpc_module_fini();
2077 mutex_unlock(&console_session.ses_mutex);
2079 LASSERT(list_empty(&console_session.ses_ndl_list));
2080 LASSERT(list_empty(&console_session.ses_grp_list));
2081 LASSERT(list_empty(&console_session.ses_bat_list));
2082 LASSERT(list_empty(&console_session.ses_trans_list));
2084 for (i = 0; i < LST_NODE_HASHSIZE; i++) {
2085 LASSERT(list_empty(&console_session.ses_ndl_hash[i]));
2088 LIBCFS_FREE(console_session.ses_ndl_hash,
2089 sizeof(struct list_head) * LST_GLOBAL_HASHSIZE);
2091 srpc_wait_service_shutdown(&lstcon_acceptor_service);