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/
31 * lnet/selftest/conctl.c
33 * Infrastructure of LST console
35 * Author: Liang Zhen <liangzhen@clusterfs.com>
38 #include <libcfs/libcfs.h>
39 #include <lnet/lib-lnet.h>
43 #define LST_NODE_STATE_COUNTER(nd, p) \
45 if ((nd)->nd_state == LST_NODE_ACTIVE) \
46 (p)->nle_nactive ++; \
47 else if ((nd)->nd_state == LST_NODE_BUSY) \
49 else if ((nd)->nd_state == LST_NODE_DOWN) \
52 (p)->nle_nunknown ++; \
56 struct lstcon_session console_session;
59 lstcon_node_get(struct lstcon_node *nd)
61 LASSERT (nd->nd_ref >= 1);
67 lstcon_node_find(struct lnet_process_id id, struct lstcon_node **ndpp,
70 struct lstcon_ndlink *ndl;
71 unsigned int idx = LNET_NIDADDR(id.nid) % LST_GLOBAL_HASHSIZE;
73 LASSERT(id.nid != LNET_NID_ANY);
75 list_for_each_entry(ndl, &console_session.ses_ndl_hash[idx],
77 if (ndl->ndl_node->nd_id.nid != id.nid ||
78 ndl->ndl_node->nd_id.pid != id.pid)
81 lstcon_node_get(ndl->ndl_node);
82 *ndpp = ndl->ndl_node;
89 LIBCFS_ALLOC(*ndpp, sizeof(**ndpp) + sizeof(*ndl));
93 ndl = (struct lstcon_ndlink *)(*ndpp + 1);
95 ndl->ndl_node = *ndpp;
97 ndl->ndl_node->nd_ref = 1;
98 ndl->ndl_node->nd_id = id;
99 ndl->ndl_node->nd_stamp = ktime_get();
100 ndl->ndl_node->nd_state = LST_NODE_UNKNOWN;
101 ndl->ndl_node->nd_timeout = 0;
102 memset(&ndl->ndl_node->nd_ping, 0, sizeof(ndl->ndl_node->nd_ping));
104 /* queued in global hash & list, no refcount is taken by
105 * global hash & list, if caller release his refcount,
106 * node will be released */
107 list_add_tail(&ndl->ndl_hlink, &console_session.ses_ndl_hash[idx]);
108 list_add_tail(&ndl->ndl_link, &console_session.ses_ndl_list);
114 lstcon_node_put(struct lstcon_node *nd)
116 struct lstcon_ndlink *ndl;
118 LASSERT(nd->nd_ref > 0);
120 if (--nd->nd_ref > 0)
123 ndl = (struct lstcon_ndlink *)(nd + 1);
125 LASSERT(!list_empty(&ndl->ndl_link));
126 LASSERT(!list_empty(&ndl->ndl_hlink));
128 /* remove from session */
129 list_del(&ndl->ndl_link);
130 list_del(&ndl->ndl_hlink);
132 LIBCFS_FREE(nd, sizeof(*nd) + sizeof(*ndl));
136 lstcon_ndlink_find(struct list_head *hash, struct lnet_process_id id,
137 struct lstcon_ndlink **ndlpp, int create)
139 unsigned int idx = LNET_NIDADDR(id.nid) % LST_NODE_HASHSIZE;
140 struct lstcon_ndlink *ndl;
141 struct lstcon_node *nd;
144 if (id.nid == LNET_NID_ANY)
148 list_for_each_entry(ndl, &hash[idx], ndl_hlink) {
149 if (ndl->ndl_node->nd_id.nid != id.nid ||
150 ndl->ndl_node->nd_id.pid != id.pid)
160 /* find or create in session hash */
161 rc = lstcon_node_find(id, &nd, (create == 1) ? 1 : 0);
165 LIBCFS_ALLOC(ndl, sizeof(*ndl));
174 INIT_LIST_HEAD(&ndl->ndl_link);
175 list_add_tail(&ndl->ndl_hlink, &hash[idx]);
181 lstcon_ndlink_release(struct lstcon_ndlink *ndl)
183 LASSERT(list_empty(&ndl->ndl_link));
184 LASSERT(!list_empty(&ndl->ndl_hlink));
186 list_del(&ndl->ndl_hlink); /* delete from hash */
187 lstcon_node_put(ndl->ndl_node);
189 LIBCFS_FREE(ndl, sizeof(*ndl));
193 lstcon_group_alloc(char *name, struct lstcon_group **grpp)
195 struct lstcon_group *grp;
198 LIBCFS_ALLOC(grp, offsetof(struct lstcon_group,
199 grp_ndl_hash[LST_NODE_HASHSIZE]));
205 if (strlen(name) > sizeof(grp->grp_name)-1) {
206 LIBCFS_FREE(grp, offsetof(struct lstcon_group,
207 grp_ndl_hash[LST_NODE_HASHSIZE]));
210 strncpy(grp->grp_name, name, sizeof(grp->grp_name));
213 INIT_LIST_HEAD(&grp->grp_link);
214 INIT_LIST_HEAD(&grp->grp_ndl_list);
215 INIT_LIST_HEAD(&grp->grp_trans_list);
217 for (i = 0; i < LST_NODE_HASHSIZE; i++)
218 INIT_LIST_HEAD(&grp->grp_ndl_hash[i]);
226 lstcon_group_addref(struct lstcon_group *grp)
231 static void lstcon_group_ndlink_release(struct lstcon_group *,
232 struct lstcon_ndlink *);
235 lstcon_group_drain(struct lstcon_group *grp, int keep)
237 struct lstcon_ndlink *ndl;
238 struct lstcon_ndlink *tmp;
240 list_for_each_entry_safe(ndl, tmp, &grp->grp_ndl_list, ndl_link) {
241 if ((ndl->ndl_node->nd_state & keep) == 0)
242 lstcon_group_ndlink_release(grp, ndl);
247 lstcon_group_decref(struct lstcon_group *grp)
251 if (--grp->grp_ref > 0)
254 if (!list_empty(&grp->grp_link))
255 list_del(&grp->grp_link);
257 lstcon_group_drain(grp, 0);
259 for (i = 0; i < LST_NODE_HASHSIZE; i++)
260 LASSERT(list_empty(&grp->grp_ndl_hash[i]));
262 LIBCFS_FREE(grp, offsetof(struct lstcon_group,
263 grp_ndl_hash[LST_NODE_HASHSIZE]));
267 lstcon_group_find(const char *name, struct lstcon_group **grpp)
269 struct lstcon_group *grp;
271 list_for_each_entry(grp, &console_session.ses_grp_list, grp_link) {
272 if (strncmp(grp->grp_name, name, LST_NAME_SIZE) != 0)
275 lstcon_group_addref(grp); /* +1 ref for caller */
284 lstcon_group_ndlink_find(struct lstcon_group *grp, struct lnet_process_id id,
285 struct lstcon_ndlink **ndlpp, int create)
289 rc = lstcon_ndlink_find(&grp->grp_ndl_hash[0], id, ndlpp, create);
293 if (!list_empty(&(*ndlpp)->ndl_link))
296 list_add_tail(&(*ndlpp)->ndl_link, &grp->grp_ndl_list);
303 lstcon_group_ndlink_release(struct lstcon_group *grp, struct lstcon_ndlink *ndl)
305 list_del_init(&ndl->ndl_link);
306 lstcon_ndlink_release(ndl);
311 lstcon_group_ndlink_move(struct lstcon_group *old,
312 struct lstcon_group *new, struct lstcon_ndlink *ndl)
314 unsigned int idx = LNET_NIDADDR(ndl->ndl_node->nd_id.nid) %
319 list_move_tail(&ndl->ndl_hlink, &new->grp_ndl_hash[idx]);
320 list_move_tail(&ndl->ndl_link, &new->grp_ndl_list);
325 lstcon_group_move(struct lstcon_group *old, struct lstcon_group *new)
327 struct lstcon_ndlink *ndl;
329 while (!list_empty(&old->grp_ndl_list)) {
330 ndl = list_entry(old->grp_ndl_list.next,
331 struct lstcon_ndlink, ndl_link);
332 lstcon_group_ndlink_move(old, new, ndl);
337 lstcon_sesrpc_condition(int transop, struct lstcon_node *nd, void *arg)
339 struct lstcon_group *grp = arg;
342 case LST_TRANS_SESNEW:
343 if (nd->nd_state == LST_NODE_ACTIVE)
347 case LST_TRANS_SESEND:
348 if (nd->nd_state != LST_NODE_ACTIVE)
351 if (grp != NULL && nd->nd_ref > 1)
355 case LST_TRANS_SESQRY:
366 lstcon_sesrpc_readent(int transop, struct srpc_msg *msg,
367 struct lstcon_rpc_ent __user *ent_up)
369 struct srpc_debug_reply *rep;
372 case LST_TRANS_SESNEW:
373 case LST_TRANS_SESEND:
376 case LST_TRANS_SESQRY:
377 rep = &msg->msg_body.dbg_reply;
379 if (copy_to_user(&ent_up->rpe_priv[0],
380 &rep->dbg_timeout, sizeof(int)) ||
381 copy_to_user(&ent_up->rpe_payload[0],
382 &rep->dbg_name, LST_NAME_SIZE))
395 lstcon_group_nodes_add(struct lstcon_group *grp,
396 int count, struct lnet_process_id __user *ids_up,
398 struct list_head __user *result_up)
400 struct lstcon_rpc_trans *trans;
401 struct lstcon_ndlink *ndl;
402 struct lstcon_group *tmp;
403 struct lnet_process_id id;
407 rc = lstcon_group_alloc(NULL, &tmp);
409 CERROR("Out of memory\n");
413 for (i = 0 ; i < count; i++) {
414 if (copy_from_user(&id, &ids_up[i], sizeof(id))) {
419 /* skip if it's in this group already */
420 rc = lstcon_group_ndlink_find(grp, id, &ndl, 0);
424 /* add to tmp group */
425 rc = lstcon_group_ndlink_find(tmp, id, &ndl, 1);
427 CERROR("Can't create ndlink, out of memory\n");
433 lstcon_group_decref(tmp);
437 rc = lstcon_rpc_trans_ndlist(&tmp->grp_ndl_list,
438 &tmp->grp_trans_list, LST_TRANS_SESNEW,
439 tmp, lstcon_sesrpc_condition, &trans);
441 CERROR("Can't create transaction: %d\n", rc);
442 lstcon_group_decref(tmp);
447 lstcon_rpc_trans_postwait(trans, LST_TRANS_TIMEOUT);
449 rc = lstcon_rpc_trans_interpreter(trans, result_up,
450 lstcon_sesrpc_readent);
451 *featp = trans->tas_features;
453 /* destroy all RPGs */
454 lstcon_rpc_trans_destroy(trans);
456 lstcon_group_move(tmp, grp);
457 lstcon_group_decref(tmp);
463 lstcon_group_nodes_remove(struct lstcon_group *grp,
464 int count, struct lnet_process_id __user *ids_up,
465 struct list_head __user *result_up)
467 struct lstcon_rpc_trans *trans;
468 struct lstcon_ndlink *ndl;
469 struct lstcon_group *tmp;
470 struct lnet_process_id id;
474 /* End session and remove node from the group */
476 rc = lstcon_group_alloc(NULL, &tmp);
478 CERROR("Out of memory\n");
482 for (i = 0; i < count; i++) {
483 if (copy_from_user(&id, &ids_up[i], sizeof(id))) {
488 /* move node to tmp group */
489 if (lstcon_group_ndlink_find(grp, id, &ndl, 0) == 0)
490 lstcon_group_ndlink_move(grp, tmp, ndl);
493 rc = lstcon_rpc_trans_ndlist(&tmp->grp_ndl_list,
494 &tmp->grp_trans_list, LST_TRANS_SESEND,
495 tmp, lstcon_sesrpc_condition, &trans);
497 CERROR("Can't create transaction: %d\n", rc);
501 lstcon_rpc_trans_postwait(trans, LST_TRANS_TIMEOUT);
503 rc = lstcon_rpc_trans_interpreter(trans, result_up, NULL);
505 lstcon_rpc_trans_destroy(trans);
506 /* release nodes anyway, because we can't rollback status */
507 lstcon_group_decref(tmp);
511 lstcon_group_move(tmp, grp);
512 lstcon_group_decref(tmp);
518 lstcon_group_add(char *name)
520 struct lstcon_group *grp;
523 rc = (lstcon_group_find(name, &grp) == 0)? -EEXIST: 0;
525 /* find a group with same name */
526 lstcon_group_decref(grp);
530 rc = lstcon_group_alloc(name, &grp);
532 CERROR("Can't allocate descriptor for group %s\n", name);
536 list_add_tail(&grp->grp_link, &console_session.ses_grp_list);
542 lstcon_nodes_add(char *name, int count, struct lnet_process_id __user *ids_up,
543 unsigned *featp, struct list_head __user *result_up)
545 struct lstcon_group *grp;
549 LASSERT (ids_up != NULL);
551 rc = lstcon_group_find(name, &grp);
553 CDEBUG(D_NET, "Can't find group %s\n", name);
557 if (grp->grp_ref > 2) {
558 /* referred by other threads or test */
559 CDEBUG(D_NET, "Group %s is busy\n", name);
560 lstcon_group_decref(grp);
565 rc = lstcon_group_nodes_add(grp, count, ids_up, featp, result_up);
567 lstcon_group_decref(grp);
573 lstcon_group_del(char *name)
575 struct lstcon_rpc_trans *trans;
576 struct lstcon_group *grp;
579 rc = lstcon_group_find(name, &grp);
581 CDEBUG(D_NET, "Can't find group: %s\n", name);
585 if (grp->grp_ref > 2) {
586 /* referred by others threads or test */
587 CDEBUG(D_NET, "Group %s is busy\n", name);
588 lstcon_group_decref(grp);
592 rc = lstcon_rpc_trans_ndlist(&grp->grp_ndl_list,
593 &grp->grp_trans_list, LST_TRANS_SESEND,
594 grp, lstcon_sesrpc_condition, &trans);
596 CERROR("Can't create transaction: %d\n", rc);
597 lstcon_group_decref(grp);
601 lstcon_rpc_trans_postwait(trans, LST_TRANS_TIMEOUT);
603 lstcon_rpc_trans_destroy(trans);
605 lstcon_group_decref(grp);
606 /* -ref for session, it's destroyed,
607 * status can't be rolled back, destroy group anway */
608 lstcon_group_decref(grp);
614 lstcon_group_clean(char *name, int args)
616 struct lstcon_group *grp = NULL;
619 rc = lstcon_group_find(name, &grp);
621 CDEBUG(D_NET, "Can't find group %s\n", name);
625 if (grp->grp_ref > 2) {
626 /* referred by test */
627 CDEBUG(D_NET, "Group %s is busy\n", name);
628 lstcon_group_decref(grp);
632 args = (LST_NODE_ACTIVE | LST_NODE_BUSY |
633 LST_NODE_DOWN | LST_NODE_UNKNOWN) & ~args;
635 lstcon_group_drain(grp, args);
637 lstcon_group_decref(grp);
638 /* release empty group */
639 if (list_empty(&grp->grp_ndl_list))
640 lstcon_group_decref(grp);
646 lstcon_nodes_remove(char *name, int count,
647 struct lnet_process_id __user *ids_up,
648 struct list_head __user *result_up)
650 struct lstcon_group *grp = NULL;
653 rc = lstcon_group_find(name, &grp);
655 CDEBUG(D_NET, "Can't find group: %s\n", name);
659 if (grp->grp_ref > 2) {
660 /* referred by test */
661 CDEBUG(D_NET, "Group %s is busy\n", name);
662 lstcon_group_decref(grp);
666 rc = lstcon_group_nodes_remove(grp, count, ids_up, result_up);
668 lstcon_group_decref(grp);
669 /* release empty group */
670 if (list_empty(&grp->grp_ndl_list))
671 lstcon_group_decref(grp);
677 lstcon_group_refresh(char *name, struct list_head __user *result_up)
679 struct lstcon_rpc_trans *trans;
680 struct lstcon_group *grp;
683 rc = lstcon_group_find(name, &grp);
685 CDEBUG(D_NET, "Can't find group: %s\n", name);
689 if (grp->grp_ref > 2) {
690 /* referred by test */
691 CDEBUG(D_NET, "Group %s is busy\n", name);
692 lstcon_group_decref(grp);
696 /* re-invite all inactive nodes int the group */
697 rc = lstcon_rpc_trans_ndlist(&grp->grp_ndl_list,
698 &grp->grp_trans_list, LST_TRANS_SESNEW,
699 grp, lstcon_sesrpc_condition, &trans);
701 /* local error, return */
702 CDEBUG(D_NET, "Can't create transaction: %d\n", rc);
703 lstcon_group_decref(grp);
707 lstcon_rpc_trans_postwait(trans, LST_TRANS_TIMEOUT);
709 rc = lstcon_rpc_trans_interpreter(trans, result_up, NULL);
711 lstcon_rpc_trans_destroy(trans);
713 lstcon_group_decref(grp);
719 lstcon_group_list(int index, int len, char __user *name_up)
721 struct lstcon_group *grp;
724 LASSERT(name_up != NULL);
726 list_for_each_entry(grp, &console_session.ses_grp_list, grp_link) {
728 return copy_to_user(name_up, grp->grp_name, len) ?
737 lstcon_nodes_getent(struct list_head *head, int *index_p,
738 int *count_p, struct lstcon_node_ent __user *dents_up)
740 struct lstcon_ndlink *ndl;
741 struct lstcon_node *nd;
745 LASSERT(index_p != NULL && count_p != NULL);
746 LASSERT(dents_up != NULL);
747 LASSERT(*index_p >= 0);
748 LASSERT(*count_p > 0);
750 list_for_each_entry(ndl, head, ndl_link) {
751 if (index++ < *index_p)
754 if (count >= *count_p)
758 if (copy_to_user(&dents_up[count].nde_id,
759 &nd->nd_id, sizeof(nd->nd_id)) ||
760 copy_to_user(&dents_up[count].nde_state,
761 &nd->nd_state, sizeof(nd->nd_state)))
767 if (index <= *index_p)
777 lstcon_group_info(char *name, struct lstcon_ndlist_ent __user *gents_p,
778 int *index_p, int *count_p,
779 struct lstcon_node_ent __user *dents_up)
781 struct lstcon_ndlist_ent *gentp;
782 struct lstcon_group *grp;
783 struct lstcon_ndlink *ndl;
786 rc = lstcon_group_find(name, &grp);
788 CDEBUG(D_NET, "Can't find group %s\n", name);
792 if (dents_up != NULL) {
794 rc = lstcon_nodes_getent(&grp->grp_ndl_list,
795 index_p, count_p, dents_up);
796 lstcon_group_decref(grp);
801 /* non-verbose query */
802 CFS_ALLOC_PTR(gentp);
804 CERROR("Can't allocate ndlist_ent\n");
805 lstcon_group_decref(grp);
810 list_for_each_entry(ndl, &grp->grp_ndl_list, ndl_link)
811 LST_NODE_STATE_COUNTER(ndl->ndl_node, gentp);
813 rc = copy_to_user(gents_p, gentp,
814 sizeof(struct lstcon_ndlist_ent)) ? -EFAULT : 0;
818 lstcon_group_decref(grp);
824 lstcon_batch_find(const char *name, struct lstcon_batch **batpp)
826 struct lstcon_batch *bat;
828 list_for_each_entry(bat, &console_session.ses_bat_list, bat_link) {
829 if (strncmp(bat->bat_name, name, LST_NAME_SIZE) == 0) {
839 lstcon_batch_add(char *name)
841 struct lstcon_batch *bat;
845 rc = (lstcon_batch_find(name, &bat) == 0)? -EEXIST: 0;
847 CDEBUG(D_NET, "Batch %s already exists\n", name);
851 LIBCFS_ALLOC(bat, sizeof(*bat));
853 CERROR("Can't allocate descriptor for batch %s\n", name);
857 CFS_ALLOC_PTR_ARRAY(bat->bat_cli_hash, LST_NODE_HASHSIZE);
858 if (bat->bat_cli_hash == NULL) {
859 CERROR("Can't allocate hash for batch %s\n", name);
860 LIBCFS_FREE(bat, sizeof(*bat));
865 CFS_ALLOC_PTR_ARRAY(bat->bat_srv_hash, LST_NODE_HASHSIZE);
866 if (bat->bat_srv_hash == NULL) {
867 CERROR("Can't allocate hash for batch %s\n", name);
868 LIBCFS_FREE(bat->bat_cli_hash, LST_NODE_HASHSIZE);
869 LIBCFS_FREE(bat, sizeof(*bat));
874 if (strlen(name) > sizeof(bat->bat_name)-1) {
875 LIBCFS_FREE(bat->bat_srv_hash, LST_NODE_HASHSIZE);
876 LIBCFS_FREE(bat->bat_cli_hash, LST_NODE_HASHSIZE);
877 LIBCFS_FREE(bat, sizeof(*bat));
880 strncpy(bat->bat_name, name, sizeof(bat->bat_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 __user *name_up)
905 struct lstcon_batch *bat;
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, struct lstcon_test_batch_ent __user *ent_up,
922 int server, int testidx, int *index_p, int *ndent_p,
923 struct lstcon_node_ent __user *dents_up)
925 struct lstcon_test_batch_ent *entp;
926 struct list_head *clilst;
927 struct list_head *srvlst;
928 struct lstcon_test *test = NULL;
929 struct lstcon_batch *bat;
930 struct lstcon_ndlink *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 */
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(struct lstcon_test_batch_ent)) ? -EFAULT : 0;
994 lstcon_batrpc_condition(int transop, struct lstcon_node *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(struct lstcon_batch *bat, int transop,
1017 struct list_head __user *result_up)
1019 struct lstcon_rpc_trans *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 __user *result_up)
1042 struct lstcon_batch *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 __user *result_up)
1064 struct lstcon_batch *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(struct lstcon_batch *bat)
1086 struct lstcon_ndlink *ndl;
1087 struct lstcon_test *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 struct lstcon_test, tes_link);
1095 LASSERT(list_empty(&test->tes_trans_list));
1097 list_del(&test->tes_link);
1099 lstcon_group_decref(test->tes_src_grp);
1100 lstcon_group_decref(test->tes_dst_grp);
1102 LIBCFS_FREE(test, offsetof(struct lstcon_test,
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 struct lstcon_ndlink, 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 struct lstcon_ndlink, 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(*bat));
1137 lstcon_testrpc_condition(int transop, struct lstcon_node *nd, void *arg)
1139 struct lstcon_test *test = arg;
1140 struct lstcon_batch *batch;
1141 struct lstcon_ndlink *ndl;
1142 struct list_head *hash;
1143 struct list_head *head;
1145 LASSERT(test != NULL);
1147 batch = test->tes_batch;
1148 LASSERT(batch != NULL);
1150 if (test->tes_oneside &&
1151 transop == LST_TRANS_TSBSRVADD)
1154 if (nd->nd_state != LST_NODE_ACTIVE)
1157 if (transop == LST_TRANS_TSBCLIADD) {
1158 hash = batch->bat_cli_hash;
1159 head = &batch->bat_cli_list;
1162 LASSERT (transop == LST_TRANS_TSBSRVADD);
1164 hash = batch->bat_srv_hash;
1165 head = &batch->bat_srv_list;
1168 LASSERT (nd->nd_id.nid != LNET_NID_ANY);
1170 if (lstcon_ndlink_find(hash, nd->nd_id, &ndl, 1) != 0)
1173 if (list_empty(&ndl->ndl_link))
1174 list_add_tail(&ndl->ndl_link, head);
1180 lstcon_test_nodes_add(struct lstcon_test *test,
1181 struct list_head __user *result_up)
1183 struct lstcon_rpc_trans *trans;
1184 struct lstcon_group *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, "
1211 "RPC error %d, framework error %d\n",
1212 transop == LST_TRANS_TSBCLIADD ? "client" : "server",
1213 lstcon_trans_stat()->trs_rpc_errno,
1214 lstcon_trans_stat()->trs_fwk_errno);
1219 lstcon_rpc_trans_destroy(trans);
1221 if (transop == LST_TRANS_TSBCLIADD)
1224 transop = LST_TRANS_TSBCLIADD;
1225 grp = test->tes_src_grp;
1226 test->tes_cliidx = 0;
1228 /* requests to test clients */
1233 lstcon_verify_batch(const char *name, struct lstcon_batch **batch)
1237 rc = lstcon_batch_find(name, batch);
1239 CDEBUG(D_NET, "Can't find batch %s\n", name);
1243 if ((*batch)->bat_state != LST_BATCH_IDLE) {
1244 CDEBUG(D_NET, "Can't change running batch %s\n", name);
1252 lstcon_verify_group(const char *name, struct lstcon_group **grp)
1255 struct lstcon_ndlink *ndl;
1257 rc = lstcon_group_find(name, grp);
1259 CDEBUG(D_NET, "can't find group %s\n", name);
1263 list_for_each_entry(ndl, &(*grp)->grp_ndl_list, ndl_link) {
1264 if (ndl->ndl_node->nd_state == LST_NODE_ACTIVE) {
1269 CDEBUG(D_NET, "Group %s has no ACTIVE nodes\n", name);
1275 lstcon_test_add(char *batch_name, int type, int loop,
1276 int concur, int dist, int span,
1277 char *src_name, char *dst_name,
1278 void *param, int paramlen, int *retp,
1279 struct list_head __user *result_up)
1281 struct lstcon_test *test = NULL;
1283 struct lstcon_group *src_grp = NULL;
1284 struct lstcon_group *dst_grp = NULL;
1285 struct lstcon_batch *batch = NULL;
1288 * verify that a batch of the given name exists, and the groups
1289 * that will be part of the batch exist and have at least one
1292 rc = lstcon_verify_batch(batch_name, &batch);
1296 rc = lstcon_verify_group(src_name, &src_grp);
1300 rc = lstcon_verify_group(dst_name, &dst_grp);
1304 if (dst_grp->grp_userland)
1307 LIBCFS_ALLOC(test, offsetof(struct lstcon_test, tes_param[paramlen]));
1309 CERROR("Can't allocate test descriptor\n");
1315 test->tes_hdr.tsb_id = batch->bat_hdr.tsb_id;
1316 test->tes_batch = batch;
1317 test->tes_type = type;
1318 test->tes_oneside = 0; /* TODO */
1319 test->tes_loop = loop;
1320 test->tes_concur = concur;
1321 test->tes_stop_onerr = 1; /* TODO */
1322 test->tes_span = span;
1323 test->tes_dist = dist;
1324 test->tes_cliidx = 0; /* just used for creating RPC */
1325 test->tes_src_grp = src_grp;
1326 test->tes_dst_grp = dst_grp;
1327 INIT_LIST_HEAD(&test->tes_trans_list);
1329 if (param != NULL) {
1330 test->tes_paramlen = paramlen;
1331 memcpy(&test->tes_param[0], param, paramlen);
1334 rc = lstcon_test_nodes_add(test, result_up);
1339 if (lstcon_trans_stat()->trs_rpc_errno != 0 ||
1340 lstcon_trans_stat()->trs_fwk_errno != 0)
1341 CDEBUG(D_NET, "Failed to add test %d to batch %s\n", type,
1344 /* add to test list anyway, so user can check what's going on */
1345 list_add_tail(&test->tes_link, &batch->bat_test_list);
1348 test->tes_hdr.tsb_index = batch->bat_ntest;
1350 /* hold groups so nobody can change them */
1354 LIBCFS_FREE(test, offsetof(struct lstcon_test,
1355 tes_param[paramlen]));
1357 if (dst_grp != NULL)
1358 lstcon_group_decref(dst_grp);
1360 if (src_grp != NULL)
1361 lstcon_group_decref(src_grp);
1367 lstcon_test_find(struct lstcon_batch *batch, int idx,
1368 struct lstcon_test **testpp)
1370 struct lstcon_test *test;
1372 list_for_each_entry(test, &batch->bat_test_list, tes_link) {
1373 if (idx == test->tes_hdr.tsb_index) {
1383 lstcon_tsbrpc_readent(int transop, struct srpc_msg *msg,
1384 struct lstcon_rpc_ent __user *ent_up)
1386 struct srpc_batch_reply *rep = &msg->msg_body.bat_reply;
1388 LASSERT (transop == LST_TRANS_TSBCLIQRY ||
1389 transop == LST_TRANS_TSBSRVQRY);
1391 /* positive errno, framework error code */
1392 if (copy_to_user(&ent_up->rpe_priv[0],
1393 &rep->bar_active, sizeof(rep->bar_active)))
1400 lstcon_test_batch_query(char *name, int testidx, int client,
1401 int timeout, struct list_head __user *result_up)
1403 struct lstcon_rpc_trans *trans;
1404 struct list_head *translist;
1405 struct list_head *ndlist;
1406 struct lstcon_tsb_hdr *hdr;
1407 struct lstcon_batch *batch;
1408 struct lstcon_test *test = NULL;
1412 rc = lstcon_batch_find(name, &batch);
1414 CDEBUG(D_NET, "Can't find batch: %s\n", name);
1419 translist = &batch->bat_trans_list;
1420 ndlist = &batch->bat_cli_list;
1421 hdr = &batch->bat_hdr;
1424 /* query specified test only */
1425 rc = lstcon_test_find(batch, testidx, &test);
1427 CDEBUG(D_NET, "Can't find test: %d\n", testidx);
1431 translist = &test->tes_trans_list;
1432 ndlist = &test->tes_src_grp->grp_ndl_list;
1433 hdr = &test->tes_hdr;
1436 transop = client ? LST_TRANS_TSBCLIQRY : LST_TRANS_TSBSRVQRY;
1438 rc = lstcon_rpc_trans_ndlist(ndlist, translist, transop, hdr,
1439 lstcon_batrpc_condition, &trans);
1441 CERROR("Can't create transaction: %d\n", rc);
1445 lstcon_rpc_trans_postwait(trans, timeout);
1447 if (testidx == 0 && /* query a batch, not a test */
1448 lstcon_rpc_stat_failure(lstcon_trans_stat(), 0) == 0 &&
1449 lstcon_tsbqry_stat_run(lstcon_trans_stat(), 0) == 0) {
1450 /* all RPCs finished, and no active test */
1451 batch->bat_state = LST_BATCH_IDLE;
1454 rc = lstcon_rpc_trans_interpreter(trans, result_up,
1455 lstcon_tsbrpc_readent);
1456 lstcon_rpc_trans_destroy(trans);
1462 lstcon_statrpc_readent(int transop, struct srpc_msg *msg,
1463 struct lstcon_rpc_ent __user *ent_up)
1465 struct srpc_stat_reply *rep = &msg->msg_body.stat_reply;
1466 struct sfw_counters __user *sfwk_stat;
1467 struct srpc_counters __user *srpc_stat;
1468 struct lnet_counters_common __user *lnet_stat;
1470 if (rep->str_status != 0)
1473 sfwk_stat = (struct sfw_counters __user *)&ent_up->rpe_payload[0];
1474 srpc_stat = (struct srpc_counters __user *)
1475 ((char __user *)sfwk_stat + sizeof(*sfwk_stat));
1476 lnet_stat = (struct lnet_counters_common __user *)
1477 ((char __user *)srpc_stat + sizeof(*srpc_stat));
1479 if (copy_to_user(sfwk_stat, &rep->str_fw, sizeof(*sfwk_stat)) ||
1480 copy_to_user(srpc_stat, &rep->str_rpc, sizeof(*srpc_stat)) ||
1481 copy_to_user(lnet_stat, &rep->str_lnet, sizeof(*lnet_stat)))
1488 lstcon_ndlist_stat(struct list_head *ndlist,
1489 int timeout, struct list_head __user *result_up)
1492 struct lstcon_rpc_trans *trans;
1495 rc = lstcon_rpc_trans_ndlist(ndlist, &head,
1496 LST_TRANS_STATQRY, NULL, NULL, &trans);
1498 CERROR("Can't create transaction: %d\n", rc);
1502 lstcon_rpc_trans_postwait(trans, LST_VALIDATE_TIMEOUT(timeout));
1504 rc = lstcon_rpc_trans_interpreter(trans, result_up,
1505 lstcon_statrpc_readent);
1506 lstcon_rpc_trans_destroy(trans);
1512 lstcon_group_stat(char *grp_name, int timeout,
1513 struct list_head __user *result_up)
1515 struct lstcon_group *grp;
1518 rc = lstcon_group_find(grp_name, &grp);
1520 CDEBUG(D_NET, "Can't find group %s\n", grp_name);
1524 rc = lstcon_ndlist_stat(&grp->grp_ndl_list, timeout, result_up);
1526 lstcon_group_decref(grp);
1532 lstcon_nodes_stat(int count, struct lnet_process_id __user *ids_up,
1533 int timeout, struct list_head __user *result_up)
1535 struct lstcon_ndlink *ndl;
1536 struct lstcon_group *tmp;
1537 struct lnet_process_id id;
1541 rc = lstcon_group_alloc(NULL, &tmp);
1543 CERROR("Out of memory\n");
1547 for (i = 0 ; i < count; i++) {
1548 if (copy_from_user(&id, &ids_up[i], sizeof(id))) {
1553 /* add to tmp group */
1554 rc = lstcon_group_ndlink_find(tmp, id, &ndl, 2);
1556 CDEBUG((rc == -ENOMEM) ? D_ERROR : D_NET,
1557 "Failed to find or create %s: %d\n",
1558 libcfs_id2str(id), rc);
1564 lstcon_group_decref(tmp);
1568 rc = lstcon_ndlist_stat(&tmp->grp_ndl_list, timeout, result_up);
1570 lstcon_group_decref(tmp);
1576 lstcon_debug_ndlist(struct list_head *ndlist,
1577 struct list_head *translist,
1578 int timeout, struct list_head __user *result_up)
1580 struct lstcon_rpc_trans *trans;
1583 rc = lstcon_rpc_trans_ndlist(ndlist, translist, LST_TRANS_SESQRY,
1584 NULL, lstcon_sesrpc_condition, &trans);
1586 CERROR("Can't create transaction: %d\n", rc);
1590 lstcon_rpc_trans_postwait(trans, LST_VALIDATE_TIMEOUT(timeout));
1592 rc = lstcon_rpc_trans_interpreter(trans, result_up,
1593 lstcon_sesrpc_readent);
1594 lstcon_rpc_trans_destroy(trans);
1600 lstcon_session_debug(int timeout, struct list_head __user *result_up)
1602 return lstcon_debug_ndlist(&console_session.ses_ndl_list,
1603 NULL, timeout, result_up);
1607 lstcon_batch_debug(int timeout, char *name,
1608 int client, struct list_head __user *result_up)
1610 struct lstcon_batch *bat;
1613 rc = lstcon_batch_find(name, &bat);
1617 rc = lstcon_debug_ndlist(client ? &bat->bat_cli_list :
1619 NULL, timeout, result_up);
1625 lstcon_group_debug(int timeout, char *name,
1626 struct list_head __user *result_up)
1628 struct lstcon_group *grp;
1631 rc = lstcon_group_find(name, &grp);
1635 rc = lstcon_debug_ndlist(&grp->grp_ndl_list, NULL,
1636 timeout, result_up);
1637 lstcon_group_decref(grp);
1643 lstcon_nodes_debug(int timeout, int count,
1644 struct lnet_process_id __user *ids_up,
1645 struct list_head __user *result_up)
1647 struct lnet_process_id id;
1648 struct lstcon_ndlink *ndl;
1649 struct lstcon_group *grp;
1653 rc = lstcon_group_alloc(NULL, &grp);
1655 CDEBUG(D_NET, "Out of memory\n");
1659 for (i = 0; i < count; i++) {
1660 if (copy_from_user(&id, &ids_up[i], sizeof(id))) {
1665 /* node is added to tmp group */
1666 rc = lstcon_group_ndlink_find(grp, id, &ndl, 1);
1668 CERROR("Can't create node link\n");
1674 lstcon_group_decref(grp);
1678 rc = lstcon_debug_ndlist(&grp->grp_ndl_list, NULL,
1679 timeout, result_up);
1681 lstcon_group_decref(grp);
1687 lstcon_session_match(struct lst_sid sid)
1689 return (console_session.ses_id.ses_nid == sid.ses_nid &&
1690 console_session.ses_id.ses_stamp == sid.ses_stamp) ? 1: 0;
1694 lstcon_new_session_id(struct lst_sid *sid)
1696 struct lnet_process_id id;
1698 LASSERT(console_session.ses_state == LST_SESSION_NONE);
1701 sid->ses_nid = id.nid;
1702 sid->ses_stamp = div_u64(ktime_get_ns(), NSEC_PER_MSEC);
1706 lstcon_session_new(char *name, int key, unsigned feats,
1707 int timeout, int force, struct lst_sid __user *sid_up)
1712 if (console_session.ses_state != LST_SESSION_NONE) {
1713 /* session exists */
1715 CNETERR("Session %s already exists\n",
1716 console_session.ses_name);
1720 rc = lstcon_session_end();
1722 /* lstcon_session_end() only return local error */
1727 if ((feats & ~LST_FEATS_MASK) != 0) {
1728 CNETERR("Unknown session features %x\n",
1729 (feats & ~LST_FEATS_MASK));
1733 for (i = 0; i < LST_GLOBAL_HASHSIZE; i++)
1734 LASSERT(list_empty(&console_session.ses_ndl_hash[i]));
1736 lstcon_new_session_id(&console_session.ses_id);
1738 console_session.ses_key = key;
1739 console_session.ses_state = LST_SESSION_ACTIVE;
1740 console_session.ses_force = !!force;
1741 console_session.ses_features = feats;
1742 console_session.ses_feats_updated = 0;
1743 console_session.ses_timeout = (timeout <= 0) ?
1744 LST_CONSOLE_TIMEOUT : timeout;
1746 if (strlen(name) > sizeof(console_session.ses_name)-1)
1748 strlcpy(console_session.ses_name, name,
1749 sizeof(console_session.ses_name));
1751 rc = lstcon_batch_add(LST_DEFAULT_BATCH);
1755 rc = lstcon_rpc_pinger_start();
1757 struct lstcon_batch *bat = NULL;
1759 lstcon_batch_find(LST_DEFAULT_BATCH, &bat);
1760 lstcon_batch_destroy(bat);
1765 if (copy_to_user(sid_up, &console_session.ses_id,
1766 sizeof(struct lst_sid)) == 0)
1769 lstcon_session_end();
1775 lstcon_session_info(struct lst_sid __user *sid_up, int __user *key_up,
1776 unsigned __user *featp,
1777 struct lstcon_ndlist_ent __user *ndinfo_up,
1778 char __user *name_up, int len)
1780 struct lstcon_ndlist_ent *entp;
1781 struct lstcon_ndlink *ndl;
1784 if (console_session.ses_state != LST_SESSION_ACTIVE)
1787 LIBCFS_ALLOC(entp, sizeof(*entp));
1791 list_for_each_entry(ndl, &console_session.ses_ndl_list, ndl_link)
1792 LST_NODE_STATE_COUNTER(ndl->ndl_node, entp);
1794 if (copy_to_user(sid_up, &console_session.ses_id,
1795 sizeof(struct lst_sid)) ||
1796 copy_to_user(key_up, &console_session.ses_key,
1798 copy_to_user(featp, &console_session.ses_features,
1800 copy_to_user(ndinfo_up, entp, sizeof(*entp)) ||
1801 copy_to_user(name_up, console_session.ses_name, len))
1804 LIBCFS_FREE(entp, sizeof(*entp));
1810 lstcon_session_end(void)
1812 struct lstcon_rpc_trans *trans;
1813 struct lstcon_group *grp;
1814 struct lstcon_batch *bat;
1817 LASSERT (console_session.ses_state == LST_SESSION_ACTIVE);
1819 rc = lstcon_rpc_trans_ndlist(&console_session.ses_ndl_list,
1820 NULL, LST_TRANS_SESEND, NULL,
1821 lstcon_sesrpc_condition, &trans);
1823 CERROR("Can't create transaction: %d\n", rc);
1827 console_session.ses_shutdown = 1;
1829 lstcon_rpc_pinger_stop();
1831 lstcon_rpc_trans_postwait(trans, LST_TRANS_TIMEOUT);
1833 lstcon_rpc_trans_destroy(trans);
1834 /* User can do nothing even rpc failed, so go on */
1836 /* waiting for orphan rpcs to die */
1837 lstcon_rpc_cleanup_wait();
1839 console_session.ses_id = LST_INVALID_SID;
1840 console_session.ses_state = LST_SESSION_NONE;
1841 console_session.ses_key = 0;
1842 console_session.ses_force = 0;
1843 console_session.ses_feats_updated = 0;
1845 /* destroy all batches */
1846 while (!list_empty(&console_session.ses_bat_list)) {
1847 bat = list_entry(console_session.ses_bat_list.next,
1848 struct lstcon_batch, bat_link);
1850 lstcon_batch_destroy(bat);
1853 /* destroy all groups */
1854 while (!list_empty(&console_session.ses_grp_list)) {
1855 grp = list_entry(console_session.ses_grp_list.next,
1856 struct lstcon_group, grp_link);
1857 LASSERT(grp->grp_ref == 1);
1859 lstcon_group_decref(grp);
1862 /* all nodes should be released */
1863 LASSERT(list_empty(&console_session.ses_ndl_list));
1865 console_session.ses_shutdown = 0;
1866 console_session.ses_expired = 0;
1872 lstcon_session_feats_check(unsigned feats)
1876 if ((feats & ~LST_FEATS_MASK) != 0) {
1877 CERROR("Can't support these features: %x\n",
1878 (feats & ~LST_FEATS_MASK));
1882 spin_lock(&console_session.ses_rpc_lock);
1884 if (!console_session.ses_feats_updated) {
1885 console_session.ses_feats_updated = 1;
1886 console_session.ses_features = feats;
1889 if (console_session.ses_features != feats)
1892 spin_unlock(&console_session.ses_rpc_lock);
1895 CERROR("remote features %x do not match with "
1896 "session features %x of console\n",
1897 feats, console_session.ses_features);
1904 lstcon_acceptor_handle(struct srpc_server_rpc *rpc)
1906 struct srpc_msg *rep = &rpc->srpc_replymsg;
1907 struct srpc_msg *req = &rpc->srpc_reqstbuf->buf_msg;
1908 struct srpc_join_reqst *jreq = &req->msg_body.join_reqst;
1909 struct srpc_join_reply *jrep = &rep->msg_body.join_reply;
1910 struct lstcon_group *grp = NULL;
1911 struct lstcon_ndlink *ndl;
1914 sfw_unpack_message(req);
1916 mutex_lock(&console_session.ses_mutex);
1918 jrep->join_sid = console_session.ses_id;
1920 if (console_session.ses_id.ses_nid == LNET_NID_ANY) {
1921 jrep->join_status = ESRCH;
1925 if (lstcon_session_feats_check(req->msg_ses_feats) != 0) {
1926 jrep->join_status = EPROTO;
1930 if (jreq->join_sid.ses_nid != LNET_NID_ANY &&
1931 !lstcon_session_match(jreq->join_sid)) {
1932 jrep->join_status = EBUSY;
1936 if (lstcon_group_find(jreq->join_group, &grp) != 0) {
1937 rc = lstcon_group_alloc(jreq->join_group, &grp);
1939 CERROR("Out of memory\n");
1943 list_add_tail(&grp->grp_link,
1944 &console_session.ses_grp_list);
1945 lstcon_group_addref(grp);
1948 if (grp->grp_ref > 2) {
1949 /* Group in using */
1950 jrep->join_status = EBUSY;
1954 rc = lstcon_group_ndlink_find(grp, rpc->srpc_peer, &ndl, 0);
1956 jrep->join_status = EEXIST;
1960 rc = lstcon_group_ndlink_find(grp, rpc->srpc_peer, &ndl, 1);
1962 CERROR("Out of memory\n");
1966 ndl->ndl_node->nd_state = LST_NODE_ACTIVE;
1967 ndl->ndl_node->nd_timeout = console_session.ses_timeout;
1969 if (grp->grp_userland == 0)
1970 grp->grp_userland = 1;
1972 strlcpy(jrep->join_session, console_session.ses_name,
1973 sizeof(jrep->join_session));
1974 jrep->join_timeout = console_session.ses_timeout;
1975 jrep->join_status = 0;
1978 rep->msg_ses_feats = console_session.ses_features;
1980 lstcon_group_decref(grp);
1982 mutex_unlock(&console_session.ses_mutex);
1987 static struct srpc_service lstcon_acceptor_service;
1989 static void lstcon_init_acceptor_service(void)
1991 /* initialize selftest console acceptor service table */
1992 lstcon_acceptor_service.sv_name = "join session";
1993 lstcon_acceptor_service.sv_handler = lstcon_acceptor_handle;
1994 lstcon_acceptor_service.sv_id = SRPC_SERVICE_JOIN;
1995 lstcon_acceptor_service.sv_wi_total = SFW_FRWK_WI_MAX;
1998 static struct notifier_block lstcon_ioctl_handler = {
1999 .notifier_call = lstcon_ioctl_entry,
2002 /* initialize console */
2004 lstcon_console_init(void)
2009 console_session.ses_id = LST_INVALID_SID;
2010 console_session.ses_state = LST_SESSION_NONE;
2011 console_session.ses_timeout = 0;
2012 console_session.ses_force = 0;
2013 console_session.ses_expired = 0;
2014 console_session.ses_feats_updated = 0;
2015 console_session.ses_features = LST_FEATS_MASK;
2016 console_session.ses_laststamp = ktime_get_real_seconds();
2018 mutex_init(&console_session.ses_mutex);
2020 INIT_LIST_HEAD(&console_session.ses_ndl_list);
2021 INIT_LIST_HEAD(&console_session.ses_grp_list);
2022 INIT_LIST_HEAD(&console_session.ses_bat_list);
2023 INIT_LIST_HEAD(&console_session.ses_trans_list);
2025 CFS_ALLOC_PTR_ARRAY(console_session.ses_ndl_hash,
2026 LST_GLOBAL_HASHSIZE);
2027 if (console_session.ses_ndl_hash == NULL)
2030 for (i = 0; i < LST_GLOBAL_HASHSIZE; i++)
2031 INIT_LIST_HEAD(&console_session.ses_ndl_hash[i]);
2034 /* initialize acceptor service table */
2035 lstcon_init_acceptor_service();
2037 rc = srpc_add_service(&lstcon_acceptor_service);
2038 LASSERT(rc != -EBUSY);
2040 CFS_FREE_PTR_ARRAY(console_session.ses_ndl_hash,
2041 LST_GLOBAL_HASHSIZE);
2045 rc = srpc_service_add_buffers(&lstcon_acceptor_service,
2046 lstcon_acceptor_service.sv_wi_total);
2052 rc = blocking_notifier_chain_register(&libcfs_ioctl_list,
2053 &lstcon_ioctl_handler);
2055 lstcon_rpc_module_init();
2060 srpc_shutdown_service(&lstcon_acceptor_service);
2061 srpc_remove_service(&lstcon_acceptor_service);
2063 CFS_FREE_PTR_ARRAY(console_session.ses_ndl_hash, LST_GLOBAL_HASHSIZE);
2065 srpc_wait_service_shutdown(&lstcon_acceptor_service);
2071 lstcon_console_fini(void)
2075 blocking_notifier_chain_unregister(&libcfs_ioctl_list,
2076 &lstcon_ioctl_handler);
2078 mutex_lock(&console_session.ses_mutex);
2080 srpc_shutdown_service(&lstcon_acceptor_service);
2081 srpc_remove_service(&lstcon_acceptor_service);
2083 if (console_session.ses_state != LST_SESSION_NONE)
2084 lstcon_session_end();
2086 lstcon_rpc_module_fini();
2088 mutex_unlock(&console_session.ses_mutex);
2090 LASSERT(list_empty(&console_session.ses_ndl_list));
2091 LASSERT(list_empty(&console_session.ses_grp_list));
2092 LASSERT(list_empty(&console_session.ses_bat_list));
2093 LASSERT(list_empty(&console_session.ses_trans_list));
2095 for (i = 0; i < LST_NODE_HASHSIZE; i++)
2096 LASSERT(list_empty(&console_session.ses_ndl_hash[i]));
2098 CFS_FREE_PTR_ARRAY(console_session.ses_ndl_hash,
2099 LST_GLOBAL_HASHSIZE);
2101 srpc_wait_service_shutdown(&lstcon_acceptor_service);