4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 only,
8 * as published by the Free Software Foundation.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License version 2 for more details (a copy is included
14 * in the LICENSE file that accompanied this code).
16 * You should have received a copy of the GNU General Public License
17 * version 2 along with this program; If not, see
18 * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
20 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
21 * CA 95054 USA or visit www.sun.com if you need additional information or
27 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
28 * Use is subject to license terms.
30 * Copyright (c) 2012, Intel Corporation.
33 * This file is part of Lustre, http://www.lustre.org/
34 * Lustre is a trademark of Sun Microsystems, Inc.
36 * lnet/selftest/conctl.c
38 * Infrastructure of LST console
40 * Author: Liang Zhen <liangzhen@clusterfs.com>
44 #include <linux/libcfs/libcfs.h>
45 #include <linux/lnet/lib-lnet.h>
49 #define LST_NODE_STATE_COUNTER(nd, p) \
51 if ((nd)->nd_state == LST_NODE_ACTIVE) \
52 (p)->nle_nactive ++; \
53 else if ((nd)->nd_state == LST_NODE_BUSY) \
55 else if ((nd)->nd_state == LST_NODE_DOWN) \
58 (p)->nle_nunknown ++; \
62 lstcon_session_t console_session
;
65 lstcon_node_get(lstcon_node_t
*nd
)
67 LASSERT (nd
->nd_ref
>= 1);
73 lstcon_node_find(lnet_process_id_t id
, lstcon_node_t
**ndpp
, int create
)
76 unsigned int idx
= LNET_NIDADDR(id
.nid
) % LST_GLOBAL_HASHSIZE
;
78 LASSERT (id
.nid
!= LNET_NID_ANY
);
80 list_for_each_entry(ndl
, &console_session
.ses_ndl_hash
[idx
], ndl_hlink
) {
81 if (ndl
->ndl_node
->nd_id
.nid
!= id
.nid
||
82 ndl
->ndl_node
->nd_id
.pid
!= id
.pid
)
85 lstcon_node_get(ndl
->ndl_node
);
86 *ndpp
= ndl
->ndl_node
;
93 LIBCFS_ALLOC(*ndpp
, sizeof(lstcon_node_t
) + sizeof(lstcon_ndlink_t
));
97 ndl
= (lstcon_ndlink_t
*)(*ndpp
+ 1);
99 ndl
->ndl_node
= *ndpp
;
101 ndl
->ndl_node
->nd_ref
= 1;
102 ndl
->ndl_node
->nd_id
= id
;
103 ndl
->ndl_node
->nd_stamp
= cfs_time_current();
104 ndl
->ndl_node
->nd_state
= LST_NODE_UNKNOWN
;
105 ndl
->ndl_node
->nd_timeout
= 0;
106 memset(&ndl
->ndl_node
->nd_ping
, 0, sizeof(lstcon_rpc_t
));
108 /* queued in global hash & list, no refcount is taken by
109 * global hash & list, if caller release his refcount,
110 * node will be released */
111 list_add_tail(&ndl
->ndl_hlink
, &console_session
.ses_ndl_hash
[idx
]);
112 list_add_tail(&ndl
->ndl_link
, &console_session
.ses_ndl_list
);
118 lstcon_node_put(lstcon_node_t
*nd
)
120 lstcon_ndlink_t
*ndl
;
122 LASSERT (nd
->nd_ref
> 0);
124 if (--nd
->nd_ref
> 0)
127 ndl
= (lstcon_ndlink_t
*)(nd
+ 1);
129 LASSERT (!list_empty(&ndl
->ndl_link
));
130 LASSERT (!list_empty(&ndl
->ndl_hlink
));
132 /* remove from session */
133 list_del(&ndl
->ndl_link
);
134 list_del(&ndl
->ndl_hlink
);
136 LIBCFS_FREE(nd
, sizeof(lstcon_node_t
) + sizeof(lstcon_ndlink_t
));
140 lstcon_ndlink_find(struct list_head
*hash
,
141 lnet_process_id_t id
, lstcon_ndlink_t
**ndlpp
, int create
)
143 unsigned int idx
= LNET_NIDADDR(id
.nid
) % LST_NODE_HASHSIZE
;
144 lstcon_ndlink_t
*ndl
;
148 if (id
.nid
== LNET_NID_ANY
)
152 list_for_each_entry(ndl
, &hash
[idx
], ndl_hlink
) {
153 if (ndl
->ndl_node
->nd_id
.nid
!= id
.nid
||
154 ndl
->ndl_node
->nd_id
.pid
!= id
.pid
)
164 /* find or create in session hash */
165 rc
= lstcon_node_find(id
, &nd
, (create
== 1) ? 1 : 0);
169 LIBCFS_ALLOC(ndl
, sizeof(lstcon_ndlink_t
));
178 INIT_LIST_HEAD(&ndl
->ndl_link
);
179 list_add_tail(&ndl
->ndl_hlink
, &hash
[idx
]);
185 lstcon_ndlink_release(lstcon_ndlink_t
*ndl
)
187 LASSERT (list_empty(&ndl
->ndl_link
));
188 LASSERT (!list_empty(&ndl
->ndl_hlink
));
190 list_del(&ndl
->ndl_hlink
); /* delete from hash */
191 lstcon_node_put(ndl
->ndl_node
);
193 LIBCFS_FREE(ndl
, sizeof(*ndl
));
197 lstcon_group_alloc(char *name
, lstcon_group_t
**grpp
)
202 LIBCFS_ALLOC(grp
, offsetof(lstcon_group_t
,
203 grp_ndl_hash
[LST_NODE_HASHSIZE
]));
207 memset(grp
, 0, offsetof(lstcon_group_t
,
208 grp_ndl_hash
[LST_NODE_HASHSIZE
]));
212 strcpy(grp
->grp_name
, name
);
214 INIT_LIST_HEAD(&grp
->grp_link
);
215 INIT_LIST_HEAD(&grp
->grp_ndl_list
);
216 INIT_LIST_HEAD(&grp
->grp_trans_list
);
218 for (i
= 0; i
< LST_NODE_HASHSIZE
; i
++)
219 INIT_LIST_HEAD(&grp
->grp_ndl_hash
[i
]);
227 lstcon_group_addref(lstcon_group_t
*grp
)
232 static void lstcon_group_ndlink_release(lstcon_group_t
*, lstcon_ndlink_t
*);
235 lstcon_group_drain(lstcon_group_t
*grp
, int keep
)
237 lstcon_ndlink_t
*ndl
;
238 lstcon_ndlink_t
*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(lstcon_group_t
*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
]));
263 LIBCFS_FREE(grp
, offsetof(lstcon_group_t
,
264 grp_ndl_hash
[LST_NODE_HASHSIZE
]));
268 lstcon_group_find(const char *name
, lstcon_group_t
**grpp
)
272 list_for_each_entry(grp
, &console_session
.ses_grp_list
, grp_link
) {
273 if (strncmp(grp
->grp_name
, name
, LST_NAME_SIZE
) != 0)
276 lstcon_group_addref(grp
); /* +1 ref for caller */
285 lstcon_group_put(lstcon_group_t
*grp
)
287 lstcon_group_decref(grp
);
291 lstcon_group_ndlink_find(lstcon_group_t
*grp
, lnet_process_id_t id
,
292 lstcon_ndlink_t
**ndlpp
, int create
)
296 rc
= lstcon_ndlink_find(&grp
->grp_ndl_hash
[0], id
, ndlpp
, create
);
300 if (!list_empty(&(*ndlpp
)->ndl_link
))
303 list_add_tail(&(*ndlpp
)->ndl_link
, &grp
->grp_ndl_list
);
310 lstcon_group_ndlink_release(lstcon_group_t
*grp
, lstcon_ndlink_t
*ndl
)
312 list_del_init(&ndl
->ndl_link
);
313 lstcon_ndlink_release(ndl
);
318 lstcon_group_ndlink_move(lstcon_group_t
*old
,
319 lstcon_group_t
*new, lstcon_ndlink_t
*ndl
)
321 unsigned int idx
= LNET_NIDADDR(ndl
->ndl_node
->nd_id
.nid
) %
324 list_del(&ndl
->ndl_hlink
);
325 list_del(&ndl
->ndl_link
);
328 list_add_tail(&ndl
->ndl_hlink
, &new->grp_ndl_hash
[idx
]);
329 list_add_tail(&ndl
->ndl_link
, &new->grp_ndl_list
);
336 lstcon_group_move(lstcon_group_t
*old
, lstcon_group_t
*new)
338 lstcon_ndlink_t
*ndl
;
340 while (!list_empty(&old
->grp_ndl_list
)) {
341 ndl
= list_entry(old
->grp_ndl_list
.next
,
342 lstcon_ndlink_t
, ndl_link
);
343 lstcon_group_ndlink_move(old
, new, ndl
);
348 lstcon_sesrpc_condition(int transop
, lstcon_node_t
*nd
, void *arg
)
350 lstcon_group_t
*grp
= (lstcon_group_t
*)arg
;
353 case LST_TRANS_SESNEW
:
354 if (nd
->nd_state
== LST_NODE_ACTIVE
)
358 case LST_TRANS_SESEND
:
359 if (nd
->nd_state
!= LST_NODE_ACTIVE
)
362 if (grp
!= NULL
&& nd
->nd_ref
> 1)
366 case LST_TRANS_SESQRY
:
377 lstcon_sesrpc_readent(int transop
, srpc_msg_t
*msg
,
378 lstcon_rpc_ent_t
*ent_up
)
380 srpc_debug_reply_t
*rep
;
383 case LST_TRANS_SESNEW
:
384 case LST_TRANS_SESEND
:
387 case LST_TRANS_SESQRY
:
388 rep
= &msg
->msg_body
.dbg_reply
;
390 if (copy_to_user(&ent_up
->rpe_priv
[0],
391 &rep
->dbg_timeout
, sizeof(int)) ||
392 copy_to_user(&ent_up
->rpe_payload
[0],
393 &rep
->dbg_name
, LST_NAME_SIZE
))
406 lstcon_group_nodes_add(lstcon_group_t
*grp
,
407 int count
, lnet_process_id_t
*ids_up
,
408 unsigned *featp
, struct list_head
*result_up
)
410 lstcon_rpc_trans_t
*trans
;
411 lstcon_ndlink_t
*ndl
;
413 lnet_process_id_t id
;
417 rc
= lstcon_group_alloc(NULL
, &tmp
);
419 CERROR("Out of memory\n");
423 for (i
= 0 ; i
< count
; i
++) {
424 if (copy_from_user(&id
, &ids_up
[i
], sizeof(id
))) {
429 /* skip if it's in this group already */
430 rc
= lstcon_group_ndlink_find(grp
, id
, &ndl
, 0);
434 /* add to tmp group */
435 rc
= lstcon_group_ndlink_find(tmp
, id
, &ndl
, 1);
437 CERROR("Can't create ndlink, out of memory\n");
443 lstcon_group_put(tmp
);
447 rc
= lstcon_rpc_trans_ndlist(&tmp
->grp_ndl_list
,
448 &tmp
->grp_trans_list
, LST_TRANS_SESNEW
,
449 tmp
, lstcon_sesrpc_condition
, &trans
);
451 CERROR("Can't create transaction: %d\n", rc
);
452 lstcon_group_put(tmp
);
457 lstcon_rpc_trans_postwait(trans
, LST_TRANS_TIMEOUT
);
459 rc
= lstcon_rpc_trans_interpreter(trans
, result_up
,
460 lstcon_sesrpc_readent
);
461 *featp
= trans
->tas_features
;
463 /* destroy all RPGs */
464 lstcon_rpc_trans_destroy(trans
);
466 lstcon_group_move(tmp
, grp
);
467 lstcon_group_put(tmp
);
473 lstcon_group_nodes_remove(lstcon_group_t
*grp
,
474 int count
, lnet_process_id_t
*ids_up
,
475 struct list_head
*result_up
)
477 lstcon_rpc_trans_t
*trans
;
478 lstcon_ndlink_t
*ndl
;
480 lnet_process_id_t id
;
484 /* End session and remove node from the group */
486 rc
= lstcon_group_alloc(NULL
, &tmp
);
488 CERROR("Out of memory\n");
492 for (i
= 0; i
< count
; i
++) {
493 if (copy_from_user(&id
, &ids_up
[i
], sizeof(id
))) {
498 /* move node to tmp group */
499 if (lstcon_group_ndlink_find(grp
, id
, &ndl
, 0) == 0)
500 lstcon_group_ndlink_move(grp
, tmp
, ndl
);
503 rc
= lstcon_rpc_trans_ndlist(&tmp
->grp_ndl_list
,
504 &tmp
->grp_trans_list
, LST_TRANS_SESEND
,
505 tmp
, lstcon_sesrpc_condition
, &trans
);
507 CERROR("Can't create transaction: %d\n", rc
);
511 lstcon_rpc_trans_postwait(trans
, LST_TRANS_TIMEOUT
);
513 rc
= lstcon_rpc_trans_interpreter(trans
, result_up
, NULL
);
515 lstcon_rpc_trans_destroy(trans
);
516 /* release nodes anyway, because we can't rollback status */
517 lstcon_group_put(tmp
);
521 lstcon_group_move(tmp
, grp
);
522 lstcon_group_put(tmp
);
528 lstcon_group_add(char *name
)
533 rc
= (lstcon_group_find(name
, &grp
) == 0)? -EEXIST
: 0;
535 /* find a group with same name */
536 lstcon_group_put(grp
);
540 rc
= lstcon_group_alloc(name
, &grp
);
542 CERROR("Can't allocate descriptor for group %s\n", name
);
546 list_add_tail(&grp
->grp_link
, &console_session
.ses_grp_list
);
552 lstcon_nodes_add(char *name
, int count
, lnet_process_id_t
*ids_up
,
553 unsigned *featp
, struct list_head
*result_up
)
559 LASSERT (ids_up
!= NULL
);
561 rc
= lstcon_group_find(name
, &grp
);
563 CDEBUG(D_NET
, "Can't find group %s\n", name
);
567 if (grp
->grp_ref
> 2) {
568 /* referred by other threads or test */
569 CDEBUG(D_NET
, "Group %s is busy\n", name
);
570 lstcon_group_put(grp
);
575 rc
= lstcon_group_nodes_add(grp
, count
, ids_up
, featp
, result_up
);
577 lstcon_group_put(grp
);
583 lstcon_group_del(char *name
)
585 lstcon_rpc_trans_t
*trans
;
589 rc
= lstcon_group_find(name
, &grp
);
591 CDEBUG(D_NET
, "Can't find group: %s\n", name
);
595 if (grp
->grp_ref
> 2) {
596 /* referred by others threads or test */
597 CDEBUG(D_NET
, "Group %s is busy\n", name
);
598 lstcon_group_put(grp
);
602 rc
= lstcon_rpc_trans_ndlist(&grp
->grp_ndl_list
,
603 &grp
->grp_trans_list
, LST_TRANS_SESEND
,
604 grp
, lstcon_sesrpc_condition
, &trans
);
606 CERROR("Can't create transaction: %d\n", rc
);
607 lstcon_group_put(grp
);
611 lstcon_rpc_trans_postwait(trans
, LST_TRANS_TIMEOUT
);
613 lstcon_rpc_trans_destroy(trans
);
615 lstcon_group_put(grp
);
616 /* -ref for session, it's destroyed,
617 * status can't be rolled back, destroy group anway */
618 lstcon_group_put(grp
);
624 lstcon_group_clean(char *name
, int args
)
626 lstcon_group_t
*grp
= NULL
;
629 rc
= lstcon_group_find(name
, &grp
);
631 CDEBUG(D_NET
, "Can't find group %s\n", name
);
635 if (grp
->grp_ref
> 2) {
636 /* referred by test */
637 CDEBUG(D_NET
, "Group %s is busy\n", name
);
638 lstcon_group_put(grp
);
642 args
= (LST_NODE_ACTIVE
| LST_NODE_BUSY
|
643 LST_NODE_DOWN
| LST_NODE_UNKNOWN
) & ~args
;
645 lstcon_group_drain(grp
, args
);
647 lstcon_group_put(grp
);
648 /* release empty group */
649 if (list_empty(&grp
->grp_ndl_list
))
650 lstcon_group_put(grp
);
656 lstcon_nodes_remove(char *name
, int count
,
657 lnet_process_id_t
*ids_up
, struct list_head
*result_up
)
659 lstcon_group_t
*grp
= NULL
;
662 rc
= lstcon_group_find(name
, &grp
);
664 CDEBUG(D_NET
, "Can't find group: %s\n", name
);
668 if (grp
->grp_ref
> 2) {
669 /* referred by test */
670 CDEBUG(D_NET
, "Group %s is busy\n", name
);
671 lstcon_group_put(grp
);
675 rc
= lstcon_group_nodes_remove(grp
, count
, ids_up
, result_up
);
677 lstcon_group_put(grp
);
678 /* release empty group */
679 if (list_empty(&grp
->grp_ndl_list
))
680 lstcon_group_put(grp
);
686 lstcon_group_refresh(char *name
, struct list_head
*result_up
)
688 lstcon_rpc_trans_t
*trans
;
692 rc
= lstcon_group_find(name
, &grp
);
694 CDEBUG(D_NET
, "Can't find group: %s\n", name
);
698 if (grp
->grp_ref
> 2) {
699 /* referred by test */
700 CDEBUG(D_NET
, "Group %s is busy\n", name
);
701 lstcon_group_put(grp
);
705 /* re-invite all inactive nodes int the group */
706 rc
= lstcon_rpc_trans_ndlist(&grp
->grp_ndl_list
,
707 &grp
->grp_trans_list
, LST_TRANS_SESNEW
,
708 grp
, lstcon_sesrpc_condition
, &trans
);
710 /* local error, return */
711 CDEBUG(D_NET
, "Can't create transaction: %d\n", rc
);
712 lstcon_group_put(grp
);
716 lstcon_rpc_trans_postwait(trans
, LST_TRANS_TIMEOUT
);
718 rc
= lstcon_rpc_trans_interpreter(trans
, result_up
, NULL
);
720 lstcon_rpc_trans_destroy(trans
);
722 lstcon_group_put(grp
);
728 lstcon_group_list(int index
, int len
, char *name_up
)
732 LASSERT (index
>= 0);
733 LASSERT (name_up
!= NULL
);
735 list_for_each_entry(grp
, &console_session
.ses_grp_list
, grp_link
) {
737 return copy_to_user(name_up
, grp
->grp_name
, len
) ?
746 lstcon_nodes_getent(struct list_head
*head
, int *index_p
,
747 int *count_p
, lstcon_node_ent_t
*dents_up
)
749 lstcon_ndlink_t
*ndl
;
754 LASSERT (index_p
!= NULL
&& count_p
!= NULL
);
755 LASSERT (dents_up
!= NULL
);
756 LASSERT (*index_p
>= 0);
757 LASSERT (*count_p
> 0);
759 list_for_each_entry(ndl
, head
, ndl_link
) {
760 if (index
++ < *index_p
)
763 if (count
>= *count_p
)
767 if (copy_to_user(&dents_up
[count
].nde_id
,
768 &nd
->nd_id
, sizeof(nd
->nd_id
)) ||
769 copy_to_user(&dents_up
[count
].nde_state
,
770 &nd
->nd_state
, sizeof(nd
->nd_state
)))
776 if (index
<= *index_p
)
786 lstcon_group_info(char *name
, lstcon_ndlist_ent_t
*gents_p
,
787 int *index_p
, int *count_p
, lstcon_node_ent_t
*dents_up
)
789 lstcon_ndlist_ent_t
*gentp
;
791 lstcon_ndlink_t
*ndl
;
794 rc
= lstcon_group_find(name
, &grp
);
796 CDEBUG(D_NET
, "Can't find group %s\n", name
);
802 rc
= lstcon_nodes_getent(&grp
->grp_ndl_list
,
803 index_p
, count_p
, dents_up
);
804 lstcon_group_put(grp
);
809 /* non-verbose query */
810 LIBCFS_ALLOC(gentp
, sizeof(lstcon_ndlist_ent_t
));
812 CERROR("Can't allocate ndlist_ent\n");
813 lstcon_group_put(grp
);
818 memset(gentp
, 0, sizeof(lstcon_ndlist_ent_t
));
820 list_for_each_entry(ndl
, &grp
->grp_ndl_list
, ndl_link
)
821 LST_NODE_STATE_COUNTER(ndl
->ndl_node
, gentp
);
823 rc
= copy_to_user(gents_p
, gentp
,
824 sizeof(lstcon_ndlist_ent_t
)) ? -EFAULT
: 0;
826 LIBCFS_FREE(gentp
, sizeof(lstcon_ndlist_ent_t
));
828 lstcon_group_put(grp
);
834 lstcon_batch_find(const char *name
, lstcon_batch_t
**batpp
)
838 list_for_each_entry(bat
, &console_session
.ses_bat_list
, bat_link
) {
839 if (strncmp(bat
->bat_name
, name
, LST_NAME_SIZE
) == 0) {
849 lstcon_batch_add(char *name
)
855 rc
= (lstcon_batch_find(name
, &bat
) == 0)? -EEXIST
: 0;
857 CDEBUG(D_NET
, "Batch %s already exists\n", name
);
861 LIBCFS_ALLOC(bat
, sizeof(lstcon_batch_t
));
863 CERROR("Can't allocate descriptor for batch %s\n", name
);
867 LIBCFS_ALLOC(bat
->bat_cli_hash
,
868 sizeof(struct list_head
) * LST_NODE_HASHSIZE
);
869 if (bat
->bat_cli_hash
== NULL
) {
870 CERROR("Can't allocate hash for batch %s\n", name
);
871 LIBCFS_FREE(bat
, sizeof(lstcon_batch_t
));
876 LIBCFS_ALLOC(bat
->bat_srv_hash
,
877 sizeof(struct list_head
) * LST_NODE_HASHSIZE
);
878 if (bat
->bat_srv_hash
== NULL
) {
879 CERROR("Can't allocate hash for batch %s\n", name
);
880 LIBCFS_FREE(bat
->bat_cli_hash
, LST_NODE_HASHSIZE
);
881 LIBCFS_FREE(bat
, sizeof(lstcon_batch_t
));
886 strcpy(bat
->bat_name
, name
);
887 bat
->bat_hdr
.tsb_index
= 0;
888 bat
->bat_hdr
.tsb_id
.bat_id
= ++console_session
.ses_id_cookie
;
891 bat
->bat_state
= LST_BATCH_IDLE
;
893 INIT_LIST_HEAD(&bat
->bat_cli_list
);
894 INIT_LIST_HEAD(&bat
->bat_srv_list
);
895 INIT_LIST_HEAD(&bat
->bat_test_list
);
896 INIT_LIST_HEAD(&bat
->bat_trans_list
);
898 for (i
= 0; i
< LST_NODE_HASHSIZE
; i
++) {
899 INIT_LIST_HEAD(&bat
->bat_cli_hash
[i
]);
900 INIT_LIST_HEAD(&bat
->bat_srv_hash
[i
]);
903 list_add_tail(&bat
->bat_link
, &console_session
.ses_bat_list
);
909 lstcon_batch_list(int index
, int len
, char *name_up
)
913 LASSERT (name_up
!= NULL
);
914 LASSERT (index
>= 0);
916 list_for_each_entry(bat
, &console_session
.ses_bat_list
, bat_link
) {
918 return copy_to_user(name_up
,bat
->bat_name
, len
) ?
927 lstcon_batch_info(char *name
, lstcon_test_batch_ent_t
*ent_up
, int server
,
928 int testidx
, int *index_p
, int *ndent_p
,
929 lstcon_node_ent_t
*dents_up
)
931 lstcon_test_batch_ent_t
*entp
;
932 struct list_head
*clilst
;
933 struct list_head
*srvlst
;
934 lstcon_test_t
*test
= NULL
;
936 lstcon_ndlink_t
*ndl
;
939 rc
= lstcon_batch_find(name
, &bat
);
941 CDEBUG(D_NET
, "Can't find batch %s\n", name
);
946 /* query test, test index start from 1 */
947 list_for_each_entry(test
, &bat
->bat_test_list
, tes_link
) {
953 CDEBUG(D_NET
, "Can't find specified test in batch\n");
958 clilst
= (test
== NULL
) ? &bat
->bat_cli_list
:
959 &test
->tes_src_grp
->grp_ndl_list
;
960 srvlst
= (test
== NULL
) ? &bat
->bat_srv_list
:
961 &test
->tes_dst_grp
->grp_ndl_list
;
963 if (dents_up
!= NULL
) {
964 rc
= lstcon_nodes_getent((server
? srvlst
: clilst
),
965 index_p
, ndent_p
, dents_up
);
969 /* non-verbose query */
970 LIBCFS_ALLOC(entp
, sizeof(lstcon_test_batch_ent_t
));
974 memset(entp
, 0, sizeof(lstcon_test_batch_ent_t
));
977 entp
->u
.tbe_batch
.bae_ntest
= bat
->bat_ntest
;
978 entp
->u
.tbe_batch
.bae_state
= bat
->bat_state
;
982 entp
->u
.tbe_test
.tse_type
= test
->tes_type
;
983 entp
->u
.tbe_test
.tse_loop
= test
->tes_loop
;
984 entp
->u
.tbe_test
.tse_concur
= test
->tes_concur
;
987 list_for_each_entry(ndl
, clilst
, ndl_link
)
988 LST_NODE_STATE_COUNTER(ndl
->ndl_node
, &entp
->tbe_cli_nle
);
990 list_for_each_entry(ndl
, srvlst
, ndl_link
)
991 LST_NODE_STATE_COUNTER(ndl
->ndl_node
, &entp
->tbe_srv_nle
);
993 rc
= copy_to_user(ent_up
, entp
,
994 sizeof(lstcon_test_batch_ent_t
)) ? -EFAULT
: 0;
996 LIBCFS_FREE(entp
, sizeof(lstcon_test_batch_ent_t
));
1002 lstcon_batrpc_condition(int transop
, lstcon_node_t
*nd
, void *arg
)
1005 case LST_TRANS_TSBRUN
:
1006 if (nd
->nd_state
!= LST_NODE_ACTIVE
)
1010 case LST_TRANS_TSBSTOP
:
1011 if (nd
->nd_state
!= LST_NODE_ACTIVE
)
1015 case LST_TRANS_TSBCLIQRY
:
1016 case LST_TRANS_TSBSRVQRY
:
1024 lstcon_batch_op(lstcon_batch_t
*bat
, int transop
,
1025 struct list_head
*result_up
)
1027 lstcon_rpc_trans_t
*trans
;
1030 rc
= lstcon_rpc_trans_ndlist(&bat
->bat_cli_list
,
1031 &bat
->bat_trans_list
, transop
,
1032 bat
, lstcon_batrpc_condition
, &trans
);
1034 CERROR("Can't create transaction: %d\n", rc
);
1038 lstcon_rpc_trans_postwait(trans
, LST_TRANS_TIMEOUT
);
1040 rc
= lstcon_rpc_trans_interpreter(trans
, result_up
, NULL
);
1042 lstcon_rpc_trans_destroy(trans
);
1048 lstcon_batch_run(char *name
, int timeout
, struct list_head
*result_up
)
1050 lstcon_batch_t
*bat
;
1053 if (lstcon_batch_find(name
, &bat
) != 0) {
1054 CDEBUG(D_NET
, "Can't find batch %s\n", name
);
1058 bat
->bat_arg
= timeout
;
1060 rc
= lstcon_batch_op(bat
, LST_TRANS_TSBRUN
, result_up
);
1062 /* mark batch as running if it's started in any node */
1063 if (lstcon_tsbop_stat_success(lstcon_trans_stat(), 0) != 0)
1064 bat
->bat_state
= LST_BATCH_RUNNING
;
1070 lstcon_batch_stop(char *name
, int force
, struct list_head
*result_up
)
1072 lstcon_batch_t
*bat
;
1075 if (lstcon_batch_find(name
, &bat
) != 0) {
1076 CDEBUG(D_NET
, "Can't find batch %s\n", name
);
1080 bat
->bat_arg
= force
;
1082 rc
= lstcon_batch_op(bat
, LST_TRANS_TSBSTOP
, result_up
);
1084 /* mark batch as stopped if all RPCs finished */
1085 if (lstcon_tsbop_stat_failure(lstcon_trans_stat(), 0) == 0)
1086 bat
->bat_state
= LST_BATCH_IDLE
;
1092 lstcon_batch_destroy(lstcon_batch_t
*bat
)
1094 lstcon_ndlink_t
*ndl
;
1095 lstcon_test_t
*test
;
1098 list_del(&bat
->bat_link
);
1100 while (!list_empty(&bat
->bat_test_list
)) {
1101 test
= list_entry(bat
->bat_test_list
.next
,
1102 lstcon_test_t
, tes_link
);
1103 LASSERT (list_empty(&test
->tes_trans_list
));
1105 list_del(&test
->tes_link
);
1107 lstcon_group_put(test
->tes_src_grp
);
1108 lstcon_group_put(test
->tes_dst_grp
);
1110 LIBCFS_FREE(test
, offsetof(lstcon_test_t
,
1111 tes_param
[test
->tes_paramlen
]));
1114 LASSERT (list_empty(&bat
->bat_trans_list
));
1116 while (!list_empty(&bat
->bat_cli_list
)) {
1117 ndl
= list_entry(bat
->bat_cli_list
.next
,
1118 lstcon_ndlink_t
, ndl_link
);
1119 list_del_init(&ndl
->ndl_link
);
1121 lstcon_ndlink_release(ndl
);
1124 while (!list_empty(&bat
->bat_srv_list
)) {
1125 ndl
= list_entry(bat
->bat_srv_list
.next
,
1126 lstcon_ndlink_t
, ndl_link
);
1127 list_del_init(&ndl
->ndl_link
);
1129 lstcon_ndlink_release(ndl
);
1132 for (i
= 0; i
< LST_NODE_HASHSIZE
; i
++) {
1133 LASSERT (list_empty(&bat
->bat_cli_hash
[i
]));
1134 LASSERT (list_empty(&bat
->bat_srv_hash
[i
]));
1137 LIBCFS_FREE(bat
->bat_cli_hash
,
1138 sizeof(struct list_head
) * LST_NODE_HASHSIZE
);
1139 LIBCFS_FREE(bat
->bat_srv_hash
,
1140 sizeof(struct list_head
) * LST_NODE_HASHSIZE
);
1141 LIBCFS_FREE(bat
, sizeof(lstcon_batch_t
));
1145 lstcon_testrpc_condition(int transop
, lstcon_node_t
*nd
, void *arg
)
1147 lstcon_test_t
*test
;
1148 lstcon_batch_t
*batch
;
1149 lstcon_ndlink_t
*ndl
;
1150 struct list_head
*hash
;
1151 struct list_head
*head
;
1153 test
= (lstcon_test_t
*)arg
;
1154 LASSERT (test
!= NULL
);
1156 batch
= test
->tes_batch
;
1157 LASSERT (batch
!= NULL
);
1159 if (test
->tes_oneside
&&
1160 transop
== LST_TRANS_TSBSRVADD
)
1163 if (nd
->nd_state
!= LST_NODE_ACTIVE
)
1166 if (transop
== LST_TRANS_TSBCLIADD
) {
1167 hash
= batch
->bat_cli_hash
;
1168 head
= &batch
->bat_cli_list
;
1171 LASSERT (transop
== LST_TRANS_TSBSRVADD
);
1173 hash
= batch
->bat_srv_hash
;
1174 head
= &batch
->bat_srv_list
;
1177 LASSERT (nd
->nd_id
.nid
!= LNET_NID_ANY
);
1179 if (lstcon_ndlink_find(hash
, nd
->nd_id
, &ndl
, 1) != 0)
1182 if (list_empty(&ndl
->ndl_link
))
1183 list_add_tail(&ndl
->ndl_link
, head
);
1189 lstcon_test_nodes_add(lstcon_test_t
*test
, struct list_head
*result_up
)
1191 lstcon_rpc_trans_t
*trans
;
1192 lstcon_group_t
*grp
;
1196 LASSERT (test
->tes_src_grp
!= NULL
);
1197 LASSERT (test
->tes_dst_grp
!= NULL
);
1199 transop
= LST_TRANS_TSBSRVADD
;
1200 grp
= test
->tes_dst_grp
;
1202 rc
= lstcon_rpc_trans_ndlist(&grp
->grp_ndl_list
,
1203 &test
->tes_trans_list
, transop
,
1204 test
, lstcon_testrpc_condition
, &trans
);
1206 CERROR("Can't create transaction: %d\n", rc
);
1210 lstcon_rpc_trans_postwait(trans
, LST_TRANS_TIMEOUT
);
1212 if (lstcon_trans_stat()->trs_rpc_errno
!= 0 ||
1213 lstcon_trans_stat()->trs_fwk_errno
!= 0) {
1214 lstcon_rpc_trans_interpreter(trans
, result_up
, NULL
);
1216 lstcon_rpc_trans_destroy(trans
);
1217 /* return if any error */
1218 CDEBUG(D_NET
, "Failed to add test %s, "
1219 "RPC error %d, framework error %d\n",
1220 transop
== LST_TRANS_TSBCLIADD
? "client" : "server",
1221 lstcon_trans_stat()->trs_rpc_errno
,
1222 lstcon_trans_stat()->trs_fwk_errno
);
1227 lstcon_rpc_trans_destroy(trans
);
1229 if (transop
== LST_TRANS_TSBCLIADD
)
1232 transop
= LST_TRANS_TSBCLIADD
;
1233 grp
= test
->tes_src_grp
;
1234 test
->tes_cliidx
= 0;
1236 /* requests to test clients */
1241 lstcon_test_add(char *name
, int type
, int loop
, int concur
,
1242 int dist
, int span
, char *src_name
, char * dst_name
,
1243 void *param
, int paramlen
, int *retp
,
1244 struct list_head
*result_up
)
1246 lstcon_group_t
*src_grp
= NULL
;
1247 lstcon_group_t
*dst_grp
= NULL
;
1248 lstcon_test_t
*test
= NULL
;
1249 lstcon_batch_t
*batch
;
1252 rc
= lstcon_batch_find(name
, &batch
);
1254 CDEBUG(D_NET
, "Can't find batch %s\n", name
);
1258 if (batch
->bat_state
!= LST_BATCH_IDLE
) {
1259 CDEBUG(D_NET
, "Can't change running batch %s\n", name
);
1263 rc
= lstcon_group_find(src_name
, &src_grp
);
1265 CDEBUG(D_NET
, "Can't find group %s\n", src_name
);
1269 rc
= lstcon_group_find(dst_name
, &dst_grp
);
1271 CDEBUG(D_NET
, "Can't find group %s\n", dst_name
);
1275 if (dst_grp
->grp_userland
)
1278 LIBCFS_ALLOC(test
, offsetof(lstcon_test_t
, tes_param
[paramlen
]));
1280 CERROR("Can't allocate test descriptor\n");
1286 memset(test
, 0, offsetof(lstcon_test_t
, tes_param
[paramlen
]));
1287 test
->tes_hdr
.tsb_id
= batch
->bat_hdr
.tsb_id
;
1288 test
->tes_batch
= batch
;
1289 test
->tes_type
= type
;
1290 test
->tes_oneside
= 0; /* TODO */
1291 test
->tes_loop
= loop
;
1292 test
->tes_concur
= concur
;
1293 test
->tes_stop_onerr
= 1; /* TODO */
1294 test
->tes_span
= span
;
1295 test
->tes_dist
= dist
;
1296 test
->tes_cliidx
= 0; /* just used for creating RPC */
1297 test
->tes_src_grp
= src_grp
;
1298 test
->tes_dst_grp
= dst_grp
;
1299 INIT_LIST_HEAD(&test
->tes_trans_list
);
1301 if (param
!= NULL
) {
1302 test
->tes_paramlen
= paramlen
;
1303 memcpy(&test
->tes_param
[0], param
, paramlen
);
1306 rc
= lstcon_test_nodes_add(test
, result_up
);
1311 if (lstcon_trans_stat()->trs_rpc_errno
!= 0 ||
1312 lstcon_trans_stat()->trs_fwk_errno
!= 0)
1313 CDEBUG(D_NET
, "Failed to add test %d to batch %s\n", type
, name
);
1315 /* add to test list anyway, so user can check what's going on */
1316 list_add_tail(&test
->tes_link
, &batch
->bat_test_list
);
1318 batch
->bat_ntest
++;
1319 test
->tes_hdr
.tsb_index
= batch
->bat_ntest
;
1321 /* hold groups so nobody can change them */
1325 LIBCFS_FREE(test
, offsetof(lstcon_test_t
, tes_param
[paramlen
]));
1327 if (dst_grp
!= NULL
)
1328 lstcon_group_put(dst_grp
);
1330 if (src_grp
!= NULL
)
1331 lstcon_group_put(src_grp
);
1337 lstcon_test_find(lstcon_batch_t
*batch
, int idx
, lstcon_test_t
**testpp
)
1339 lstcon_test_t
*test
;
1341 list_for_each_entry(test
, &batch
->bat_test_list
, tes_link
) {
1342 if (idx
== test
->tes_hdr
.tsb_index
) {
1352 lstcon_tsbrpc_readent(int transop
, srpc_msg_t
*msg
,
1353 lstcon_rpc_ent_t
*ent_up
)
1355 srpc_batch_reply_t
*rep
= &msg
->msg_body
.bat_reply
;
1357 LASSERT (transop
== LST_TRANS_TSBCLIQRY
||
1358 transop
== LST_TRANS_TSBSRVQRY
);
1360 /* positive errno, framework error code */
1361 if (copy_to_user(&ent_up
->rpe_priv
[0],
1362 &rep
->bar_active
, sizeof(rep
->bar_active
)))
1369 lstcon_test_batch_query(char *name
, int testidx
, int client
,
1370 int timeout
, struct list_head
*result_up
)
1372 lstcon_rpc_trans_t
*trans
;
1373 struct list_head
*translist
;
1374 struct list_head
*ndlist
;
1375 lstcon_tsb_hdr_t
*hdr
;
1376 lstcon_batch_t
*batch
;
1377 lstcon_test_t
*test
= NULL
;
1381 rc
= lstcon_batch_find(name
, &batch
);
1383 CDEBUG(D_NET
, "Can't find batch: %s\n", name
);
1388 translist
= &batch
->bat_trans_list
;
1389 ndlist
= &batch
->bat_cli_list
;
1390 hdr
= &batch
->bat_hdr
;
1393 /* query specified test only */
1394 rc
= lstcon_test_find(batch
, testidx
, &test
);
1396 CDEBUG(D_NET
, "Can't find test: %d\n", testidx
);
1400 translist
= &test
->tes_trans_list
;
1401 ndlist
= &test
->tes_src_grp
->grp_ndl_list
;
1402 hdr
= &test
->tes_hdr
;
1405 transop
= client
? LST_TRANS_TSBCLIQRY
: LST_TRANS_TSBSRVQRY
;
1407 rc
= lstcon_rpc_trans_ndlist(ndlist
, translist
, transop
, hdr
,
1408 lstcon_batrpc_condition
, &trans
);
1410 CERROR("Can't create transaction: %d\n", rc
);
1414 lstcon_rpc_trans_postwait(trans
, timeout
);
1416 if (testidx
== 0 && /* query a batch, not a test */
1417 lstcon_rpc_stat_failure(lstcon_trans_stat(), 0) == 0 &&
1418 lstcon_tsbqry_stat_run(lstcon_trans_stat(), 0) == 0) {
1419 /* all RPCs finished, and no active test */
1420 batch
->bat_state
= LST_BATCH_IDLE
;
1423 rc
= lstcon_rpc_trans_interpreter(trans
, result_up
,
1424 lstcon_tsbrpc_readent
);
1425 lstcon_rpc_trans_destroy(trans
);
1431 lstcon_statrpc_readent(int transop
, srpc_msg_t
*msg
,
1432 lstcon_rpc_ent_t
*ent_up
)
1434 srpc_stat_reply_t
*rep
= &msg
->msg_body
.stat_reply
;
1435 sfw_counters_t
*sfwk_stat
;
1436 srpc_counters_t
*srpc_stat
;
1437 lnet_counters_t
*lnet_stat
;
1439 if (rep
->str_status
!= 0)
1442 sfwk_stat
= (sfw_counters_t
*)&ent_up
->rpe_payload
[0];
1443 srpc_stat
= (srpc_counters_t
*)((char *)sfwk_stat
+ sizeof(*sfwk_stat
));
1444 lnet_stat
= (lnet_counters_t
*)((char *)srpc_stat
+ sizeof(*srpc_stat
));
1446 if (copy_to_user(sfwk_stat
, &rep
->str_fw
, sizeof(*sfwk_stat
)) ||
1447 copy_to_user(srpc_stat
, &rep
->str_rpc
, sizeof(*srpc_stat
)) ||
1448 copy_to_user(lnet_stat
, &rep
->str_lnet
, sizeof(*lnet_stat
)))
1455 lstcon_ndlist_stat(struct list_head
*ndlist
,
1456 int timeout
, struct list_head
*result_up
)
1458 struct list_head head
;
1459 lstcon_rpc_trans_t
*trans
;
1462 INIT_LIST_HEAD(&head
);
1464 rc
= lstcon_rpc_trans_ndlist(ndlist
, &head
,
1465 LST_TRANS_STATQRY
, NULL
, NULL
, &trans
);
1467 CERROR("Can't create transaction: %d\n", rc
);
1471 lstcon_rpc_trans_postwait(trans
, LST_VALIDATE_TIMEOUT(timeout
));
1473 rc
= lstcon_rpc_trans_interpreter(trans
, result_up
,
1474 lstcon_statrpc_readent
);
1475 lstcon_rpc_trans_destroy(trans
);
1481 lstcon_group_stat(char *grp_name
, int timeout
, struct list_head
*result_up
)
1483 lstcon_group_t
*grp
;
1486 rc
= lstcon_group_find(grp_name
, &grp
);
1488 CDEBUG(D_NET
, "Can't find group %s\n", grp_name
);
1492 rc
= lstcon_ndlist_stat(&grp
->grp_ndl_list
, timeout
, result_up
);
1494 lstcon_group_put(grp
);
1500 lstcon_nodes_stat(int count
, lnet_process_id_t
*ids_up
,
1501 int timeout
, struct list_head
*result_up
)
1503 lstcon_ndlink_t
*ndl
;
1504 lstcon_group_t
*tmp
;
1505 lnet_process_id_t id
;
1509 rc
= lstcon_group_alloc(NULL
, &tmp
);
1511 CERROR("Out of memory\n");
1515 for (i
= 0 ; i
< count
; i
++) {
1516 if (copy_from_user(&id
, &ids_up
[i
], sizeof(id
))) {
1521 /* add to tmp group */
1522 rc
= lstcon_group_ndlink_find(tmp
, id
, &ndl
, 2);
1524 CDEBUG((rc
== -ENOMEM
) ? D_ERROR
: D_NET
,
1525 "Failed to find or create %s: %d\n",
1526 libcfs_id2str(id
), rc
);
1532 lstcon_group_put(tmp
);
1536 rc
= lstcon_ndlist_stat(&tmp
->grp_ndl_list
, timeout
, result_up
);
1538 lstcon_group_put(tmp
);
1544 lstcon_debug_ndlist(struct list_head
*ndlist
,
1545 struct list_head
*translist
,
1546 int timeout
, struct list_head
*result_up
)
1548 lstcon_rpc_trans_t
*trans
;
1551 rc
= lstcon_rpc_trans_ndlist(ndlist
, translist
, LST_TRANS_SESQRY
,
1552 NULL
, lstcon_sesrpc_condition
, &trans
);
1554 CERROR("Can't create transaction: %d\n", rc
);
1558 lstcon_rpc_trans_postwait(trans
, LST_VALIDATE_TIMEOUT(timeout
));
1560 rc
= lstcon_rpc_trans_interpreter(trans
, result_up
,
1561 lstcon_sesrpc_readent
);
1562 lstcon_rpc_trans_destroy(trans
);
1568 lstcon_session_debug(int timeout
, struct list_head
*result_up
)
1570 return lstcon_debug_ndlist(&console_session
.ses_ndl_list
,
1571 NULL
, timeout
, result_up
);
1575 lstcon_batch_debug(int timeout
, char *name
,
1576 int client
, struct list_head
*result_up
)
1578 lstcon_batch_t
*bat
;
1581 rc
= lstcon_batch_find(name
, &bat
);
1585 rc
= lstcon_debug_ndlist(client
? &bat
->bat_cli_list
:
1587 NULL
, timeout
, result_up
);
1593 lstcon_group_debug(int timeout
, char *name
,
1594 struct list_head
*result_up
)
1596 lstcon_group_t
*grp
;
1599 rc
= lstcon_group_find(name
, &grp
);
1603 rc
= lstcon_debug_ndlist(&grp
->grp_ndl_list
, NULL
,
1604 timeout
, result_up
);
1605 lstcon_group_put(grp
);
1611 lstcon_nodes_debug(int timeout
,
1612 int count
, lnet_process_id_t
*ids_up
,
1613 struct list_head
*result_up
)
1615 lnet_process_id_t id
;
1616 lstcon_ndlink_t
*ndl
;
1617 lstcon_group_t
*grp
;
1621 rc
= lstcon_group_alloc(NULL
, &grp
);
1623 CDEBUG(D_NET
, "Out of memory\n");
1627 for (i
= 0; i
< count
; i
++) {
1628 if (copy_from_user(&id
, &ids_up
[i
], sizeof(id
))) {
1633 /* node is added to tmp group */
1634 rc
= lstcon_group_ndlink_find(grp
, id
, &ndl
, 1);
1636 CERROR("Can't create node link\n");
1642 lstcon_group_put(grp
);
1646 rc
= lstcon_debug_ndlist(&grp
->grp_ndl_list
, NULL
,
1647 timeout
, result_up
);
1649 lstcon_group_put(grp
);
1655 lstcon_session_match(lst_sid_t sid
)
1657 return (console_session
.ses_id
.ses_nid
== sid
.ses_nid
&&
1658 console_session
.ses_id
.ses_stamp
== sid
.ses_stamp
) ? 1: 0;
1662 lstcon_new_session_id(lst_sid_t
*sid
)
1664 lnet_process_id_t id
;
1666 LASSERT (console_session
.ses_state
== LST_SESSION_NONE
);
1669 sid
->ses_nid
= id
.nid
;
1670 sid
->ses_stamp
= cfs_time_current();
1673 extern srpc_service_t lstcon_acceptor_service
;
1676 lstcon_session_new(char *name
, int key
, unsigned feats
,
1677 int timeout
, int force
, lst_sid_t
*sid_up
)
1682 if (console_session
.ses_state
!= LST_SESSION_NONE
) {
1683 /* session exists */
1685 CNETERR("Session %s already exists\n",
1686 console_session
.ses_name
);
1690 rc
= lstcon_session_end();
1692 /* lstcon_session_end() only return local error */
1697 if ((feats
& ~LST_FEATS_MASK
) != 0) {
1698 CNETERR("Unknown session features %x\n",
1699 (feats
& ~LST_FEATS_MASK
));
1703 for (i
= 0; i
< LST_GLOBAL_HASHSIZE
; i
++)
1704 LASSERT(list_empty(&console_session
.ses_ndl_hash
[i
]));
1706 lstcon_new_session_id(&console_session
.ses_id
);
1708 console_session
.ses_key
= key
;
1709 console_session
.ses_state
= LST_SESSION_ACTIVE
;
1710 console_session
.ses_force
= !!force
;
1711 console_session
.ses_features
= feats
;
1712 console_session
.ses_feats_updated
= 0;
1713 console_session
.ses_timeout
= (timeout
<= 0) ?
1714 LST_CONSOLE_TIMEOUT
: timeout
;
1715 strcpy(console_session
.ses_name
, name
);
1717 rc
= lstcon_batch_add(LST_DEFAULT_BATCH
);
1721 rc
= lstcon_rpc_pinger_start();
1723 lstcon_batch_t
*bat
= NULL
;
1725 lstcon_batch_find(LST_DEFAULT_BATCH
, &bat
);
1726 lstcon_batch_destroy(bat
);
1731 if (copy_to_user(sid_up
, &console_session
.ses_id
,
1732 sizeof(lst_sid_t
)) == 0)
1735 lstcon_session_end();
1741 lstcon_session_info(lst_sid_t
*sid_up
, int *key_up
, unsigned *featp
,
1742 lstcon_ndlist_ent_t
*ndinfo_up
, char *name_up
, int len
)
1744 lstcon_ndlist_ent_t
*entp
;
1745 lstcon_ndlink_t
*ndl
;
1748 if (console_session
.ses_state
!= LST_SESSION_ACTIVE
)
1751 LIBCFS_ALLOC(entp
, sizeof(*entp
));
1755 memset(entp
, 0, sizeof(*entp
));
1757 list_for_each_entry(ndl
, &console_session
.ses_ndl_list
, ndl_link
)
1758 LST_NODE_STATE_COUNTER(ndl
->ndl_node
, entp
);
1760 if (copy_to_user(sid_up
, &console_session
.ses_id
,
1761 sizeof(lst_sid_t
)) ||
1762 copy_to_user(key_up
, &console_session
.ses_key
,
1764 copy_to_user(featp
, &console_session
.ses_features
,
1766 copy_to_user(ndinfo_up
, entp
, sizeof(*entp
)) ||
1767 copy_to_user(name_up
, console_session
.ses_name
, len
))
1770 LIBCFS_FREE(entp
, sizeof(*entp
));
1776 lstcon_session_end(void)
1778 lstcon_rpc_trans_t
*trans
;
1779 lstcon_group_t
*grp
;
1780 lstcon_batch_t
*bat
;
1783 LASSERT (console_session
.ses_state
== LST_SESSION_ACTIVE
);
1785 rc
= lstcon_rpc_trans_ndlist(&console_session
.ses_ndl_list
,
1786 NULL
, LST_TRANS_SESEND
, NULL
,
1787 lstcon_sesrpc_condition
, &trans
);
1789 CERROR("Can't create transaction: %d\n", rc
);
1793 console_session
.ses_shutdown
= 1;
1795 lstcon_rpc_pinger_stop();
1797 lstcon_rpc_trans_postwait(trans
, LST_TRANS_TIMEOUT
);
1799 lstcon_rpc_trans_destroy(trans
);
1800 /* User can do nothing even rpc failed, so go on */
1802 /* waiting for orphan rpcs to die */
1803 lstcon_rpc_cleanup_wait();
1805 console_session
.ses_id
= LST_INVALID_SID
;
1806 console_session
.ses_state
= LST_SESSION_NONE
;
1807 console_session
.ses_key
= 0;
1808 console_session
.ses_force
= 0;
1809 console_session
.ses_feats_updated
= 0;
1811 /* destroy all batches */
1812 while (!list_empty(&console_session
.ses_bat_list
)) {
1813 bat
= list_entry(console_session
.ses_bat_list
.next
,
1814 lstcon_batch_t
, bat_link
);
1816 lstcon_batch_destroy(bat
);
1819 /* destroy all groups */
1820 while (!list_empty(&console_session
.ses_grp_list
)) {
1821 grp
= list_entry(console_session
.ses_grp_list
.next
,
1822 lstcon_group_t
, grp_link
);
1823 LASSERT (grp
->grp_ref
== 1);
1825 lstcon_group_put(grp
);
1828 /* all nodes should be released */
1829 LASSERT (list_empty(&console_session
.ses_ndl_list
));
1831 console_session
.ses_shutdown
= 0;
1832 console_session
.ses_expired
= 0;
1838 lstcon_session_feats_check(unsigned feats
)
1842 if ((feats
& ~LST_FEATS_MASK
) != 0) {
1843 CERROR("Can't support these features: %x\n",
1844 (feats
& ~LST_FEATS_MASK
));
1848 spin_lock(&console_session
.ses_rpc_lock
);
1850 if (!console_session
.ses_feats_updated
) {
1851 console_session
.ses_feats_updated
= 1;
1852 console_session
.ses_features
= feats
;
1855 if (console_session
.ses_features
!= feats
)
1858 spin_unlock(&console_session
.ses_rpc_lock
);
1861 CERROR("remote features %x do not match with "
1862 "session features %x of console\n",
1863 feats
, console_session
.ses_features
);
1870 lstcon_acceptor_handle (srpc_server_rpc_t
*rpc
)
1872 srpc_msg_t
*rep
= &rpc
->srpc_replymsg
;
1873 srpc_msg_t
*req
= &rpc
->srpc_reqstbuf
->buf_msg
;
1874 srpc_join_reqst_t
*jreq
= &req
->msg_body
.join_reqst
;
1875 srpc_join_reply_t
*jrep
= &rep
->msg_body
.join_reply
;
1876 lstcon_group_t
*grp
= NULL
;
1877 lstcon_ndlink_t
*ndl
;
1880 sfw_unpack_message(req
);
1882 mutex_lock(&console_session
.ses_mutex
);
1884 jrep
->join_sid
= console_session
.ses_id
;
1886 if (console_session
.ses_id
.ses_nid
== LNET_NID_ANY
) {
1887 jrep
->join_status
= ESRCH
;
1891 if (lstcon_session_feats_check(req
->msg_ses_feats
) != 0) {
1892 jrep
->join_status
= EPROTO
;
1896 if (jreq
->join_sid
.ses_nid
!= LNET_NID_ANY
&&
1897 !lstcon_session_match(jreq
->join_sid
)) {
1898 jrep
->join_status
= EBUSY
;
1902 if (lstcon_group_find(jreq
->join_group
, &grp
) != 0) {
1903 rc
= lstcon_group_alloc(jreq
->join_group
, &grp
);
1905 CERROR("Out of memory\n");
1909 list_add_tail(&grp
->grp_link
,
1910 &console_session
.ses_grp_list
);
1911 lstcon_group_addref(grp
);
1914 if (grp
->grp_ref
> 2) {
1915 /* Group in using */
1916 jrep
->join_status
= EBUSY
;
1920 rc
= lstcon_group_ndlink_find(grp
, rpc
->srpc_peer
, &ndl
, 0);
1922 jrep
->join_status
= EEXIST
;
1926 rc
= lstcon_group_ndlink_find(grp
, rpc
->srpc_peer
, &ndl
, 1);
1928 CERROR("Out of memory\n");
1932 ndl
->ndl_node
->nd_state
= LST_NODE_ACTIVE
;
1933 ndl
->ndl_node
->nd_timeout
= console_session
.ses_timeout
;
1935 if (grp
->grp_userland
== 0)
1936 grp
->grp_userland
= 1;
1938 strcpy(jrep
->join_session
, console_session
.ses_name
);
1939 jrep
->join_timeout
= console_session
.ses_timeout
;
1940 jrep
->join_status
= 0;
1943 rep
->msg_ses_feats
= console_session
.ses_features
;
1945 lstcon_group_put(grp
);
1947 mutex_unlock(&console_session
.ses_mutex
);
1952 srpc_service_t lstcon_acceptor_service
;
1953 void lstcon_init_acceptor_service(void)
1955 /* initialize selftest console acceptor service table */
1956 lstcon_acceptor_service
.sv_name
= "join session";
1957 lstcon_acceptor_service
.sv_handler
= lstcon_acceptor_handle
;
1958 lstcon_acceptor_service
.sv_id
= SRPC_SERVICE_JOIN
;
1959 lstcon_acceptor_service
.sv_wi_total
= SFW_FRWK_WI_MAX
;
1962 extern int lstcon_ioctl_entry(unsigned int cmd
, struct libcfs_ioctl_data
*data
);
1964 DECLARE_IOCTL_HANDLER(lstcon_ioctl_handler
, lstcon_ioctl_entry
);
1966 /* initialize console */
1968 lstcon_console_init(void)
1973 memset(&console_session
, 0, sizeof(lstcon_session_t
));
1975 console_session
.ses_id
= LST_INVALID_SID
;
1976 console_session
.ses_state
= LST_SESSION_NONE
;
1977 console_session
.ses_timeout
= 0;
1978 console_session
.ses_force
= 0;
1979 console_session
.ses_expired
= 0;
1980 console_session
.ses_feats_updated
= 0;
1981 console_session
.ses_features
= LST_FEATS_MASK
;
1982 console_session
.ses_laststamp
= cfs_time_current_sec();
1984 mutex_init(&console_session
.ses_mutex
);
1986 INIT_LIST_HEAD(&console_session
.ses_ndl_list
);
1987 INIT_LIST_HEAD(&console_session
.ses_grp_list
);
1988 INIT_LIST_HEAD(&console_session
.ses_bat_list
);
1989 INIT_LIST_HEAD(&console_session
.ses_trans_list
);
1991 LIBCFS_ALLOC(console_session
.ses_ndl_hash
,
1992 sizeof(struct list_head
) * LST_GLOBAL_HASHSIZE
);
1993 if (console_session
.ses_ndl_hash
== NULL
)
1996 for (i
= 0; i
< LST_GLOBAL_HASHSIZE
; i
++)
1997 INIT_LIST_HEAD(&console_session
.ses_ndl_hash
[i
]);
2000 /* initialize acceptor service table */
2001 lstcon_init_acceptor_service();
2003 rc
= srpc_add_service(&lstcon_acceptor_service
);
2004 LASSERT (rc
!= -EBUSY
);
2006 LIBCFS_FREE(console_session
.ses_ndl_hash
,
2007 sizeof(struct list_head
) * LST_GLOBAL_HASHSIZE
);
2011 rc
= srpc_service_add_buffers(&lstcon_acceptor_service
,
2012 lstcon_acceptor_service
.sv_wi_total
);
2018 rc
= libcfs_register_ioctl(&lstcon_ioctl_handler
);
2021 lstcon_rpc_module_init();
2026 srpc_shutdown_service(&lstcon_acceptor_service
);
2027 srpc_remove_service(&lstcon_acceptor_service
);
2029 LIBCFS_FREE(console_session
.ses_ndl_hash
,
2030 sizeof(struct list_head
) * LST_GLOBAL_HASHSIZE
);
2032 srpc_wait_service_shutdown(&lstcon_acceptor_service
);
2038 lstcon_console_fini(void)
2042 libcfs_deregister_ioctl(&lstcon_ioctl_handler
);
2044 mutex_lock(&console_session
.ses_mutex
);
2046 srpc_shutdown_service(&lstcon_acceptor_service
);
2047 srpc_remove_service(&lstcon_acceptor_service
);
2049 if (console_session
.ses_state
!= LST_SESSION_NONE
)
2050 lstcon_session_end();
2052 lstcon_rpc_module_fini();
2054 mutex_unlock(&console_session
.ses_mutex
);
2056 LASSERT (list_empty(&console_session
.ses_ndl_list
));
2057 LASSERT (list_empty(&console_session
.ses_grp_list
));
2058 LASSERT (list_empty(&console_session
.ses_bat_list
));
2059 LASSERT (list_empty(&console_session
.ses_trans_list
));
2061 for (i
= 0; i
< LST_NODE_HASHSIZE
; i
++) {
2062 LASSERT (list_empty(&console_session
.ses_ndl_hash
[i
]));
2065 LIBCFS_FREE(console_session
.ses_ndl_hash
,
2066 sizeof(struct list_head
) * LST_GLOBAL_HASHSIZE
);
2068 srpc_wait_service_shutdown(&lstcon_acceptor_service
);