4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 only,
8 * as published by the Free Software Foundation.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License version 2 for more details (a copy is included
14 * in the LICENSE file that accompanied this code).
16 * You should have received a copy of the GNU General Public License
17 * version 2 along with this program; If not, see
18 * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
20 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
21 * CA 95054 USA or visit www.sun.com if you need additional information or
27 * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
28 * Use is subject to license terms.
30 * Copyright (c) 2011, 2012, Intel Corporation.
33 * This file is part of Lustre, http://www.lustre.org/
34 * Lustre is a trademark of Sun Microsystems, Inc.
36 * lustre/utils/lustre_cfg.c
38 * Author: Peter J. Braam <braam@clusterfs.com>
39 * Author: Phil Schwan <phil@clusterfs.com>
40 * Author: Andreas Dilger <adilger@clusterfs.com>
41 * Author: Robert Read <rread@clusterfs.com>
45 #include <sys/ioctl.h>
52 #include <libcfs/libcfs.h>
53 #include <lustre_cfg.h>
54 #include <lustre/lustre_idl.h>
55 #include <lustre/lustre_build_version.h>
66 #include <lnet/lnetctl.h>
67 #include <libcfs/libcfsutil.h>
70 static char * lcfg_devname;
72 int lcfg_set_devname(char *name)
80 /* quietly strip the unnecessary '$' */
81 if (*name == '$' || *name == '%')
85 while (*ptr != '\0') {
94 /* We can't translate from dev # to name */
97 lcfg_devname = strdup(name);
105 char * lcfg_get_devname(void)
110 int jt_lcfg_device(int argc, char **argv)
112 return jt_obd_device(argc, argv);
115 int jt_lcfg_attach(int argc, char **argv)
117 struct lustre_cfg_bufs bufs;
118 struct lustre_cfg *lcfg;
124 lustre_cfg_bufs_reset(&bufs, NULL);
126 lustre_cfg_bufs_set_string(&bufs, 1, argv[1]);
127 lustre_cfg_bufs_set_string(&bufs, 0, argv[2]);
128 lustre_cfg_bufs_set_string(&bufs, 2, argv[3]);
130 lcfg = lustre_cfg_new(LCFG_ATTACH, &bufs);
134 rc = lcfg_ioctl(argv[0], OBD_DEV_ID, lcfg);
135 lustre_cfg_free(lcfg);
138 fprintf(stderr, "error: %s: LCFG_ATTACH %s\n",
139 jt_cmdname(argv[0]), strerror(rc = errno));
141 lcfg_set_devname(argv[2]);
147 int jt_lcfg_setup(int argc, char **argv)
149 struct lustre_cfg_bufs bufs;
150 struct lustre_cfg *lcfg;
154 if (lcfg_devname == NULL) {
155 fprintf(stderr, "%s: please use 'device name' to set the "
156 "device name for config commands.\n",
157 jt_cmdname(argv[0]));
161 lustre_cfg_bufs_reset(&bufs, lcfg_devname);
166 for (i = 1; i < argc; i++) {
167 lustre_cfg_bufs_set_string(&bufs, i, argv[i]);
170 lcfg = lustre_cfg_new(LCFG_SETUP, &bufs);
174 rc = lcfg_ioctl(argv[0], OBD_DEV_ID, lcfg);
175 lustre_cfg_free(lcfg);
178 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
179 strerror(rc = errno));
184 int jt_obd_detach(int argc, char **argv)
186 struct lustre_cfg_bufs bufs;
187 struct lustre_cfg *lcfg;
190 if (lcfg_devname == NULL) {
191 fprintf(stderr, "%s: please use 'device name' to set the "
192 "device name for config commands.\n",
193 jt_cmdname(argv[0]));
197 lustre_cfg_bufs_reset(&bufs, lcfg_devname);
202 lcfg = lustre_cfg_new(LCFG_DETACH, &bufs);
206 rc = lcfg_ioctl(argv[0], OBD_DEV_ID, lcfg);
207 lustre_cfg_free(lcfg);
210 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
211 strerror(rc = errno));
216 int jt_obd_cleanup(int argc, char **argv)
218 struct lustre_cfg_bufs bufs;
219 struct lustre_cfg *lcfg;
222 char flags[3] = { 0 };
226 if (lcfg_devname == NULL) {
227 fprintf(stderr, "%s: please use 'device name' to set the "
228 "device name for config commands.\n",
229 jt_cmdname(argv[0]));
233 lustre_cfg_bufs_reset(&bufs, lcfg_devname);
235 if (argc < 1 || argc > 3)
238 /* we are protected from overflowing our buffer by the argc
241 for (n = 1; n < argc; n++) {
242 if (strcmp(argv[n], "force") == 0) {
243 flags[flag_cnt++] = force;
244 } else if (strcmp(argv[n], "failover") == 0) {
245 flags[flag_cnt++] = failover;
247 fprintf(stderr, "unknown option: %s", argv[n]);
253 lustre_cfg_bufs_set_string(&bufs, 1, flags);
256 lcfg = lustre_cfg_new(LCFG_CLEANUP, &bufs);
260 rc = lcfg_ioctl(argv[0], OBD_DEV_ID, lcfg);
261 lustre_cfg_free(lcfg);
264 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
265 strerror(rc = errno));
271 int do_add_uuid(char * func, char *uuid, lnet_nid_t nid)
274 struct lustre_cfg_bufs bufs;
275 struct lustre_cfg *lcfg;
277 lustre_cfg_bufs_reset(&bufs, lcfg_devname);
279 lustre_cfg_bufs_set_string(&bufs, 1, uuid);
281 lcfg = lustre_cfg_new(LCFG_ADD_UUID, &bufs);
285 lcfg->lcfg_nid = nid;
286 /* Poison NAL -- pre 1.4.6 will LASSERT on 0 NAL, this way it
287 * doesn't work without crashing (bz 10130) */
288 lcfg->lcfg_nal = 0x5a;
289 rc = lcfg_ioctl(func, OBD_DEV_ID, lcfg);
290 lustre_cfg_free(lcfg);
293 fprintf(stderr, "IOC_PORTAL_ADD_UUID failed: %s\n",
298 printf ("Added uuid %s: %s\n", uuid, libcfs_nid2str(nid));
302 int jt_lcfg_add_uuid(int argc, char **argv)
310 nid = libcfs_str2nid(argv[2]);
311 if (nid == LNET_NID_ANY) {
312 fprintf (stderr, "Can't parse NID %s\n", argv[2]);
316 return do_add_uuid(argv[0], argv[1], nid);
319 int jt_lcfg_del_uuid(int argc, char **argv)
322 struct lustre_cfg_bufs bufs;
323 struct lustre_cfg *lcfg;
326 fprintf(stderr, "usage: %s <uuid>\n", argv[0]);
330 lustre_cfg_bufs_reset(&bufs, lcfg_devname);
331 if (strcmp (argv[1], "_all_"))
332 lustre_cfg_bufs_set_string(&bufs, 1, argv[1]);
334 lcfg = lustre_cfg_new(LCFG_DEL_UUID, &bufs);
338 rc = lcfg_ioctl(argv[0], OBD_DEV_ID, lcfg);
339 lustre_cfg_free(lcfg);
342 fprintf(stderr, "IOC_PORTAL_DEL_UUID failed: %s\n",
349 int jt_lcfg_del_mount_option(int argc, char **argv)
352 struct lustre_cfg_bufs bufs;
353 struct lustre_cfg *lcfg;
358 lustre_cfg_bufs_reset(&bufs, lcfg_devname);
361 lustre_cfg_bufs_set_string(&bufs, 1, argv[1]);
363 lcfg = lustre_cfg_new(LCFG_DEL_MOUNTOPT, &bufs);
367 rc = lcfg_ioctl(argv[0], OBD_DEV_ID, lcfg);
368 lustre_cfg_free(lcfg);
371 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
372 strerror(rc = errno));
377 int jt_lcfg_set_timeout(int argc, char **argv)
380 struct lustre_cfg_bufs bufs;
381 struct lustre_cfg *lcfg;
383 fprintf(stderr, "%s has been deprecated. Use conf_param instead.\n"
384 "e.g. conf_param lustre-MDT0000 obd_timeout=50\n",
385 jt_cmdname(argv[0]));
392 lustre_cfg_bufs_reset(&bufs, lcfg_devname);
393 lcfg = lustre_cfg_new(LCFG_SET_TIMEOUT, &bufs);
397 lcfg->lcfg_num = atoi(argv[1]);
399 rc = lcfg_ioctl(argv[0], OBD_DEV_ID, lcfg);
400 lustre_cfg_free(lcfg);
403 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
404 strerror(rc = errno));
409 int jt_lcfg_add_conn(int argc, char **argv)
411 struct lustre_cfg_bufs bufs;
412 struct lustre_cfg *lcfg;
423 if (lcfg_devname == NULL) {
424 fprintf(stderr, "%s: please use 'device name' to set the "
425 "device name for config commands.\n",
426 jt_cmdname(argv[0]));
430 lustre_cfg_bufs_reset(&bufs, lcfg_devname);
432 lustre_cfg_bufs_set_string(&bufs, 1, argv[1]);
434 lcfg = lustre_cfg_new(LCFG_ADD_CONN, &bufs);
438 lcfg->lcfg_num = priority;
440 rc = lcfg_ioctl(argv[0], OBD_DEV_ID, lcfg);
441 lustre_cfg_free(lcfg);
444 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
445 strerror(rc = errno));
451 int jt_lcfg_del_conn(int argc, char **argv)
453 struct lustre_cfg_bufs bufs;
454 struct lustre_cfg *lcfg;
460 if (lcfg_devname == NULL) {
461 fprintf(stderr, "%s: please use 'device name' to set the "
462 "device name for config commands.\n",
463 jt_cmdname(argv[0]));
467 lustre_cfg_bufs_reset(&bufs, lcfg_devname);
469 /* connection uuid */
470 lustre_cfg_bufs_set_string(&bufs, 1, argv[1]);
472 lcfg = lustre_cfg_new(LCFG_DEL_MOUNTOPT, &bufs);
476 rc = lcfg_ioctl(argv[0], OBD_DEV_ID, lcfg);
477 lustre_cfg_free(lcfg);
480 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
481 strerror(rc = errno));
487 /* Param set locally, directly on target */
488 int jt_lcfg_param(int argc, char **argv)
491 struct lustre_cfg_bufs bufs;
492 struct lustre_cfg *lcfg;
494 if (argc >= LUSTRE_CFG_MAX_BUFCOUNT)
497 lustre_cfg_bufs_reset(&bufs, NULL);
499 for (i = 1; i < argc; i++) {
500 lustre_cfg_bufs_set_string(&bufs, i, argv[i]);
503 lcfg = lustre_cfg_new(LCFG_PARAM, &bufs);
507 rc = lcfg_ioctl(argv[0], OBD_DEV_ID, lcfg);
508 lustre_cfg_free(lcfg);
511 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
512 strerror(rc = errno));
518 unsigned int po_only_path:1;
519 unsigned int po_show_path:1;
520 unsigned int po_show_type:1;
521 unsigned int po_recursive:1;
522 unsigned int po_params2:1;
523 unsigned int po_delete:1;
526 /* Param set to single log file, used by all clients and servers.
527 * This should be loaded after the individual config logs.
528 * Called from set param with -P option.
530 static int jt_lcfg_mgsparam2(int argc, char **argv, struct param_opts *popt)
534 struct lustre_cfg_bufs bufs;
535 struct lustre_cfg *lcfg;
539 first_param = optind;
540 if (first_param < 0 || first_param >= argc)
543 for (i = first_param, rc = 0; i < argc; i++) {
544 lustre_cfg_bufs_reset(&bufs, NULL);
545 /* This same command would be executed on all nodes, many
546 * of which should fail (silently) because they don't have
547 * that proc file existing locally. There would be no
548 * preprocessing on the MGS to try to figure out which
549 * parameter files to add this to, there would be nodes
550 * processing on the cluster nodes to try to figure out
551 * if they are the intended targets. They will blindly
552 * try to set the parameter, and ENOTFOUND means it wasn't
554 * Target name "general" means call on all targets. It is
555 * left here in case some filtering will be added in
558 lustre_cfg_bufs_set_string(&bufs, 0, "general");
560 len = strlen(argv[i]);
562 /* put an '=' on the end in case it doesn't have one */
563 if (popt->po_delete && argv[i][len - 1] != '=') {
564 buf = malloc(len + 1);
565 sprintf(buf, "%s=", argv[i]);
569 lustre_cfg_bufs_set_string(&bufs, 1, buf);
571 lcfg = lustre_cfg_new(LCFG_SET_PARAM, &bufs);
573 fprintf(stderr, "error: allocating lcfg for %s: %s\n",
574 jt_cmdname(argv[0]), strerror(-ENOMEM));
578 int rc2 = lcfg_mgs_ioctl(argv[0], OBD_DEV_ID, lcfg);
580 fprintf(stderr, "error: executing %s: %s\n",
581 jt_cmdname(argv[0]), strerror(errno));
585 lustre_cfg_free(lcfg);
594 /* Param set in config log on MGS */
595 /* conf_param key=value */
596 /* Note we can actually send mgc conf_params from clients, but currently
597 * that's only done for default file striping (see ll_send_mgc_param),
599 /* After removal of a parameter (-d) Lustre will use the default
600 * AT NEXT REBOOT, not immediately. */
601 int jt_lcfg_mgsparam(int argc, char **argv)
605 struct lustre_cfg_bufs bufs;
606 struct lustre_cfg *lcfg;
609 #if LUSTRE_VERSION_CODE >= OBD_OCD_VERSION(2, 7, 53, 0)
610 fprintf(stderr, "warning: 'lctl conf_param' is deprecated, "
611 "use 'lctl set_param -P' instead\n");
614 /* mgs_setparam processes only lctl buf #1 */
615 if ((argc > 3) || (argc <= 1))
618 while ((rc = getopt(argc, argv, "d")) != -1) {
628 lustre_cfg_bufs_reset(&bufs, NULL);
632 /* for delete, make it "<param>=\0" */
633 buf = malloc(strlen(argv[optind]) + 2);
634 /* put an '=' on the end in case it doesn't have one */
635 sprintf(buf, "%s=", argv[optind]);
636 /* then truncate after the first '=' */
637 ptr = strchr(buf, '=');
639 lustre_cfg_bufs_set_string(&bufs, 1, buf);
641 lustre_cfg_bufs_set_string(&bufs, 1, argv[optind]);
644 /* We could put other opcodes here. */
645 lcfg = lustre_cfg_new(LCFG_PARAM, &bufs);
649 rc = lcfg_mgs_ioctl(argv[0], OBD_DEV_ID, lcfg);
650 lustre_cfg_free(lcfg);
655 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
656 strerror(rc = errno));
662 /* Display the path in the same format as sysctl
663 * For eg. obdfilter.lustre-OST0000.stats */
664 static char *display_name(char *filename, unsigned int po_show_type)
670 if (lstat(filename, &st) < 0)
674 filename += strlen("/proc/");
675 if (strncmp(filename, "fs/", strlen("fs/")) == 0)
676 filename += strlen("fs/");
678 filename += strlen("sys/");
680 if (strncmp(filename, "lustre/", strlen("lustre/")) == 0)
681 filename += strlen("lustre/");
682 else if (strncmp(filename, "lnet/", strlen("lnet/")) == 0)
683 filename += strlen("lnet/");
685 /* replace '/' with '.' to match conf_param and sysctl */
687 while ((tmp = strchr(tmp, '/')) != NULL)
690 /* append the indicator to entries */
692 if (S_ISDIR(st.st_mode))
693 strcat(filename, "/");
694 else if (S_ISLNK(st.st_mode))
695 strcat(filename, "@");
696 else if (st.st_mode & S_IWUSR)
697 strcat(filename, "=");
703 /* Find a character in a length limited string */
704 /* BEWARE - kernel definition of strnchr has args in different order! */
705 static char *strnchr(const char *p, char c, size_t n)
718 static char *globerrstr(int glob_rc)
722 return "Out of memory";
726 return "Found no match";
728 return "Unknown error";
731 static void clean_path(char *path)
735 /* If the input is in form Eg. obdfilter.*.stats */
736 if (strchr(path, '.')) {
738 while (*tmp != '\0') {
740 (tmp != path) && (*(tmp - 1) != '\\'))
745 /* get rid of '\', glob doesn't like it */
746 if ((tmp = strrchr(path, '\\')) != NULL) {
747 char *tail = path + strlen(path);
748 while (tmp != path) {
750 memmove(tmp, tmp + 1, tail - tmp);
758 /* Supporting file paths creates perilous behavoir: LU-888.
759 * Path support is deprecated.
760 * If a path is supplied it must begin with /proc. */
761 static void lprocfs_param_pattern(const char *cmd, const char *path, char *buf,
764 /* test path to see if it begins with '/proc/' */
765 if (strncmp(path, "/proc/", strlen("/proc/")) == 0) {
768 fprintf(stderr, "%s: specifying parameters via "
769 "full paths is deprecated.\n", cmd);
770 #if LUSTRE_VERSION_CODE >= OBD_OCD_VERSION(2, 6, 50, 0)
771 #warning "remove deprecated full path tunable access"
775 snprintf(buf, buf_size, "%s", path);
777 snprintf(buf, buf_size, "/proc/{fs,sys}/{lnet,lustre}/%s",
782 static int listparam_cmdline(int argc, char **argv, struct param_opts *popt)
786 popt->po_show_path = 1;
787 popt->po_only_path = 1;
788 popt->po_show_type = 0;
789 popt->po_recursive = 0;
791 while ((ch = getopt(argc, argv, "FR")) != -1) {
794 popt->po_show_type = 1;
797 popt->po_recursive = 1;
807 static int listparam_display(struct param_opts *popt, char *pattern)
812 char filename[PATH_MAX + 1]; /* extra 1 byte for file type */
814 rc = glob(pattern, GLOB_BRACE | (popt->po_recursive ? GLOB_MARK : 0),
817 fprintf(stderr, "error: list_param: %s: %s\n",
818 pattern, globerrstr(rc));
822 for (i = 0; i < glob_info.gl_pathc; i++) {
823 char *valuename = NULL;
826 /* Trailing '/' will indicate recursion into directory */
827 last = strlen(glob_info.gl_pathv[i]) - 1;
829 /* Remove trailing '/' or it will be converted to '.' */
830 if (last > 0 && glob_info.gl_pathv[i][last] == '/')
831 glob_info.gl_pathv[i][last] = '\0';
834 strcpy(filename, glob_info.gl_pathv[i]);
835 valuename = display_name(filename, popt->po_show_type);
837 printf("%s\n", valuename);
839 strcpy(filename, glob_info.gl_pathv[i]);
840 strcat(filename, "/*");
841 listparam_display(popt, filename);
845 globfree(&glob_info);
849 int jt_lcfg_listparam(int argc, char **argv)
852 struct param_opts popt;
853 char pattern[PATH_MAX];
856 rc = listparam_cmdline(argc, argv, &popt);
857 if (rc == argc && popt.po_recursive) {
858 rc--; /* we know at least "-R" is a parameter */
860 } else if (rc < 0 || rc >= argc) {
864 for (i = rc; i < argc; i++) {
869 lprocfs_param_pattern(argv[0], path, pattern, sizeof(pattern));
871 rc = listparam_display(&popt, pattern);
879 static int getparam_cmdline(int argc, char **argv, struct param_opts *popt)
883 popt->po_show_path = 1;
884 popt->po_only_path = 0;
885 popt->po_show_type = 0;
886 popt->po_recursive = 0;
888 while ((ch = getopt(argc, argv, "nNF")) != -1) {
891 popt->po_only_path = 1;
894 popt->po_show_path = 0;
896 popt->po_show_type = 1;
906 static int getparam_display(struct param_opts *popt, char *pattern)
913 char filename[PATH_MAX + 1]; /* extra 1 byte for file type */
915 rc = glob(pattern, GLOB_BRACE, NULL, &glob_info);
917 fprintf(stderr, "error: get_param: %s: %s\n",
918 pattern, globerrstr(rc));
922 buf = malloc(PAGE_CACHE_SIZE);
923 for (i = 0; i < glob_info.gl_pathc; i++) {
924 char *valuename = NULL;
926 memset(buf, 0, PAGE_CACHE_SIZE);
927 /* As listparam_display is used to show param name (with type),
928 * here "if (only_path)" is ignored.*/
929 if (popt->po_show_path) {
930 if (strlen(glob_info.gl_pathv[i]) >
931 sizeof(filename)-1) {
935 strncpy(filename, glob_info.gl_pathv[i],
937 valuename = display_name(filename, 0);
940 /* Write the contents of file to stdout */
941 fd = open(glob_info.gl_pathv[i], O_RDONLY);
944 "error: get_param: opening('%s') failed: %s\n",
945 glob_info.gl_pathv[i], strerror(errno));
950 rc = read(fd, buf, PAGE_CACHE_SIZE);
954 fprintf(stderr, "error: get_param: "
955 "read('%s') failed: %s\n",
956 glob_info.gl_pathv[i], strerror(errno));
959 /* Print the output in the format path=value if the
960 * value contains no new line character or cab be
961 * occupied in a line, else print value on new line */
962 if (valuename && popt->po_show_path) {
963 int longbuf = strnchr(buf, rc - 1, '\n') != NULL
965 printf("%s=%s", valuename, longbuf ? "\n" : buf);
971 rc = write(fileno(stdout), buf, rc);
973 fprintf(stderr, "error: get_param: "
974 "write to stdout failed: %s\n",
982 globfree(&glob_info);
987 int jt_lcfg_getparam(int argc, char **argv)
990 struct param_opts popt;
991 char pattern[PATH_MAX];
994 rc = getparam_cmdline(argc, argv, &popt);
995 if (rc < 0 || rc >= argc)
998 for (i = rc, rc = 0; i < argc; i++) {
1005 lprocfs_param_pattern(argv[0], path, pattern, sizeof(pattern));
1007 if (popt.po_only_path)
1008 rc2 = listparam_display(&popt, pattern);
1010 rc2 = getparam_display(&popt, pattern);
1011 if (rc2 < 0 && rc == 0)
1018 static int setparam_cmdline(int argc, char **argv, struct param_opts *popt)
1022 popt->po_show_path = 1;
1023 popt->po_only_path = 0;
1024 popt->po_show_type = 0;
1025 popt->po_recursive = 0;
1026 popt->po_params2 = 0;
1027 popt->po_delete = 0;
1029 while ((ch = getopt(argc, argv, "nPd")) != -1) {
1032 popt->po_show_path = 0;
1035 popt->po_params2 = 1;
1038 popt->po_delete = 1;
1047 static int setparam_display(struct param_opts *popt, char *pattern, char *value)
1053 char filename[PATH_MAX + 1]; /* extra 1 byte for file type */
1055 rc = glob(pattern, GLOB_BRACE, NULL, &glob_info);
1057 fprintf(stderr, "error: set_param: %s: %s\n",
1058 pattern, globerrstr(rc));
1061 for (i = 0; i < glob_info.gl_pathc; i++) {
1062 char *valuename = NULL;
1064 if (popt->po_show_path) {
1065 if (strlen(glob_info.gl_pathv[i]) > sizeof(filename)-1)
1067 strncpy(filename, glob_info.gl_pathv[i],
1069 valuename = display_name(filename, 0);
1071 printf("%s=%s\n", valuename, value);
1073 /* Write the new value to the file */
1074 fd = open(glob_info.gl_pathv[i], O_WRONLY);
1076 rc = write(fd, value, strlen(value));
1078 fprintf(stderr, "error: set_param: setting "
1079 "%s=%s: %s\n", glob_info.gl_pathv[i],
1080 value, strerror(errno));
1085 fprintf(stderr, "error: set_param: %s opening %s\n",
1086 strerror(rc = errno), glob_info.gl_pathv[i]);
1090 globfree(&glob_info);
1094 int jt_lcfg_setparam(int argc, char **argv)
1097 struct param_opts popt;
1098 char pattern[PATH_MAX];
1099 char *path = NULL, *value = NULL;
1101 rc = setparam_cmdline(argc, argv, &popt);
1102 if (rc < 0 || rc >= argc)
1105 if (popt.po_params2)
1106 /* We can't delete parameters that were
1107 * set with old conf_param interface */
1108 return jt_lcfg_mgsparam2(argc, argv, &popt);
1110 for (i = rc, rc = 0; i < argc; i++) {
1113 if ((value = strchr(argv[i], '=')) != NULL) {
1114 /* format: set_param a=b */
1121 /* format: set_param a b */
1132 lprocfs_param_pattern(argv[0], path, pattern, sizeof(pattern));
1134 rc2 = setparam_display(&popt, pattern, value);
1137 if (rc2 < 0 && rc == 0)
1140 if (path != NULL && (value == NULL || *value == '\0'))
1141 fprintf(stderr, "error: %s: setting %s=: %s\n",
1142 jt_cmdname(argv[0]), path, strerror(rc = EINVAL));