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>
53 #include <liblustre.h>
55 #include <lustre_lib.h>
56 #include <lustre_cfg.h>
57 #include <lustre/lustre_idl.h>
58 #include <lustre_dlm.h>
59 #include <obd.h> /* for struct lov_stripe_md */
61 #include <lustre/lustre_build_version.h>
72 #include <lnet/lnetctl.h>
73 #include <libcfs/libcfsutil.h>
76 static char * lcfg_devname;
78 int lcfg_set_devname(char *name)
86 /* quietly strip the unnecessary '$' */
87 if (*name == '$' || *name == '%')
91 while (*ptr != '\0') {
100 /* We can't translate from dev # to name */
103 lcfg_devname = strdup(name);
111 char * lcfg_get_devname(void)
116 int jt_lcfg_device(int argc, char **argv)
118 return jt_obd_device(argc, argv);
121 int jt_lcfg_attach(int argc, char **argv)
123 struct lustre_cfg_bufs bufs;
124 struct lustre_cfg *lcfg;
130 lustre_cfg_bufs_reset(&bufs, NULL);
132 lustre_cfg_bufs_set_string(&bufs, 1, argv[1]);
133 lustre_cfg_bufs_set_string(&bufs, 0, argv[2]);
134 lustre_cfg_bufs_set_string(&bufs, 2, argv[3]);
136 lcfg = lustre_cfg_new(LCFG_ATTACH, &bufs);
137 rc = lcfg_ioctl(argv[0], OBD_DEV_ID, lcfg);
138 lustre_cfg_free(lcfg);
140 fprintf(stderr, "error: %s: LCFG_ATTACH %s\n",
141 jt_cmdname(argv[0]), strerror(rc = errno));
142 } else if (argc == 3) {
145 lcfg_set_devname(argv[2]);
146 if (strlen(argv[2]) > 128) {
147 printf("Name too long to set environment\n");
150 snprintf(name, 512, "LUSTRE_DEV_%s", argv[2]);
151 rc = setenv(name, argv[1], 1);
153 printf("error setting env variable %s\n", name);
156 lcfg_set_devname(argv[2]);
162 int jt_lcfg_setup(int argc, char **argv)
164 struct lustre_cfg_bufs bufs;
165 struct lustre_cfg *lcfg;
169 if (lcfg_devname == NULL) {
170 fprintf(stderr, "%s: please use 'device name' to set the "
171 "device name for config commands.\n",
172 jt_cmdname(argv[0]));
176 lustre_cfg_bufs_reset(&bufs, lcfg_devname);
181 for (i = 1; i < argc; i++) {
182 lustre_cfg_bufs_set_string(&bufs, i, argv[i]);
185 lcfg = lustre_cfg_new(LCFG_SETUP, &bufs);
186 rc = lcfg_ioctl(argv[0], OBD_DEV_ID, lcfg);
187 lustre_cfg_free(lcfg);
189 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
190 strerror(rc = errno));
195 int jt_obd_detach(int argc, char **argv)
197 struct lustre_cfg_bufs bufs;
198 struct lustre_cfg *lcfg;
201 if (lcfg_devname == NULL) {
202 fprintf(stderr, "%s: please use 'device name' to set the "
203 "device name for config commands.\n",
204 jt_cmdname(argv[0]));
208 lustre_cfg_bufs_reset(&bufs, lcfg_devname);
213 lcfg = lustre_cfg_new(LCFG_DETACH, &bufs);
214 rc = lcfg_ioctl(argv[0], OBD_DEV_ID, lcfg);
215 lustre_cfg_free(lcfg);
217 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
218 strerror(rc = errno));
223 int jt_obd_cleanup(int argc, char **argv)
225 struct lustre_cfg_bufs bufs;
226 struct lustre_cfg *lcfg;
229 char flags[3] = { 0 };
233 if (lcfg_devname == NULL) {
234 fprintf(stderr, "%s: please use 'device name' to set the "
235 "device name for config commands.\n",
236 jt_cmdname(argv[0]));
240 lustre_cfg_bufs_reset(&bufs, lcfg_devname);
242 if (argc < 1 || argc > 3)
245 /* we are protected from overflowing our buffer by the argc
248 for (n = 1; n < argc; n++) {
249 if (strcmp(argv[n], "force") == 0) {
250 flags[flag_cnt++] = force;
251 } else if (strcmp(argv[n], "failover") == 0) {
252 flags[flag_cnt++] = failover;
254 fprintf(stderr, "unknown option: %s", argv[n]);
260 lustre_cfg_bufs_set_string(&bufs, 1, flags);
263 lcfg = lustre_cfg_new(LCFG_CLEANUP, &bufs);
264 rc = lcfg_ioctl(argv[0], OBD_DEV_ID, lcfg);
265 lustre_cfg_free(lcfg);
267 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
268 strerror(rc = errno));
274 int do_add_uuid(char * func, char *uuid, lnet_nid_t nid)
277 struct lustre_cfg_bufs bufs;
278 struct lustre_cfg *lcfg;
280 lustre_cfg_bufs_reset(&bufs, lcfg_devname);
282 lustre_cfg_bufs_set_string(&bufs, 1, uuid);
284 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;
291 fprintf(stderr, "adding\tnid: %d\tuuid: %s\n",
292 lcfg->lcfg_nid, uuid);
294 rc = lcfg_ioctl(func, OBD_DEV_ID, lcfg);
295 lustre_cfg_free(lcfg);
297 fprintf(stderr, "IOC_PORTAL_ADD_UUID failed: %s\n",
302 printf ("Added uuid %s: %s\n", uuid, libcfs_nid2str(nid));
306 int jt_lcfg_add_uuid(int argc, char **argv)
314 nid = libcfs_str2nid(argv[2]);
315 if (nid == LNET_NID_ANY) {
316 fprintf (stderr, "Can't parse NID %s\n", argv[2]);
320 return do_add_uuid(argv[0], argv[1], nid);
323 int obd_add_uuid(char *uuid, lnet_nid_t nid)
325 return do_add_uuid("obd_add_uuid", uuid, nid);
328 int jt_lcfg_del_uuid(int argc, char **argv)
331 struct lustre_cfg_bufs bufs;
332 struct lustre_cfg *lcfg;
335 fprintf(stderr, "usage: %s <uuid>\n", argv[0]);
339 lustre_cfg_bufs_reset(&bufs, lcfg_devname);
340 if (strcmp (argv[1], "_all_"))
341 lustre_cfg_bufs_set_string(&bufs, 1, argv[1]);
343 lcfg = lustre_cfg_new(LCFG_DEL_UUID, &bufs);
344 rc = lcfg_ioctl(argv[0], OBD_DEV_ID, lcfg);
345 lustre_cfg_free(lcfg);
347 fprintf(stderr, "IOC_PORTAL_DEL_UUID failed: %s\n",
354 int jt_lcfg_del_mount_option(int argc, char **argv)
357 struct lustre_cfg_bufs bufs;
358 struct lustre_cfg *lcfg;
363 lustre_cfg_bufs_reset(&bufs, lcfg_devname);
366 lustre_cfg_bufs_set_string(&bufs, 1, argv[1]);
368 lcfg = lustre_cfg_new(LCFG_DEL_MOUNTOPT, &bufs);
369 rc = lcfg_ioctl(argv[0], OBD_DEV_ID, lcfg);
370 lustre_cfg_free(lcfg);
372 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
373 strerror(rc = errno));
378 int jt_lcfg_set_timeout(int argc, char **argv)
381 struct lustre_cfg_bufs bufs;
382 struct lustre_cfg *lcfg;
384 fprintf(stderr, "%s has been deprecated. Use conf_param instead.\n"
385 "e.g. conf_param lustre-MDT0000 obd_timeout=50\n",
386 jt_cmdname(argv[0]));
393 lustre_cfg_bufs_reset(&bufs, lcfg_devname);
394 lcfg = lustre_cfg_new(LCFG_SET_TIMEOUT, &bufs);
395 lcfg->lcfg_num = atoi(argv[1]);
397 rc = lcfg_ioctl(argv[0], OBD_DEV_ID, lcfg);
398 //rc = lcfg_mgs_ioctl(argv[0], OBD_DEV_ID, lcfg);
400 lustre_cfg_free(lcfg);
402 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
403 strerror(rc = errno));
408 int jt_lcfg_add_conn(int argc, char **argv)
410 struct lustre_cfg_bufs bufs;
411 struct lustre_cfg *lcfg;
422 if (lcfg_devname == NULL) {
423 fprintf(stderr, "%s: please use 'device name' to set the "
424 "device name for config commands.\n",
425 jt_cmdname(argv[0]));
429 lustre_cfg_bufs_reset(&bufs, lcfg_devname);
431 lustre_cfg_bufs_set_string(&bufs, 1, argv[1]);
433 lcfg = lustre_cfg_new(LCFG_ADD_CONN, &bufs);
434 lcfg->lcfg_num = priority;
436 rc = lcfg_ioctl(argv[0], OBD_DEV_ID, lcfg);
437 lustre_cfg_free (lcfg);
439 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
440 strerror(rc = errno));
446 int jt_lcfg_del_conn(int argc, char **argv)
448 struct lustre_cfg_bufs bufs;
449 struct lustre_cfg *lcfg;
455 if (lcfg_devname == NULL) {
456 fprintf(stderr, "%s: please use 'device name' to set the "
457 "device name for config commands.\n",
458 jt_cmdname(argv[0]));
462 lustre_cfg_bufs_reset(&bufs, lcfg_devname);
464 /* connection uuid */
465 lustre_cfg_bufs_set_string(&bufs, 1, argv[1]);
467 lcfg = lustre_cfg_new(LCFG_DEL_MOUNTOPT, &bufs);
469 rc = lcfg_ioctl(argv[0], OBD_DEV_ID, lcfg);
470 lustre_cfg_free(lcfg);
472 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
473 strerror(rc = errno));
479 /* Param set locally, directly on target */
480 int jt_lcfg_param(int argc, char **argv)
483 struct lustre_cfg_bufs bufs;
484 struct lustre_cfg *lcfg;
486 if (argc >= LUSTRE_CFG_MAX_BUFCOUNT)
489 lustre_cfg_bufs_reset(&bufs, NULL);
491 for (i = 1; i < argc; i++) {
492 lustre_cfg_bufs_set_string(&bufs, i, argv[i]);
495 lcfg = lustre_cfg_new(LCFG_PARAM, &bufs);
497 rc = lcfg_ioctl(argv[0], OBD_DEV_ID, lcfg);
498 lustre_cfg_free(lcfg);
500 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
501 strerror(rc = errno));
507 unsigned int po_only_path:1;
508 unsigned int po_show_path:1;
509 unsigned int po_show_type:1;
510 unsigned int po_recursive:1;
511 unsigned int po_params2:1;
512 unsigned int po_delete:1;
515 /* Param set to single log file, used by all clients and servers.
516 * This should be loaded after the individual config logs.
517 * Called from set param with -P option.
519 static int jt_lcfg_mgsparam2(int argc, char **argv, struct param_opts *popt)
523 struct lustre_cfg_bufs bufs;
524 struct lustre_cfg *lcfg;
528 first_param = optind;
529 if (first_param < 0 || first_param >= argc)
532 for (i = first_param, rc = 0; i < argc; i++) {
533 lustre_cfg_bufs_reset(&bufs, NULL);
534 /* This same command would be executed on all nodes, many
535 * of which should fail (silently) because they don't have
536 * that proc file existing locally. There would be no
537 * preprocessing on the MGS to try to figure out which
538 * parameter files to add this to, there would be nodes
539 * processing on the cluster nodes to try to figure out
540 * if they are the intended targets. They will blindly
541 * try to set the parameter, and ENOTFOUND means it wasn't
543 * Target name "general" means call on all targets. It is
544 * left here in case some filtering will be added in
547 lustre_cfg_bufs_set_string(&bufs, 0, "general");
549 len = strlen(argv[i]);
551 /* put an '=' on the end in case it doesn't have one */
552 if (popt->po_delete && argv[i][len - 1] != '=') {
553 buf = malloc(len + 1);
554 sprintf(buf, "%s=", argv[i]);
558 lustre_cfg_bufs_set_string(&bufs, 1, buf);
560 lcfg = lustre_cfg_new(LCFG_SET_PARAM, &bufs);
562 fprintf(stderr, "error: allocating lcfg for %s: %s\n",
563 jt_cmdname(argv[0]), strerror(PTR_ERR(lcfg)));
567 int rc2 = lcfg_mgs_ioctl(argv[0], OBD_DEV_ID, lcfg);
569 fprintf(stderr, "error: executing %s: %s\n",
570 jt_cmdname(argv[0]), strerror(rc2));
574 lustre_cfg_free(lcfg);
583 /* Param set in config log on MGS */
584 /* conf_param key=value */
585 /* Note we can actually send mgc conf_params from clients, but currently
586 * that's only done for default file striping (see ll_send_mgc_param),
588 /* After removal of a parameter (-d) Lustre will use the default
589 * AT NEXT REBOOT, not immediately. */
590 int jt_lcfg_mgsparam(int argc, char **argv)
594 struct lustre_cfg_bufs bufs;
595 struct lustre_cfg *lcfg;
598 /* mgs_setparam processes only lctl buf #1 */
599 if ((argc > 3) || (argc <= 1))
602 while ((rc = getopt(argc, argv, "d")) != -1) {
612 lustre_cfg_bufs_reset(&bufs, NULL);
616 /* for delete, make it "<param>=\0" */
617 buf = malloc(strlen(argv[optind]) + 2);
618 /* put an '=' on the end in case it doesn't have one */
619 sprintf(buf, "%s=", argv[optind]);
620 /* then truncate after the first '=' */
621 ptr = strchr(buf, '=');
623 lustre_cfg_bufs_set_string(&bufs, 1, buf);
625 lustre_cfg_bufs_set_string(&bufs, 1, argv[optind]);
628 /* We could put other opcodes here. */
629 lcfg = lustre_cfg_new(LCFG_PARAM, &bufs);
631 rc = lcfg_mgs_ioctl(argv[0], OBD_DEV_ID, lcfg);
632 lustre_cfg_free(lcfg);
636 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
637 strerror(rc = errno));
643 /* Display the path in the same format as sysctl
644 * For eg. obdfilter.lustre-OST0000.stats */
645 static char *display_name(char *filename, unsigned int po_show_type)
651 if (lstat(filename, &st) < 0)
655 filename += strlen("/proc/");
656 if (strncmp(filename, "fs/", strlen("fs/")) == 0)
657 filename += strlen("fs/");
659 filename += strlen("sys/");
661 if (strncmp(filename, "lustre/", strlen("lustre/")) == 0)
662 filename += strlen("lustre/");
663 else if (strncmp(filename, "lnet/", strlen("lnet/")) == 0)
664 filename += strlen("lnet/");
666 /* replace '/' with '.' to match conf_param and sysctl */
668 while ((tmp = strchr(tmp, '/')) != NULL)
671 /* append the indicator to entries */
673 if (S_ISDIR(st.st_mode))
674 strcat(filename, "/");
675 else if (S_ISLNK(st.st_mode))
676 strcat(filename, "@");
677 else if (st.st_mode & S_IWUSR)
678 strcat(filename, "=");
684 /* Find a character in a length limited string */
685 /* BEWARE - kernel definition of strnchr has args in different order! */
686 static char *strnchr(const char *p, char c, size_t n)
699 static char *globerrstr(int glob_rc)
703 return "Out of memory";
707 return "Found no match";
709 return "Unknown error";
712 static void clean_path(char *path)
716 /* If the input is in form Eg. obdfilter.*.stats */
717 if (strchr(path, '.')) {
719 while (*tmp != '\0') {
721 (tmp != path) && (*(tmp - 1) != '\\'))
726 /* get rid of '\', glob doesn't like it */
727 if ((tmp = strrchr(path, '\\')) != NULL) {
728 char *tail = path + strlen(path);
729 while (tmp != path) {
731 memmove(tmp, tmp + 1, tail - tmp);
739 /* Supporting file paths creates perilous behavoir: LU-888.
740 * Path support is deprecated.
741 * If a path is supplied it must begin with /proc. */
742 static void lprocfs_param_pattern(const char *cmd, const char *path, char *buf,
745 /* test path to see if it begins with '/proc/' */
746 if (strncmp(path, "/proc/", strlen("/proc/")) == 0) {
749 fprintf(stderr, "%s: specifying parameters via "
750 "full paths is deprecated.\n", cmd);
751 #if LUSTRE_VERSION_CODE >= OBD_OCD_VERSION(2, 6, 50, 0)
752 #warning "remove deprecated full path tunable access"
756 snprintf(buf, buf_size, "%s", path);
758 snprintf(buf, buf_size, "/proc/{fs,sys}/{lnet,lustre}/%s",
763 static int listparam_cmdline(int argc, char **argv, struct param_opts *popt)
767 popt->po_show_path = 1;
768 popt->po_only_path = 1;
769 popt->po_show_type = 0;
770 popt->po_recursive = 0;
772 while ((ch = getopt(argc, argv, "FR")) != -1) {
775 popt->po_show_type = 1;
778 popt->po_recursive = 1;
788 static int listparam_display(struct param_opts *popt, char *pattern)
793 char filename[PATH_MAX + 1]; /* extra 1 byte for file type */
795 rc = glob(pattern, GLOB_BRACE | (popt->po_recursive ? GLOB_MARK : 0),
798 fprintf(stderr, "error: list_param: %s: %s\n",
799 pattern, globerrstr(rc));
803 for (i = 0; i < glob_info.gl_pathc; i++) {
804 char *valuename = NULL;
807 /* Trailing '/' will indicate recursion into directory */
808 last = strlen(glob_info.gl_pathv[i]) - 1;
810 /* Remove trailing '/' or it will be converted to '.' */
811 if (last > 0 && glob_info.gl_pathv[i][last] == '/')
812 glob_info.gl_pathv[i][last] = '\0';
815 strcpy(filename, glob_info.gl_pathv[i]);
816 valuename = display_name(filename, popt->po_show_type);
818 printf("%s\n", valuename);
820 strcpy(filename, glob_info.gl_pathv[i]);
821 strcat(filename, "/*");
822 listparam_display(popt, filename);
826 globfree(&glob_info);
830 int jt_lcfg_listparam(int argc, char **argv)
833 struct param_opts popt;
834 char pattern[PATH_MAX];
837 rc = listparam_cmdline(argc, argv, &popt);
838 if (rc == argc && popt.po_recursive) {
839 rc--; /* we know at least "-R" is a parameter */
841 } else if (rc < 0 || rc >= argc) {
845 for (i = rc; i < argc; i++) {
850 lprocfs_param_pattern(argv[0], path, pattern, sizeof(pattern));
852 rc = listparam_display(&popt, pattern);
860 static int getparam_cmdline(int argc, char **argv, struct param_opts *popt)
864 popt->po_show_path = 1;
865 popt->po_only_path = 0;
866 popt->po_show_type = 0;
867 popt->po_recursive = 0;
869 while ((ch = getopt(argc, argv, "nNF")) != -1) {
872 popt->po_only_path = 1;
875 popt->po_show_path = 0;
877 popt->po_show_type = 1;
887 static int getparam_display(struct param_opts *popt, char *pattern)
894 char filename[PATH_MAX + 1]; /* extra 1 byte for file type */
896 rc = glob(pattern, GLOB_BRACE, NULL, &glob_info);
898 fprintf(stderr, "error: get_param: %s: %s\n",
899 pattern, globerrstr(rc));
903 buf = malloc(PAGE_CACHE_SIZE);
904 for (i = 0; i < glob_info.gl_pathc; i++) {
905 char *valuename = NULL;
907 memset(buf, 0, PAGE_CACHE_SIZE);
908 /* As listparam_display is used to show param name (with type),
909 * here "if (only_path)" is ignored.*/
910 if (popt->po_show_path) {
911 strcpy(filename, glob_info.gl_pathv[i]);
912 valuename = display_name(filename, 0);
915 /* Write the contents of file to stdout */
916 fd = open(glob_info.gl_pathv[i], O_RDONLY);
919 "error: get_param: opening('%s') failed: %s\n",
920 glob_info.gl_pathv[i], strerror(errno));
925 rc = read(fd, buf, PAGE_CACHE_SIZE);
929 fprintf(stderr, "error: get_param: "
930 "read('%s') failed: %s\n",
931 glob_info.gl_pathv[i], strerror(errno));
934 /* Print the output in the format path=value if the
935 * value contains no new line character or cab be
936 * occupied in a line, else print value on new line */
937 if (valuename && popt->po_show_path) {
938 int longbuf = strnchr(buf, rc - 1, '\n') != NULL
940 printf("%s=%s", valuename, longbuf ? "\n" : buf);
946 rc = write(fileno(stdout), buf, rc);
948 fprintf(stderr, "error: get_param: "
949 "write to stdout failed: %s\n",
957 globfree(&glob_info);
962 int jt_lcfg_getparam(int argc, char **argv)
965 struct param_opts popt;
966 char pattern[PATH_MAX];
969 rc = getparam_cmdline(argc, argv, &popt);
970 if (rc < 0 || rc >= argc)
973 for (i = rc, rc = 0; i < argc; i++) {
980 lprocfs_param_pattern(argv[0], path, pattern, sizeof(pattern));
982 if (popt.po_only_path)
983 rc2 = listparam_display(&popt, pattern);
985 rc2 = getparam_display(&popt, pattern);
986 if (rc2 < 0 && rc == 0)
993 static int setparam_cmdline(int argc, char **argv, struct param_opts *popt)
997 popt->po_show_path = 1;
998 popt->po_only_path = 0;
999 popt->po_show_type = 0;
1000 popt->po_recursive = 0;
1001 popt->po_params2 = 0;
1002 popt->po_delete = 0;
1004 while ((ch = getopt(argc, argv, "nPd")) != -1) {
1007 popt->po_show_path = 0;
1010 popt->po_params2 = 1;
1013 popt->po_delete = 1;
1022 static int setparam_display(struct param_opts *popt, char *pattern, char *value)
1028 char filename[PATH_MAX + 1]; /* extra 1 byte for file type */
1030 rc = glob(pattern, GLOB_BRACE, NULL, &glob_info);
1032 fprintf(stderr, "error: set_param: %s: %s\n",
1033 pattern, globerrstr(rc));
1036 for (i = 0; i < glob_info.gl_pathc; i++) {
1037 char *valuename = NULL;
1039 if (popt->po_show_path) {
1040 strcpy(filename, glob_info.gl_pathv[i]);
1041 valuename = display_name(filename, 0);
1043 printf("%s=%s\n", valuename, value);
1045 /* Write the new value to the file */
1046 fd = open(glob_info.gl_pathv[i], O_WRONLY);
1048 rc = write(fd, value, strlen(value));
1050 fprintf(stderr, "error: set_param: setting "
1051 "%s=%s: %s\n", glob_info.gl_pathv[i],
1052 value, strerror(errno));
1057 fprintf(stderr, "error: set_param: %s opening %s\n",
1058 strerror(rc = errno), glob_info.gl_pathv[i]);
1062 globfree(&glob_info);
1066 int jt_lcfg_setparam(int argc, char **argv)
1069 struct param_opts popt;
1070 char pattern[PATH_MAX];
1071 char *path = NULL, *value = NULL;
1073 rc = setparam_cmdline(argc, argv, &popt);
1074 if (rc < 0 || rc >= argc)
1077 if (popt.po_params2)
1078 /* We can't delete parameters that were
1079 * set with old conf_param interface */
1080 return jt_lcfg_mgsparam2(argc, argv, &popt);
1082 for (i = rc, rc = 0; i < argc; i++) {
1085 if ((value = strchr(argv[i], '=')) != NULL) {
1086 /* format: set_param a=b */
1091 /* format: set_param a b */
1102 lprocfs_param_pattern(argv[0], path, pattern, sizeof(pattern));
1104 rc2 = setparam_display(&popt, pattern, value);
1107 if (rc2 < 0 && rc == 0)