1 // SPDX-License-Identifier: GPL-2.0
4 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
5 * Use is subject to license terms.
7 * Copyright (c) 2012, 2014, Intel Corporation.
11 * This file is part of Lustre, http://www.lustre.org/
13 * Infrastructure of LST console
15 * Author: Liang Zhen <liangzhen@clusterfs.com>
18 #include <libcfs/libcfs.h>
19 #include <lnet/lib-lnet.h>
23 #define LST_NODE_STATE_COUNTER(nd, p) \
25 if ((nd)->nd_state == LST_NODE_ACTIVE) \
26 (p)->nle_nactive ++; \
27 else if ((nd)->nd_state == LST_NODE_BUSY) \
29 else if ((nd)->nd_state == LST_NODE_DOWN) \
32 (p)->nle_nunknown ++; \
36 struct lstcon_session console_session;
39 lstcon_node_get(struct lstcon_node *nd)
41 LASSERT (nd->nd_ref >= 1);
47 lstcon_node_find(struct lnet_process_id id, struct lstcon_node **ndpp,
50 struct lstcon_ndlink *ndl;
51 unsigned int idx = LNET_NIDADDR(id.nid) % LST_GLOBAL_HASHSIZE;
53 LASSERT(id.nid != LNET_NID_ANY);
55 list_for_each_entry(ndl, &console_session.ses_ndl_hash[idx],
57 if (ndl->ndl_node->nd_id.nid != id.nid ||
58 ndl->ndl_node->nd_id.pid != id.pid)
61 lstcon_node_get(ndl->ndl_node);
62 *ndpp = ndl->ndl_node;
69 LIBCFS_ALLOC(*ndpp, sizeof(**ndpp) + sizeof(*ndl));
73 ndl = (struct lstcon_ndlink *)(*ndpp + 1);
75 ndl->ndl_node = *ndpp;
77 ndl->ndl_node->nd_ref = 1;
78 ndl->ndl_node->nd_id = id;
79 ndl->ndl_node->nd_stamp = ktime_get();
80 ndl->ndl_node->nd_state = LST_NODE_UNKNOWN;
81 ndl->ndl_node->nd_timeout = 0;
82 memset(&ndl->ndl_node->nd_ping, 0, sizeof(ndl->ndl_node->nd_ping));
84 /* queued in global hash & list, no refcount is taken by
85 * global hash & list, if caller release his refcount,
86 * node will be released */
87 list_add_tail(&ndl->ndl_hlink, &console_session.ses_ndl_hash[idx]);
88 list_add_tail(&ndl->ndl_link, &console_session.ses_ndl_list);
94 lstcon_node_put(struct lstcon_node *nd)
96 struct lstcon_ndlink *ndl;
98 LASSERT(nd->nd_ref > 0);
100 if (--nd->nd_ref > 0)
103 ndl = (struct lstcon_ndlink *)(nd + 1);
105 LASSERT(!list_empty(&ndl->ndl_link));
106 LASSERT(!list_empty(&ndl->ndl_hlink));
108 /* remove from session */
109 list_del(&ndl->ndl_link);
110 list_del(&ndl->ndl_hlink);
112 LIBCFS_FREE(nd, sizeof(*nd) + sizeof(*ndl));
116 lstcon_ndlink_find(struct list_head *hash, struct lnet_process_id id,
117 struct lstcon_ndlink **ndlpp, int create)
119 unsigned int idx = LNET_NIDADDR(id.nid) % LST_NODE_HASHSIZE;
120 struct lstcon_ndlink *ndl;
121 struct lstcon_node *nd;
124 if (id.nid == LNET_NID_ANY)
128 list_for_each_entry(ndl, &hash[idx], ndl_hlink) {
129 if (ndl->ndl_node->nd_id.nid != id.nid ||
130 ndl->ndl_node->nd_id.pid != id.pid)
140 /* find or create in session hash */
141 rc = lstcon_node_find(id, &nd, (create == 1) ? 1 : 0);
145 LIBCFS_ALLOC(ndl, sizeof(*ndl));
154 INIT_LIST_HEAD(&ndl->ndl_link);
155 list_add_tail(&ndl->ndl_hlink, &hash[idx]);
161 lstcon_ndlink_release(struct lstcon_ndlink *ndl)
163 LASSERT(list_empty(&ndl->ndl_link));
164 LASSERT(!list_empty(&ndl->ndl_hlink));
166 list_del(&ndl->ndl_hlink); /* delete from hash */
167 lstcon_node_put(ndl->ndl_node);
169 LIBCFS_FREE(ndl, sizeof(*ndl));
173 lstcon_group_alloc(char *name, struct lstcon_group **grpp)
175 struct lstcon_group *grp;
178 LIBCFS_ALLOC(grp, offsetof(struct lstcon_group,
179 grp_ndl_hash[LST_NODE_HASHSIZE]));
185 if (strlen(name) > sizeof(grp->grp_name)-1) {
186 LIBCFS_FREE(grp, offsetof(struct lstcon_group,
187 grp_ndl_hash[LST_NODE_HASHSIZE]));
190 strncpy(grp->grp_name, name, sizeof(grp->grp_name));
193 INIT_LIST_HEAD(&grp->grp_link);
194 INIT_LIST_HEAD(&grp->grp_ndl_list);
195 INIT_LIST_HEAD(&grp->grp_trans_list);
197 for (i = 0; i < LST_NODE_HASHSIZE; i++)
198 INIT_LIST_HEAD(&grp->grp_ndl_hash[i]);
205 void lstcon_group_addref(struct lstcon_group *grp)
210 static void lstcon_group_ndlink_release(struct lstcon_group *,
211 struct lstcon_ndlink *);
214 lstcon_group_drain(struct lstcon_group *grp, int keep)
216 struct lstcon_ndlink *ndl;
217 struct lstcon_ndlink *tmp;
219 list_for_each_entry_safe(ndl, tmp, &grp->grp_ndl_list, ndl_link) {
220 if ((ndl->ndl_node->nd_state & keep) == 0)
221 lstcon_group_ndlink_release(grp, ndl);
225 void lstcon_group_decref(struct lstcon_group *grp)
229 if (--grp->grp_ref > 0)
232 if (!list_empty(&grp->grp_link))
233 list_del(&grp->grp_link);
235 lstcon_group_drain(grp, 0);
237 for (i = 0; i < LST_NODE_HASHSIZE; i++)
238 LASSERT(list_empty(&grp->grp_ndl_hash[i]));
240 LIBCFS_FREE(grp, offsetof(struct lstcon_group,
241 grp_ndl_hash[LST_NODE_HASHSIZE]));
244 int lstcon_group_find(const char *name, struct lstcon_group **grpp)
246 struct lstcon_group *grp;
248 list_for_each_entry(grp, &console_session.ses_grp_list, grp_link) {
249 if (strncmp(grp->grp_name, name, LST_NAME_SIZE) != 0)
252 lstcon_group_addref(grp); /* +1 ref for caller */
261 lstcon_group_ndlink_find(struct lstcon_group *grp, struct lnet_process_id id,
262 struct lstcon_ndlink **ndlpp, int create)
266 rc = lstcon_ndlink_find(&grp->grp_ndl_hash[0], id, ndlpp, create);
270 if (!list_empty(&(*ndlpp)->ndl_link))
273 list_add_tail(&(*ndlpp)->ndl_link, &grp->grp_ndl_list);
280 lstcon_group_ndlink_release(struct lstcon_group *grp, struct lstcon_ndlink *ndl)
282 list_del_init(&ndl->ndl_link);
283 lstcon_ndlink_release(ndl);
288 lstcon_group_ndlink_move(struct lstcon_group *old,
289 struct lstcon_group *new, struct lstcon_ndlink *ndl)
291 unsigned int idx = LNET_NIDADDR(ndl->ndl_node->nd_id.nid) %
296 list_move_tail(&ndl->ndl_hlink, &new->grp_ndl_hash[idx]);
297 list_move_tail(&ndl->ndl_link, &new->grp_ndl_list);
302 lstcon_group_move(struct lstcon_group *old, struct lstcon_group *new)
304 struct lstcon_ndlink *ndl;
306 while (!list_empty(&old->grp_ndl_list)) {
307 ndl = list_first_entry(&old->grp_ndl_list,
308 struct lstcon_ndlink, ndl_link);
309 lstcon_group_ndlink_move(old, new, ndl);
314 lstcon_sesrpc_condition(int transop, struct lstcon_node *nd, void *arg)
316 struct lstcon_group *grp = arg;
319 case LST_TRANS_SESNEW:
320 if (nd->nd_state == LST_NODE_ACTIVE)
324 case LST_TRANS_SESEND:
325 if (nd->nd_state != LST_NODE_ACTIVE)
328 if (grp != NULL && nd->nd_ref > 1)
332 case LST_TRANS_SESQRY:
343 lstcon_sesrpc_readent(int transop, struct srpc_msg *msg,
344 struct lstcon_rpc_ent __user *ent_up)
346 struct srpc_debug_reply *rep;
349 case LST_TRANS_SESNEW:
350 case LST_TRANS_SESEND:
353 case LST_TRANS_SESQRY:
354 rep = &msg->msg_body.dbg_reply;
356 if (copy_to_user(&ent_up->rpe_priv[0],
357 &rep->dbg_timeout, sizeof(int)) ||
358 copy_to_user(&ent_up->rpe_payload[0],
359 &rep->dbg_name, LST_NAME_SIZE))
372 lstcon_group_nodes_add(struct lstcon_group *grp,
373 int count, struct lnet_process_id __user *ids_up,
375 struct list_head __user *result_up)
377 struct lstcon_rpc_trans *trans;
378 struct lstcon_ndlink *ndl;
379 struct lstcon_group *tmp;
380 struct lnet_process_id id;
384 rc = lstcon_group_alloc(NULL, &tmp);
386 CERROR("Out of memory\n");
390 for (i = 0 ; i < count; i++) {
391 if (copy_from_user(&id, &ids_up[i], sizeof(id))) {
396 /* skip if it's in this group already */
397 rc = lstcon_group_ndlink_find(grp, id, &ndl, 0);
401 /* add to tmp group */
402 rc = lstcon_group_ndlink_find(tmp, id, &ndl, 1);
404 CERROR("Can't create ndlink, out of memory\n");
410 lstcon_group_decref(tmp);
414 rc = lstcon_rpc_trans_ndlist(&tmp->grp_ndl_list,
415 &tmp->grp_trans_list, LST_TRANS_SESNEW,
416 tmp, lstcon_sesrpc_condition, &trans);
418 CERROR("Can't create transaction: %d\n", rc);
419 lstcon_group_decref(tmp);
424 lstcon_rpc_trans_postwait(trans, LST_TRANS_TIMEOUT);
426 rc = lstcon_rpc_trans_interpreter(trans, result_up,
427 lstcon_sesrpc_readent);
428 *featp = trans->tas_features;
430 /* destroy all RPGs */
431 lstcon_rpc_trans_destroy(trans);
433 lstcon_group_move(tmp, grp);
434 lstcon_group_decref(tmp);
440 lstcon_group_nodes_remove(struct lstcon_group *grp,
441 int count, struct lnet_process_id __user *ids_up,
442 struct list_head __user *result_up)
444 struct lstcon_rpc_trans *trans;
445 struct lstcon_ndlink *ndl;
446 struct lstcon_group *tmp;
447 struct lnet_process_id id;
451 /* End session and remove node from the group */
453 rc = lstcon_group_alloc(NULL, &tmp);
455 CERROR("Out of memory\n");
459 for (i = 0; i < count; i++) {
460 if (copy_from_user(&id, &ids_up[i], sizeof(id))) {
465 /* move node to tmp group */
466 if (lstcon_group_ndlink_find(grp, id, &ndl, 0) == 0)
467 lstcon_group_ndlink_move(grp, tmp, ndl);
470 rc = lstcon_rpc_trans_ndlist(&tmp->grp_ndl_list,
471 &tmp->grp_trans_list, LST_TRANS_SESEND,
472 tmp, lstcon_sesrpc_condition, &trans);
474 CERROR("Can't create transaction: %d\n", rc);
478 lstcon_rpc_trans_postwait(trans, LST_TRANS_TIMEOUT);
480 rc = lstcon_rpc_trans_interpreter(trans, result_up, NULL);
482 lstcon_rpc_trans_destroy(trans);
483 /* release nodes anyway, because we can't rollback status */
484 lstcon_group_decref(tmp);
488 lstcon_group_move(tmp, grp);
489 lstcon_group_decref(tmp);
495 lstcon_group_add(char *name)
497 struct lstcon_group *grp;
500 rc = (lstcon_group_find(name, &grp) == 0)? -EEXIST: 0;
502 /* find a group with same name */
503 lstcon_group_decref(grp);
507 rc = lstcon_group_alloc(name, &grp);
509 CERROR("Can't allocate descriptor for group %s\n", name);
513 list_add_tail(&grp->grp_link, &console_session.ses_grp_list);
519 lstcon_nodes_add(char *name, int count, struct lnet_process_id __user *ids_up,
520 unsigned *featp, struct list_head __user *result_up)
522 struct lstcon_group *grp;
526 LASSERT (ids_up != NULL);
528 rc = lstcon_group_find(name, &grp);
530 CDEBUG(D_NET, "Can't find group %s\n", name);
534 if (grp->grp_ref > 2) {
535 /* referred by other threads or test */
536 CDEBUG(D_NET, "Group %s is busy\n", name);
537 lstcon_group_decref(grp);
542 rc = lstcon_group_nodes_add(grp, count, ids_up, featp, result_up);
544 lstcon_group_decref(grp);
550 lstcon_group_del(char *name)
552 struct lstcon_rpc_trans *trans;
553 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 others threads or test */
564 CDEBUG(D_NET, "Group %s is busy\n", name);
565 lstcon_group_decref(grp);
569 rc = lstcon_rpc_trans_ndlist(&grp->grp_ndl_list,
570 &grp->grp_trans_list, LST_TRANS_SESEND,
571 grp, lstcon_sesrpc_condition, &trans);
573 CERROR("Can't create transaction: %d\n", rc);
574 lstcon_group_decref(grp);
578 lstcon_rpc_trans_postwait(trans, LST_TRANS_TIMEOUT);
580 lstcon_rpc_trans_destroy(trans);
582 lstcon_group_decref(grp);
583 /* -ref for session, it's destroyed,
584 * status can't be rolled back, destroy group anway */
585 lstcon_group_decref(grp);
591 lstcon_group_clean(char *name, int args)
593 struct lstcon_group *grp = NULL;
596 rc = lstcon_group_find(name, &grp);
598 CDEBUG(D_NET, "Can't find group %s\n", name);
602 if (grp->grp_ref > 2) {
603 /* referred by test */
604 CDEBUG(D_NET, "Group %s is busy\n", name);
605 lstcon_group_decref(grp);
609 args = (LST_NODE_ACTIVE | LST_NODE_BUSY |
610 LST_NODE_DOWN | LST_NODE_UNKNOWN) & ~args;
612 lstcon_group_drain(grp, args);
614 lstcon_group_decref(grp);
615 /* release empty group */
616 if (list_empty(&grp->grp_ndl_list))
617 lstcon_group_decref(grp);
623 lstcon_nodes_remove(char *name, int count,
624 struct lnet_process_id __user *ids_up,
625 struct list_head __user *result_up)
627 struct lstcon_group *grp = NULL;
630 rc = lstcon_group_find(name, &grp);
632 CDEBUG(D_NET, "Can't find group: %s\n", name);
636 if (grp->grp_ref > 2) {
637 /* referred by test */
638 CDEBUG(D_NET, "Group %s is busy\n", name);
639 lstcon_group_decref(grp);
643 rc = lstcon_group_nodes_remove(grp, count, ids_up, result_up);
645 lstcon_group_decref(grp);
646 /* release empty group */
647 if (list_empty(&grp->grp_ndl_list))
648 lstcon_group_decref(grp);
654 lstcon_group_refresh(char *name, struct list_head __user *result_up)
656 struct lstcon_rpc_trans *trans;
657 struct lstcon_group *grp;
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 /* re-invite all inactive nodes int the group */
674 rc = lstcon_rpc_trans_ndlist(&grp->grp_ndl_list,
675 &grp->grp_trans_list, LST_TRANS_SESNEW,
676 grp, lstcon_sesrpc_condition, &trans);
678 /* local error, return */
679 CDEBUG(D_NET, "Can't create transaction: %d\n", rc);
680 lstcon_group_decref(grp);
684 lstcon_rpc_trans_postwait(trans, LST_TRANS_TIMEOUT);
686 rc = lstcon_rpc_trans_interpreter(trans, result_up, NULL);
688 lstcon_rpc_trans_destroy(trans);
690 lstcon_group_decref(grp);
696 lstcon_nodes_getent(struct list_head *head, int *index_p,
697 int *count_p, struct lstcon_node_ent __user *dents_up)
699 struct lstcon_ndlink *ndl;
700 struct lstcon_node *nd;
704 LASSERT(index_p != NULL && count_p != NULL);
705 LASSERT(dents_up != NULL);
706 LASSERT(*index_p >= 0);
707 LASSERT(*count_p > 0);
709 list_for_each_entry(ndl, head, ndl_link) {
710 if (index++ < *index_p)
713 if (count >= *count_p)
717 if (copy_to_user(&dents_up[count].nde_id,
718 &nd->nd_id, sizeof(nd->nd_id)) ||
719 copy_to_user(&dents_up[count].nde_state,
720 &nd->nd_state, sizeof(nd->nd_state)))
726 if (index <= *index_p)
736 lstcon_group_info(char *name, struct lstcon_ndlist_ent __user *gents_p,
737 int *index_p, int *count_p,
738 struct lstcon_node_ent __user *dents_up)
740 struct lstcon_ndlist_ent *gentp;
741 struct lstcon_group *grp;
742 struct lstcon_ndlink *ndl;
745 rc = lstcon_group_find(name, &grp);
747 CDEBUG(D_NET, "Can't find group %s\n", name);
751 if (dents_up != NULL) {
753 rc = lstcon_nodes_getent(&grp->grp_ndl_list,
754 index_p, count_p, dents_up);
755 lstcon_group_decref(grp);
760 /* non-verbose query */
761 CFS_ALLOC_PTR(gentp);
763 CERROR("Can't allocate ndlist_ent\n");
764 lstcon_group_decref(grp);
769 list_for_each_entry(ndl, &grp->grp_ndl_list, ndl_link)
770 LST_NODE_STATE_COUNTER(ndl->ndl_node, gentp);
772 rc = copy_to_user(gents_p, gentp,
773 sizeof(struct lstcon_ndlist_ent)) ? -EFAULT : 0;
777 lstcon_group_decref(grp);
783 lstcon_batch_find(const char *name, struct lstcon_batch **batpp)
785 struct lstcon_batch *bat;
787 list_for_each_entry(bat, &console_session.ses_bat_list, bat_link) {
788 if (strncmp(bat->bat_name, name, LST_NAME_SIZE) == 0) {
798 lstcon_batch_add(char *name)
800 struct lstcon_batch *bat;
804 rc = (lstcon_batch_find(name, &bat) == 0)? -EEXIST: 0;
806 CDEBUG(D_NET, "Batch %s already exists\n", name);
810 LIBCFS_ALLOC(bat, sizeof(*bat));
812 CERROR("Can't allocate descriptor for batch %s\n", name);
816 CFS_ALLOC_PTR_ARRAY(bat->bat_cli_hash, LST_NODE_HASHSIZE);
817 if (bat->bat_cli_hash == NULL) {
818 CERROR("Can't allocate hash for batch %s\n", name);
819 LIBCFS_FREE(bat, sizeof(*bat));
824 CFS_ALLOC_PTR_ARRAY(bat->bat_srv_hash, LST_NODE_HASHSIZE);
825 if (bat->bat_srv_hash == NULL) {
826 CERROR("Can't allocate hash for batch %s\n", name);
827 LIBCFS_FREE(bat->bat_cli_hash, LST_NODE_HASHSIZE);
828 LIBCFS_FREE(bat, sizeof(*bat));
833 if (strlen(name) > sizeof(bat->bat_name)-1) {
834 LIBCFS_FREE(bat->bat_srv_hash, LST_NODE_HASHSIZE);
835 LIBCFS_FREE(bat->bat_cli_hash, LST_NODE_HASHSIZE);
836 LIBCFS_FREE(bat, sizeof(*bat));
839 strncpy(bat->bat_name, name, sizeof(bat->bat_name));
840 bat->bat_hdr.tsb_index = 0;
841 bat->bat_hdr.tsb_id.bat_id = ++console_session.ses_id_cookie;
844 bat->bat_state = LST_BATCH_IDLE;
846 INIT_LIST_HEAD(&bat->bat_cli_list);
847 INIT_LIST_HEAD(&bat->bat_srv_list);
848 INIT_LIST_HEAD(&bat->bat_test_list);
849 INIT_LIST_HEAD(&bat->bat_trans_list);
851 for (i = 0; i < LST_NODE_HASHSIZE; i++) {
852 INIT_LIST_HEAD(&bat->bat_cli_hash[i]);
853 INIT_LIST_HEAD(&bat->bat_srv_hash[i]);
856 list_add_tail(&bat->bat_link, &console_session.ses_bat_list);
862 lstcon_batch_list(int index, int len, char __user *name_up)
864 struct lstcon_batch *bat;
866 LASSERT(name_up != NULL);
869 list_for_each_entry(bat, &console_session.ses_bat_list, bat_link) {
871 return copy_to_user(name_up, bat->bat_name, len) ?
880 lstcon_batch_info(char *name, struct lstcon_test_batch_ent __user *ent_up,
881 int server, int testidx, int *index_p, int *ndent_p,
882 struct lstcon_node_ent __user *dents_up)
884 struct lstcon_test_batch_ent *entp;
885 struct list_head *clilst;
886 struct list_head *srvlst;
887 struct lstcon_test *test = NULL;
888 struct lstcon_batch *bat;
889 struct lstcon_ndlink *ndl;
892 rc = lstcon_batch_find(name, &bat);
894 CDEBUG(D_NET, "Can't find batch %s\n", name);
899 /* query test, test index start from 1 */
900 list_for_each_entry(test, &bat->bat_test_list, tes_link) {
906 CDEBUG(D_NET, "Can't find specified test in batch\n");
911 clilst = (test == NULL) ? &bat->bat_cli_list :
912 &test->tes_src_grp->grp_ndl_list;
913 srvlst = (test == NULL) ? &bat->bat_srv_list :
914 &test->tes_dst_grp->grp_ndl_list;
916 if (dents_up != NULL) {
917 rc = lstcon_nodes_getent((server ? srvlst: clilst),
918 index_p, ndent_p, dents_up);
922 /* non-verbose query */
928 entp->u.tbe_batch.bae_ntest = bat->bat_ntest;
929 entp->u.tbe_batch.bae_state = bat->bat_state;
933 entp->u.tbe_test.tse_type = test->tes_type;
934 entp->u.tbe_test.tse_loop = test->tes_loop;
935 entp->u.tbe_test.tse_concur = test->tes_concur;
938 list_for_each_entry(ndl, clilst, ndl_link)
939 LST_NODE_STATE_COUNTER(ndl->ndl_node, &entp->tbe_cli_nle);
941 list_for_each_entry(ndl, srvlst, ndl_link)
942 LST_NODE_STATE_COUNTER(ndl->ndl_node, &entp->tbe_srv_nle);
944 rc = copy_to_user(ent_up, entp,
945 sizeof(struct lstcon_test_batch_ent)) ? -EFAULT : 0;
953 lstcon_batrpc_condition(int transop, struct lstcon_node *nd, void *arg)
956 case LST_TRANS_TSBRUN:
957 if (nd->nd_state != LST_NODE_ACTIVE)
961 case LST_TRANS_TSBSTOP:
962 if (nd->nd_state != LST_NODE_ACTIVE)
966 case LST_TRANS_TSBCLIQRY:
967 case LST_TRANS_TSBSRVQRY:
975 lstcon_batch_op(struct lstcon_batch *bat, int transop,
976 struct list_head __user *result_up)
978 struct lstcon_rpc_trans *trans;
981 rc = lstcon_rpc_trans_ndlist(&bat->bat_cli_list,
982 &bat->bat_trans_list, transop,
983 bat, lstcon_batrpc_condition, &trans);
985 CERROR("Can't create transaction: %d\n", rc);
989 lstcon_rpc_trans_postwait(trans, LST_TRANS_TIMEOUT);
991 rc = lstcon_rpc_trans_interpreter(trans, result_up, NULL);
993 lstcon_rpc_trans_destroy(trans);
999 lstcon_batch_run(char *name, int timeout, struct list_head __user *result_up)
1001 struct lstcon_batch *bat;
1004 if (lstcon_batch_find(name, &bat) != 0) {
1005 CDEBUG(D_NET, "Can't find batch %s\n", name);
1009 bat->bat_arg = timeout;
1011 rc = lstcon_batch_op(bat, LST_TRANS_TSBRUN, result_up);
1013 /* mark batch as running if it's started in any node */
1014 if (lstcon_tsbop_stat_success(lstcon_trans_stat(), 0) != 0)
1015 bat->bat_state = LST_BATCH_RUNNING;
1021 lstcon_batch_stop(char *name, int force, struct list_head __user *result_up)
1023 struct lstcon_batch *bat;
1026 if (lstcon_batch_find(name, &bat) != 0) {
1027 CDEBUG(D_NET, "Can't find batch %s\n", name);
1031 bat->bat_arg = force;
1033 rc = lstcon_batch_op(bat, LST_TRANS_TSBSTOP, result_up);
1035 /* mark batch as stopped if all RPCs finished */
1036 if (lstcon_tsbop_stat_failure(lstcon_trans_stat(), 0) == 0)
1037 bat->bat_state = LST_BATCH_IDLE;
1043 lstcon_batch_destroy(struct lstcon_batch *bat)
1045 struct lstcon_ndlink *ndl;
1046 struct lstcon_test *test;
1049 list_del(&bat->bat_link);
1051 while (!list_empty(&bat->bat_test_list)) {
1052 test = list_first_entry(&bat->bat_test_list,
1053 struct lstcon_test, tes_link);
1054 LASSERT(list_empty(&test->tes_trans_list));
1056 list_del(&test->tes_link);
1058 lstcon_group_decref(test->tes_src_grp);
1059 lstcon_group_decref(test->tes_dst_grp);
1061 LIBCFS_FREE(test, offsetof(struct lstcon_test,
1062 tes_param[test->tes_paramlen]));
1065 LASSERT(list_empty(&bat->bat_trans_list));
1067 while (!list_empty(&bat->bat_cli_list)) {
1068 ndl = list_first_entry(&bat->bat_cli_list,
1069 struct lstcon_ndlink, ndl_link);
1070 list_del_init(&ndl->ndl_link);
1072 lstcon_ndlink_release(ndl);
1075 while (!list_empty(&bat->bat_srv_list)) {
1076 ndl = list_first_entry(&bat->bat_srv_list,
1077 struct lstcon_ndlink, ndl_link);
1078 list_del_init(&ndl->ndl_link);
1080 lstcon_ndlink_release(ndl);
1083 for (i = 0; i < LST_NODE_HASHSIZE; i++) {
1084 LASSERT(list_empty(&bat->bat_cli_hash[i]));
1085 LASSERT(list_empty(&bat->bat_srv_hash[i]));
1088 LIBCFS_FREE(bat->bat_cli_hash,
1089 sizeof(struct list_head) * LST_NODE_HASHSIZE);
1090 LIBCFS_FREE(bat->bat_srv_hash,
1091 sizeof(struct list_head) * LST_NODE_HASHSIZE);
1092 LIBCFS_FREE(bat, sizeof(*bat));
1096 lstcon_testrpc_condition(int transop, struct lstcon_node *nd, void *arg)
1098 struct lstcon_test *test = arg;
1099 struct lstcon_batch *batch;
1100 struct lstcon_ndlink *ndl;
1101 struct list_head *hash;
1102 struct list_head *head;
1104 LASSERT(test != NULL);
1106 batch = test->tes_batch;
1107 LASSERT(batch != NULL);
1109 if (test->tes_oneside &&
1110 transop == LST_TRANS_TSBSRVADD)
1113 if (nd->nd_state != LST_NODE_ACTIVE)
1116 if (transop == LST_TRANS_TSBCLIADD) {
1117 hash = batch->bat_cli_hash;
1118 head = &batch->bat_cli_list;
1121 LASSERT (transop == LST_TRANS_TSBSRVADD);
1123 hash = batch->bat_srv_hash;
1124 head = &batch->bat_srv_list;
1127 LASSERT (nd->nd_id.nid != LNET_NID_ANY);
1129 if (lstcon_ndlink_find(hash, nd->nd_id, &ndl, 1) != 0)
1132 if (list_empty(&ndl->ndl_link))
1133 list_add_tail(&ndl->ndl_link, head);
1139 lstcon_test_nodes_add(struct lstcon_test *test,
1140 struct list_head __user *result_up)
1142 struct lstcon_rpc_trans *trans;
1143 struct lstcon_group *grp;
1147 LASSERT (test->tes_src_grp != NULL);
1148 LASSERT (test->tes_dst_grp != NULL);
1150 transop = LST_TRANS_TSBSRVADD;
1151 grp = test->tes_dst_grp;
1153 rc = lstcon_rpc_trans_ndlist(&grp->grp_ndl_list,
1154 &test->tes_trans_list, transop,
1155 test, lstcon_testrpc_condition, &trans);
1157 CERROR("Can't create transaction: %d\n", rc);
1161 lstcon_rpc_trans_postwait(trans, LST_TRANS_TIMEOUT);
1163 if (lstcon_trans_stat()->trs_rpc_errno != 0 ||
1164 lstcon_trans_stat()->trs_fwk_errno != 0) {
1165 lstcon_rpc_trans_interpreter(trans, result_up, NULL);
1167 lstcon_rpc_trans_destroy(trans);
1168 /* return if any error */
1169 CDEBUG(D_NET, "Failed to add test %s, "
1170 "RPC error %d, framework error %d\n",
1171 transop == LST_TRANS_TSBCLIADD ? "client" : "server",
1172 lstcon_trans_stat()->trs_rpc_errno,
1173 lstcon_trans_stat()->trs_fwk_errno);
1178 lstcon_rpc_trans_destroy(trans);
1180 if (transop == LST_TRANS_TSBCLIADD)
1183 transop = LST_TRANS_TSBCLIADD;
1184 grp = test->tes_src_grp;
1185 test->tes_cliidx = 0;
1187 /* requests to test clients */
1192 lstcon_verify_batch(const char *name, struct lstcon_batch **batch)
1196 rc = lstcon_batch_find(name, batch);
1198 CDEBUG(D_NET, "Can't find batch %s\n", name);
1202 if ((*batch)->bat_state != LST_BATCH_IDLE) {
1203 CDEBUG(D_NET, "Can't change running batch %s\n", name);
1211 lstcon_verify_group(const char *name, struct lstcon_group **grp)
1214 struct lstcon_ndlink *ndl;
1216 rc = lstcon_group_find(name, grp);
1218 CDEBUG(D_NET, "can't find group %s\n", name);
1222 list_for_each_entry(ndl, &(*grp)->grp_ndl_list, ndl_link) {
1223 if (ndl->ndl_node->nd_state == LST_NODE_ACTIVE) {
1228 CDEBUG(D_NET, "Group %s has no ACTIVE nodes\n", name);
1234 lstcon_test_add(char *batch_name, int type, int loop,
1235 int concur, int dist, int span,
1236 char *src_name, char *dst_name,
1237 void *param, int paramlen, int *retp,
1238 struct list_head __user *result_up)
1240 struct lstcon_test *test = NULL;
1242 struct lstcon_group *src_grp = NULL;
1243 struct lstcon_group *dst_grp = NULL;
1244 struct lstcon_batch *batch = NULL;
1247 * verify that a batch of the given name exists, and the groups
1248 * that will be part of the batch exist and have at least one
1251 rc = lstcon_verify_batch(batch_name, &batch);
1255 rc = lstcon_verify_group(src_name, &src_grp);
1259 rc = lstcon_verify_group(dst_name, &dst_grp);
1263 if (dst_grp->grp_userland)
1266 LIBCFS_ALLOC(test, offsetof(struct lstcon_test, tes_param[paramlen]));
1268 CERROR("Can't allocate test descriptor\n");
1274 test->tes_hdr.tsb_id = batch->bat_hdr.tsb_id;
1275 test->tes_batch = batch;
1276 test->tes_type = type;
1277 test->tes_oneside = 0; /* TODO */
1278 test->tes_loop = loop;
1279 test->tes_concur = concur;
1280 test->tes_stop_onerr = 1; /* TODO */
1281 test->tes_span = span;
1282 test->tes_dist = dist;
1283 test->tes_cliidx = 0; /* just used for creating RPC */
1284 test->tes_src_grp = src_grp;
1285 test->tes_dst_grp = dst_grp;
1286 INIT_LIST_HEAD(&test->tes_trans_list);
1288 if (param != NULL) {
1289 test->tes_paramlen = paramlen;
1290 memcpy(&test->tes_param[0], param, paramlen);
1293 rc = lstcon_test_nodes_add(test, result_up);
1298 if (lstcon_trans_stat()->trs_rpc_errno != 0 ||
1299 lstcon_trans_stat()->trs_fwk_errno != 0)
1300 CDEBUG(D_NET, "Failed to add test %d to batch %s\n", type,
1303 /* add to test list anyway, so user can check what's going on */
1304 list_add_tail(&test->tes_link, &batch->bat_test_list);
1307 test->tes_hdr.tsb_index = batch->bat_ntest;
1309 /* hold groups so nobody can change them */
1313 LIBCFS_FREE(test, offsetof(struct lstcon_test,
1314 tes_param[paramlen]));
1316 if (dst_grp != NULL)
1317 lstcon_group_decref(dst_grp);
1319 if (src_grp != NULL)
1320 lstcon_group_decref(src_grp);
1326 lstcon_test_find(struct lstcon_batch *batch, int idx,
1327 struct lstcon_test **testpp)
1329 struct lstcon_test *test;
1331 list_for_each_entry(test, &batch->bat_test_list, tes_link) {
1332 if (idx == test->tes_hdr.tsb_index) {
1342 lstcon_tsbrpc_readent(int transop, struct srpc_msg *msg,
1343 struct lstcon_rpc_ent __user *ent_up)
1345 struct srpc_batch_reply *rep = &msg->msg_body.bat_reply;
1347 LASSERT (transop == LST_TRANS_TSBCLIQRY ||
1348 transop == LST_TRANS_TSBSRVQRY);
1350 /* positive errno, framework error code */
1351 if (copy_to_user(&ent_up->rpe_priv[0],
1352 &rep->bar_active, sizeof(rep->bar_active)))
1359 lstcon_test_batch_query(char *name, int testidx, int client,
1360 int timeout, struct list_head __user *result_up)
1362 struct lstcon_rpc_trans *trans;
1363 struct list_head *translist;
1364 struct list_head *ndlist;
1365 struct lstcon_tsb_hdr *hdr;
1366 struct lstcon_batch *batch;
1367 struct lstcon_test *test = NULL;
1371 rc = lstcon_batch_find(name, &batch);
1373 CDEBUG(D_NET, "Can't find batch: %s\n", name);
1378 translist = &batch->bat_trans_list;
1379 ndlist = &batch->bat_cli_list;
1380 hdr = &batch->bat_hdr;
1383 /* query specified test only */
1384 rc = lstcon_test_find(batch, testidx, &test);
1386 CDEBUG(D_NET, "Can't find test: %d\n", testidx);
1390 translist = &test->tes_trans_list;
1391 ndlist = &test->tes_src_grp->grp_ndl_list;
1392 hdr = &test->tes_hdr;
1395 transop = client ? LST_TRANS_TSBCLIQRY : LST_TRANS_TSBSRVQRY;
1397 rc = lstcon_rpc_trans_ndlist(ndlist, translist, transop, hdr,
1398 lstcon_batrpc_condition, &trans);
1400 CERROR("Can't create transaction: %d\n", rc);
1404 lstcon_rpc_trans_postwait(trans, timeout);
1406 if (testidx == 0 && /* query a batch, not a test */
1407 lstcon_rpc_stat_failure(lstcon_trans_stat(), 0) == 0 &&
1408 lstcon_tsbqry_stat_run(lstcon_trans_stat(), 0) == 0) {
1409 /* all RPCs finished, and no active test */
1410 batch->bat_state = LST_BATCH_IDLE;
1413 rc = lstcon_rpc_trans_interpreter(trans, result_up,
1414 lstcon_tsbrpc_readent);
1415 lstcon_rpc_trans_destroy(trans);
1421 lstcon_statrpc_readent(int transop, struct srpc_msg *msg,
1422 struct lstcon_rpc_ent __user *ent_up)
1424 struct srpc_stat_reply *rep = &msg->msg_body.stat_reply;
1425 struct sfw_counters __user *sfwk_stat;
1426 struct srpc_counters __user *srpc_stat;
1427 struct lnet_counters_common __user *lnet_stat;
1429 if (rep->str_status != 0)
1432 sfwk_stat = (struct sfw_counters __user *)&ent_up->rpe_payload[0];
1433 srpc_stat = (struct srpc_counters __user *)
1434 ((char __user *)sfwk_stat + sizeof(*sfwk_stat));
1435 lnet_stat = (struct lnet_counters_common __user *)
1436 ((char __user *)srpc_stat + sizeof(*srpc_stat));
1438 if (copy_to_user(sfwk_stat, &rep->str_fw, sizeof(*sfwk_stat)) ||
1439 copy_to_user(srpc_stat, &rep->str_rpc, sizeof(*srpc_stat)) ||
1440 copy_to_user(lnet_stat, &rep->str_lnet, sizeof(*lnet_stat)))
1447 lstcon_ndlist_stat(struct list_head *ndlist,
1448 int timeout, struct list_head __user *result_up)
1451 struct lstcon_rpc_trans *trans;
1454 rc = lstcon_rpc_trans_ndlist(ndlist, &head,
1455 LST_TRANS_STATQRY, NULL, NULL, &trans);
1457 CERROR("Can't create transaction: %d\n", rc);
1461 lstcon_rpc_trans_postwait(trans, LST_VALIDATE_TIMEOUT(timeout));
1463 rc = lstcon_rpc_trans_interpreter(trans, result_up,
1464 lstcon_statrpc_readent);
1465 lstcon_rpc_trans_destroy(trans);
1471 lstcon_group_stat(char *grp_name, int timeout,
1472 struct list_head __user *result_up)
1474 struct lstcon_group *grp;
1477 rc = lstcon_group_find(grp_name, &grp);
1479 CDEBUG(D_NET, "Can't find group %s\n", grp_name);
1483 rc = lstcon_ndlist_stat(&grp->grp_ndl_list, timeout, result_up);
1485 lstcon_group_decref(grp);
1491 lstcon_nodes_stat(int count, struct lnet_process_id __user *ids_up,
1492 int timeout, struct list_head __user *result_up)
1494 struct lstcon_ndlink *ndl;
1495 struct lstcon_group *tmp;
1496 struct lnet_process_id id;
1500 rc = lstcon_group_alloc(NULL, &tmp);
1502 CERROR("Out of memory\n");
1506 for (i = 0 ; i < count; i++) {
1507 if (copy_from_user(&id, &ids_up[i], sizeof(id))) {
1512 /* add to tmp group */
1513 rc = lstcon_group_ndlink_find(tmp, id, &ndl, 2);
1515 CDEBUG((rc == -ENOMEM) ? D_ERROR : D_NET,
1516 "Failed to find or create %s: %d\n",
1517 libcfs_id2str(id), rc);
1523 lstcon_group_decref(tmp);
1527 rc = lstcon_ndlist_stat(&tmp->grp_ndl_list, timeout, result_up);
1529 lstcon_group_decref(tmp);
1535 lstcon_debug_ndlist(struct list_head *ndlist,
1536 struct list_head *translist,
1537 int timeout, struct list_head __user *result_up)
1539 struct lstcon_rpc_trans *trans;
1542 rc = lstcon_rpc_trans_ndlist(ndlist, translist, LST_TRANS_SESQRY,
1543 NULL, lstcon_sesrpc_condition, &trans);
1545 CERROR("Can't create transaction: %d\n", rc);
1549 lstcon_rpc_trans_postwait(trans, LST_VALIDATE_TIMEOUT(timeout));
1551 rc = lstcon_rpc_trans_interpreter(trans, result_up,
1552 lstcon_sesrpc_readent);
1553 lstcon_rpc_trans_destroy(trans);
1559 lstcon_session_debug(int timeout, struct list_head __user *result_up)
1561 return lstcon_debug_ndlist(&console_session.ses_ndl_list,
1562 NULL, timeout, result_up);
1566 lstcon_batch_debug(int timeout, char *name,
1567 int client, struct list_head __user *result_up)
1569 struct lstcon_batch *bat;
1572 rc = lstcon_batch_find(name, &bat);
1576 rc = lstcon_debug_ndlist(client ? &bat->bat_cli_list :
1578 NULL, timeout, result_up);
1584 lstcon_group_debug(int timeout, char *name,
1585 struct list_head __user *result_up)
1587 struct lstcon_group *grp;
1590 rc = lstcon_group_find(name, &grp);
1594 rc = lstcon_debug_ndlist(&grp->grp_ndl_list, NULL,
1595 timeout, result_up);
1596 lstcon_group_decref(grp);
1602 lstcon_nodes_debug(int timeout, int count,
1603 struct lnet_process_id __user *ids_up,
1604 struct list_head __user *result_up)
1606 struct lnet_process_id id;
1607 struct lstcon_ndlink *ndl;
1608 struct lstcon_group *grp;
1612 rc = lstcon_group_alloc(NULL, &grp);
1614 CDEBUG(D_NET, "Out of memory\n");
1618 for (i = 0; i < count; i++) {
1619 if (copy_from_user(&id, &ids_up[i], sizeof(id))) {
1624 /* node is added to tmp group */
1625 rc = lstcon_group_ndlink_find(grp, id, &ndl, 1);
1627 CERROR("Can't create node link\n");
1633 lstcon_group_decref(grp);
1637 rc = lstcon_debug_ndlist(&grp->grp_ndl_list, NULL,
1638 timeout, result_up);
1640 lstcon_group_decref(grp);
1646 lstcon_session_match(struct lst_sid id)
1648 struct lst_session_id sid;
1650 sid.ses_stamp = id.ses_stamp;
1651 lnet_nid4_to_nid(id.ses_nid, &sid.ses_nid);
1653 return (nid_same(&console_session.ses_id.ses_nid, &sid.ses_nid) &&
1654 console_session.ses_id.ses_stamp == sid.ses_stamp) ? 1 : 0;
1658 lstcon_new_session_id(struct lst_session_id *sid)
1660 struct lnet_processid id;
1662 LASSERT(console_session.ses_state == LST_SESSION_NONE);
1664 LNetGetId(1, &id, true);
1665 sid->ses_nid = id.nid;
1666 sid->ses_stamp = div_u64(ktime_get_ns(), NSEC_PER_MSEC);
1670 lstcon_session_new(char *name, int key, unsigned feats,
1671 int timeout, int force)
1676 if (console_session.ses_state != LST_SESSION_NONE) {
1677 /* session exists */
1679 CNETERR("Session %s already exists\n",
1680 console_session.ses_name);
1684 rc = lstcon_session_end();
1686 /* lstcon_session_end() only return local error */
1691 if ((feats & ~LST_FEATS_MASK) != 0) {
1692 CNETERR("Unknown session features %x\n",
1693 (feats & ~LST_FEATS_MASK));
1697 for (i = 0; i < LST_GLOBAL_HASHSIZE; i++)
1698 LASSERT(list_empty(&console_session.ses_ndl_hash[i]));
1700 lstcon_new_session_id(&console_session.ses_id);
1702 console_session.ses_key = key;
1703 console_session.ses_force = !!force;
1704 console_session.ses_features = feats;
1705 console_session.ses_feats_updated = 0;
1706 console_session.ses_timeout = (timeout <= 0) ?
1707 LST_CONSOLE_TIMEOUT : timeout;
1709 if (strlen(name) > sizeof(console_session.ses_name)-1)
1711 strscpy(console_session.ses_name, name,
1712 sizeof(console_session.ses_name));
1714 rc = lstcon_batch_add(LST_DEFAULT_BATCH);
1718 rc = lstcon_rpc_pinger_start();
1720 struct lstcon_batch *bat = NULL;
1722 lstcon_batch_find(LST_DEFAULT_BATCH, &bat);
1723 lstcon_batch_destroy(bat);
1728 console_session.ses_state = LST_SESSION_ACTIVE;
1733 int lstcon_session_end(void)
1735 struct lstcon_rpc_trans *trans;
1736 struct lstcon_group *grp;
1737 struct lstcon_batch *bat;
1740 LASSERT (console_session.ses_state == LST_SESSION_ACTIVE);
1742 rc = lstcon_rpc_trans_ndlist(&console_session.ses_ndl_list,
1743 NULL, LST_TRANS_SESEND, NULL,
1744 lstcon_sesrpc_condition, &trans);
1746 CERROR("Can't create transaction: %d\n", rc);
1750 console_session.ses_shutdown = 1;
1752 lstcon_rpc_pinger_stop();
1754 lstcon_rpc_trans_postwait(trans, LST_TRANS_TIMEOUT);
1756 lstcon_rpc_trans_destroy(trans);
1757 /* User can do nothing even rpc failed, so go on */
1759 /* waiting for orphan rpcs to die */
1760 lstcon_rpc_cleanup_wait();
1762 console_session.ses_id = LST_INVALID_SID;
1763 console_session.ses_state = LST_SESSION_NONE;
1764 console_session.ses_key = 0;
1765 console_session.ses_force = 0;
1766 console_session.ses_feats_updated = 0;
1768 /* destroy all batches */
1769 while (!list_empty(&console_session.ses_bat_list)) {
1770 bat = list_first_entry(&console_session.ses_bat_list,
1771 struct lstcon_batch, bat_link);
1773 lstcon_batch_destroy(bat);
1776 /* destroy all groups */
1777 while (!list_empty(&console_session.ses_grp_list)) {
1778 grp = list_first_entry(&console_session.ses_grp_list,
1779 struct lstcon_group, grp_link);
1780 LASSERT(grp->grp_ref == 1);
1782 lstcon_group_decref(grp);
1785 /* all nodes should be released */
1786 LASSERT(list_empty(&console_session.ses_ndl_list));
1788 console_session.ses_shutdown = 0;
1789 console_session.ses_expired = 0;
1795 lstcon_session_feats_check(unsigned feats)
1799 if ((feats & ~LST_FEATS_MASK) != 0) {
1800 CERROR("Can't support these features: %x\n",
1801 (feats & ~LST_FEATS_MASK));
1805 spin_lock(&console_session.ses_rpc_lock);
1807 if (!console_session.ses_feats_updated) {
1808 console_session.ses_feats_updated = 1;
1809 console_session.ses_features = feats;
1812 if (console_session.ses_features != feats)
1815 spin_unlock(&console_session.ses_rpc_lock);
1818 CERROR("remote features %x do not match with "
1819 "session features %x of console\n",
1820 feats, console_session.ses_features);
1827 lstcon_acceptor_handle(struct srpc_server_rpc *rpc)
1829 struct srpc_msg *rep = &rpc->srpc_replymsg;
1830 struct srpc_msg *req = &rpc->srpc_reqstbuf->buf_msg;
1831 struct srpc_join_reqst *jreq = &req->msg_body.join_reqst;
1832 struct srpc_join_reply *jrep = &rep->msg_body.join_reply;
1833 struct lstcon_group *grp = NULL;
1834 struct lstcon_ndlink *ndl;
1837 sfw_unpack_message(req);
1839 mutex_lock(&console_session.ses_mutex);
1841 jrep->join_sid.ses_stamp = console_session.ses_id.ses_stamp;
1842 jrep->join_sid.ses_nid = lnet_nid_to_nid4(&console_session.ses_id.ses_nid);
1844 if (LNET_NID_IS_ANY(&console_session.ses_id.ses_nid)) {
1845 jrep->join_status = ESRCH;
1849 if (lstcon_session_feats_check(req->msg_ses_feats) != 0) {
1850 jrep->join_status = EPROTO;
1854 if (jreq->join_sid.ses_nid != LNET_NID_ANY &&
1855 !lstcon_session_match(jreq->join_sid)) {
1856 jrep->join_status = EBUSY;
1860 if (lstcon_group_find(jreq->join_group, &grp) != 0) {
1861 rc = lstcon_group_alloc(jreq->join_group, &grp);
1863 CERROR("Out of memory\n");
1867 list_add_tail(&grp->grp_link,
1868 &console_session.ses_grp_list);
1869 lstcon_group_addref(grp);
1872 if (grp->grp_ref > 2) {
1873 /* Group in using */
1874 jrep->join_status = EBUSY;
1878 rc = lstcon_group_ndlink_find(grp, rpc->srpc_peer, &ndl, 0);
1880 jrep->join_status = EEXIST;
1884 rc = lstcon_group_ndlink_find(grp, rpc->srpc_peer, &ndl, 1);
1886 CERROR("Out of memory\n");
1890 ndl->ndl_node->nd_state = LST_NODE_ACTIVE;
1891 ndl->ndl_node->nd_timeout = console_session.ses_timeout;
1893 if (grp->grp_userland == 0)
1894 grp->grp_userland = 1;
1896 strscpy(jrep->join_session, console_session.ses_name,
1897 sizeof(jrep->join_session));
1898 jrep->join_timeout = console_session.ses_timeout;
1899 jrep->join_status = 0;
1902 rep->msg_ses_feats = console_session.ses_features;
1904 lstcon_group_decref(grp);
1906 mutex_unlock(&console_session.ses_mutex);
1911 static struct srpc_service lstcon_acceptor_service;
1913 static void lstcon_init_acceptor_service(void)
1915 /* initialize selftest console acceptor service table */
1916 lstcon_acceptor_service.sv_name = "join session";
1917 lstcon_acceptor_service.sv_handler = lstcon_acceptor_handle;
1918 lstcon_acceptor_service.sv_id = SRPC_SERVICE_JOIN;
1919 lstcon_acceptor_service.sv_wi_total = SFW_FRWK_WI_MAX;
1922 static struct notifier_block lstcon_ioctl_handler = {
1923 .notifier_call = lstcon_ioctl_entry,
1926 /* initialize console */
1928 lstcon_console_init(void)
1933 console_session.ses_id = LST_INVALID_SID;
1934 console_session.ses_state = LST_SESSION_NONE;
1935 console_session.ses_timeout = 0;
1936 console_session.ses_force = 0;
1937 console_session.ses_expired = 0;
1938 console_session.ses_feats_updated = 0;
1939 console_session.ses_features = LST_FEATS_MASK;
1940 console_session.ses_laststamp = ktime_get_real_seconds();
1942 mutex_init(&console_session.ses_mutex);
1944 INIT_LIST_HEAD(&console_session.ses_ndl_list);
1945 INIT_LIST_HEAD(&console_session.ses_grp_list);
1946 INIT_LIST_HEAD(&console_session.ses_bat_list);
1947 INIT_LIST_HEAD(&console_session.ses_trans_list);
1949 CFS_ALLOC_PTR_ARRAY(console_session.ses_ndl_hash,
1950 LST_GLOBAL_HASHSIZE);
1951 if (console_session.ses_ndl_hash == NULL)
1954 for (i = 0; i < LST_GLOBAL_HASHSIZE; i++)
1955 INIT_LIST_HEAD(&console_session.ses_ndl_hash[i]);
1958 /* initialize acceptor service table */
1959 lstcon_init_acceptor_service();
1961 rc = srpc_add_service(&lstcon_acceptor_service);
1962 LASSERT(rc != -EBUSY);
1964 CFS_FREE_PTR_ARRAY(console_session.ses_ndl_hash,
1965 LST_GLOBAL_HASHSIZE);
1969 rc = srpc_service_add_buffers(&lstcon_acceptor_service,
1970 lstcon_acceptor_service.sv_wi_total);
1976 rc = lstcon_init_netlink();
1980 rc = blocking_notifier_chain_register(&lnet_ioctl_list,
1981 &lstcon_ioctl_handler);
1983 lstcon_fini_netlink();
1987 lstcon_rpc_module_init();
1991 srpc_shutdown_service(&lstcon_acceptor_service);
1992 srpc_remove_service(&lstcon_acceptor_service);
1994 CFS_FREE_PTR_ARRAY(console_session.ses_ndl_hash, LST_GLOBAL_HASHSIZE);
1996 srpc_wait_service_shutdown(&lstcon_acceptor_service);
2002 lstcon_console_fini(void)
2006 blocking_notifier_chain_unregister(&lnet_ioctl_list,
2007 &lstcon_ioctl_handler);
2008 lstcon_fini_netlink();
2010 mutex_lock(&console_session.ses_mutex);
2012 srpc_shutdown_service(&lstcon_acceptor_service);
2013 srpc_remove_service(&lstcon_acceptor_service);
2015 if (console_session.ses_state != LST_SESSION_NONE)
2016 lstcon_session_end();
2018 lstcon_rpc_module_fini();
2020 mutex_unlock(&console_session.ses_mutex);
2022 LASSERT(list_empty(&console_session.ses_ndl_list));
2023 LASSERT(list_empty(&console_session.ses_grp_list));
2024 LASSERT(list_empty(&console_session.ses_bat_list));
2025 LASSERT(list_empty(&console_session.ses_trans_list));
2027 for (i = 0; i < LST_NODE_HASHSIZE; i++)
2028 LASSERT(list_empty(&console_session.ses_ndl_hash[i]));
2030 CFS_FREE_PTR_ARRAY(console_session.ses_ndl_hash,
2031 LST_GLOBAL_HASHSIZE);
2033 srpc_wait_service_shutdown(&lstcon_acceptor_service);