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 * IOC handle in kernel
15 * Author: Liang Zhen <liangzhen@clusterfs.com>
18 #include <linux/generic-radix-tree.h>
19 #include <libcfs/linux/linux-net.h>
20 #include <libcfs/libcfs.h>
21 #include <lnet/lib-lnet.h>
25 lst_debug_ioctl(struct lstio_debug_args *args)
31 if (args->lstio_dbg_key != console_session.ses_key)
34 if (args->lstio_dbg_resultp == NULL)
37 if (args->lstio_dbg_namep != NULL && /* name of batch/group */
38 (args->lstio_dbg_nmlen <= 0 ||
39 args->lstio_dbg_nmlen > LST_NAME_SIZE))
42 if (args->lstio_dbg_namep != NULL) {
43 LIBCFS_ALLOC(name, args->lstio_dbg_nmlen + 1);
47 if (copy_from_user(name, args->lstio_dbg_namep,
48 args->lstio_dbg_nmlen)) {
49 LIBCFS_FREE(name, args->lstio_dbg_nmlen + 1);
54 name[args->lstio_dbg_nmlen] = 0;
59 switch (args->lstio_dbg_type) {
61 rc = lstcon_session_debug(args->lstio_dbg_timeout,
62 args->lstio_dbg_resultp);
65 case LST_OPC_BATCHSRV:
68 case LST_OPC_BATCHCLI:
72 rc = lstcon_batch_debug(args->lstio_dbg_timeout,
73 name, client, args->lstio_dbg_resultp);
80 rc = lstcon_group_debug(args->lstio_dbg_timeout,
81 name, args->lstio_dbg_resultp);
85 if (args->lstio_dbg_count <= 0 ||
86 args->lstio_dbg_idsp == NULL)
89 rc = lstcon_nodes_debug(args->lstio_dbg_timeout,
90 args->lstio_dbg_count,
92 args->lstio_dbg_resultp);
101 LIBCFS_FREE(name, args->lstio_dbg_nmlen + 1);
107 lst_group_add_ioctl(struct lstio_group_add_args *args)
112 if (args->lstio_grp_key != console_session.ses_key)
115 if (args->lstio_grp_namep == NULL ||
116 args->lstio_grp_nmlen <= 0 ||
117 args->lstio_grp_nmlen > LST_NAME_SIZE)
120 LIBCFS_ALLOC(name, args->lstio_grp_nmlen + 1);
124 if (copy_from_user(name, args->lstio_grp_namep,
125 args->lstio_grp_nmlen)) {
126 LIBCFS_FREE(name, args->lstio_grp_nmlen);
130 name[args->lstio_grp_nmlen] = 0;
132 rc = lstcon_group_add(name);
134 LIBCFS_FREE(name, args->lstio_grp_nmlen + 1);
140 lst_group_del_ioctl(struct lstio_group_del_args *args)
145 if (args->lstio_grp_key != console_session.ses_key)
148 if (args->lstio_grp_namep == NULL ||
149 args->lstio_grp_nmlen <= 0 ||
150 args->lstio_grp_nmlen > LST_NAME_SIZE)
153 LIBCFS_ALLOC(name, args->lstio_grp_nmlen + 1);
157 if (copy_from_user(name, args->lstio_grp_namep,
158 args->lstio_grp_nmlen)) {
159 LIBCFS_FREE(name, args->lstio_grp_nmlen + 1);
163 name[args->lstio_grp_nmlen] = 0;
165 rc = lstcon_group_del(name);
167 LIBCFS_FREE(name, args->lstio_grp_nmlen + 1);
173 lst_group_update_ioctl(struct lstio_group_update_args *args)
178 if (args->lstio_grp_key != console_session.ses_key)
181 if (args->lstio_grp_resultp == NULL ||
182 args->lstio_grp_namep == NULL ||
183 args->lstio_grp_nmlen <= 0 ||
184 args->lstio_grp_nmlen > LST_NAME_SIZE)
187 LIBCFS_ALLOC(name, args->lstio_grp_nmlen + 1);
191 if (copy_from_user(name, args->lstio_grp_namep,
192 args->lstio_grp_nmlen)) {
193 LIBCFS_FREE(name, args->lstio_grp_nmlen + 1);
197 name[args->lstio_grp_nmlen] = 0;
199 switch (args->lstio_grp_opc) {
200 case LST_GROUP_CLEAN:
201 rc = lstcon_group_clean(name, args->lstio_grp_args);
204 case LST_GROUP_REFRESH:
205 rc = lstcon_group_refresh(name, args->lstio_grp_resultp);
209 if (args->lstio_grp_count <= 0 ||
210 args->lstio_grp_idsp == NULL) {
214 rc = lstcon_nodes_remove(name, args->lstio_grp_count,
215 args->lstio_grp_idsp,
216 args->lstio_grp_resultp);
224 LIBCFS_FREE(name, args->lstio_grp_nmlen + 1);
230 lst_nodes_add_ioctl(struct lstio_group_nodes_args *args)
236 if (args->lstio_grp_key != console_session.ses_key)
239 if (args->lstio_grp_idsp == NULL || /* array of ids */
240 args->lstio_grp_count <= 0 ||
241 args->lstio_grp_resultp == NULL ||
242 args->lstio_grp_featp == NULL ||
243 args->lstio_grp_namep == NULL ||
244 args->lstio_grp_nmlen <= 0 ||
245 args->lstio_grp_nmlen > LST_NAME_SIZE)
248 LIBCFS_ALLOC(name, args->lstio_grp_nmlen + 1);
252 if (copy_from_user(name, args->lstio_grp_namep,
253 args->lstio_grp_nmlen)) {
254 LIBCFS_FREE(name, args->lstio_grp_nmlen + 1);
259 name[args->lstio_grp_nmlen] = 0;
261 rc = lstcon_nodes_add(name, args->lstio_grp_count,
262 args->lstio_grp_idsp, &feats,
263 args->lstio_grp_resultp);
265 LIBCFS_FREE(name, args->lstio_grp_nmlen + 1);
267 copy_to_user(args->lstio_grp_featp, &feats, sizeof(feats))) {
275 lst_batch_add_ioctl(struct lstio_batch_add_args *args)
280 if (args->lstio_bat_key != console_session.ses_key)
283 if (args->lstio_bat_namep == NULL ||
284 args->lstio_bat_nmlen <= 0 ||
285 args->lstio_bat_nmlen > LST_NAME_SIZE)
288 LIBCFS_ALLOC(name, args->lstio_bat_nmlen + 1);
292 if (copy_from_user(name, args->lstio_bat_namep,
293 args->lstio_bat_nmlen)) {
294 LIBCFS_FREE(name, args->lstio_bat_nmlen + 1);
298 name[args->lstio_bat_nmlen] = 0;
300 rc = lstcon_batch_add(name);
302 LIBCFS_FREE(name, args->lstio_bat_nmlen + 1);
308 lst_batch_run_ioctl(struct lstio_batch_run_args *args)
313 if (args->lstio_bat_key != console_session.ses_key)
316 if (args->lstio_bat_namep == NULL ||
317 args->lstio_bat_nmlen <= 0 ||
318 args->lstio_bat_nmlen > LST_NAME_SIZE)
321 LIBCFS_ALLOC(name, args->lstio_bat_nmlen + 1);
325 if (copy_from_user(name, args->lstio_bat_namep,
326 args->lstio_bat_nmlen)) {
327 LIBCFS_FREE(name, args->lstio_bat_nmlen + 1);
331 name[args->lstio_bat_nmlen] = 0;
333 rc = lstcon_batch_run(name, args->lstio_bat_timeout,
334 args->lstio_bat_resultp);
336 LIBCFS_FREE(name, args->lstio_bat_nmlen + 1);
342 lst_batch_stop_ioctl(struct lstio_batch_stop_args *args)
347 if (args->lstio_bat_key != console_session.ses_key)
350 if (args->lstio_bat_resultp == NULL ||
351 args->lstio_bat_namep == NULL ||
352 args->lstio_bat_nmlen <= 0 ||
353 args->lstio_bat_nmlen > LST_NAME_SIZE)
356 LIBCFS_ALLOC(name, args->lstio_bat_nmlen + 1);
360 if (copy_from_user(name, args->lstio_bat_namep,
361 args->lstio_bat_nmlen)) {
362 LIBCFS_FREE(name, args->lstio_bat_nmlen + 1);
366 name[args->lstio_bat_nmlen] = 0;
368 rc = lstcon_batch_stop(name, args->lstio_bat_force,
369 args->lstio_bat_resultp);
371 LIBCFS_FREE(name, args->lstio_bat_nmlen + 1);
377 lst_batch_query_ioctl(struct lstio_batch_query_args *args)
382 if (args->lstio_bat_key != console_session.ses_key)
385 if (args->lstio_bat_resultp == NULL ||
386 args->lstio_bat_namep == NULL ||
387 args->lstio_bat_nmlen <= 0 ||
388 args->lstio_bat_nmlen > LST_NAME_SIZE)
391 if (args->lstio_bat_testidx < 0)
394 LIBCFS_ALLOC(name, args->lstio_bat_nmlen + 1);
398 if (copy_from_user(name, args->lstio_bat_namep,
399 args->lstio_bat_nmlen)) {
400 LIBCFS_FREE(name, args->lstio_bat_nmlen + 1);
404 name[args->lstio_bat_nmlen] = 0;
406 rc = lstcon_test_batch_query(name,
407 args->lstio_bat_testidx,
408 args->lstio_bat_client,
409 args->lstio_bat_timeout,
410 args->lstio_bat_resultp);
412 LIBCFS_FREE(name, args->lstio_bat_nmlen + 1);
418 lst_batch_list_ioctl(struct lstio_batch_list_args *args)
420 if (args->lstio_bat_key != console_session.ses_key)
423 if (args->lstio_bat_idx < 0 ||
424 args->lstio_bat_namep == NULL ||
425 args->lstio_bat_nmlen <= 0 ||
426 args->lstio_bat_nmlen > LST_NAME_SIZE)
429 return lstcon_batch_list(args->lstio_bat_idx,
430 args->lstio_bat_nmlen,
431 args->lstio_bat_namep);
435 lst_batch_info_ioctl(struct lstio_batch_info_args *args)
442 if (args->lstio_bat_key != console_session.ses_key)
445 if (args->lstio_bat_namep == NULL || /* batch name */
446 args->lstio_bat_nmlen <= 0 ||
447 args->lstio_bat_nmlen > LST_NAME_SIZE)
450 if (args->lstio_bat_entp == NULL && /* output: batch entry */
451 args->lstio_bat_dentsp == NULL) /* output: node entry */
454 if (args->lstio_bat_dentsp != NULL) { /* have node entry */
455 if (args->lstio_bat_idxp == NULL || /* node index */
456 args->lstio_bat_ndentp == NULL) /* # of node entry */
459 if (copy_from_user(&index, args->lstio_bat_idxp,
461 copy_from_user(&ndent, args->lstio_bat_ndentp,
465 if (ndent <= 0 || index < 0)
469 LIBCFS_ALLOC(name, args->lstio_bat_nmlen + 1);
473 if (copy_from_user(name, args->lstio_bat_namep,
474 args->lstio_bat_nmlen)) {
475 LIBCFS_FREE(name, args->lstio_bat_nmlen + 1);
479 name[args->lstio_bat_nmlen] = 0;
481 rc = lstcon_batch_info(name,
482 args->lstio_bat_entp, args->lstio_bat_server,
483 args->lstio_bat_testidx, &index, &ndent,
484 args->lstio_bat_dentsp);
486 LIBCFS_FREE(name, args->lstio_bat_nmlen + 1);
491 if (args->lstio_bat_dentsp != NULL &&
492 (copy_to_user(args->lstio_bat_idxp, &index, sizeof(index)) ||
493 copy_to_user(args->lstio_bat_ndentp, &ndent, sizeof(ndent))))
500 lst_stat_query_ioctl(struct lstio_stat_args *args)
505 /* TODO: not finished */
506 if (args->lstio_sta_key != console_session.ses_key)
509 if (args->lstio_sta_resultp == NULL)
512 if (args->lstio_sta_idsp != NULL) {
513 if (args->lstio_sta_count <= 0)
516 rc = lstcon_nodes_stat(args->lstio_sta_count,
517 args->lstio_sta_idsp,
518 args->lstio_sta_timeout,
519 args->lstio_sta_resultp);
520 } else if (args->lstio_sta_namep != NULL) {
521 if (args->lstio_sta_nmlen <= 0 ||
522 args->lstio_sta_nmlen > LST_NAME_SIZE)
525 LIBCFS_ALLOC(name, args->lstio_sta_nmlen + 1);
529 rc = copy_from_user(name, args->lstio_sta_namep,
530 args->lstio_sta_nmlen);
532 rc = lstcon_group_stat(name, args->lstio_sta_timeout,
533 args->lstio_sta_resultp);
542 LIBCFS_FREE(name, args->lstio_sta_nmlen + 1);
546 static int lst_test_add_ioctl(struct lstio_test_args *args)
549 char *src_name = NULL;
550 char *dst_name = NULL;
555 if (args->lstio_tes_resultp == NULL ||
556 args->lstio_tes_retp == NULL ||
557 args->lstio_tes_bat_name == NULL || /* no specified batch */
558 args->lstio_tes_bat_nmlen <= 0 ||
559 args->lstio_tes_bat_nmlen > LST_NAME_SIZE ||
560 args->lstio_tes_sgrp_name == NULL || /* no source group */
561 args->lstio_tes_sgrp_nmlen <= 0 ||
562 args->lstio_tes_sgrp_nmlen > LST_NAME_SIZE ||
563 args->lstio_tes_dgrp_name == NULL || /* no target group */
564 args->lstio_tes_dgrp_nmlen <= 0 ||
565 args->lstio_tes_dgrp_nmlen > LST_NAME_SIZE)
568 if (args->lstio_tes_loop == 0 || /* negative is infinite */
569 args->lstio_tes_concur <= 0 ||
570 args->lstio_tes_dist <= 0 ||
571 args->lstio_tes_span <= 0)
574 /* have parameter, check if parameter length is valid */
575 if (args->lstio_tes_param != NULL &&
576 (args->lstio_tes_param_len <= 0 ||
577 args->lstio_tes_param_len >
578 PAGE_SIZE - sizeof(struct lstcon_test)))
581 LIBCFS_ALLOC(batch_name, args->lstio_tes_bat_nmlen + 1);
582 if (batch_name == NULL)
585 LIBCFS_ALLOC(src_name, args->lstio_tes_sgrp_nmlen + 1);
586 if (src_name == NULL)
589 LIBCFS_ALLOC(dst_name, args->lstio_tes_dgrp_nmlen + 1);
590 if (dst_name == NULL)
593 if (args->lstio_tes_param != NULL) {
594 LIBCFS_ALLOC(param, args->lstio_tes_param_len);
597 if (copy_from_user(param, args->lstio_tes_param,
598 args->lstio_tes_param_len)) {
605 if (copy_from_user(batch_name, args->lstio_tes_bat_name,
606 args->lstio_tes_bat_nmlen) ||
607 copy_from_user(src_name, args->lstio_tes_sgrp_name,
608 args->lstio_tes_sgrp_nmlen) ||
609 copy_from_user(dst_name, args->lstio_tes_dgrp_name,
610 args->lstio_tes_dgrp_nmlen))
613 rc = lstcon_test_add(batch_name,
614 args->lstio_tes_type,
615 args->lstio_tes_loop,
616 args->lstio_tes_concur,
617 args->lstio_tes_dist, args->lstio_tes_span,
618 src_name, dst_name, param,
619 args->lstio_tes_param_len,
620 &ret, args->lstio_tes_resultp);
623 rc = (copy_to_user(args->lstio_tes_retp, &ret,
624 sizeof(ret))) ? -EFAULT : 0;
626 if (batch_name != NULL)
627 LIBCFS_FREE(batch_name, args->lstio_tes_bat_nmlen + 1);
629 if (src_name != NULL)
630 LIBCFS_FREE(src_name, args->lstio_tes_sgrp_nmlen + 1);
632 if (dst_name != NULL)
633 LIBCFS_FREE(dst_name, args->lstio_tes_dgrp_nmlen + 1);
636 LIBCFS_FREE(param, args->lstio_tes_param_len);
642 lstcon_ioctl_entry(struct notifier_block *nb,
643 unsigned long cmd, void *vdata)
645 struct libcfs_ioctl_hdr *hdr = vdata;
646 struct libcfs_ioctl_data *data;
651 if (cmd != IOC_LIBCFS_LNETST)
654 data = container_of(hdr, struct libcfs_ioctl_data, ioc_hdr);
656 opc = data->ioc_u32[0];
658 if (data->ioc_plen1 > PAGE_SIZE)
661 LIBCFS_ALLOC(buf, data->ioc_plen1);
667 /* copy in parameter */
668 if (copy_from_user(buf, data->ioc_pbuf1, data->ioc_plen1)) {
673 mutex_lock(&console_session.ses_mutex);
675 console_session.ses_laststamp = ktime_get_real_seconds();
677 if (console_session.ses_shutdown) {
682 if (console_session.ses_expired)
683 lstcon_session_end();
685 if (opc != LSTIO_SESSION_NEW &&
686 console_session.ses_state == LST_SESSION_NONE) {
687 CDEBUG(D_NET, "LST no active session\n");
692 memset(&console_session.ses_trans_stat, 0,
693 sizeof(struct lstcon_trans_stat));
696 case LSTIO_SESSION_NEW:
698 case LSTIO_SESSION_END:
700 case LSTIO_SESSION_INFO:
704 rc = lst_debug_ioctl((struct lstio_debug_args *)buf);
706 case LSTIO_GROUP_ADD:
707 rc = lst_group_add_ioctl((struct lstio_group_add_args *)buf);
709 case LSTIO_GROUP_DEL:
710 rc = lst_group_del_ioctl((struct lstio_group_del_args *)buf);
712 case LSTIO_GROUP_UPDATE:
713 rc = lst_group_update_ioctl((struct lstio_group_update_args *)buf);
715 case LSTIO_NODES_ADD:
716 rc = lst_nodes_add_ioctl((struct lstio_group_nodes_args *)buf);
718 case LSTIO_GROUP_LIST:
720 case LSTIO_GROUP_INFO:
723 case LSTIO_BATCH_ADD:
724 rc = lst_batch_add_ioctl((struct lstio_batch_add_args *)buf);
726 case LSTIO_BATCH_START:
727 rc = lst_batch_run_ioctl((struct lstio_batch_run_args *)buf);
729 case LSTIO_BATCH_STOP:
730 rc = lst_batch_stop_ioctl((struct lstio_batch_stop_args *)buf);
732 case LSTIO_BATCH_QUERY:
733 rc = lst_batch_query_ioctl((struct lstio_batch_query_args *)buf);
735 case LSTIO_BATCH_LIST:
736 rc = lst_batch_list_ioctl((struct lstio_batch_list_args *)buf);
738 case LSTIO_BATCH_INFO:
739 rc = lst_batch_info_ioctl((struct lstio_batch_info_args *)buf);
742 rc = lst_test_add_ioctl((struct lstio_test_args *)buf);
744 case LSTIO_STAT_QUERY:
745 rc = lst_stat_query_ioctl((struct lstio_stat_args *)buf);
752 if (copy_to_user(data->ioc_pbuf2, &console_session.ses_trans_stat,
753 sizeof(struct lstcon_trans_stat)))
756 mutex_unlock(&console_session.ses_mutex);
758 LIBCFS_FREE(buf, data->ioc_plen1);
760 return notifier_from_ioctl_errno(rc);
763 static struct genl_family lst_family;
765 static const struct ln_key_list lst_session_keys = {
766 .lkl_maxattr = LNET_SELFTEST_SESSION_MAX,
768 [LNET_SELFTEST_SESSION_HDR] = {
769 .lkp_value = "session",
770 .lkp_key_format = LNKF_MAPPING,
771 .lkp_data_type = NLA_NUL_STRING,
773 [LNET_SELFTEST_SESSION_NAME] = {
775 .lkp_data_type = NLA_STRING,
777 [LNET_SELFTEST_SESSION_KEY] = {
779 .lkp_data_type = NLA_U32,
781 [LNET_SELFTEST_SESSION_TIMESTAMP] = {
782 .lkp_value = "timestamp",
783 .lkp_data_type = NLA_S64,
785 [LNET_SELFTEST_SESSION_NID] = {
787 .lkp_data_type = NLA_STRING,
789 [LNET_SELFTEST_SESSION_NODE_COUNT] = {
790 .lkp_value = "nodes",
791 .lkp_data_type = NLA_U16,
796 static int lst_sessions_show_dump(struct sk_buff *msg,
797 struct netlink_callback *cb)
799 const struct ln_key_list *all[] = {
800 &lst_session_keys, NULL
802 #ifdef HAVE_NL_PARSE_WITH_EXT_ACK
803 struct netlink_ext_ack *extack = NULL;
805 int portid = NETLINK_CB(cb->skb).portid;
806 int seq = cb->nlh->nlmsg_seq;
807 unsigned int node_count = 0;
808 struct lstcon_ndlink *ndl;
809 int flag = NLM_F_MULTI;
813 #ifdef HAVE_NL_DUMP_WITH_EXT_ACK
816 if (console_session.ses_state != LST_SESSION_ACTIVE) {
817 NL_SET_ERR_MSG(extack, "session is not active");
818 GOTO(out_unlock, rc = -ESRCH);
821 list_for_each_entry(ndl, &console_session.ses_ndl_list, ndl_link)
824 rc = lnet_genl_send_scalar_list(msg, portid, seq, &lst_family,
825 NLM_F_CREATE | NLM_F_MULTI,
826 LNET_SELFTEST_CMD_SESSIONS, all);
828 NL_SET_ERR_MSG(extack, "failed to send key table");
829 GOTO(out_unlock, rc);
832 if (console_session.ses_force)
833 flag |= NLM_F_REPLACE;
835 hdr = genlmsg_put(msg, portid, seq, &lst_family, flag,
836 LNET_SELFTEST_CMD_SESSIONS);
838 NL_SET_ERR_MSG(extack, "failed to send values");
839 genlmsg_cancel(msg, hdr);
840 GOTO(out_unlock, rc = -EMSGSIZE);
843 nla_put_string(msg, LNET_SELFTEST_SESSION_NAME,
844 console_session.ses_name);
845 nla_put_u32(msg, LNET_SELFTEST_SESSION_KEY,
846 console_session.ses_key);
847 nla_put_u64_64bit(msg, LNET_SELFTEST_SESSION_TIMESTAMP,
848 console_session.ses_id.ses_stamp,
849 LNET_SELFTEST_SESSION_PAD);
850 nla_put_string(msg, LNET_SELFTEST_SESSION_NID,
851 libcfs_nidstr(&console_session.ses_id.ses_nid));
852 nla_put_u16(msg, LNET_SELFTEST_SESSION_NODE_COUNT,
854 genlmsg_end(msg, hdr);
856 return lnet_nl_send_error(cb->skb, portid, seq, rc);
859 static int lst_sessions_cmd(struct sk_buff *skb, struct genl_info *info)
861 struct sk_buff *msg = NULL;
864 mutex_lock(&console_session.ses_mutex);
866 console_session.ses_laststamp = ktime_get_real_seconds();
868 if (console_session.ses_shutdown) {
869 GENL_SET_ERR_MSG(info, "session is shutdown");
870 GOTO(out_unlock, rc = -ESHUTDOWN);
873 if (console_session.ses_expired)
874 lstcon_session_end();
876 if (!(info->nlhdr->nlmsg_flags & NLM_F_CREATE) &&
877 console_session.ses_state == LST_SESSION_NONE) {
878 GENL_SET_ERR_MSG(info, "session is not active");
879 GOTO(out_unlock, rc = -ESRCH);
882 memset(&console_session.ses_trans_stat, 0,
883 sizeof(struct lstcon_trans_stat));
885 if (!(info->nlhdr->nlmsg_flags & NLM_F_CREATE)) {
886 lstcon_session_end();
887 GOTO(out_unlock, rc);
890 if (info->attrs[LN_SCALAR_ATTR_LIST]) {
891 struct genlmsghdr *gnlh = nlmsg_data(info->nlhdr);
892 const struct ln_key_list *all[] = {
893 &lst_session_keys, NULL
895 char name[LST_NAME_SIZE];
896 struct nlmsghdr *nlh;
903 if (info->nlhdr->nlmsg_flags & NLM_F_REPLACE)
906 nla_for_each_nested(item, info->attrs[LN_SCALAR_ATTR_LIST],
908 if (nla_type(item) != LN_SCALAR_ATTR_VALUE)
911 if (nla_strcmp(item, "name") == 0) {
914 item = nla_next(item, &rem);
915 if (nla_type(item) != LN_SCALAR_ATTR_VALUE)
916 GOTO(err_conf, rc = -EINVAL);
918 len = nla_strscpy(name, item, sizeof(name));
921 } else if (nla_strcmp(item, "timeout") == 0) {
922 item = nla_next(item, &rem);
923 if (nla_type(item) !=
924 LN_SCALAR_ATTR_INT_VALUE)
925 GOTO(err_conf, rc = -EINVAL);
927 timeout = nla_get_s64(item);
933 GENL_SET_ERR_MSG(info,
934 "failed to get config");
935 GOTO(out_unlock, rc);
939 rc = lstcon_session_new(name, info->nlhdr->nlmsg_pid,
940 gnlh->version, timeout,
943 GENL_SET_ERR_MSG(info, "new session creation failed");
944 lstcon_session_end();
945 GOTO(out_unlock, rc);
948 msg = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_KERNEL);
950 GENL_SET_ERR_MSG(info, "msg allocation failed");
951 GOTO(out_unlock, rc = -ENOMEM);
954 rc = lnet_genl_send_scalar_list(msg, info->snd_portid,
955 info->snd_seq, &lst_family,
956 NLM_F_CREATE | NLM_F_MULTI,
957 LNET_SELFTEST_CMD_SESSIONS,
960 GENL_SET_ERR_MSG(info, "failed to send key table");
961 GOTO(out_unlock, rc);
964 hdr = genlmsg_put(msg, info->snd_portid, info->snd_seq,
965 &lst_family, NLM_F_MULTI,
966 LNET_SELFTEST_CMD_SESSIONS);
968 GENL_SET_ERR_MSG(info, "failed to send values");
969 genlmsg_cancel(msg, hdr);
970 GOTO(out_unlock, rc = -EMSGSIZE);
973 nla_put_string(msg, LNET_SELFTEST_SESSION_NAME,
974 console_session.ses_name);
975 nla_put_u32(msg, LNET_SELFTEST_SESSION_KEY,
976 console_session.ses_key);
977 nla_put_u64_64bit(msg, LNET_SELFTEST_SESSION_TIMESTAMP,
978 console_session.ses_id.ses_stamp,
979 LNET_SELFTEST_SESSION_PAD);
980 nla_put_string(msg, LNET_SELFTEST_SESSION_NID,
981 libcfs_nidstr(&console_session.ses_id.ses_nid));
982 nla_put_u16(msg, LNET_SELFTEST_SESSION_NODE_COUNT, 0);
984 genlmsg_end(msg, hdr);
986 nlh = nlmsg_put(msg, info->snd_portid, info->snd_seq,
987 NLMSG_DONE, 0, NLM_F_MULTI);
989 GENL_SET_ERR_MSG(info, "failed to complete message");
990 genlmsg_cancel(msg, hdr);
991 GOTO(out_unlock, rc = -ENOMEM);
993 rc = genlmsg_reply(msg, info);
995 GENL_SET_ERR_MSG(info, "failed to send reply");
1000 mutex_unlock(&console_session.ses_mutex);
1004 static char *lst_node_state2str(int state)
1006 if (state == LST_NODE_ACTIVE)
1008 if (state == LST_NODE_BUSY)
1010 if (state == LST_NODE_DOWN)
1016 static int lst_node_str2state(char *str)
1020 if (strcasecmp(str, "Active") == 0)
1021 state = LST_NODE_ACTIVE;
1022 else if (strcasecmp(str, "Busy") == 0)
1023 state = LST_NODE_BUSY;
1024 else if (strcasecmp(str, "Down") == 0)
1025 state = LST_NODE_DOWN;
1026 else if (strcasecmp(str, "Unknown") == 0)
1027 state = LST_NODE_UNKNOWN;
1028 else if (strcasecmp(str, "Invalid") == 0)
1029 state = LST_NODE_UNKNOWN | LST_NODE_DOWN | LST_NODE_BUSY;
1033 struct lst_genl_group_prop {
1034 struct lstcon_group *lggp_grp;
1035 int lggp_state_filter;
1038 struct lst_genl_group_list {
1039 GENRADIX(struct lst_genl_group_prop) lggl_groups;
1040 unsigned int lggl_count;
1041 unsigned int lggl_index;
1045 static inline struct lst_genl_group_list *
1046 lst_group_dump_ctx(struct netlink_callback *cb)
1048 return (struct lst_genl_group_list *)cb->args[0];
1051 static int lst_groups_show_done(struct netlink_callback *cb)
1053 struct lst_genl_group_list *glist = lst_group_dump_ctx(cb);
1058 for (i = 0; i < glist->lggl_count; i++) {
1059 struct lst_genl_group_prop *prop;
1061 prop = genradix_ptr(&glist->lggl_groups, i);
1062 if (!prop || !prop->lggp_grp)
1064 lstcon_group_decref(prop->lggp_grp);
1066 genradix_free(&glist->lggl_groups);
1067 LIBCFS_FREE(glist, sizeof(*glist));
1074 /* LNet selftest groups ->start() handler for GET requests */
1075 static int lst_groups_show_start(struct netlink_callback *cb)
1077 struct genlmsghdr *gnlh = nlmsg_data(cb->nlh);
1078 #ifdef HAVE_NL_PARSE_WITH_EXT_ACK
1079 struct netlink_ext_ack *extack = NULL;
1081 struct nlattr *params = genlmsg_data(gnlh);
1082 struct lst_genl_group_list *glist;
1083 int msg_len = genlmsg_len(gnlh);
1084 struct lstcon_group *grp;
1085 struct nlattr *groups;
1088 LIBCFS_ALLOC(glist, sizeof(*glist));
1092 genradix_init(&glist->lggl_groups);
1093 cb->args[0] = (long)glist;
1096 list_for_each_entry(grp, &console_session.ses_grp_list,
1098 struct lst_genl_group_prop *prop;
1100 prop = genradix_ptr_alloc(&glist->lggl_groups,
1101 glist->lggl_count++,
1104 NL_SET_ERR_MSG(extack,
1105 "failed to allocate group info");
1106 GOTO(report_err, rc = -ENOMEM);
1108 lstcon_group_addref(grp); /* +1 ref for caller */
1109 prop->lggp_grp = grp;
1112 if (!glist->lggl_count) {
1113 NL_SET_ERR_MSG(extack, "No groups found");
1116 GOTO(report_err, rc);
1118 glist->lggl_verbose = true;
1119 #ifdef HAVE_NL_DUMP_WITH_EXT_ACK
1120 extack = cb->extack;
1123 if (!(nla_type(params) & LN_SCALAR_ATTR_LIST)) {
1124 NL_SET_ERR_MSG(extack, "no configuration");
1125 GOTO(report_err, rc);
1128 nla_for_each_nested(groups, params, rem) {
1129 struct lst_genl_group_prop *prop = NULL;
1130 struct nlattr *group;
1133 if (nla_type(groups) != LN_SCALAR_ATTR_LIST)
1136 nla_for_each_nested(group, groups, rem2) {
1137 if (nla_type(group) == LN_SCALAR_ATTR_VALUE) {
1138 char name[LST_NAME_SIZE];
1140 prop = genradix_ptr_alloc(&glist->lggl_groups,
1141 glist->lggl_count++,
1144 NL_SET_ERR_MSG(extack,
1145 "failed to allocate group info");
1146 GOTO(report_err, rc = -ENOMEM);
1149 rc = nla_strscpy(name, group, sizeof(name));
1151 NL_SET_ERR_MSG(extack,
1152 "failed to get name");
1153 GOTO(report_err, rc);
1155 rc = lstcon_group_find(name, &prop->lggp_grp);
1157 /* don't stop reporting groups if one
1160 CWARN("LNet selftest group %s does not exit\n",
1164 } else if (nla_type(group) == LN_SCALAR_ATTR_LIST) {
1165 struct nlattr *attr;
1169 NL_SET_ERR_MSG(extack,
1170 "missing group information");
1171 GOTO(report_err, rc = -EINVAL);
1174 nla_for_each_nested(attr, group, rem3) {
1177 if (nla_type(attr) != LN_SCALAR_ATTR_VALUE ||
1178 nla_strcmp(attr, "status") != 0)
1181 attr = nla_next(attr, &rem3);
1182 if (nla_type(attr) !=
1183 LN_SCALAR_ATTR_VALUE) {
1184 NL_SET_ERR_MSG(extack,
1185 "invalid config param");
1186 GOTO(report_err, rc = -EINVAL);
1189 rc = nla_strscpy(tmp, attr, sizeof(tmp));
1191 NL_SET_ERR_MSG(extack,
1192 "failed to get prop attr");
1193 GOTO(report_err, rc);
1196 prop->lggp_state_filter |=
1197 lst_node_str2state(tmp);
1202 if (!glist->lggl_count) {
1203 NL_SET_ERR_MSG(extack, "No groups found");
1208 lst_groups_show_done(cb);
1213 static const struct ln_key_list lst_group_keys = {
1214 .lkl_maxattr = LNET_SELFTEST_GROUP_MAX,
1216 [LNET_SELFTEST_GROUP_ATTR_HDR] = {
1217 .lkp_value = "groups",
1218 .lkp_key_format = LNKF_SEQUENCE,
1219 .lkp_data_type = NLA_NUL_STRING,
1221 [LNET_SELFTEST_GROUP_ATTR_NAME] = {
1222 .lkp_data_type = NLA_STRING,
1224 [LNET_SELFTEST_GROUP_ATTR_NODELIST] = {
1225 .lkp_key_format = LNKF_MAPPING | LNKF_SEQUENCE,
1226 .lkp_data_type = NLA_NESTED,
1231 static const struct ln_key_list lst_group_nodelist_keys = {
1232 .lkl_maxattr = LNET_SELFTEST_GROUP_NODELIST_PROP_MAX,
1234 [LNET_SELFTEST_GROUP_NODELIST_PROP_ATTR_NID] = {
1236 .lkp_data_type = NLA_STRING,
1238 [LNET_SELFTEST_GROUP_NODELIST_PROP_ATTR_STATUS] = {
1239 .lkp_value = "status",
1240 .lkp_data_type = NLA_STRING,
1245 static int lst_groups_show_dump(struct sk_buff *msg,
1246 struct netlink_callback *cb)
1248 struct lst_genl_group_list *glist = lst_group_dump_ctx(cb);
1249 #ifdef HAVE_NL_PARSE_WITH_EXT_ACK
1250 struct netlink_ext_ack *extack = NULL;
1252 int portid = NETLINK_CB(cb->skb).portid;
1253 int seq = cb->nlh->nlmsg_seq;
1254 int idx = 0, rc = 0;
1256 #ifdef HAVE_NL_DUMP_WITH_EXT_ACK
1257 extack = cb->extack;
1259 if (!glist->lggl_index) {
1260 const struct ln_key_list *all[] = {
1261 &lst_group_keys, &lst_group_nodelist_keys, NULL
1264 rc = lnet_genl_send_scalar_list(msg, portid, seq, &lst_family,
1265 NLM_F_CREATE | NLM_F_MULTI,
1266 LNET_SELFTEST_CMD_GROUPS, all);
1268 NL_SET_ERR_MSG(extack, "failed to send key table");
1269 GOTO(send_error, rc);
1273 for (idx = glist->lggl_index; idx < glist->lggl_count; idx++) {
1274 struct lst_genl_group_prop *group;
1275 struct lstcon_ndlink *ndl;
1276 struct nlattr *nodelist;
1277 unsigned int count = 1;
1280 group = genradix_ptr(&glist->lggl_groups, idx);
1284 hdr = genlmsg_put(msg, portid, seq, &lst_family,
1285 NLM_F_MULTI, LNET_SELFTEST_CMD_GROUPS);
1287 NL_SET_ERR_MSG(extack, "failed to send values");
1288 GOTO(send_error, rc = -EMSGSIZE);
1292 nla_put_string(msg, LNET_SELFTEST_GROUP_ATTR_HDR, "");
1294 nla_put_string(msg, LNET_SELFTEST_GROUP_ATTR_NAME,
1295 group->lggp_grp->grp_name);
1297 if (!glist->lggl_verbose)
1300 nodelist = nla_nest_start(msg,
1301 LNET_SELFTEST_GROUP_ATTR_NODELIST);
1302 list_for_each_entry(ndl, &group->lggp_grp->grp_ndl_list,
1304 struct nlattr *node = nla_nest_start(msg, count);
1307 if (group->lggp_state_filter &&
1308 !(group->lggp_state_filter & ndl->ndl_node->nd_state))
1312 LNET_SELFTEST_GROUP_NODELIST_PROP_ATTR_NID,
1313 libcfs_id2str(ndl->ndl_node->nd_id));
1315 ndstate = lst_node_state2str(ndl->ndl_node->nd_state);
1317 LNET_SELFTEST_GROUP_NODELIST_PROP_ATTR_STATUS,
1319 nla_nest_end(msg, node);
1321 nla_nest_end(msg, nodelist);
1323 genlmsg_end(msg, hdr);
1325 glist->lggl_index = idx;
1327 return lnet_nl_send_error(cb->skb, portid, seq, rc);
1330 #ifndef HAVE_NETLINK_CALLBACK_START
1331 static int lst_old_groups_show_dump(struct sk_buff *msg,
1332 struct netlink_callback *cb)
1335 int rc = lst_groups_show_start(cb);
1338 return lnet_nl_send_error(cb->skb,
1339 NETLINK_CB(cb->skb).portid,
1344 return lst_groups_show_dump(msg, cb);
1348 static const struct genl_multicast_group lst_mcast_grps[] = {
1349 { .name = "sessions", },
1350 { .name = "groups", },
1353 static const struct genl_ops lst_genl_ops[] = {
1355 .cmd = LNET_SELFTEST_CMD_SESSIONS,
1356 .dumpit = lst_sessions_show_dump,
1357 .doit = lst_sessions_cmd,
1360 .cmd = LNET_SELFTEST_CMD_GROUPS,
1361 #ifdef HAVE_NETLINK_CALLBACK_START
1362 .start = lst_groups_show_start,
1363 .dumpit = lst_groups_show_dump,
1365 .dumpit = lst_old_groups_show_dump,
1367 .done = lst_groups_show_done,
1371 static struct genl_family lst_family = {
1372 .name = LNET_SELFTEST_GENL_NAME,
1373 .version = LNET_SELFTEST_GENL_VERSION,
1374 .maxattr = LN_SCALAR_MAX,
1375 .module = THIS_MODULE,
1376 .ops = lst_genl_ops,
1377 .n_ops = ARRAY_SIZE(lst_genl_ops),
1378 .mcgrps = lst_mcast_grps,
1379 .n_mcgrps = ARRAY_SIZE(lst_mcast_grps),
1380 #ifdef GENL_FAMILY_HAS_RESV_START_OP
1381 .resv_start_op = __LNET_SELFTEST_CMD_MAX_PLUS_ONE,
1385 int lstcon_init_netlink(void)
1387 return genl_register_family(&lst_family);
1390 void lstcon_fini_netlink(void)
1392 genl_unregister_family(&lst_family);