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 * IOC handle in kernel
35 * Author: Liang Zhen <liangzhen@clusterfs.com>
38 #include <linux/generic-radix-tree.h>
39 #include <libcfs/linux/linux-net.h>
40 #include <libcfs/libcfs.h>
41 #include <lnet/lib-lnet.h>
45 lst_debug_ioctl(struct lstio_debug_args *args)
51 if (args->lstio_dbg_key != console_session.ses_key)
54 if (args->lstio_dbg_resultp == NULL)
57 if (args->lstio_dbg_namep != NULL && /* name of batch/group */
58 (args->lstio_dbg_nmlen <= 0 ||
59 args->lstio_dbg_nmlen > LST_NAME_SIZE))
62 if (args->lstio_dbg_namep != NULL) {
63 LIBCFS_ALLOC(name, args->lstio_dbg_nmlen + 1);
67 if (copy_from_user(name, args->lstio_dbg_namep,
68 args->lstio_dbg_nmlen)) {
69 LIBCFS_FREE(name, args->lstio_dbg_nmlen + 1);
74 name[args->lstio_dbg_nmlen] = 0;
79 switch (args->lstio_dbg_type) {
81 rc = lstcon_session_debug(args->lstio_dbg_timeout,
82 args->lstio_dbg_resultp);
85 case LST_OPC_BATCHSRV:
88 case LST_OPC_BATCHCLI:
92 rc = lstcon_batch_debug(args->lstio_dbg_timeout,
93 name, client, args->lstio_dbg_resultp);
100 rc = lstcon_group_debug(args->lstio_dbg_timeout,
101 name, args->lstio_dbg_resultp);
105 if (args->lstio_dbg_count <= 0 ||
106 args->lstio_dbg_idsp == NULL)
109 rc = lstcon_nodes_debug(args->lstio_dbg_timeout,
110 args->lstio_dbg_count,
111 args->lstio_dbg_idsp,
112 args->lstio_dbg_resultp);
121 LIBCFS_FREE(name, args->lstio_dbg_nmlen + 1);
127 lst_group_add_ioctl(struct lstio_group_add_args *args)
132 if (args->lstio_grp_key != console_session.ses_key)
135 if (args->lstio_grp_namep == NULL ||
136 args->lstio_grp_nmlen <= 0 ||
137 args->lstio_grp_nmlen > LST_NAME_SIZE)
140 LIBCFS_ALLOC(name, args->lstio_grp_nmlen + 1);
144 if (copy_from_user(name, args->lstio_grp_namep,
145 args->lstio_grp_nmlen)) {
146 LIBCFS_FREE(name, args->lstio_grp_nmlen);
150 name[args->lstio_grp_nmlen] = 0;
152 rc = lstcon_group_add(name);
154 LIBCFS_FREE(name, args->lstio_grp_nmlen + 1);
160 lst_group_del_ioctl(struct lstio_group_del_args *args)
165 if (args->lstio_grp_key != console_session.ses_key)
168 if (args->lstio_grp_namep == NULL ||
169 args->lstio_grp_nmlen <= 0 ||
170 args->lstio_grp_nmlen > LST_NAME_SIZE)
173 LIBCFS_ALLOC(name, args->lstio_grp_nmlen + 1);
177 if (copy_from_user(name, args->lstio_grp_namep,
178 args->lstio_grp_nmlen)) {
179 LIBCFS_FREE(name, args->lstio_grp_nmlen + 1);
183 name[args->lstio_grp_nmlen] = 0;
185 rc = lstcon_group_del(name);
187 LIBCFS_FREE(name, args->lstio_grp_nmlen + 1);
193 lst_group_update_ioctl(struct lstio_group_update_args *args)
198 if (args->lstio_grp_key != console_session.ses_key)
201 if (args->lstio_grp_resultp == NULL ||
202 args->lstio_grp_namep == NULL ||
203 args->lstio_grp_nmlen <= 0 ||
204 args->lstio_grp_nmlen > LST_NAME_SIZE)
207 LIBCFS_ALLOC(name, args->lstio_grp_nmlen + 1);
211 if (copy_from_user(name, args->lstio_grp_namep,
212 args->lstio_grp_nmlen)) {
213 LIBCFS_FREE(name, args->lstio_grp_nmlen + 1);
217 name[args->lstio_grp_nmlen] = 0;
219 switch (args->lstio_grp_opc) {
220 case LST_GROUP_CLEAN:
221 rc = lstcon_group_clean(name, args->lstio_grp_args);
224 case LST_GROUP_REFRESH:
225 rc = lstcon_group_refresh(name, args->lstio_grp_resultp);
229 if (args->lstio_grp_count <= 0 ||
230 args->lstio_grp_idsp == NULL) {
234 rc = lstcon_nodes_remove(name, args->lstio_grp_count,
235 args->lstio_grp_idsp,
236 args->lstio_grp_resultp);
244 LIBCFS_FREE(name, args->lstio_grp_nmlen + 1);
250 lst_nodes_add_ioctl(struct lstio_group_nodes_args *args)
256 if (args->lstio_grp_key != console_session.ses_key)
259 if (args->lstio_grp_idsp == NULL || /* array of ids */
260 args->lstio_grp_count <= 0 ||
261 args->lstio_grp_resultp == NULL ||
262 args->lstio_grp_featp == NULL ||
263 args->lstio_grp_namep == NULL ||
264 args->lstio_grp_nmlen <= 0 ||
265 args->lstio_grp_nmlen > LST_NAME_SIZE)
268 LIBCFS_ALLOC(name, args->lstio_grp_nmlen + 1);
272 if (copy_from_user(name, args->lstio_grp_namep,
273 args->lstio_grp_nmlen)) {
274 LIBCFS_FREE(name, args->lstio_grp_nmlen + 1);
279 name[args->lstio_grp_nmlen] = 0;
281 rc = lstcon_nodes_add(name, args->lstio_grp_count,
282 args->lstio_grp_idsp, &feats,
283 args->lstio_grp_resultp);
285 LIBCFS_FREE(name, args->lstio_grp_nmlen + 1);
287 copy_to_user(args->lstio_grp_featp, &feats, sizeof(feats))) {
295 lst_batch_add_ioctl(struct lstio_batch_add_args *args)
300 if (args->lstio_bat_key != console_session.ses_key)
303 if (args->lstio_bat_namep == NULL ||
304 args->lstio_bat_nmlen <= 0 ||
305 args->lstio_bat_nmlen > LST_NAME_SIZE)
308 LIBCFS_ALLOC(name, args->lstio_bat_nmlen + 1);
312 if (copy_from_user(name, args->lstio_bat_namep,
313 args->lstio_bat_nmlen)) {
314 LIBCFS_FREE(name, args->lstio_bat_nmlen + 1);
318 name[args->lstio_bat_nmlen] = 0;
320 rc = lstcon_batch_add(name);
322 LIBCFS_FREE(name, args->lstio_bat_nmlen + 1);
328 lst_batch_run_ioctl(struct lstio_batch_run_args *args)
333 if (args->lstio_bat_key != console_session.ses_key)
336 if (args->lstio_bat_namep == NULL ||
337 args->lstio_bat_nmlen <= 0 ||
338 args->lstio_bat_nmlen > LST_NAME_SIZE)
341 LIBCFS_ALLOC(name, args->lstio_bat_nmlen + 1);
345 if (copy_from_user(name, args->lstio_bat_namep,
346 args->lstio_bat_nmlen)) {
347 LIBCFS_FREE(name, args->lstio_bat_nmlen + 1);
351 name[args->lstio_bat_nmlen] = 0;
353 rc = lstcon_batch_run(name, args->lstio_bat_timeout,
354 args->lstio_bat_resultp);
356 LIBCFS_FREE(name, args->lstio_bat_nmlen + 1);
362 lst_batch_stop_ioctl(struct lstio_batch_stop_args *args)
367 if (args->lstio_bat_key != console_session.ses_key)
370 if (args->lstio_bat_resultp == NULL ||
371 args->lstio_bat_namep == NULL ||
372 args->lstio_bat_nmlen <= 0 ||
373 args->lstio_bat_nmlen > LST_NAME_SIZE)
376 LIBCFS_ALLOC(name, args->lstio_bat_nmlen + 1);
380 if (copy_from_user(name, args->lstio_bat_namep,
381 args->lstio_bat_nmlen)) {
382 LIBCFS_FREE(name, args->lstio_bat_nmlen + 1);
386 name[args->lstio_bat_nmlen] = 0;
388 rc = lstcon_batch_stop(name, args->lstio_bat_force,
389 args->lstio_bat_resultp);
391 LIBCFS_FREE(name, args->lstio_bat_nmlen + 1);
397 lst_batch_query_ioctl(struct lstio_batch_query_args *args)
402 if (args->lstio_bat_key != console_session.ses_key)
405 if (args->lstio_bat_resultp == NULL ||
406 args->lstio_bat_namep == NULL ||
407 args->lstio_bat_nmlen <= 0 ||
408 args->lstio_bat_nmlen > LST_NAME_SIZE)
411 if (args->lstio_bat_testidx < 0)
414 LIBCFS_ALLOC(name, args->lstio_bat_nmlen + 1);
418 if (copy_from_user(name, args->lstio_bat_namep,
419 args->lstio_bat_nmlen)) {
420 LIBCFS_FREE(name, args->lstio_bat_nmlen + 1);
424 name[args->lstio_bat_nmlen] = 0;
426 rc = lstcon_test_batch_query(name,
427 args->lstio_bat_testidx,
428 args->lstio_bat_client,
429 args->lstio_bat_timeout,
430 args->lstio_bat_resultp);
432 LIBCFS_FREE(name, args->lstio_bat_nmlen + 1);
438 lst_batch_list_ioctl(struct lstio_batch_list_args *args)
440 if (args->lstio_bat_key != console_session.ses_key)
443 if (args->lstio_bat_idx < 0 ||
444 args->lstio_bat_namep == NULL ||
445 args->lstio_bat_nmlen <= 0 ||
446 args->lstio_bat_nmlen > LST_NAME_SIZE)
449 return lstcon_batch_list(args->lstio_bat_idx,
450 args->lstio_bat_nmlen,
451 args->lstio_bat_namep);
455 lst_batch_info_ioctl(struct lstio_batch_info_args *args)
462 if (args->lstio_bat_key != console_session.ses_key)
465 if (args->lstio_bat_namep == NULL || /* batch name */
466 args->lstio_bat_nmlen <= 0 ||
467 args->lstio_bat_nmlen > LST_NAME_SIZE)
470 if (args->lstio_bat_entp == NULL && /* output: batch entry */
471 args->lstio_bat_dentsp == NULL) /* output: node entry */
474 if (args->lstio_bat_dentsp != NULL) { /* have node entry */
475 if (args->lstio_bat_idxp == NULL || /* node index */
476 args->lstio_bat_ndentp == NULL) /* # of node entry */
479 if (copy_from_user(&index, args->lstio_bat_idxp,
481 copy_from_user(&ndent, args->lstio_bat_ndentp,
485 if (ndent <= 0 || index < 0)
489 LIBCFS_ALLOC(name, args->lstio_bat_nmlen + 1);
493 if (copy_from_user(name, args->lstio_bat_namep,
494 args->lstio_bat_nmlen)) {
495 LIBCFS_FREE(name, args->lstio_bat_nmlen + 1);
499 name[args->lstio_bat_nmlen] = 0;
501 rc = lstcon_batch_info(name,
502 args->lstio_bat_entp, args->lstio_bat_server,
503 args->lstio_bat_testidx, &index, &ndent,
504 args->lstio_bat_dentsp);
506 LIBCFS_FREE(name, args->lstio_bat_nmlen + 1);
511 if (args->lstio_bat_dentsp != NULL &&
512 (copy_to_user(args->lstio_bat_idxp, &index, sizeof(index)) ||
513 copy_to_user(args->lstio_bat_ndentp, &ndent, sizeof(ndent))))
520 lst_stat_query_ioctl(struct lstio_stat_args *args)
525 /* TODO: not finished */
526 if (args->lstio_sta_key != console_session.ses_key)
529 if (args->lstio_sta_resultp == NULL)
532 if (args->lstio_sta_idsp != NULL) {
533 if (args->lstio_sta_count <= 0)
536 rc = lstcon_nodes_stat(args->lstio_sta_count,
537 args->lstio_sta_idsp,
538 args->lstio_sta_timeout,
539 args->lstio_sta_resultp);
540 } else if (args->lstio_sta_namep != NULL) {
541 if (args->lstio_sta_nmlen <= 0 ||
542 args->lstio_sta_nmlen > LST_NAME_SIZE)
545 LIBCFS_ALLOC(name, args->lstio_sta_nmlen + 1);
549 rc = copy_from_user(name, args->lstio_sta_namep,
550 args->lstio_sta_nmlen);
552 rc = lstcon_group_stat(name, args->lstio_sta_timeout,
553 args->lstio_sta_resultp);
562 LIBCFS_FREE(name, args->lstio_sta_nmlen + 1);
566 static int lst_test_add_ioctl(struct lstio_test_args *args)
569 char *src_name = NULL;
570 char *dst_name = NULL;
575 if (args->lstio_tes_resultp == NULL ||
576 args->lstio_tes_retp == NULL ||
577 args->lstio_tes_bat_name == NULL || /* no specified batch */
578 args->lstio_tes_bat_nmlen <= 0 ||
579 args->lstio_tes_bat_nmlen > LST_NAME_SIZE ||
580 args->lstio_tes_sgrp_name == NULL || /* no source group */
581 args->lstio_tes_sgrp_nmlen <= 0 ||
582 args->lstio_tes_sgrp_nmlen > LST_NAME_SIZE ||
583 args->lstio_tes_dgrp_name == NULL || /* no target group */
584 args->lstio_tes_dgrp_nmlen <= 0 ||
585 args->lstio_tes_dgrp_nmlen > LST_NAME_SIZE)
588 if (args->lstio_tes_loop == 0 || /* negative is infinite */
589 args->lstio_tes_concur <= 0 ||
590 args->lstio_tes_dist <= 0 ||
591 args->lstio_tes_span <= 0)
594 /* have parameter, check if parameter length is valid */
595 if (args->lstio_tes_param != NULL &&
596 (args->lstio_tes_param_len <= 0 ||
597 args->lstio_tes_param_len >
598 PAGE_SIZE - sizeof(struct lstcon_test)))
601 LIBCFS_ALLOC(batch_name, args->lstio_tes_bat_nmlen + 1);
602 if (batch_name == NULL)
605 LIBCFS_ALLOC(src_name, args->lstio_tes_sgrp_nmlen + 1);
606 if (src_name == NULL)
609 LIBCFS_ALLOC(dst_name, args->lstio_tes_dgrp_nmlen + 1);
610 if (dst_name == NULL)
613 if (args->lstio_tes_param != NULL) {
614 LIBCFS_ALLOC(param, args->lstio_tes_param_len);
617 if (copy_from_user(param, args->lstio_tes_param,
618 args->lstio_tes_param_len)) {
625 if (copy_from_user(batch_name, args->lstio_tes_bat_name,
626 args->lstio_tes_bat_nmlen) ||
627 copy_from_user(src_name, args->lstio_tes_sgrp_name,
628 args->lstio_tes_sgrp_nmlen) ||
629 copy_from_user(dst_name, args->lstio_tes_dgrp_name,
630 args->lstio_tes_dgrp_nmlen))
633 rc = lstcon_test_add(batch_name,
634 args->lstio_tes_type,
635 args->lstio_tes_loop,
636 args->lstio_tes_concur,
637 args->lstio_tes_dist, args->lstio_tes_span,
638 src_name, dst_name, param,
639 args->lstio_tes_param_len,
640 &ret, args->lstio_tes_resultp);
643 rc = (copy_to_user(args->lstio_tes_retp, &ret,
644 sizeof(ret))) ? -EFAULT : 0;
646 if (batch_name != NULL)
647 LIBCFS_FREE(batch_name, args->lstio_tes_bat_nmlen + 1);
649 if (src_name != NULL)
650 LIBCFS_FREE(src_name, args->lstio_tes_sgrp_nmlen + 1);
652 if (dst_name != NULL)
653 LIBCFS_FREE(dst_name, args->lstio_tes_dgrp_nmlen + 1);
656 LIBCFS_FREE(param, args->lstio_tes_param_len);
662 lstcon_ioctl_entry(struct notifier_block *nb,
663 unsigned long cmd, void *vdata)
665 struct libcfs_ioctl_hdr *hdr = vdata;
666 struct libcfs_ioctl_data *data;
671 if (cmd != IOC_LIBCFS_LNETST)
674 data = container_of(hdr, struct libcfs_ioctl_data, ioc_hdr);
676 opc = data->ioc_u32[0];
678 if (data->ioc_plen1 > PAGE_SIZE)
681 LIBCFS_ALLOC(buf, data->ioc_plen1);
687 /* copy in parameter */
688 if (copy_from_user(buf, data->ioc_pbuf1, data->ioc_plen1)) {
693 mutex_lock(&console_session.ses_mutex);
695 console_session.ses_laststamp = ktime_get_real_seconds();
697 if (console_session.ses_shutdown) {
702 if (console_session.ses_expired)
703 lstcon_session_end();
705 if (opc != LSTIO_SESSION_NEW &&
706 console_session.ses_state == LST_SESSION_NONE) {
707 CDEBUG(D_NET, "LST no active session\n");
712 memset(&console_session.ses_trans_stat, 0,
713 sizeof(struct lstcon_trans_stat));
716 case LSTIO_SESSION_NEW:
718 case LSTIO_SESSION_END:
720 case LSTIO_SESSION_INFO:
724 rc = lst_debug_ioctl((struct lstio_debug_args *)buf);
726 case LSTIO_GROUP_ADD:
727 rc = lst_group_add_ioctl((struct lstio_group_add_args *)buf);
729 case LSTIO_GROUP_DEL:
730 rc = lst_group_del_ioctl((struct lstio_group_del_args *)buf);
732 case LSTIO_GROUP_UPDATE:
733 rc = lst_group_update_ioctl((struct lstio_group_update_args *)buf);
735 case LSTIO_NODES_ADD:
736 rc = lst_nodes_add_ioctl((struct lstio_group_nodes_args *)buf);
738 case LSTIO_GROUP_LIST:
740 case LSTIO_GROUP_INFO:
743 case LSTIO_BATCH_ADD:
744 rc = lst_batch_add_ioctl((struct lstio_batch_add_args *)buf);
746 case LSTIO_BATCH_START:
747 rc = lst_batch_run_ioctl((struct lstio_batch_run_args *)buf);
749 case LSTIO_BATCH_STOP:
750 rc = lst_batch_stop_ioctl((struct lstio_batch_stop_args *)buf);
752 case LSTIO_BATCH_QUERY:
753 rc = lst_batch_query_ioctl((struct lstio_batch_query_args *)buf);
755 case LSTIO_BATCH_LIST:
756 rc = lst_batch_list_ioctl((struct lstio_batch_list_args *)buf);
758 case LSTIO_BATCH_INFO:
759 rc = lst_batch_info_ioctl((struct lstio_batch_info_args *)buf);
762 rc = lst_test_add_ioctl((struct lstio_test_args *)buf);
764 case LSTIO_STAT_QUERY:
765 rc = lst_stat_query_ioctl((struct lstio_stat_args *)buf);
772 if (copy_to_user(data->ioc_pbuf2, &console_session.ses_trans_stat,
773 sizeof(struct lstcon_trans_stat)))
776 mutex_unlock(&console_session.ses_mutex);
778 LIBCFS_FREE(buf, data->ioc_plen1);
780 return notifier_from_ioctl_errno(rc);
783 static struct genl_family lst_family;
785 static const struct ln_key_list lst_session_keys = {
786 .lkl_maxattr = LNET_SELFTEST_SESSION_MAX,
788 [LNET_SELFTEST_SESSION_HDR] = {
789 .lkp_value = "session",
790 .lkp_key_format = LNKF_MAPPING,
791 .lkp_data_type = NLA_NUL_STRING,
793 [LNET_SELFTEST_SESSION_NAME] = {
795 .lkp_data_type = NLA_STRING,
797 [LNET_SELFTEST_SESSION_KEY] = {
799 .lkp_data_type = NLA_U32,
801 [LNET_SELFTEST_SESSION_TIMESTAMP] = {
802 .lkp_value = "timestamp",
803 .lkp_data_type = NLA_S64,
805 [LNET_SELFTEST_SESSION_NID] = {
807 .lkp_data_type = NLA_STRING,
809 [LNET_SELFTEST_SESSION_NODE_COUNT] = {
810 .lkp_value = "nodes",
811 .lkp_data_type = NLA_U16,
816 static int lst_sessions_show_dump(struct sk_buff *msg,
817 struct netlink_callback *cb)
819 const struct ln_key_list *all[] = {
820 &lst_session_keys, NULL
822 #ifdef HAVE_NL_PARSE_WITH_EXT_ACK
823 struct netlink_ext_ack *extack = NULL;
825 int portid = NETLINK_CB(cb->skb).portid;
826 int seq = cb->nlh->nlmsg_seq;
827 unsigned int node_count = 0;
828 struct lstcon_ndlink *ndl;
829 int flag = NLM_F_MULTI;
833 #ifdef HAVE_NL_DUMP_WITH_EXT_ACK
836 if (console_session.ses_state != LST_SESSION_ACTIVE) {
837 NL_SET_ERR_MSG(extack, "session is not active");
838 GOTO(out_unlock, rc = -ESRCH);
841 list_for_each_entry(ndl, &console_session.ses_ndl_list, ndl_link)
844 rc = lnet_genl_send_scalar_list(msg, portid, seq, &lst_family,
845 NLM_F_CREATE | NLM_F_MULTI,
846 LNET_SELFTEST_CMD_SESSIONS, all);
848 NL_SET_ERR_MSG(extack, "failed to send key table");
849 GOTO(out_unlock, rc);
852 if (console_session.ses_force)
853 flag |= NLM_F_REPLACE;
855 hdr = genlmsg_put(msg, portid, seq, &lst_family, flag,
856 LNET_SELFTEST_CMD_SESSIONS);
858 NL_SET_ERR_MSG(extack, "failed to send values");
859 genlmsg_cancel(msg, hdr);
860 GOTO(out_unlock, rc = -EMSGSIZE);
863 nla_put_string(msg, LNET_SELFTEST_SESSION_NAME,
864 console_session.ses_name);
865 nla_put_u32(msg, LNET_SELFTEST_SESSION_KEY,
866 console_session.ses_key);
867 nla_put_u64_64bit(msg, LNET_SELFTEST_SESSION_TIMESTAMP,
868 console_session.ses_id.ses_stamp,
869 LNET_SELFTEST_SESSION_PAD);
870 nla_put_string(msg, LNET_SELFTEST_SESSION_NID,
871 libcfs_nidstr(&console_session.ses_id.ses_nid));
872 nla_put_u16(msg, LNET_SELFTEST_SESSION_NODE_COUNT,
874 genlmsg_end(msg, hdr);
876 return lnet_nl_send_error(cb->skb, portid, seq, rc);
879 static int lst_sessions_cmd(struct sk_buff *skb, struct genl_info *info)
881 struct sk_buff *msg = NULL;
884 mutex_lock(&console_session.ses_mutex);
886 console_session.ses_laststamp = ktime_get_real_seconds();
888 if (console_session.ses_shutdown) {
889 GENL_SET_ERR_MSG(info, "session is shutdown");
890 GOTO(out_unlock, rc = -ESHUTDOWN);
893 if (console_session.ses_expired)
894 lstcon_session_end();
896 if (!(info->nlhdr->nlmsg_flags & NLM_F_CREATE) &&
897 console_session.ses_state == LST_SESSION_NONE) {
898 GENL_SET_ERR_MSG(info, "session is not active");
899 GOTO(out_unlock, rc = -ESRCH);
902 memset(&console_session.ses_trans_stat, 0,
903 sizeof(struct lstcon_trans_stat));
905 if (!(info->nlhdr->nlmsg_flags & NLM_F_CREATE)) {
906 lstcon_session_end();
907 GOTO(out_unlock, rc);
910 if (info->attrs[LN_SCALAR_ATTR_LIST]) {
911 struct genlmsghdr *gnlh = nlmsg_data(info->nlhdr);
912 const struct ln_key_list *all[] = {
913 &lst_session_keys, NULL
915 char name[LST_NAME_SIZE];
916 struct nlmsghdr *nlh;
923 if (info->nlhdr->nlmsg_flags & NLM_F_REPLACE)
926 nla_for_each_nested(item, info->attrs[LN_SCALAR_ATTR_LIST],
928 if (nla_type(item) != LN_SCALAR_ATTR_VALUE)
931 if (nla_strcmp(item, "name") == 0) {
934 item = nla_next(item, &rem);
935 if (nla_type(item) != LN_SCALAR_ATTR_VALUE)
936 GOTO(err_conf, rc = -EINVAL);
938 len = nla_strscpy(name, item, sizeof(name));
941 } else if (nla_strcmp(item, "timeout") == 0) {
942 item = nla_next(item, &rem);
943 if (nla_type(item) !=
944 LN_SCALAR_ATTR_INT_VALUE)
945 GOTO(err_conf, rc = -EINVAL);
947 timeout = nla_get_s64(item);
953 GENL_SET_ERR_MSG(info,
954 "failed to get config");
955 GOTO(out_unlock, rc);
959 rc = lstcon_session_new(name, info->nlhdr->nlmsg_pid,
960 gnlh->version, timeout,
963 GENL_SET_ERR_MSG(info, "new session creation failed");
964 lstcon_session_end();
965 GOTO(out_unlock, rc);
968 msg = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_KERNEL);
970 GENL_SET_ERR_MSG(info, "msg allocation failed");
971 GOTO(out_unlock, rc = -ENOMEM);
974 rc = lnet_genl_send_scalar_list(msg, info->snd_portid,
975 info->snd_seq, &lst_family,
976 NLM_F_CREATE | NLM_F_MULTI,
977 LNET_SELFTEST_CMD_SESSIONS,
980 GENL_SET_ERR_MSG(info, "failed to send key table");
981 GOTO(out_unlock, rc);
984 hdr = genlmsg_put(msg, info->snd_portid, info->snd_seq,
985 &lst_family, NLM_F_MULTI,
986 LNET_SELFTEST_CMD_SESSIONS);
988 GENL_SET_ERR_MSG(info, "failed to send values");
989 genlmsg_cancel(msg, hdr);
990 GOTO(out_unlock, rc = -EMSGSIZE);
993 nla_put_string(msg, LNET_SELFTEST_SESSION_NAME,
994 console_session.ses_name);
995 nla_put_u32(msg, LNET_SELFTEST_SESSION_KEY,
996 console_session.ses_key);
997 nla_put_u64_64bit(msg, LNET_SELFTEST_SESSION_TIMESTAMP,
998 console_session.ses_id.ses_stamp,
999 LNET_SELFTEST_SESSION_PAD);
1000 nla_put_string(msg, LNET_SELFTEST_SESSION_NID,
1001 libcfs_nidstr(&console_session.ses_id.ses_nid));
1002 nla_put_u16(msg, LNET_SELFTEST_SESSION_NODE_COUNT, 0);
1004 genlmsg_end(msg, hdr);
1006 nlh = nlmsg_put(msg, info->snd_portid, info->snd_seq,
1007 NLMSG_DONE, 0, NLM_F_MULTI);
1009 GENL_SET_ERR_MSG(info, "failed to complete message");
1010 genlmsg_cancel(msg, hdr);
1011 GOTO(out_unlock, rc = -ENOMEM);
1013 rc = genlmsg_reply(msg, info);
1015 GENL_SET_ERR_MSG(info, "failed to send reply");
1020 mutex_unlock(&console_session.ses_mutex);
1024 static char *lst_node_state2str(int state)
1026 if (state == LST_NODE_ACTIVE)
1028 if (state == LST_NODE_BUSY)
1030 if (state == LST_NODE_DOWN)
1036 int lst_node_str2state(char *str)
1040 if (strcasecmp(str, "Active") == 0)
1041 state = LST_NODE_ACTIVE;
1042 else if (strcasecmp(str, "Busy") == 0)
1043 state = LST_NODE_BUSY;
1044 else if (strcasecmp(str, "Down") == 0)
1045 state = LST_NODE_DOWN;
1046 else if (strcasecmp(str, "Unknown") == 0)
1047 state = LST_NODE_UNKNOWN;
1048 else if (strcasecmp(str, "Invalid") == 0)
1049 state = LST_NODE_UNKNOWN | LST_NODE_DOWN | LST_NODE_BUSY;
1053 struct lst_genl_group_prop {
1054 struct lstcon_group *lggp_grp;
1055 int lggp_state_filter;
1058 struct lst_genl_group_list {
1059 GENRADIX(struct lst_genl_group_prop) lggl_groups;
1060 unsigned int lggl_count;
1061 unsigned int lggl_index;
1065 static inline struct lst_genl_group_list *
1066 lst_group_dump_ctx(struct netlink_callback *cb)
1068 return (struct lst_genl_group_list *)cb->args[0];
1071 static int lst_groups_show_done(struct netlink_callback *cb)
1073 struct lst_genl_group_list *glist = lst_group_dump_ctx(cb);
1078 for (i = 0; i < glist->lggl_count; i++) {
1079 struct lst_genl_group_prop *prop;
1081 prop = genradix_ptr(&glist->lggl_groups, i);
1082 if (!prop || !prop->lggp_grp)
1084 lstcon_group_decref(prop->lggp_grp);
1086 genradix_free(&glist->lggl_groups);
1087 LIBCFS_FREE(glist, sizeof(*glist));
1094 /* LNet selftest groups ->start() handler for GET requests */
1095 static int lst_groups_show_start(struct netlink_callback *cb)
1097 struct genlmsghdr *gnlh = nlmsg_data(cb->nlh);
1098 #ifdef HAVE_NL_PARSE_WITH_EXT_ACK
1099 struct netlink_ext_ack *extack = NULL;
1101 struct nlattr *params = genlmsg_data(gnlh);
1102 struct lst_genl_group_list *glist;
1103 int msg_len = genlmsg_len(gnlh);
1104 struct lstcon_group *grp;
1105 struct nlattr *groups;
1108 LIBCFS_ALLOC(glist, sizeof(*glist));
1112 genradix_init(&glist->lggl_groups);
1113 cb->args[0] = (long)glist;
1116 list_for_each_entry(grp, &console_session.ses_grp_list,
1118 struct lst_genl_group_prop *prop;
1120 prop = genradix_ptr_alloc(&glist->lggl_groups,
1121 glist->lggl_count++,
1124 NL_SET_ERR_MSG(extack,
1125 "failed to allocate group info");
1126 GOTO(report_err, rc = -ENOMEM);
1128 lstcon_group_addref(grp); /* +1 ref for caller */
1129 prop->lggp_grp = grp;
1132 if (!glist->lggl_count) {
1133 NL_SET_ERR_MSG(extack, "No groups found");
1136 GOTO(report_err, rc);
1138 glist->lggl_verbose = true;
1139 #ifdef HAVE_NL_DUMP_WITH_EXT_ACK
1140 extack = cb->extack;
1143 if (!(nla_type(params) & LN_SCALAR_ATTR_LIST)) {
1144 NL_SET_ERR_MSG(extack, "no configuration");
1145 GOTO(report_err, rc);
1148 nla_for_each_nested(groups, params, rem) {
1149 struct lst_genl_group_prop *prop = NULL;
1150 struct nlattr *group;
1153 if (nla_type(groups) != LN_SCALAR_ATTR_LIST)
1156 nla_for_each_nested(group, groups, rem2) {
1157 if (nla_type(group) == LN_SCALAR_ATTR_VALUE) {
1158 char name[LST_NAME_SIZE];
1160 prop = genradix_ptr_alloc(&glist->lggl_groups,
1161 glist->lggl_count++,
1164 NL_SET_ERR_MSG(extack,
1165 "failed to allocate group info");
1166 GOTO(report_err, rc = -ENOMEM);
1169 rc = nla_strscpy(name, group, sizeof(name));
1171 NL_SET_ERR_MSG(extack,
1172 "failed to get name");
1173 GOTO(report_err, rc);
1175 rc = lstcon_group_find(name, &prop->lggp_grp);
1177 /* don't stop reporting groups if one
1180 CWARN("LNet selftest group %s does not exit\n",
1184 } else if (nla_type(group) == LN_SCALAR_ATTR_LIST) {
1185 struct nlattr *attr;
1189 NL_SET_ERR_MSG(extack,
1190 "missing group information");
1191 GOTO(report_err, rc = -EINVAL);
1194 nla_for_each_nested(attr, group, rem3) {
1197 if (nla_type(attr) != LN_SCALAR_ATTR_VALUE ||
1198 nla_strcmp(attr, "status") != 0)
1201 attr = nla_next(attr, &rem3);
1202 if (nla_type(attr) !=
1203 LN_SCALAR_ATTR_VALUE) {
1204 NL_SET_ERR_MSG(extack,
1205 "invalid config param");
1206 GOTO(report_err, rc = -EINVAL);
1209 rc = nla_strscpy(tmp, attr, sizeof(tmp));
1211 NL_SET_ERR_MSG(extack,
1212 "failed to get prop attr");
1213 GOTO(report_err, rc);
1216 prop->lggp_state_filter |=
1217 lst_node_str2state(tmp);
1222 if (!glist->lggl_count) {
1223 NL_SET_ERR_MSG(extack, "No groups found");
1228 lst_groups_show_done(cb);
1233 static const struct ln_key_list lst_group_keys = {
1234 .lkl_maxattr = LNET_SELFTEST_GROUP_MAX,
1236 [LNET_SELFTEST_GROUP_ATTR_HDR] = {
1237 .lkp_value = "groups",
1238 .lkp_key_format = LNKF_SEQUENCE,
1239 .lkp_data_type = NLA_NUL_STRING,
1241 [LNET_SELFTEST_GROUP_ATTR_NAME] = {
1242 .lkp_data_type = NLA_STRING,
1244 [LNET_SELFTEST_GROUP_ATTR_NODELIST] = {
1245 .lkp_key_format = LNKF_MAPPING | LNKF_SEQUENCE,
1246 .lkp_data_type = NLA_NESTED,
1251 static const struct ln_key_list lst_group_nodelist_keys = {
1252 .lkl_maxattr = LNET_SELFTEST_GROUP_NODELIST_PROP_MAX,
1254 [LNET_SELFTEST_GROUP_NODELIST_PROP_ATTR_NID] = {
1256 .lkp_data_type = NLA_STRING,
1258 [LNET_SELFTEST_GROUP_NODELIST_PROP_ATTR_STATUS] = {
1259 .lkp_value = "status",
1260 .lkp_data_type = NLA_STRING,
1265 static int lst_groups_show_dump(struct sk_buff *msg,
1266 struct netlink_callback *cb)
1268 struct lst_genl_group_list *glist = lst_group_dump_ctx(cb);
1269 #ifdef HAVE_NL_PARSE_WITH_EXT_ACK
1270 struct netlink_ext_ack *extack = NULL;
1272 int portid = NETLINK_CB(cb->skb).portid;
1273 int seq = cb->nlh->nlmsg_seq;
1274 int idx = 0, rc = 0;
1276 #ifdef HAVE_NL_DUMP_WITH_EXT_ACK
1277 extack = cb->extack;
1279 if (!glist->lggl_index) {
1280 const struct ln_key_list *all[] = {
1281 &lst_group_keys, &lst_group_nodelist_keys, NULL
1284 rc = lnet_genl_send_scalar_list(msg, portid, seq, &lst_family,
1285 NLM_F_CREATE | NLM_F_MULTI,
1286 LNET_SELFTEST_CMD_GROUPS, all);
1288 NL_SET_ERR_MSG(extack, "failed to send key table");
1289 GOTO(send_error, rc);
1293 for (idx = glist->lggl_index; idx < glist->lggl_count; idx++) {
1294 struct lst_genl_group_prop *group;
1295 struct lstcon_ndlink *ndl;
1296 struct nlattr *nodelist;
1297 unsigned int count = 1;
1300 group = genradix_ptr(&glist->lggl_groups, idx);
1304 hdr = genlmsg_put(msg, portid, seq, &lst_family,
1305 NLM_F_MULTI, LNET_SELFTEST_CMD_GROUPS);
1307 NL_SET_ERR_MSG(extack, "failed to send values");
1308 GOTO(send_error, rc = -EMSGSIZE);
1312 nla_put_string(msg, LNET_SELFTEST_GROUP_ATTR_HDR, "");
1314 nla_put_string(msg, LNET_SELFTEST_GROUP_ATTR_NAME,
1315 group->lggp_grp->grp_name);
1317 if (!glist->lggl_verbose)
1320 nodelist = nla_nest_start(msg,
1321 LNET_SELFTEST_GROUP_ATTR_NODELIST);
1322 list_for_each_entry(ndl, &group->lggp_grp->grp_ndl_list,
1324 struct nlattr *node = nla_nest_start(msg, count);
1327 if (group->lggp_state_filter &&
1328 !(group->lggp_state_filter & ndl->ndl_node->nd_state))
1332 LNET_SELFTEST_GROUP_NODELIST_PROP_ATTR_NID,
1333 libcfs_id2str(ndl->ndl_node->nd_id));
1335 ndstate = lst_node_state2str(ndl->ndl_node->nd_state);
1337 LNET_SELFTEST_GROUP_NODELIST_PROP_ATTR_STATUS,
1339 nla_nest_end(msg, node);
1341 nla_nest_end(msg, nodelist);
1343 genlmsg_end(msg, hdr);
1345 glist->lggl_index = idx;
1347 return lnet_nl_send_error(cb->skb, portid, seq, rc);
1350 #ifndef HAVE_NETLINK_CALLBACK_START
1351 static int lst_old_groups_show_dump(struct sk_buff *msg,
1352 struct netlink_callback *cb)
1355 int rc = lst_groups_show_start(cb);
1361 return lst_groups_show_dump(msg, cb);
1365 static const struct genl_multicast_group lst_mcast_grps[] = {
1366 { .name = "sessions", },
1367 { .name = "groups", },
1370 static const struct genl_ops lst_genl_ops[] = {
1372 .cmd = LNET_SELFTEST_CMD_SESSIONS,
1373 .dumpit = lst_sessions_show_dump,
1374 .doit = lst_sessions_cmd,
1377 .cmd = LNET_SELFTEST_CMD_GROUPS,
1378 #ifdef HAVE_NETLINK_CALLBACK_START
1379 .start = lst_groups_show_start,
1380 .dumpit = lst_groups_show_dump,
1382 .dumpit = lst_old_groups_show_dump,
1384 .done = lst_groups_show_done,
1388 static struct genl_family lst_family = {
1389 .name = LNET_SELFTEST_GENL_NAME,
1390 .version = LNET_SELFTEST_GENL_VERSION,
1391 .maxattr = LN_SCALAR_MAX,
1392 .module = THIS_MODULE,
1393 .ops = lst_genl_ops,
1394 .n_ops = ARRAY_SIZE(lst_genl_ops),
1395 .mcgrps = lst_mcast_grps,
1396 .n_mcgrps = ARRAY_SIZE(lst_mcast_grps),
1399 int lstcon_init_netlink(void)
1401 return genl_register_family(&lst_family);
1404 void lstcon_fini_netlink(void)
1406 genl_unregister_family(&lst_family);