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) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Use is subject to license terms.
26 * Copyright (c) 2011, 2016, Intel Corporation.
29 * This file is part of Lustre, http://www.lustre.org/
31 * lustre/utils/lustre_cfg.c
33 * Author: Peter J. Braam <braam@clusterfs.com>
34 * Author: Phil Schwan <phil@clusterfs.com>
35 * Author: Andreas Dilger <adilger@clusterfs.com>
36 * Author: Robert Read <rread@clusterfs.com>
46 #include <sys/ioctl.h>
53 #include <libcfs/util/ioctl.h>
54 #include <libcfs/util/string.h>
55 #include <libcfs/util/param.h>
56 #include <libcfs/util/parser.h>
57 #include <lustre/lustreapi.h>
58 #include <linux/lnet/nidstr.h>
59 #include <linux/lnet/lnetctl.h>
60 #include <linux/lustre/lustre_cfg.h>
61 #include <linux/lustre/lustre_ioctl.h>
62 #include <linux/lustre/lustre_ver.h>
64 #include <linux/lustre/lustre_kernelcomm.h>
65 #include <lnetconfig/liblnetconfig.h>
66 #include "lustreapi_internal.h"
78 static char *lcfg_devname;
80 int lcfg_set_devname(char *name)
88 /* quietly strip the unnecessary '$' */
89 if (*name == '$' || *name == '%')
93 while (*ptr != '\0') {
102 /* We can't translate from dev # to name */
105 lcfg_devname = strdup(name);
113 char *lcfg_get_devname(void)
118 int jt_lcfg_device(int argc, char **argv)
120 return jt_obd_device(argc, argv);
123 static int jt_lcfg_ioctl(struct lustre_cfg_bufs *bufs, char *arg, int cmd)
125 struct lustre_cfg *lcfg;
128 lcfg = malloc(lustre_cfg_len(bufs->lcfg_bufcount, bufs->lcfg_buflen));
132 lustre_cfg_init(lcfg, cmd, bufs);
133 rc = lcfg_ioctl(arg, OBD_DEV_ID, lcfg);
137 fprintf(stderr, "error: %s: %s\n", jt_cmdname(arg),
138 strerror(rc = errno));
142 int jt_lcfg_attach(int argc, char **argv)
144 struct lustre_cfg_bufs bufs;
150 lustre_cfg_bufs_reset(&bufs, NULL);
152 lustre_cfg_bufs_set_string(&bufs, 1, argv[1]);
153 lustre_cfg_bufs_set_string(&bufs, 0, argv[2]);
154 lustre_cfg_bufs_set_string(&bufs, 2, argv[3]);
156 rc = jt_lcfg_ioctl(&bufs, argv[0], LCFG_ATTACH);
158 lcfg_set_devname(argv[2]);
163 int jt_lcfg_setup(int argc, char **argv)
165 struct lustre_cfg_bufs bufs;
170 "%s: please use 'device name' to set the device name for config commands.\n",
171 jt_cmdname(argv[0]));
175 lustre_cfg_bufs_reset(&bufs, lcfg_devname);
180 for (i = 1; i < argc; i++)
181 lustre_cfg_bufs_set_string(&bufs, i, argv[i]);
183 return jt_lcfg_ioctl(&bufs, argv[0], LCFG_SETUP);
186 int jt_obd_detach(int argc, char **argv)
188 struct lustre_cfg_bufs bufs;
192 "%s: please use 'device name' to set the device name for config commands.\n",
193 jt_cmdname(argv[0]));
197 lustre_cfg_bufs_reset(&bufs, lcfg_devname);
202 return jt_lcfg_ioctl(&bufs, argv[0], LCFG_DETACH);
205 int jt_obd_cleanup(int argc, char **argv)
207 struct lustre_cfg_bufs bufs;
210 char flags[3] = { 0 };
215 "%s: please use 'device name' to set the device name for config commands.\n",
216 jt_cmdname(argv[0]));
220 lustre_cfg_bufs_reset(&bufs, lcfg_devname);
222 if (argc < 1 || argc > 3)
226 * we are protected from overflowing our buffer by the argc
229 for (n = 1; n < argc; n++) {
230 if (strcmp(argv[n], "force") == 0) {
231 flags[flag_cnt++] = force;
232 } else if (strcmp(argv[n], "failover") == 0) {
233 flags[flag_cnt++] = failover;
235 fprintf(stderr, "unknown option: %s\n", argv[n]);
241 lustre_cfg_bufs_set_string(&bufs, 1, flags);
243 return jt_lcfg_ioctl(&bufs, argv[0], LCFG_CLEANUP);
247 int do_add_uuid(char *func, char *uuid, lnet_nid_t nid)
250 struct lustre_cfg_bufs bufs;
251 struct lustre_cfg *lcfg;
253 lustre_cfg_bufs_reset(&bufs, lcfg_devname);
255 lustre_cfg_bufs_set_string(&bufs, 1, uuid);
257 lcfg = malloc(lustre_cfg_len(bufs.lcfg_bufcount, bufs.lcfg_buflen));
261 lustre_cfg_init(lcfg, LCFG_ADD_UUID, &bufs);
262 lcfg->lcfg_nid = nid;
264 rc = lcfg_ioctl(func, OBD_DEV_ID, lcfg);
268 fprintf(stderr, "IOC_PORTAL_ADD_UUID failed: %s\n",
274 printf("Added uuid %s: %s\n", uuid, libcfs_nid2str(nid));
279 int jt_lcfg_add_uuid(int argc, char **argv)
286 nid = libcfs_str2nid(argv[2]);
287 if (nid == LNET_NID_ANY) {
288 fprintf(stderr, "Can't parse NID %s\n", argv[2]);
292 return do_add_uuid(argv[0], argv[1], nid);
295 int jt_lcfg_del_uuid(int argc, char **argv)
297 struct lustre_cfg_bufs bufs;
300 fprintf(stderr, "usage: %s <uuid>\n", argv[0]);
304 lustre_cfg_bufs_reset(&bufs, lcfg_devname);
305 if (strcmp(argv[1], "_all_"))
306 lustre_cfg_bufs_set_string(&bufs, 1, argv[1]);
308 return jt_lcfg_ioctl(&bufs, argv[0], LCFG_DEL_UUID);
311 int jt_lcfg_del_mount_option(int argc, char **argv)
313 struct lustre_cfg_bufs bufs;
318 lustre_cfg_bufs_reset(&bufs, lcfg_devname);
321 lustre_cfg_bufs_set_string(&bufs, 1, argv[1]);
323 return jt_lcfg_ioctl(&bufs, argv[0], LCFG_DEL_MOUNTOPT);
326 int jt_lcfg_set_timeout(int argc, char **argv)
329 struct lustre_cfg_bufs bufs;
330 struct lustre_cfg *lcfg;
333 "%s has been deprecated. Use conf_param instead.\ne.g. conf_param lustre-MDT0000 obd_timeout=50\n",
334 jt_cmdname(argv[0]));
340 lustre_cfg_bufs_reset(&bufs, lcfg_devname);
342 lcfg = malloc(lustre_cfg_len(bufs.lcfg_bufcount, bufs.lcfg_buflen));
346 lustre_cfg_init(lcfg, LCFG_SET_TIMEOUT, &bufs);
347 lcfg->lcfg_num = atoi(argv[1]);
349 rc = lcfg_ioctl(argv[0], OBD_DEV_ID, lcfg);
353 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
354 strerror(rc = errno));
359 int jt_lcfg_add_conn(int argc, char **argv)
361 struct lustre_cfg_bufs bufs;
362 struct lustre_cfg *lcfg;
375 "%s: please use 'device name' to set the device name for config commands.\n",
376 jt_cmdname(argv[0]));
380 lustre_cfg_bufs_reset(&bufs, lcfg_devname);
382 lustre_cfg_bufs_set_string(&bufs, 1, argv[1]);
384 lcfg = malloc(lustre_cfg_len(bufs.lcfg_bufcount, bufs.lcfg_buflen));
388 lustre_cfg_init(lcfg, LCFG_ADD_CONN, &bufs);
389 lcfg->lcfg_num = priority;
391 rc = lcfg_ioctl(argv[0], OBD_DEV_ID, lcfg);
395 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
396 strerror(rc = errno));
402 int jt_lcfg_del_conn(int argc, char **argv)
404 struct lustre_cfg_bufs bufs;
411 "%s: please use 'device name' to set the device name for config commands.\n",
412 jt_cmdname(argv[0]));
416 lustre_cfg_bufs_reset(&bufs, lcfg_devname);
418 /* connection uuid */
419 lustre_cfg_bufs_set_string(&bufs, 1, argv[1]);
421 return jt_lcfg_ioctl(&bufs, argv[0], LCFG_DEL_MOUNTOPT);
424 /* Param set locally, directly on target */
425 int jt_lcfg_param(int argc, char **argv)
427 struct lustre_cfg_bufs bufs;
430 if (argc >= LUSTRE_CFG_MAX_BUFCOUNT)
433 lustre_cfg_bufs_reset(&bufs, NULL);
435 for (i = 1; i < argc; i++)
436 lustre_cfg_bufs_set_string(&bufs, i, argv[i]);
438 return jt_lcfg_ioctl(&bufs, argv[0], LCFG_PARAM);
442 unsigned int po_only_path:1;
443 unsigned int po_show_path:1;
444 unsigned int po_show_type:1;
445 unsigned int po_recursive:1;
446 unsigned int po_perm:1;
447 unsigned int po_delete:1;
448 unsigned int po_only_dir:1;
449 unsigned int po_file:1;
450 unsigned int po_yaml:1;
451 unsigned int po_detail:1;
454 int lcfg_setparam_perm(char *func, char *buf)
457 struct lustre_cfg_bufs bufs;
458 struct lustre_cfg *lcfg;
460 lustre_cfg_bufs_reset(&bufs, NULL);
462 * This same command would be executed on all nodes, many
463 * of which should fail (silently) because they don't have
464 * that proc file existing locally. There would be no
465 * preprocessing on the MGS to try to figure out which
466 * parameter files to add this to, there would be nodes
467 * processing on the cluster nodes to try to figure out
468 * if they are the intended targets. They will blindly
469 * try to set the parameter, and ENOTFOUND means it wasn't
471 * Target name "general" means call on all targets. It is
472 * left here in case some filtering will be added in
475 lustre_cfg_bufs_set_string(&bufs, 0, "general");
477 lustre_cfg_bufs_set_string(&bufs, 1, buf);
479 lcfg = malloc(lustre_cfg_len(bufs.lcfg_bufcount,
483 fprintf(stderr, "error: allocating lcfg for %s: %s\n",
484 jt_cmdname(func), strerror(rc));
487 lustre_cfg_init(lcfg, LCFG_SET_PARAM, &bufs);
488 rc = lcfg_mgs_ioctl(func, OBD_DEV_ID, lcfg);
490 fprintf(stderr, "error: executing %s: %s\n",
491 jt_cmdname(func), strerror(errno));
499 * Param set to single log file, used by all clients and servers.
500 * This should be loaded after the individual config logs.
501 * Called from set param with -P option.
503 static int jt_lcfg_setparam_perm(int argc, char **argv,
504 struct param_opts *popt)
511 first_param = optind;
512 if (first_param < 0 || first_param >= argc)
515 for (i = first_param, rc = 0; i < argc; i++) {
517 if (popt->po_delete) {
522 /* Consider param ends at the first '=' in the buffer
523 * and make sure it always ends with '=' as well
525 end_pos = memchr(buf, '=', len - 1);
528 } else if (buf[len - 1] != '=') {
529 buf = malloc(len + 2);
532 sprintf(buf, "%s=", argv[i]);
536 rc = lcfg_setparam_perm(argv[0], buf);
544 int lcfg_conf_param(char *func, char *buf)
547 struct lustre_cfg_bufs bufs;
548 struct lustre_cfg *lcfg;
550 lustre_cfg_bufs_reset(&bufs, NULL);
551 lustre_cfg_bufs_set_string(&bufs, 1, buf);
553 /* We could put other opcodes here. */
554 lcfg = malloc(lustre_cfg_len(bufs.lcfg_bufcount, bufs.lcfg_buflen));
558 lustre_cfg_init(lcfg, LCFG_PARAM, &bufs);
559 rc = lcfg_mgs_ioctl(func, OBD_DEV_ID, lcfg);
569 * Param set in config log on MGS
570 * conf_param key=value
572 * Note we can actually send mgc conf_params from clients, but currently
573 * that's only done for default file striping (see ll_send_mgc_param),
576 * After removal of a parameter (-d) Lustre will use the default
577 * AT NEXT REBOOT, not immediately.
579 int jt_lcfg_confparam(int argc, char **argv)
585 /* mgs_setparam processes only lctl buf #1 */
586 if ((argc > 3) || (argc <= 1))
589 while ((rc = getopt(argc, argv, "d")) != -1) {
604 /* for delete, make it "<param>=\0" */
605 buf = malloc(strlen(argv[optind]) + 2);
610 /* put an '=' on the end in case it doesn't have one */
611 sprintf(buf, "%s=", argv[optind]);
612 /* then truncate after the first '=' */
613 ptr = strchr(buf, '=');
617 rc = lcfg_conf_param(argv[0], buf);
619 if (buf != argv[optind])
623 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
631 * Display a parameter path in the same format as sysctl.
632 * E.g. obdfilter.lustre-OST0000.stats
634 * \param[in] filename file name of the parameter
635 * \param[in] st parameter file stats
636 * \param[in] popt set/get param options
638 * \retval allocated pointer containing modified filename
641 display_name(const char *filename, struct stat *st, struct param_opts *popt)
643 size_t suffix_len = 0;
648 if (popt->po_show_type) {
649 if (S_ISDIR(st->st_mode))
651 else if (S_ISLNK(st->st_mode))
653 else if (st->st_mode & S_IWUSR)
657 /* Take the original filename string and chop off the glob addition */
658 tmp = strstr(filename, "/lustre/");
660 tmp = strstr(filename, "/lnet/");
662 tmp += strlen("/lnet/");
664 tmp += strlen("/lustre/");
667 /* Allocate return string */
668 param_name = strdup(tmp);
672 /* replace '/' with '.' to match conf_param and sysctl */
673 for (tmp = strchr(param_name, '/'); tmp != NULL; tmp = strchr(tmp, '/'))
676 /* Append the indicator to entries if needed. */
677 if (popt->po_show_type && suffix != NULL) {
678 suffix_len = strlen(suffix);
680 tmp = realloc(param_name, suffix_len + strlen(param_name) + 1);
683 strncat(param_name, suffix,
684 strlen(param_name) + suffix_len);
692 * Turns a lctl parameter string into a procfs/sysfs subdirectory path pattern.
694 * \param[in] popt Used to control parameter usage. For this
695 * function it is used to see if the path has
697 * \param[in,out] path lctl parameter string that is turned into
698 * the subdirectory path pattern that is used
699 * to search the procfs/sysfs tree.
701 * \retval -errno on error.
704 clean_path(struct param_opts *popt, char *path)
706 char *nidstart = NULL;
710 if (popt == NULL || path == NULL || strlen(path) == 0)
713 /* If path contains a suffix we need to remove it */
714 if (popt->po_show_type) {
715 size_t path_end = strlen(path) - 1;
717 tmp = path + path_end;
728 /* get rid of '\', glob doesn't like it */
729 tmp = strrchr(path, '\\');
731 char *tail = path + strlen(path);
733 while (tmp != path) {
735 memmove(tmp, tmp + 1, tail - tmp);
742 /* Does path contain a NID string? Skip '.->/' replacement for it. */
743 tmp = strchr(path, '@');
745 /* First find the NID start. NIDs may have variable (0-4) '.',
746 * so find the common NID prefixes instead of trying to count
747 * the dots. Not great, but there are only two, and faster
748 * than multiple speculative NID parses and bad DNS lookups.
750 if ((tmp = strstr(path, ".exports.")))
751 nidstart = tmp + strlen(".exports.");
752 else if ((tmp = strstr(path, ".MGC")))
755 /* Next, find the end of the NID string. */
757 nidend = strchrnul(strchr(nidstart, '@'), '.');
760 /* replace param '.' with '/' */
761 for (tmp = strchr(path, '.'); tmp != NULL; tmp = strchr(tmp, '.')) {
765 * There exist cases where some of the subdirectories of the
766 * the parameter tree has embedded in its name a NID string.
767 * This means that it is possible that these subdirectories
768 * could have actual '.' in its name. If this is the case we
769 * don't want to blindly replace the '.' with '/', so skip
770 * over the part of the parameter containing the NID.
780 * The application lctl can perform three operations for lustre
781 * tunables. This enum defines those three operations which are
783 * 1) LIST_PARAM - list available tunables
784 * 2) GET_PARAM - report the current setting of a tunable
785 * 3) SET_PARAM - set the tunable to a new value
787 enum parameter_operation {
793 char *parameter_opname[] = {
794 [LIST_PARAM] = "list_param",
795 [GET_PARAM] = "get_param",
796 [SET_PARAM] = "set_param",
800 * Read the value of parameter
802 * \param[in] path full path to the parameter
803 * \param[in] param_name lctl parameter format of the
805 * \param[in] popt set/get param options
807 * \retval 0 on success.
808 * \retval -errno on error.
811 read_param(const char *path, const char *param_name, struct param_opts *popt)
817 rc = llapi_param_get_value(path, &buf, &buflen);
820 "error: read_param: \'%s\': %s\n",
821 path, strerror(-rc));
824 /* don't print anything for empty files */
828 if (popt->po_show_path) {
831 longbuf = memchr(buf, '\n', buflen - 1) ||
832 buflen + strlen(param_name) >= 80;
833 printf("%s=%s", param_name, longbuf ? "\n" : "");
843 * Set a parameter to a specified value
845 * \param[in] path full path to the parameter
846 * \param[in] param_name lctl parameter format of the parameter path
847 * \param[in] popt set/get param options
848 * \param[in] value value to set the parameter to
850 * \retval number of bytes written on success.
851 * \retval -errno on error.
854 write_param(const char *path, const char *param_name, struct param_opts *popt,
863 /* Write the new value to the file */
864 fd = open(path, O_WRONLY);
867 fprintf(stderr, "error: set_param: opening '%s': %s\n",
868 path, strerror(errno));
872 count = write(fd, value, strlen(value));
876 fprintf(stderr, "error: set_param: setting %s=%s: %s\n",
877 path, value, strerror(errno));
879 } else if (count < strlen(value)) { /* Truncate case */
882 "error: set_param: setting %s=%s: wrote only %zd\n",
884 } else if (popt->po_show_path) {
885 printf("%s=%s\n", param_name, value);
892 void print_obd_line(char *s)
894 const char *param = "osc/%s/ost_conn_uuid";
895 char obd_name[MAX_OBD_NAME];
896 char buf[MAX_OBD_NAME];
901 /* obd device type is the first 3 characters of param name */
902 snprintf(buf, sizeof(buf), " %%*d %%*s %.3s %%%zus %%*s %%*d ",
903 param, sizeof(obd_name) - 1);
904 if (sscanf(s, buf, obd_name) == 0)
906 if (cfs_get_param_paths(&path, param, obd_name) != 0)
908 fp = fopen(path.gl_pathv[0], "r");
910 /* need to free path data before retry */
911 cfs_free_param_data(&path);
913 if (param[0] == 'o') { /* failed with osc, try mdc */
914 param = "mdc/%s/mds_conn_uuid";
921 /* should not ignore fgets(3)'s return value */
922 if (!fgets(buf, sizeof(buf), fp)) {
923 fprintf(stderr, "reading from %s: %s", buf, strerror(errno));
929 cfs_free_param_data(&path);
931 /* trim trailing newlines */
932 ptr = strrchr(buf, '\n');
936 ptr = strrchr(s, '\n');
939 printf("%s%s%s\n", s, buf[0] ? " " : "", buf);
942 static int print_out_devices(yaml_parser_t *reply, struct param_opts *popt)
944 char buf[MAX_OBD_NAME], *tmp = NULL;
945 size_t buf_len = sizeof(buf);
950 bzero(buf, sizeof(buf));
953 rc = yaml_parser_parse(reply, &event);
957 if (event.type == YAML_MAPPING_START_EVENT) {
958 size_t len = strlen(buf);
961 /* eat last white space */
968 bzero(buf, sizeof(buf));
972 if (event.type == YAML_SCALAR_EVENT) {
973 char *value = (char *)event.data.scalar.value;
975 if (strcmp(value, "index") == 0) {
976 yaml_event_delete(&event);
977 rc = yaml_parser_parse(reply, &event);
981 value = (char *)event.data.scalar.value;
983 snprintf(tmp, buf_len, "%3s ", value);
988 if (strcmp(value, "status") == 0 ||
989 strcmp(value, "type") == 0 ||
990 strcmp(value, "name") == 0 ||
991 strcmp(value, "uuid") == 0 ||
992 strcmp(value, "refcount") == 0) {
993 yaml_event_delete(&event);
994 rc = yaml_parser_parse(reply, &event);
998 value = (char *)event.data.scalar.value;
1000 snprintf(tmp, buf_len, "%s ", value);
1001 buf_len -= strlen(value) + 1;
1002 tmp += strlen(value) + 1;
1006 done = (event.type == YAML_DOCUMENT_END_EVENT);
1008 size_t len = strlen(buf);
1011 /* eat last white space */
1012 buf[len - 1] = '\0';
1013 if (popt->po_detail)
1014 print_obd_line(buf);
1016 printf("%s\n", buf);
1018 bzero(buf, sizeof(buf));
1021 yaml_event_delete(&event);
1027 int lcfg_param_get_yaml(yaml_parser_t *reply, struct nl_sock *sk, char *pattern)
1029 char source[MAX_OBD_NAME], group[GENL_NAMSIZ + 1];
1030 int version = LUSTRE_GENL_VERSION;
1031 char *family = "lustre", *tmp;
1032 yaml_emitter_t request;
1037 bzero(source, sizeof(source));
1038 tmp = strrchr(pattern, '/');
1040 size_t len = tmp - pattern;
1042 strncpy(group, tmp + 1, GENL_NAMSIZ);
1043 strncpy(source, pattern, len);
1045 /* replace '/' with '.' to match conf_param and sysctl */
1046 for (tmp = strchr(pattern, '/'); tmp != NULL;
1047 tmp = strchr(tmp, '/'))
1050 strncpy(group, pattern, GENL_NAMSIZ);
1053 if (strcmp(group, "devices") == 0)
1054 cmd = LUSTRE_CMD_DEVICES;
1059 /* Setup parser to recieve Netlink packets */
1060 rc = yaml_parser_initialize(reply);
1064 rc = yaml_parser_set_input_netlink(reply, sk, false);
1068 /* Create Netlink emitter to send request to kernel */
1069 yaml_emitter_initialize(&request);
1070 rc = yaml_emitter_set_output_netlink(&request, sk,
1076 yaml_emitter_open(&request);
1078 yaml_document_start_event_initialize(&event, NULL, NULL, NULL, 0);
1079 rc = yaml_emitter_emit(&request, &event);
1083 yaml_mapping_start_event_initialize(&event, NULL,
1084 (yaml_char_t *)YAML_MAP_TAG,
1085 1, YAML_ANY_MAPPING_STYLE);
1086 rc = yaml_emitter_emit(&request, &event);
1090 yaml_scalar_event_initialize(&event, NULL,
1091 (yaml_char_t *)YAML_STR_TAG,
1092 (yaml_char_t *)group,
1093 strlen(group), 1, 0,
1094 YAML_PLAIN_SCALAR_STYLE);
1095 rc = yaml_emitter_emit(&request, &event);
1100 const char *key = "name";
1102 /* Now fill in 'path' filter */
1103 yaml_sequence_start_event_initialize(&event, NULL,
1104 (yaml_char_t *)YAML_SEQ_TAG,
1105 1, YAML_ANY_SEQUENCE_STYLE);
1106 rc = yaml_emitter_emit(&request, &event);
1110 yaml_mapping_start_event_initialize(&event, NULL,
1111 (yaml_char_t *)YAML_MAP_TAG,
1112 1, YAML_ANY_MAPPING_STYLE);
1113 rc = yaml_emitter_emit(&request, &event);
1117 yaml_scalar_event_initialize(&event, NULL,
1118 (yaml_char_t *)YAML_STR_TAG,
1119 (yaml_char_t *)key, strlen(key),
1120 1, 0, YAML_PLAIN_SCALAR_STYLE);
1121 rc = yaml_emitter_emit(&request, &event);
1125 yaml_scalar_event_initialize(&event, NULL,
1126 (yaml_char_t *)YAML_STR_TAG,
1127 (yaml_char_t *)source,
1128 strlen(source), 1, 0,
1129 YAML_PLAIN_SCALAR_STYLE);
1130 rc = yaml_emitter_emit(&request, &event);
1134 yaml_mapping_end_event_initialize(&event);
1135 rc = yaml_emitter_emit(&request, &event);
1139 yaml_sequence_end_event_initialize(&event);
1140 rc = yaml_emitter_emit(&request, &event);
1144 yaml_scalar_event_initialize(&event, NULL,
1145 (yaml_char_t *)YAML_STR_TAG,
1148 YAML_PLAIN_SCALAR_STYLE);
1149 rc = yaml_emitter_emit(&request, &event);
1153 yaml_mapping_end_event_initialize(&event);
1154 rc = yaml_emitter_emit(&request, &event);
1158 yaml_document_end_event_initialize(&event, 0);
1159 rc = yaml_emitter_emit(&request, &event);
1163 yaml_emitter_close(&request);
1166 yaml_emitter_log_error(&request, stderr);
1169 yaml_emitter_delete(&request);
1171 return rc == 1 ? 0 : -EINVAL;
1174 int lcfg_getparam_yaml(char *path, struct param_opts *popt)
1176 yaml_parser_t reply;
1180 sk = nl_socket_alloc();
1184 rc = lcfg_param_get_yaml(&reply, sk, path);
1188 if (popt->po_yaml) {
1189 yaml_document_t results;
1190 yaml_emitter_t output;
1192 /* load the reply results */
1193 rc = yaml_parser_load(&reply, &results);
1195 yaml_parser_log_error(&reply, stderr, "get_param: ");
1196 yaml_document_delete(&results);
1201 /* create emitter to output results */
1202 rc = yaml_emitter_initialize(&output);
1204 yaml_emitter_set_output_file(&output, stdout);
1206 rc = yaml_emitter_dump(&output, &results);
1209 yaml_document_delete(&results);
1211 yaml_emitter_log_error(&output, stderr);
1214 yaml_emitter_delete(&output);
1220 rc = yaml_parser_parse(&reply, &event);
1224 if (event.type == YAML_SCALAR_EVENT) {
1225 char *value = (char *)event.data.scalar.value;
1227 if (strcmp(value, "devices") == 0)
1228 rc = print_out_devices(&reply, popt);
1233 done = (event.type == YAML_STREAM_END_EVENT);
1234 yaml_event_delete(&event);
1238 yaml_parser_log_error(&reply, stderr, "get_param: ");
1243 yaml_parser_delete(&reply);
1245 return rc == 1 ? 0 : rc;
1249 * Perform a read, write or just a listing of a parameter
1251 * \param[in] popt list,set,get parameter options
1252 * \param[in] pattern search filter for the path of the parameter
1253 * \param[in] value value to set the parameter if write operation
1254 * \param[in] mode what operation to perform with the parameter
1256 * \retval number of bytes written on success.
1257 * \retval -errno on error and prints error message.
1260 param_display(struct param_opts *popt, char *pattern, char *value,
1261 enum parameter_operation mode)
1266 char *opname = parameter_opname[mode];
1269 rc = llapi_param_get_paths(pattern, &paths);
1272 if (!popt->po_recursive && !(rc == -ENOENT && getuid() != 0)) {
1273 fprintf(stderr, "error: %s: param_path '%s': %s\n",
1274 opname, pattern, strerror(errno));
1279 dup_cache = calloc(paths.gl_pathc, sizeof(char *));
1283 "error: %s: allocating '%s' dup_cache[%zd]: %s\n",
1284 opname, pattern, paths.gl_pathc, strerror(-rc));
1288 for (i = 0; i < paths.gl_pathc; i++) {
1289 char *param_name = NULL, *tmp;
1290 char pathname[PATH_MAX], param_dir[PATH_MAX + 2];
1294 if (stat(paths.gl_pathv[i], &st) == -1) {
1295 fprintf(stderr, "error: %s: stat '%s': %s\n",
1296 opname, paths.gl_pathv[i], strerror(errno));
1302 if (popt->po_only_dir && !S_ISDIR(st.st_mode))
1305 param_name = display_name(paths.gl_pathv[i], &st, popt);
1308 "error: %s: generating name for '%s': %s\n",
1309 opname, paths.gl_pathv[i], strerror(ENOMEM));
1317 /* Read the contents of file to stdout */
1318 if (S_ISREG(st.st_mode)) {
1319 rc2 = read_param(paths.gl_pathv[i], param_name,
1321 if (rc2 < 0 && rc == 0)
1326 if (S_ISREG(st.st_mode)) {
1327 rc2 = write_param(paths.gl_pathv[i],
1328 param_name, popt, value);
1329 if (rc2 < 0 && rc == 0)
1335 * For the upstream client the parameter files locations
1336 * are split between under both /sys/kernel/debug/lustre
1337 * and /sys/fs/lustre. The parameter files containing
1338 * small amounts of data, less than a page in size, are
1339 * located under /sys/fs/lustre and in the case of large
1340 * parameter data files, think stats for example, are
1341 * located in the debugfs tree. Since the files are
1342 * split across two trees the directories are often
1343 * duplicated which means these directories are listed
1344 * twice which leads to duplicate output to the user.
1345 * To avoid scanning a directory twice we have to cache
1346 * any directory and check if a search has been
1349 for (j = 0; j < dup_count; j++) {
1350 if (!strcmp(dup_cache[j], param_name))
1353 if (j != dup_count) {
1358 dup_cache[dup_count++] = strdup(param_name);
1360 if (popt->po_show_path)
1361 printf("%s\n", param_name);
1366 * Only directories are searched recursively if
1367 * requested by the user
1369 if (!S_ISDIR(st.st_mode) || !popt->po_recursive) {
1375 /* Turn param_name into file path format */
1376 rc2 = clean_path(popt, param_name);
1378 fprintf(stderr, "error: %s: cleaning '%s': %s\n",
1379 opname, param_name, strerror(-rc2));
1387 /* Use param_name to grab subdirectory tree from full path */
1388 snprintf(param_dir, sizeof(param_dir), "/%s", param_name);
1389 tmp = strstr(paths.gl_pathv[i], param_dir);
1391 /* cleanup paramname now that we are done with it */
1394 memset(¶m_dir, '\0', sizeof(param_dir));
1396 /* Shouldn't happen but just in case */
1404 rc2 = snprintf(pathname, sizeof(pathname), "%s/*", tmp);
1407 * snprintf() should never an error, and if it does
1408 * there isn't much point trying to use fprintf()
1412 if (rc2 >= sizeof(pathname)) {
1413 fprintf(stderr, "error: %s: overflow processing '%s'\n",
1420 rc2 = param_display(popt, pathname, value, mode);
1421 if (rc2 != 0 && rc2 != -ENOENT) {
1422 /* errors will be printed by param_display() */
1429 for (i = 0; i < dup_count; i++)
1433 llapi_param_paths_free(&paths);
1437 static int listparam_cmdline(int argc, char **argv, struct param_opts *popt)
1441 popt->po_show_path = 1;
1442 popt->po_only_path = 1;
1444 while ((ch = getopt(argc, argv, "FRD")) != -1) {
1447 popt->po_show_type = 1;
1450 popt->po_recursive = 1;
1453 popt->po_only_dir = 1;
1463 int jt_lcfg_listparam(int argc, char **argv)
1465 int rc = 0, index, i;
1466 struct param_opts popt;
1469 memset(&popt, 0, sizeof(popt));
1470 index = listparam_cmdline(argc, argv, &popt);
1471 if (index < 0 || index >= argc)
1474 for (i = index; i < argc; i++) {
1479 rc2 = clean_path(&popt, path);
1481 fprintf(stderr, "error: %s: cleaning '%s': %s\n",
1482 jt_cmdname(argv[0]), path, strerror(-rc2));
1488 rc2 = param_display(&popt, path, NULL, LIST_PARAM);
1490 fprintf(stderr, "error: %s: listing '%s': %s\n",
1491 jt_cmdname(argv[0]), path, strerror(-rc2));
1501 static int getparam_cmdline(int argc, char **argv, struct param_opts *popt)
1505 popt->po_show_path = 1;
1507 while ((ch = getopt(argc, argv, "FnNR")) != -1) {
1510 popt->po_show_type = 1;
1513 popt->po_show_path = 0;
1516 popt->po_only_path = 1;
1519 popt->po_recursive = 1;
1529 int jt_lcfg_getparam(int argc, char **argv)
1531 enum parameter_operation mode;
1532 int rc = 0, index, i;
1533 struct param_opts popt;
1536 memset(&popt, 0, sizeof(popt));
1537 index = getparam_cmdline(argc, argv, &popt);
1538 if (index < 0 || index >= argc)
1541 mode = popt.po_only_path ? LIST_PARAM : GET_PARAM;
1542 for (i = index; i < argc; i++) {
1547 rc2 = clean_path(&popt, path);
1549 fprintf(stderr, "error: %s: cleaning '%s': %s\n",
1550 jt_cmdname(argv[0]), path, strerror(-rc2));
1556 rc2 = param_display(&popt, path, NULL, mode);
1558 if (mode == GET_PARAM && rc2 == -ENOENT &&
1560 rc2 = lcfg_getparam_yaml(path, &popt);
1571 /* get device list by netlink or debugfs */
1572 int jt_obd_list(int argc, char **argv)
1574 static const struct option long_opts[] = {
1575 { .name = "target", .has_arg = no_argument, .val = 't' },
1576 { .name = "yaml", .has_arg = no_argument, .val = 'y' },
1579 struct param_opts opts;
1580 char buf[MAX_OBD_NAME];
1589 memset(&opts, 0, sizeof(opts));
1591 while ((c = getopt_long(argc, argv, "ty", long_opts, NULL)) != -1) {
1594 opts.po_detail = true;
1597 opts.po_yaml = true;
1604 if (optind < argc) {
1610 sk = nl_socket_alloc();
1614 /* Use YAML to list all devices */
1615 rc = lcfg_getparam_yaml("devices", &opts);
1625 rc = llapi_param_get_paths("devices", &path);
1629 fp = fopen(path.gl_pathv[0], "r");
1631 cfs_free_param_data(&path);
1635 while (fgets(buf, sizeof(buf), fp) != NULL)
1637 print_obd_line(buf);
1641 cfs_free_param_data(&path);
1646 static int do_name2dev(char *func, char *name, int dev_id)
1648 struct obd_ioctl_data data;
1649 char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf;
1650 yaml_parser_t output;
1656 memset(buf, 0, sizeof(rawbuf));
1657 scnprintf(buf, sizeof(rawbuf), "%s/devices",
1660 sk = nl_socket_alloc();
1664 /* Use YAML to list all devices */
1665 rc = lcfg_param_get_yaml(&output, sk, buf);
1667 if (rc == -EOPNOTSUPP)
1673 rc = yaml_parser_parse(&output, &event);
1675 yaml_parser_log_error(&output, stdout, "lctl: ");
1680 if (event.type == YAML_SCALAR_EVENT) {
1681 char *value = (char *)event.data.scalar.value;
1683 if (strcmp(value, "index") == 0) {
1684 yaml_event_delete(&event);
1685 rc = yaml_parser_parse(&output, &event);
1687 value = (char *)event.data.scalar.value;
1689 rc = strtoul(value, NULL, 10);
1691 yaml_event_delete(&event);
1699 done = (event.type == YAML_STREAM_END_EVENT);
1700 yaml_event_delete(&event);
1706 if (rc > 0 || rc != -EOPNOTSUPP)
1709 memset(&data, 0, sizeof(data));
1710 data.ioc_dev = dev_id;
1711 data.ioc_inllen1 = strlen(name) + 1;
1712 data.ioc_inlbuf1 = name;
1714 memset(buf, 0, sizeof(rawbuf));
1715 rc = llapi_ioctl_pack(&data, &buf, sizeof(rawbuf));
1717 fprintf(stderr, "error: %s: invalid ioctl\n", jt_cmdname(func));
1720 rc = l_ioctl(OBD_DEV_ID, OBD_IOC_NAME2DEV, buf);
1723 rc = llapi_ioctl_unpack(&data, buf, sizeof(rawbuf));
1725 fprintf(stderr, "error: %s: invalid reply\n", jt_cmdname(func));
1729 return data.ioc_dev;
1733 * resolve a device name to a device number.
1734 * supports a number, $name or %uuid.
1736 int parse_devname(char *func, char *name, int dev_id)
1744 /* Test if its a pure number string */
1745 if (strspn(name, "0123456789") != strlen(name)) {
1746 if (name[0] == '$' || name[0] == '%')
1749 rc = do_name2dev(func, name, dev_id);
1754 ret = strtoul(name, NULL, 10);
1760 fprintf(stderr, "No device found for name %s: %s\n",
1761 name, strerror(rc));
1765 #ifdef HAVE_SERVER_SUPPORT
1767 * Output information about nodemaps.
1768 * \param argc number of args
1769 * \param argv[] variable string arguments
1771 * [list|nodemap_name|all] \a list will list all nodemaps (default).
1772 * Specifying a \a nodemap_name will
1773 * display info about that specific nodemap.
1774 * \a all will display info for all nodemaps.
1775 * \retval 0 on success
1777 int jt_nodemap_info(int argc, char **argv)
1779 const char usage_str[] = "usage: nodemap_info [list|nodemap_name|all]\n";
1780 struct param_opts popt;
1783 memset(&popt, 0, sizeof(popt));
1784 popt.po_show_path = 1;
1787 fprintf(stderr, usage_str);
1791 if (argc == 1 || strcmp("list", argv[1]) == 0) {
1792 popt.po_only_path = 1;
1793 popt.po_only_dir = 1;
1794 rc = param_display(&popt, "nodemap/*", NULL, LIST_PARAM);
1795 } else if (strcmp("all", argv[1]) == 0) {
1796 rc = param_display(&popt, "nodemap/*/*", NULL, LIST_PARAM);
1798 char pattern[PATH_MAX];
1800 snprintf(pattern, sizeof(pattern), "nodemap/%s/*", argv[1]);
1801 rc = param_display(&popt, pattern, NULL, LIST_PARAM);
1804 "error: nodemap_info: cannot find nodemap %s\n",
1811 static int setparam_cmdline(int argc, char **argv, struct param_opts *popt)
1815 popt->po_show_path = 1;
1816 popt->po_only_path = 0;
1817 popt->po_show_type = 0;
1818 popt->po_recursive = 0;
1820 popt->po_delete = 0;
1823 while ((ch = getopt(argc, argv, "nPdF")) != -1) {
1826 popt->po_show_path = 0;
1832 popt->po_delete = 1;
1851 #define PS_PARAM_FOUND 1
1852 #define PS_PARAM_SET 2
1853 #define PS_VAL_FOUND 4
1854 #define PS_VAL_SET 8
1855 #define PS_DEVICE_FOUND 16
1856 #define PS_DEVICE_SET 32
1858 #define PARAM_SZ 256
1860 static struct cfg_type_data {
1861 enum paramtype ptype;
1863 } cfg_type_table[] = {
1864 { PT_SETPARAM, "set_param" },
1865 { PT_CONFPARAM, "conf_param" },
1869 static struct cfg_stage_data {
1872 } cfg_stage_table[] = {
1873 { PS_PARAM_FOUND, "parameter" },
1874 { PS_VAL_FOUND, "value" },
1875 { PS_DEVICE_FOUND, "device" },
1879 void conf_to_set_param(enum paramtype confset, const char *param,
1880 const char *device, char *buf,
1885 if (confset == PT_SETPARAM) {
1886 strncpy(buf, param, bufsize);
1891 * sys.* params are top level, we just need to trim the sys.
1893 tmp = strstr(param, "sys.");
1896 strncpy(buf, tmp, bufsize);
1901 * parameters look like type.parameter, we need to stick the device
1902 * in the middle. Example combine mdt.identity_upcall with device
1903 * lustre-MDT0000 for mdt.lustre-MDT0000.identity_upcall
1906 tmp = strchrnul(param, '.');
1907 snprintf(buf, tmp - param + 1, "%s", param);
1909 bufsize -= tmp - param;
1910 snprintf(buf, bufsize, ".%s%s", device, tmp);
1913 int lcfg_setparam_yaml(char *func, char *filename)
1916 yaml_parser_t parser;
1920 enum paramtype confset = PT_NONE;
1921 int param = PS_NONE;
1923 char parameter[PARAM_SZ + 1];
1924 char value[PARAM_SZ + 1];
1925 char device[PARAM_SZ + 1];
1927 file = fopen(filename, "rb");
1928 yaml_parser_initialize(&parser);
1929 yaml_parser_set_input_file(&parser, file);
1932 * Search tokens for conf_param or set_param
1933 * The token after "parameter" goes into parameter
1934 * The token after "value" goes into value
1935 * when we have all 3, create param=val and call the
1936 * appropriate function for set/conf param
1938 while (token.type != YAML_STREAM_END_TOKEN && rc == 0) {
1941 yaml_token_delete(&token);
1942 if (!yaml_parser_scan(&parser, &token)) {
1947 if (token.type != YAML_SCALAR_TOKEN)
1950 for (i = 0; cfg_type_table[i].ptype != PT_NONE; i++) {
1951 if (!strncmp((char *)token.data.alias.value,
1952 cfg_type_table[i].type_name,
1953 strlen(cfg_type_table[i].type_name))) {
1954 confset = cfg_type_table[i].ptype;
1959 if (confset == PT_NONE)
1962 for (i = 0; cfg_stage_table[i].pstage != PS_NONE; i++) {
1963 if (!strncmp((char *)token.data.alias.value,
1964 cfg_stage_table[i].stage_name,
1965 strlen(cfg_stage_table[i].stage_name))) {
1966 param |= cfg_stage_table[i].pstage;
1971 if (cfg_stage_table[i].pstage != PS_NONE)
1974 if (param & PS_PARAM_FOUND) {
1975 conf_to_set_param(confset,
1976 (char *)token.data.alias.value,
1977 device, parameter, PARAM_SZ);
1978 param |= PS_PARAM_SET;
1979 param &= ~PS_PARAM_FOUND;
1982 * we're getting parameter: param=val
1983 * copy val and mark that we've got it in case
1984 * there is no value: tag
1986 tmp = strchrnul(parameter, '=');
1988 strncpy(value, tmp + 1, sizeof(value) - 1);
1990 param |= PS_VAL_SET;
1994 } else if (param & PS_VAL_FOUND) {
1995 strncpy(value, (char *)token.data.alias.value,
1997 param |= PS_VAL_SET;
1998 param &= ~PS_VAL_FOUND;
1999 } else if (param & PS_DEVICE_FOUND) {
2000 strncpy(device, (char *)token.data.alias.value,
2002 param |= PS_DEVICE_SET;
2003 param &= ~PS_DEVICE_FOUND;
2006 if (confset && param & PS_VAL_SET && param & PS_PARAM_SET) {
2007 int size = strlen(parameter) + strlen(value) + 2;
2008 char *buf = malloc(size);
2014 snprintf(buf, size, "%s=%s", parameter, value);
2016 printf("set_param: %s\n", buf);
2017 rc = lcfg_setparam_perm(func, buf);
2021 parameter[0] = '\0';
2028 yaml_parser_delete(&parser);
2034 int jt_lcfg_setparam(int argc, char **argv)
2036 int rc = 0, index, i;
2037 struct param_opts popt;
2038 char *path = NULL, *value = NULL;
2040 memset(&popt, 0, sizeof(popt));
2041 index = setparam_cmdline(argc, argv, &popt);
2042 if (index < 0 || index >= argc)
2047 * We can't delete parameters that were
2048 * set with old conf_param interface
2050 return jt_lcfg_setparam_perm(argc, argv, &popt);
2053 return lcfg_setparam_yaml(argv[0], argv[index]);
2055 for (i = index; i < argc; i++) {
2059 value = strchr(path, '=');
2061 /* format: set_param a=b */
2064 if (*value == '\0') {
2066 "error: %s: setting %s: no value\n",
2067 jt_cmdname(argv[0]), path);
2073 /* format: set_param a b */
2077 "error: %s: setting %s: no value\n",
2078 jt_cmdname(argv[0]), path);
2086 rc2 = clean_path(&popt, path);
2088 fprintf(stderr, "error: %s: cleaning %s: %s\n",
2089 jt_cmdname(argv[0]), path, strerror(-rc2));
2095 rc2 = param_display(&popt, path, value, SET_PARAM);