4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 only,
8 * as published by the Free Software Foundation.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License version 2 for more details (a copy is included
14 * in the LICENSE file that accompanied this code).
16 * You should have received a copy of the GNU General Public License
17 * version 2 along with this program; If not, see
18 * http://www.gnu.org/licenses/gpl-2.0.html
23 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Use is subject to license terms.
26 * Copyright (c) 2012, Intel Corporation.
29 * This file is part of Lustre, http://www.lustre.org/
30 * Lustre is a trademark of Sun Microsystems, Inc.
32 * lnet/selftest/conctl.c
34 * Infrastructure of LST console
36 * Author: Liang Zhen <liangzhen@clusterfs.com>
39 #include <linux/libcfs/libcfs.h>
40 #include <linux/lnet/lib-lnet.h>
44 #define LST_NODE_STATE_COUNTER(nd, p) \
46 if ((nd)->nd_state == LST_NODE_ACTIVE) \
48 else if ((nd)->nd_state == LST_NODE_BUSY) \
50 else if ((nd)->nd_state == LST_NODE_DOWN) \
53 (p)->nle_nunknown++; \
57 struct lstcon_session console_session;
60 lstcon_node_get(struct lstcon_node *nd)
62 LASSERT(nd->nd_ref >= 1);
68 lstcon_node_find(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 = cfs_time_current();
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(struct lstcon_rpc));
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
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(struct lstcon_node *nd)
119 struct lstcon_ndlink *ndl;
121 LASSERT(nd->nd_ref > 0);
123 if (--nd->nd_ref > 0)
126 ndl = (struct lstcon_ndlink *)(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(*nd) + sizeof(*ndl));
139 lstcon_ndlink_find(struct list_head *hash, struct lnet_process_id id,
140 struct lstcon_ndlink **ndlpp, int create)
142 unsigned int idx = LNET_NIDADDR(id.nid) % LST_NODE_HASHSIZE;
143 struct lstcon_ndlink *ndl;
144 struct lstcon_node *nd;
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(struct lstcon_ndlink));
177 INIT_LIST_HEAD(&ndl->ndl_link);
178 list_add_tail(&ndl->ndl_hlink, &hash[idx]);
184 lstcon_ndlink_release(struct lstcon_ndlink *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, struct lstcon_group **grpp)
198 struct lstcon_group *grp;
201 LIBCFS_ALLOC(grp, offsetof(struct lstcon_group,
202 grp_ndl_hash[LST_NODE_HASHSIZE]));
208 if (strlen(name) > sizeof(grp->grp_name) - 1) {
209 LIBCFS_FREE(grp, offsetof(struct lstcon_group,
210 grp_ndl_hash[LST_NODE_HASHSIZE]));
213 strncpy(grp->grp_name, name, sizeof(grp->grp_name));
216 INIT_LIST_HEAD(&grp->grp_link);
217 INIT_LIST_HEAD(&grp->grp_ndl_list);
218 INIT_LIST_HEAD(&grp->grp_trans_list);
220 for (i = 0; i < LST_NODE_HASHSIZE; i++)
221 INIT_LIST_HEAD(&grp->grp_ndl_hash[i]);
229 lstcon_group_addref(struct lstcon_group *grp)
234 static void lstcon_group_ndlink_release(struct lstcon_group *,
235 struct lstcon_ndlink *);
238 lstcon_group_drain(struct lstcon_group *grp, int keep)
240 struct lstcon_ndlink *ndl;
241 struct lstcon_ndlink *tmp;
243 list_for_each_entry_safe(ndl, tmp, &grp->grp_ndl_list, ndl_link) {
244 if (!(ndl->ndl_node->nd_state & keep))
245 lstcon_group_ndlink_release(grp, ndl);
250 lstcon_group_decref(struct lstcon_group *grp)
254 if (--grp->grp_ref > 0)
257 if (!list_empty(&grp->grp_link))
258 list_del(&grp->grp_link);
260 lstcon_group_drain(grp, 0);
262 for (i = 0; i < LST_NODE_HASHSIZE; i++)
263 LASSERT(list_empty(&grp->grp_ndl_hash[i]));
265 LIBCFS_FREE(grp, offsetof(struct lstcon_group,
266 grp_ndl_hash[LST_NODE_HASHSIZE]));
270 lstcon_group_find(const char *name, struct lstcon_group **grpp)
272 struct lstcon_group *grp;
274 list_for_each_entry(grp, &console_session.ses_grp_list, grp_link) {
275 if (strncmp(grp->grp_name, name, LST_NAME_SIZE))
278 lstcon_group_addref(grp); /* +1 ref for caller */
287 lstcon_group_ndlink_find(struct lstcon_group *grp, struct lnet_process_id id,
288 struct lstcon_ndlink **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(struct lstcon_group *grp, struct lstcon_ndlink *ndl)
308 list_del_init(&ndl->ndl_link);
309 lstcon_ndlink_release(ndl);
314 lstcon_group_ndlink_move(struct lstcon_group *old,
315 struct lstcon_group *new, struct lstcon_ndlink *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);
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 = (struct lstcon_group *)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 && 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))
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;
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 int *featp, struct list_head __user *result_up)
550 struct lstcon_group *grp;
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);
612 * -ref for session, it's destroyed,
613 * status can't be rolled back, destroy group anyway
615 lstcon_group_decref(grp);
621 lstcon_group_clean(char *name, int args)
623 struct lstcon_group *grp = NULL;
626 rc = lstcon_group_find(name, &grp);
628 CDEBUG(D_NET, "Can't find group %s\n", name);
632 if (grp->grp_ref > 2) {
633 /* referred by test */
634 CDEBUG(D_NET, "Group %s is busy\n", name);
635 lstcon_group_decref(grp);
639 args = (LST_NODE_ACTIVE | LST_NODE_BUSY |
640 LST_NODE_DOWN | LST_NODE_UNKNOWN) & ~args;
642 lstcon_group_drain(grp, args);
644 lstcon_group_decref(grp);
645 /* release empty group */
646 if (list_empty(&grp->grp_ndl_list))
647 lstcon_group_decref(grp);
653 lstcon_nodes_remove(char *name, int count,
654 struct lnet_process_id __user *ids_up,
655 struct list_head __user *result_up)
657 struct lstcon_group *grp = NULL;
660 rc = lstcon_group_find(name, &grp);
662 CDEBUG(D_NET, "Can't find group: %s\n", name);
666 if (grp->grp_ref > 2) {
667 /* referred by test */
668 CDEBUG(D_NET, "Group %s is busy\n", name);
669 lstcon_group_decref(grp);
673 rc = lstcon_group_nodes_remove(grp, count, ids_up, result_up);
675 lstcon_group_decref(grp);
676 /* release empty group */
677 if (list_empty(&grp->grp_ndl_list))
678 lstcon_group_decref(grp);
684 lstcon_group_refresh(char *name, struct list_head __user *result_up)
686 struct lstcon_rpc_trans *trans;
687 struct lstcon_group *grp;
690 rc = lstcon_group_find(name, &grp);
692 CDEBUG(D_NET, "Can't find group: %s\n", name);
696 if (grp->grp_ref > 2) {
697 /* referred by test */
698 CDEBUG(D_NET, "Group %s is busy\n", name);
699 lstcon_group_decref(grp);
703 /* re-invite all inactive nodes int the group */
704 rc = lstcon_rpc_trans_ndlist(&grp->grp_ndl_list,
705 &grp->grp_trans_list, LST_TRANS_SESNEW,
706 grp, lstcon_sesrpc_condition, &trans);
708 /* local error, return */
709 CDEBUG(D_NET, "Can't create transaction: %d\n", rc);
710 lstcon_group_decref(grp);
714 lstcon_rpc_trans_postwait(trans, LST_TRANS_TIMEOUT);
716 rc = lstcon_rpc_trans_interpreter(trans, result_up, NULL);
718 lstcon_rpc_trans_destroy(trans);
720 lstcon_group_decref(grp);
726 lstcon_group_list(int index, int len, char __user *name_up)
728 struct lstcon_group *grp;
733 list_for_each_entry(grp, &console_session.ses_grp_list, grp_link) {
735 return copy_to_user(name_up, grp->grp_name, len) ?
744 lstcon_nodes_getent(struct list_head *head, int *index_p,
745 int *count_p, struct lstcon_node_ent __user *dents_up)
747 struct lstcon_ndlink *ndl;
748 struct lstcon_node *nd;
752 LASSERT(index_p && count_p);
754 LASSERT(*index_p >= 0);
755 LASSERT(*count_p > 0);
757 list_for_each_entry(ndl, head, ndl_link) {
758 if (index++ < *index_p)
761 if (count >= *count_p)
765 if (copy_to_user(&dents_up[count].nde_id,
766 &nd->nd_id, sizeof(nd->nd_id)) ||
767 copy_to_user(&dents_up[count].nde_state,
768 &nd->nd_state, sizeof(nd->nd_state)))
774 if (index <= *index_p)
784 lstcon_group_info(char *name, struct lstcon_ndlist_ent __user *gents_p,
785 int *index_p, int *count_p,
786 struct lstcon_node_ent __user *dents_up)
788 struct lstcon_ndlist_ent *gentp;
789 struct lstcon_group *grp;
790 struct lstcon_ndlink *ndl;
793 rc = lstcon_group_find(name, &grp);
795 CDEBUG(D_NET, "Can't find group %s\n", name);
801 rc = lstcon_nodes_getent(&grp->grp_ndl_list,
802 index_p, count_p, dents_up);
803 lstcon_group_decref(grp);
808 /* non-verbose query */
809 LIBCFS_ALLOC(gentp, sizeof(struct lstcon_ndlist_ent));
811 CERROR("Can't allocate ndlist_ent\n");
812 lstcon_group_decref(grp);
817 list_for_each_entry(ndl, &grp->grp_ndl_list, ndl_link)
818 LST_NODE_STATE_COUNTER(ndl->ndl_node, gentp);
820 rc = copy_to_user(gents_p, gentp,
821 sizeof(struct lstcon_ndlist_ent)) ? -EFAULT : 0;
823 LIBCFS_FREE(gentp, sizeof(struct lstcon_ndlist_ent));
825 lstcon_group_decref(grp);
831 lstcon_batch_find(const char *name, struct lstcon_batch **batpp)
833 struct lstcon_batch *bat;
835 list_for_each_entry(bat, &console_session.ses_bat_list, bat_link) {
836 if (!strncmp(bat->bat_name, name, LST_NAME_SIZE)) {
846 lstcon_batch_add(char *name)
848 struct lstcon_batch *bat;
852 rc = !lstcon_batch_find(name, &bat) ? -EEXIST : 0;
854 CDEBUG(D_NET, "Batch %s already exists\n", name);
858 LIBCFS_ALLOC(bat, sizeof(struct lstcon_batch));
860 CERROR("Can't allocate descriptor for batch %s\n", name);
864 LIBCFS_ALLOC(bat->bat_cli_hash,
865 sizeof(struct list_head) * LST_NODE_HASHSIZE);
866 if (!bat->bat_cli_hash) {
867 CERROR("Can't allocate hash for batch %s\n", name);
868 LIBCFS_FREE(bat, sizeof(struct lstcon_batch));
873 LIBCFS_ALLOC(bat->bat_srv_hash,
874 sizeof(struct list_head) * LST_NODE_HASHSIZE);
875 if (!bat->bat_srv_hash) {
876 CERROR("Can't allocate hash for batch %s\n", name);
877 LIBCFS_FREE(bat->bat_cli_hash, LST_NODE_HASHSIZE);
878 LIBCFS_FREE(bat, sizeof(struct lstcon_batch));
883 if (strlen(name) > sizeof(bat->bat_name) - 1) {
884 LIBCFS_FREE(bat->bat_srv_hash, LST_NODE_HASHSIZE);
885 LIBCFS_FREE(bat->bat_cli_hash, LST_NODE_HASHSIZE);
886 LIBCFS_FREE(bat, sizeof(struct lstcon_batch));
889 strncpy(bat->bat_name, name, sizeof(bat->bat_name));
890 bat->bat_hdr.tsb_index = 0;
891 bat->bat_hdr.tsb_id.bat_id = ++console_session.ses_id_cookie;
894 bat->bat_state = LST_BATCH_IDLE;
896 INIT_LIST_HEAD(&bat->bat_cli_list);
897 INIT_LIST_HEAD(&bat->bat_srv_list);
898 INIT_LIST_HEAD(&bat->bat_test_list);
899 INIT_LIST_HEAD(&bat->bat_trans_list);
901 for (i = 0; i < LST_NODE_HASHSIZE; i++) {
902 INIT_LIST_HEAD(&bat->bat_cli_hash[i]);
903 INIT_LIST_HEAD(&bat->bat_srv_hash[i]);
906 list_add_tail(&bat->bat_link, &console_session.ses_bat_list);
912 lstcon_batch_list(int index, int len, char __user *name_up)
914 struct lstcon_batch *bat;
919 list_for_each_entry(bat, &console_session.ses_bat_list, bat_link) {
921 return copy_to_user(name_up, bat->bat_name, len) ?
930 lstcon_batch_info(char *name, struct lstcon_test_batch_ent __user *ent_up,
931 int server, int testidx, int *index_p, int *ndent_p,
932 struct lstcon_node_ent __user *dents_up)
934 struct lstcon_test_batch_ent *entp;
935 struct list_head *clilst;
936 struct list_head *srvlst;
937 struct lstcon_test *test = NULL;
938 struct lstcon_batch *bat;
939 struct lstcon_ndlink *ndl;
942 rc = lstcon_batch_find(name, &bat);
944 CDEBUG(D_NET, "Can't find batch %s\n", name);
949 /* query test, test index start from 1 */
950 list_for_each_entry(test, &bat->bat_test_list, tes_link) {
956 CDEBUG(D_NET, "Can't find specified test in batch\n");
961 clilst = !test ? &bat->bat_cli_list :
962 &test->tes_src_grp->grp_ndl_list;
963 srvlst = !test ? &bat->bat_srv_list :
964 &test->tes_dst_grp->grp_ndl_list;
967 rc = lstcon_nodes_getent((server ? srvlst : clilst),
968 index_p, ndent_p, dents_up);
972 /* non-verbose query */
973 LIBCFS_ALLOC(entp, sizeof(struct lstcon_test_batch_ent));
978 entp->u.tbe_batch.bae_ntest = bat->bat_ntest;
979 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)) {
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))
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)) {
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))
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(struct lstcon_batch));
1144 lstcon_testrpc_condition(int transop, struct lstcon_node *nd, void *arg)
1146 struct lstcon_test *test;
1147 struct lstcon_batch *batch;
1148 struct lstcon_ndlink *ndl;
1149 struct list_head *hash;
1150 struct list_head *head;
1152 test = (struct lstcon_test *)arg;
1155 batch = test->tes_batch;
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))
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);
1197 LASSERT(test->tes_dst_grp);
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 ||
1213 lstcon_trans_stat()->trs_fwk_errno) {
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, 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)
1275 CDEBUG(D_NET, "Group %s has no ACTIVE nodes\n", name);
1281 lstcon_test_add(char *batch_name, int type, int loop,
1282 int concur, int dist, int span,
1283 char *src_name, char *dst_name,
1284 void *param, int paramlen, int *retp,
1285 struct list_head __user *result_up)
1287 struct lstcon_test *test = NULL;
1289 struct lstcon_group *src_grp = NULL;
1290 struct lstcon_group *dst_grp = NULL;
1291 struct lstcon_batch *batch = NULL;
1294 * verify that a batch of the given name exists, and the groups
1295 * that will be part of the batch exist and have at least one
1298 rc = lstcon_verify_batch(batch_name, &batch);
1302 rc = lstcon_verify_group(src_name, &src_grp);
1306 rc = lstcon_verify_group(dst_name, &dst_grp);
1310 if (dst_grp->grp_userland)
1313 LIBCFS_ALLOC(test, offsetof(struct lstcon_test, tes_param[paramlen]));
1315 CERROR("Can't allocate test descriptor\n");
1321 test->tes_hdr.tsb_id = batch->bat_hdr.tsb_id;
1322 test->tes_batch = batch;
1323 test->tes_type = type;
1324 test->tes_oneside = 0; /* TODO */
1325 test->tes_loop = loop;
1326 test->tes_concur = concur;
1327 test->tes_stop_onerr = 1; /* TODO */
1328 test->tes_span = span;
1329 test->tes_dist = dist;
1330 test->tes_cliidx = 0; /* just used for creating RPC */
1331 test->tes_src_grp = src_grp;
1332 test->tes_dst_grp = dst_grp;
1333 INIT_LIST_HEAD(&test->tes_trans_list);
1336 test->tes_paramlen = paramlen;
1337 memcpy(&test->tes_param[0], param, paramlen);
1340 rc = lstcon_test_nodes_add(test, result_up);
1345 if (lstcon_trans_stat()->trs_rpc_errno ||
1346 lstcon_trans_stat()->trs_fwk_errno)
1347 CDEBUG(D_NET, "Failed to add test %d to batch %s\n", type,
1350 /* add to test list anyway, so user can check what's going on */
1351 list_add_tail(&test->tes_link, &batch->bat_test_list);
1354 test->tes_hdr.tsb_index = batch->bat_ntest;
1356 /* hold groups so nobody can change them */
1360 LIBCFS_FREE(test, offsetof(struct lstcon_test, tes_param[paramlen]));
1363 lstcon_group_decref(dst_grp);
1366 lstcon_group_decref(src_grp);
1372 lstcon_test_find(struct lstcon_batch *batch, int idx,
1373 struct lstcon_test **testpp)
1375 struct lstcon_test *test;
1377 list_for_each_entry(test, &batch->bat_test_list, tes_link) {
1378 if (idx == test->tes_hdr.tsb_index) {
1388 lstcon_tsbrpc_readent(int transop, struct srpc_msg *msg,
1389 struct lstcon_rpc_ent __user *ent_up)
1391 struct srpc_batch_reply *rep = &msg->msg_body.bat_reply;
1393 LASSERT(transop == LST_TRANS_TSBCLIQRY ||
1394 transop == LST_TRANS_TSBSRVQRY);
1396 /* positive errno, framework error code */
1397 if (copy_to_user(&ent_up->rpe_priv[0], &rep->bar_active,
1398 sizeof(rep->bar_active)))
1405 lstcon_test_batch_query(char *name, int testidx, int client,
1406 int timeout, struct list_head __user *result_up)
1408 struct lstcon_rpc_trans *trans;
1409 struct list_head *translist;
1410 struct list_head *ndlist;
1411 struct lstcon_tsb_hdr *hdr;
1412 struct lstcon_batch *batch;
1413 struct lstcon_test *test = NULL;
1417 rc = lstcon_batch_find(name, &batch);
1419 CDEBUG(D_NET, "Can't find batch: %s\n", name);
1424 translist = &batch->bat_trans_list;
1425 ndlist = &batch->bat_cli_list;
1426 hdr = &batch->bat_hdr;
1428 /* query specified test only */
1429 rc = lstcon_test_find(batch, testidx, &test);
1431 CDEBUG(D_NET, "Can't find test: %d\n", testidx);
1435 translist = &test->tes_trans_list;
1436 ndlist = &test->tes_src_grp->grp_ndl_list;
1437 hdr = &test->tes_hdr;
1440 transop = client ? LST_TRANS_TSBCLIQRY : LST_TRANS_TSBSRVQRY;
1442 rc = lstcon_rpc_trans_ndlist(ndlist, translist, transop, hdr,
1443 lstcon_batrpc_condition, &trans);
1445 CERROR("Can't create transaction: %d\n", rc);
1449 lstcon_rpc_trans_postwait(trans, timeout);
1451 /* query a batch, not a test */
1453 !lstcon_rpc_stat_failure(lstcon_trans_stat(), 0) &&
1454 !lstcon_tsbqry_stat_run(lstcon_trans_stat(), 0)) {
1455 /* all RPCs finished, and no active test */
1456 batch->bat_state = LST_BATCH_IDLE;
1459 rc = lstcon_rpc_trans_interpreter(trans, result_up,
1460 lstcon_tsbrpc_readent);
1461 lstcon_rpc_trans_destroy(trans);
1467 lstcon_statrpc_readent(int transop, struct srpc_msg *msg,
1468 struct lstcon_rpc_ent __user *ent_up)
1470 struct srpc_stat_reply *rep = &msg->msg_body.stat_reply;
1471 struct sfw_counters __user *sfwk_stat;
1472 struct srpc_counters __user *srpc_stat;
1473 struct lnet_counters __user *lnet_stat;
1475 if (rep->str_status)
1478 sfwk_stat = (struct sfw_counters __user *)&ent_up->rpe_payload[0];
1479 srpc_stat = (struct srpc_counters __user *)(sfwk_stat + 1);
1480 lnet_stat = (struct lnet_counters __user *)(srpc_stat + 1);
1482 if (copy_to_user(sfwk_stat, &rep->str_fw, sizeof(*sfwk_stat)) ||
1483 copy_to_user(srpc_stat, &rep->str_rpc, sizeof(*srpc_stat)) ||
1484 copy_to_user(lnet_stat, &rep->str_lnet, sizeof(*lnet_stat)))
1491 lstcon_ndlist_stat(struct list_head *ndlist,
1492 int timeout, struct list_head __user *result_up)
1494 struct list_head head;
1495 struct lstcon_rpc_trans *trans;
1498 INIT_LIST_HEAD(&head);
1500 rc = lstcon_rpc_trans_ndlist(ndlist, &head,
1501 LST_TRANS_STATQRY, NULL, NULL, &trans);
1503 CERROR("Can't create transaction: %d\n", rc);
1507 lstcon_rpc_trans_postwait(trans, LST_VALIDATE_TIMEOUT(timeout));
1509 rc = lstcon_rpc_trans_interpreter(trans, result_up,
1510 lstcon_statrpc_readent);
1511 lstcon_rpc_trans_destroy(trans);
1517 lstcon_group_stat(char *grp_name, int timeout,
1518 struct list_head __user *result_up)
1520 struct lstcon_group *grp;
1523 rc = lstcon_group_find(grp_name, &grp);
1525 CDEBUG(D_NET, "Can't find group %s\n", grp_name);
1529 rc = lstcon_ndlist_stat(&grp->grp_ndl_list, timeout, result_up);
1531 lstcon_group_decref(grp);
1537 lstcon_nodes_stat(int count, struct lnet_process_id __user *ids_up,
1538 int timeout, struct list_head __user *result_up)
1540 struct lstcon_ndlink *ndl;
1541 struct lstcon_group *tmp;
1542 struct lnet_process_id id;
1546 rc = lstcon_group_alloc(NULL, &tmp);
1548 CERROR("Out of memory\n");
1552 for (i = 0 ; i < count; i++) {
1553 if (copy_from_user(&id, &ids_up[i], sizeof(id))) {
1558 /* add to tmp group */
1559 rc = lstcon_group_ndlink_find(tmp, id, &ndl, 2);
1561 CDEBUG((rc == -ENOMEM) ? D_ERROR : D_NET,
1562 "Failed to find or create %s: %d\n",
1563 libcfs_id2str(id), rc);
1569 lstcon_group_decref(tmp);
1573 rc = lstcon_ndlist_stat(&tmp->grp_ndl_list, timeout, result_up);
1575 lstcon_group_decref(tmp);
1581 lstcon_debug_ndlist(struct list_head *ndlist,
1582 struct list_head *translist,
1583 int timeout, struct list_head __user *result_up)
1585 struct lstcon_rpc_trans *trans;
1588 rc = lstcon_rpc_trans_ndlist(ndlist, translist, LST_TRANS_SESQRY,
1589 NULL, lstcon_sesrpc_condition, &trans);
1591 CERROR("Can't create transaction: %d\n", rc);
1595 lstcon_rpc_trans_postwait(trans, LST_VALIDATE_TIMEOUT(timeout));
1597 rc = lstcon_rpc_trans_interpreter(trans, result_up,
1598 lstcon_sesrpc_readent);
1599 lstcon_rpc_trans_destroy(trans);
1605 lstcon_session_debug(int timeout, struct list_head __user *result_up)
1607 return lstcon_debug_ndlist(&console_session.ses_ndl_list,
1608 NULL, timeout, result_up);
1612 lstcon_batch_debug(int timeout, char *name,
1613 int client, struct list_head __user *result_up)
1615 struct lstcon_batch *bat;
1618 rc = lstcon_batch_find(name, &bat);
1622 rc = lstcon_debug_ndlist(client ? &bat->bat_cli_list :
1624 NULL, timeout, result_up);
1630 lstcon_group_debug(int timeout, char *name,
1631 struct list_head __user *result_up)
1633 struct lstcon_group *grp;
1636 rc = lstcon_group_find(name, &grp);
1640 rc = lstcon_debug_ndlist(&grp->grp_ndl_list, NULL,
1641 timeout, result_up);
1642 lstcon_group_decref(grp);
1648 lstcon_nodes_debug(int timeout, int count,
1649 struct lnet_process_id __user *ids_up,
1650 struct list_head __user *result_up)
1652 struct lnet_process_id id;
1653 struct lstcon_ndlink *ndl;
1654 struct lstcon_group *grp;
1658 rc = lstcon_group_alloc(NULL, &grp);
1660 CDEBUG(D_NET, "Out of memory\n");
1664 for (i = 0; i < count; i++) {
1665 if (copy_from_user(&id, &ids_up[i], sizeof(id))) {
1670 /* node is added to tmp group */
1671 rc = lstcon_group_ndlink_find(grp, id, &ndl, 1);
1673 CERROR("Can't create node link\n");
1679 lstcon_group_decref(grp);
1683 rc = lstcon_debug_ndlist(&grp->grp_ndl_list, NULL,
1684 timeout, result_up);
1686 lstcon_group_decref(grp);
1692 lstcon_session_match(struct lst_sid sid)
1694 return (console_session.ses_id.ses_nid == sid.ses_nid &&
1695 console_session.ses_id.ses_stamp == sid.ses_stamp) ? 1 : 0;
1699 lstcon_new_session_id(struct lst_sid *sid)
1701 struct lnet_process_id id;
1703 LASSERT(console_session.ses_state == LST_SESSION_NONE);
1706 sid->ses_nid = id.nid;
1707 sid->ses_stamp = cfs_time_current();
1711 lstcon_session_new(char *name, int key, unsigned int feats,
1712 int timeout, int force, struct lst_sid __user *sid_up)
1717 if (console_session.ses_state != LST_SESSION_NONE) {
1718 /* session exists */
1720 CNETERR("Session %s already exists\n",
1721 console_session.ses_name);
1725 rc = lstcon_session_end();
1727 /* lstcon_session_end() only return local error */
1732 if (feats & ~LST_FEATS_MASK) {
1733 CNETERR("Unknown session features %x\n",
1734 (feats & ~LST_FEATS_MASK));
1738 for (i = 0; i < LST_GLOBAL_HASHSIZE; i++)
1739 LASSERT(list_empty(&console_session.ses_ndl_hash[i]));
1741 lstcon_new_session_id(&console_session.ses_id);
1743 console_session.ses_key = key;
1744 console_session.ses_state = LST_SESSION_ACTIVE;
1745 console_session.ses_force = !!force;
1746 console_session.ses_features = feats;
1747 console_session.ses_feats_updated = 0;
1748 console_session.ses_timeout = (timeout <= 0) ?
1749 LST_CONSOLE_TIMEOUT : timeout;
1751 if (strlen(name) > sizeof(console_session.ses_name) - 1)
1753 strlcpy(console_session.ses_name, name,
1754 sizeof(console_session.ses_name));
1756 rc = lstcon_batch_add(LST_DEFAULT_BATCH);
1760 rc = lstcon_rpc_pinger_start();
1762 struct lstcon_batch *bat = NULL;
1764 lstcon_batch_find(LST_DEFAULT_BATCH, &bat);
1765 lstcon_batch_destroy(bat);
1770 if (!copy_to_user(sid_up, &console_session.ses_id,
1771 sizeof(struct lst_sid)))
1774 lstcon_session_end();
1780 lstcon_session_info(struct lst_sid __user *sid_up, int __user *key_up,
1781 unsigned __user *featp,
1782 struct lstcon_ndlist_ent __user *ndinfo_up,
1783 char __user *name_up, int len)
1785 struct lstcon_ndlist_ent *entp;
1786 struct lstcon_ndlink *ndl;
1789 if (console_session.ses_state != LST_SESSION_ACTIVE)
1792 LIBCFS_ALLOC(entp, sizeof(*entp));
1796 list_for_each_entry(ndl, &console_session.ses_ndl_list, ndl_link)
1797 LST_NODE_STATE_COUNTER(ndl->ndl_node, entp);
1799 if (copy_to_user(sid_up, &console_session.ses_id,
1801 copy_to_user(key_up, &console_session.ses_key,
1803 copy_to_user(featp, &console_session.ses_features,
1805 copy_to_user(ndinfo_up, entp, sizeof(*entp)) ||
1806 copy_to_user(name_up, console_session.ses_name, len))
1809 LIBCFS_FREE(entp, sizeof(*entp));
1815 lstcon_session_end(void)
1817 struct lstcon_rpc_trans *trans;
1818 struct lstcon_group *grp;
1819 struct lstcon_batch *bat;
1822 LASSERT(console_session.ses_state == LST_SESSION_ACTIVE);
1824 rc = lstcon_rpc_trans_ndlist(&console_session.ses_ndl_list,
1825 NULL, LST_TRANS_SESEND, NULL,
1826 lstcon_sesrpc_condition, &trans);
1828 CERROR("Can't create transaction: %d\n", rc);
1832 console_session.ses_shutdown = 1;
1834 lstcon_rpc_pinger_stop();
1836 lstcon_rpc_trans_postwait(trans, LST_TRANS_TIMEOUT);
1838 lstcon_rpc_trans_destroy(trans);
1839 /* User can do nothing even rpc failed, so go on */
1841 /* waiting for orphan rpcs to die */
1842 lstcon_rpc_cleanup_wait();
1844 console_session.ses_id = LST_INVALID_SID;
1845 console_session.ses_state = LST_SESSION_NONE;
1846 console_session.ses_key = 0;
1847 console_session.ses_force = 0;
1848 console_session.ses_feats_updated = 0;
1850 /* destroy all batches */
1851 while (!list_empty(&console_session.ses_bat_list)) {
1852 bat = list_entry(console_session.ses_bat_list.next,
1853 struct lstcon_batch, bat_link);
1855 lstcon_batch_destroy(bat);
1858 /* destroy all groups */
1859 while (!list_empty(&console_session.ses_grp_list)) {
1860 grp = list_entry(console_session.ses_grp_list.next,
1861 struct lstcon_group, grp_link);
1862 LASSERT(grp->grp_ref == 1);
1864 lstcon_group_decref(grp);
1867 /* all nodes should be released */
1868 LASSERT(list_empty(&console_session.ses_ndl_list));
1870 console_session.ses_shutdown = 0;
1871 console_session.ses_expired = 0;
1877 lstcon_session_feats_check(unsigned int feats)
1881 if (feats & ~LST_FEATS_MASK) {
1882 CERROR("Can't support these features: %x\n",
1883 (feats & ~LST_FEATS_MASK));
1887 spin_lock(&console_session.ses_rpc_lock);
1889 if (!console_session.ses_feats_updated) {
1890 console_session.ses_feats_updated = 1;
1891 console_session.ses_features = feats;
1894 if (console_session.ses_features != feats)
1897 spin_unlock(&console_session.ses_rpc_lock);
1900 CERROR("remote features %x do not match with session features %x of console\n",
1901 feats, console_session.ses_features);
1908 lstcon_acceptor_handle(struct srpc_server_rpc *rpc)
1910 struct srpc_msg *rep = &rpc->srpc_replymsg;
1911 struct srpc_msg *req = &rpc->srpc_reqstbuf->buf_msg;
1912 struct srpc_join_reqst *jreq = &req->msg_body.join_reqst;
1913 struct srpc_join_reply *jrep = &rep->msg_body.join_reply;
1914 struct lstcon_group *grp = NULL;
1915 struct lstcon_ndlink *ndl;
1918 sfw_unpack_message(req);
1920 mutex_lock(&console_session.ses_mutex);
1922 jrep->join_sid = console_session.ses_id;
1924 if (console_session.ses_id.ses_nid == LNET_NID_ANY) {
1925 jrep->join_status = ESRCH;
1929 if (lstcon_session_feats_check(req->msg_ses_feats)) {
1930 jrep->join_status = EPROTO;
1934 if (jreq->join_sid.ses_nid != LNET_NID_ANY &&
1935 !lstcon_session_match(jreq->join_sid)) {
1936 jrep->join_status = EBUSY;
1940 if (lstcon_group_find(jreq->join_group, &grp)) {
1941 rc = lstcon_group_alloc(jreq->join_group, &grp);
1943 CERROR("Out of memory\n");
1947 list_add_tail(&grp->grp_link,
1948 &console_session.ses_grp_list);
1949 lstcon_group_addref(grp);
1952 if (grp->grp_ref > 2) {
1953 /* Group in using */
1954 jrep->join_status = EBUSY;
1958 rc = lstcon_group_ndlink_find(grp, rpc->srpc_peer, &ndl, 0);
1960 jrep->join_status = EEXIST;
1964 rc = lstcon_group_ndlink_find(grp, rpc->srpc_peer, &ndl, 1);
1966 CERROR("Out of memory\n");
1970 ndl->ndl_node->nd_state = LST_NODE_ACTIVE;
1971 ndl->ndl_node->nd_timeout = console_session.ses_timeout;
1973 if (!grp->grp_userland)
1974 grp->grp_userland = 1;
1976 strlcpy(jrep->join_session, console_session.ses_name,
1977 sizeof(jrep->join_session));
1978 jrep->join_timeout = console_session.ses_timeout;
1979 jrep->join_status = 0;
1982 rep->msg_ses_feats = console_session.ses_features;
1984 lstcon_group_decref(grp);
1986 mutex_unlock(&console_session.ses_mutex);
1991 static struct srpc_service lstcon_acceptor_service;
1993 static void lstcon_init_acceptor_service(void)
1995 /* initialize selftest console acceptor service table */
1996 lstcon_acceptor_service.sv_name = "join session";
1997 lstcon_acceptor_service.sv_handler = lstcon_acceptor_handle;
1998 lstcon_acceptor_service.sv_id = SRPC_SERVICE_JOIN;
1999 lstcon_acceptor_service.sv_wi_total = SFW_FRWK_WI_MAX;
2002 static DECLARE_IOCTL_HANDLER(lstcon_ioctl_handler, lstcon_ioctl_entry);
2004 /* initialize console */
2006 lstcon_console_init(void)
2011 memset(&console_session, 0, sizeof(struct lstcon_session));
2013 console_session.ses_id = LST_INVALID_SID;
2014 console_session.ses_state = LST_SESSION_NONE;
2015 console_session.ses_timeout = 0;
2016 console_session.ses_force = 0;
2017 console_session.ses_expired = 0;
2018 console_session.ses_feats_updated = 0;
2019 console_session.ses_features = LST_FEATS_MASK;
2020 console_session.ses_laststamp = ktime_get_real_seconds();
2022 mutex_init(&console_session.ses_mutex);
2024 INIT_LIST_HEAD(&console_session.ses_ndl_list);
2025 INIT_LIST_HEAD(&console_session.ses_grp_list);
2026 INIT_LIST_HEAD(&console_session.ses_bat_list);
2027 INIT_LIST_HEAD(&console_session.ses_trans_list);
2029 LIBCFS_ALLOC(console_session.ses_ndl_hash,
2030 sizeof(struct list_head) * LST_GLOBAL_HASHSIZE);
2031 if (!console_session.ses_ndl_hash)
2034 for (i = 0; i < LST_GLOBAL_HASHSIZE; i++)
2035 INIT_LIST_HEAD(&console_session.ses_ndl_hash[i]);
2037 /* initialize acceptor service table */
2038 lstcon_init_acceptor_service();
2040 rc = srpc_add_service(&lstcon_acceptor_service);
2041 LASSERT(rc != -EBUSY);
2043 LIBCFS_FREE(console_session.ses_ndl_hash,
2044 sizeof(struct list_head) * LST_GLOBAL_HASHSIZE);
2048 rc = srpc_service_add_buffers(&lstcon_acceptor_service,
2049 lstcon_acceptor_service.sv_wi_total);
2055 rc = libcfs_register_ioctl(&lstcon_ioctl_handler);
2058 lstcon_rpc_module_init();
2063 srpc_shutdown_service(&lstcon_acceptor_service);
2064 srpc_remove_service(&lstcon_acceptor_service);
2066 LIBCFS_FREE(console_session.ses_ndl_hash,
2067 sizeof(struct list_head) * LST_GLOBAL_HASHSIZE);
2069 srpc_wait_service_shutdown(&lstcon_acceptor_service);
2075 lstcon_console_fini(void)
2079 libcfs_deregister_ioctl(&lstcon_ioctl_handler);
2081 mutex_lock(&console_session.ses_mutex);
2083 srpc_shutdown_service(&lstcon_acceptor_service);
2084 srpc_remove_service(&lstcon_acceptor_service);
2086 if (console_session.ses_state != LST_SESSION_NONE)
2087 lstcon_session_end();
2089 lstcon_rpc_module_fini();
2091 mutex_unlock(&console_session.ses_mutex);
2093 LASSERT(list_empty(&console_session.ses_ndl_list));
2094 LASSERT(list_empty(&console_session.ses_grp_list));
2095 LASSERT(list_empty(&console_session.ses_bat_list));
2096 LASSERT(list_empty(&console_session.ses_trans_list));
2098 for (i = 0; i < LST_NODE_HASHSIZE; i++)
2099 LASSERT(list_empty(&console_session.ses_ndl_hash[i]));
2101 LIBCFS_FREE(console_session.ses_ndl_hash,
2102 sizeof(struct list_head) * LST_GLOBAL_HASHSIZE);
2104 srpc_wait_service_shutdown(&lstcon_acceptor_service);