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_cfg.h>
56 #include <lustre/lustre_idl.h>
57 #include <lustre/lustre_build_version.h>
68 #include <lnet/lnetctl.h>
69 #include <libcfs/libcfsutil.h>
72 static char * lcfg_devname;
74 int lcfg_set_devname(char *name)
82 /* quietly strip the unnecessary '$' */
83 if (*name == '$' || *name == '%')
87 while (*ptr != '\0') {
96 /* We can't translate from dev # to name */
99 lcfg_devname = strdup(name);
107 char * lcfg_get_devname(void)
112 int jt_lcfg_device(int argc, char **argv)
114 return jt_obd_device(argc, argv);
117 int jt_lcfg_attach(int argc, char **argv)
119 struct lustre_cfg_bufs bufs;
120 struct lustre_cfg *lcfg;
126 lustre_cfg_bufs_reset(&bufs, NULL);
128 lustre_cfg_bufs_set_string(&bufs, 1, argv[1]);
129 lustre_cfg_bufs_set_string(&bufs, 0, argv[2]);
130 lustre_cfg_bufs_set_string(&bufs, 2, argv[3]);
132 lcfg = lustre_cfg_new(LCFG_ATTACH, &bufs);
133 rc = lcfg_ioctl(argv[0], OBD_DEV_ID, lcfg);
134 lustre_cfg_free(lcfg);
136 fprintf(stderr, "error: %s: LCFG_ATTACH %s\n",
137 jt_cmdname(argv[0]), strerror(rc = errno));
139 lcfg_set_devname(argv[2]);
145 int jt_lcfg_setup(int argc, char **argv)
147 struct lustre_cfg_bufs bufs;
148 struct lustre_cfg *lcfg;
152 if (lcfg_devname == NULL) {
153 fprintf(stderr, "%s: please use 'device name' to set the "
154 "device name for config commands.\n",
155 jt_cmdname(argv[0]));
159 lustre_cfg_bufs_reset(&bufs, lcfg_devname);
164 for (i = 1; i < argc; i++) {
165 lustre_cfg_bufs_set_string(&bufs, i, argv[i]);
168 lcfg = lustre_cfg_new(LCFG_SETUP, &bufs);
169 rc = lcfg_ioctl(argv[0], OBD_DEV_ID, lcfg);
170 lustre_cfg_free(lcfg);
172 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
173 strerror(rc = errno));
178 int jt_obd_detach(int argc, char **argv)
180 struct lustre_cfg_bufs bufs;
181 struct lustre_cfg *lcfg;
184 if (lcfg_devname == NULL) {
185 fprintf(stderr, "%s: please use 'device name' to set the "
186 "device name for config commands.\n",
187 jt_cmdname(argv[0]));
191 lustre_cfg_bufs_reset(&bufs, lcfg_devname);
196 lcfg = lustre_cfg_new(LCFG_DETACH, &bufs);
197 rc = lcfg_ioctl(argv[0], OBD_DEV_ID, lcfg);
198 lustre_cfg_free(lcfg);
200 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
201 strerror(rc = errno));
206 int jt_obd_cleanup(int argc, char **argv)
208 struct lustre_cfg_bufs bufs;
209 struct lustre_cfg *lcfg;
212 char flags[3] = { 0 };
216 if (lcfg_devname == NULL) {
217 fprintf(stderr, "%s: please use 'device name' to set the "
218 "device name for config commands.\n",
219 jt_cmdname(argv[0]));
223 lustre_cfg_bufs_reset(&bufs, lcfg_devname);
225 if (argc < 1 || argc > 3)
228 /* we are protected from overflowing our buffer by the argc
231 for (n = 1; n < argc; n++) {
232 if (strcmp(argv[n], "force") == 0) {
233 flags[flag_cnt++] = force;
234 } else if (strcmp(argv[n], "failover") == 0) {
235 flags[flag_cnt++] = failover;
237 fprintf(stderr, "unknown option: %s", argv[n]);
243 lustre_cfg_bufs_set_string(&bufs, 1, flags);
246 lcfg = lustre_cfg_new(LCFG_CLEANUP, &bufs);
247 rc = lcfg_ioctl(argv[0], OBD_DEV_ID, lcfg);
248 lustre_cfg_free(lcfg);
250 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
251 strerror(rc = errno));
257 int do_add_uuid(char * func, char *uuid, lnet_nid_t nid)
260 struct lustre_cfg_bufs bufs;
261 struct lustre_cfg *lcfg;
263 lustre_cfg_bufs_reset(&bufs, lcfg_devname);
265 lustre_cfg_bufs_set_string(&bufs, 1, uuid);
267 lcfg = lustre_cfg_new(LCFG_ADD_UUID, &bufs);
268 lcfg->lcfg_nid = nid;
269 /* Poison NAL -- pre 1.4.6 will LASSERT on 0 NAL, this way it
270 doesn't work without crashing (bz 10130) */
271 lcfg->lcfg_nal = 0x5a;
274 fprintf(stderr, "adding\tnid: %d\tuuid: %s\n",
275 lcfg->lcfg_nid, uuid);
277 rc = lcfg_ioctl(func, OBD_DEV_ID, lcfg);
278 lustre_cfg_free(lcfg);
280 fprintf(stderr, "IOC_PORTAL_ADD_UUID failed: %s\n",
285 printf ("Added uuid %s: %s\n", uuid, libcfs_nid2str(nid));
289 int jt_lcfg_add_uuid(int argc, char **argv)
297 nid = libcfs_str2nid(argv[2]);
298 if (nid == LNET_NID_ANY) {
299 fprintf (stderr, "Can't parse NID %s\n", argv[2]);
303 return do_add_uuid(argv[0], argv[1], nid);
306 int jt_lcfg_del_uuid(int argc, char **argv)
309 struct lustre_cfg_bufs bufs;
310 struct lustre_cfg *lcfg;
313 fprintf(stderr, "usage: %s <uuid>\n", argv[0]);
317 lustre_cfg_bufs_reset(&bufs, lcfg_devname);
318 if (strcmp (argv[1], "_all_"))
319 lustre_cfg_bufs_set_string(&bufs, 1, argv[1]);
321 lcfg = lustre_cfg_new(LCFG_DEL_UUID, &bufs);
322 rc = lcfg_ioctl(argv[0], OBD_DEV_ID, lcfg);
323 lustre_cfg_free(lcfg);
325 fprintf(stderr, "IOC_PORTAL_DEL_UUID failed: %s\n",
332 int jt_lcfg_del_mount_option(int argc, char **argv)
335 struct lustre_cfg_bufs bufs;
336 struct lustre_cfg *lcfg;
341 lustre_cfg_bufs_reset(&bufs, lcfg_devname);
344 lustre_cfg_bufs_set_string(&bufs, 1, argv[1]);
346 lcfg = lustre_cfg_new(LCFG_DEL_MOUNTOPT, &bufs);
347 rc = lcfg_ioctl(argv[0], OBD_DEV_ID, lcfg);
348 lustre_cfg_free(lcfg);
350 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
351 strerror(rc = errno));
356 int jt_lcfg_set_timeout(int argc, char **argv)
359 struct lustre_cfg_bufs bufs;
360 struct lustre_cfg *lcfg;
362 fprintf(stderr, "%s has been deprecated. Use conf_param instead.\n"
363 "e.g. conf_param lustre-MDT0000 obd_timeout=50\n",
364 jt_cmdname(argv[0]));
371 lustre_cfg_bufs_reset(&bufs, lcfg_devname);
372 lcfg = lustre_cfg_new(LCFG_SET_TIMEOUT, &bufs);
373 lcfg->lcfg_num = atoi(argv[1]);
375 rc = lcfg_ioctl(argv[0], OBD_DEV_ID, lcfg);
376 //rc = lcfg_mgs_ioctl(argv[0], OBD_DEV_ID, lcfg);
378 lustre_cfg_free(lcfg);
380 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
381 strerror(rc = errno));
386 int jt_lcfg_add_conn(int argc, char **argv)
388 struct lustre_cfg_bufs bufs;
389 struct lustre_cfg *lcfg;
400 if (lcfg_devname == NULL) {
401 fprintf(stderr, "%s: please use 'device name' to set the "
402 "device name for config commands.\n",
403 jt_cmdname(argv[0]));
407 lustre_cfg_bufs_reset(&bufs, lcfg_devname);
409 lustre_cfg_bufs_set_string(&bufs, 1, argv[1]);
411 lcfg = lustre_cfg_new(LCFG_ADD_CONN, &bufs);
412 lcfg->lcfg_num = priority;
414 rc = lcfg_ioctl(argv[0], OBD_DEV_ID, lcfg);
415 lustre_cfg_free (lcfg);
417 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
418 strerror(rc = errno));
424 int jt_lcfg_del_conn(int argc, char **argv)
426 struct lustre_cfg_bufs bufs;
427 struct lustre_cfg *lcfg;
433 if (lcfg_devname == NULL) {
434 fprintf(stderr, "%s: please use 'device name' to set the "
435 "device name for config commands.\n",
436 jt_cmdname(argv[0]));
440 lustre_cfg_bufs_reset(&bufs, lcfg_devname);
442 /* connection uuid */
443 lustre_cfg_bufs_set_string(&bufs, 1, argv[1]);
445 lcfg = lustre_cfg_new(LCFG_DEL_MOUNTOPT, &bufs);
447 rc = lcfg_ioctl(argv[0], OBD_DEV_ID, lcfg);
448 lustre_cfg_free(lcfg);
450 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
451 strerror(rc = errno));
457 /* Param set locally, directly on target */
458 int jt_lcfg_param(int argc, char **argv)
461 struct lustre_cfg_bufs bufs;
462 struct lustre_cfg *lcfg;
464 if (argc >= LUSTRE_CFG_MAX_BUFCOUNT)
467 lustre_cfg_bufs_reset(&bufs, NULL);
469 for (i = 1; i < argc; i++) {
470 lustre_cfg_bufs_set_string(&bufs, i, argv[i]);
473 lcfg = lustre_cfg_new(LCFG_PARAM, &bufs);
475 rc = lcfg_ioctl(argv[0], OBD_DEV_ID, lcfg);
476 lustre_cfg_free(lcfg);
478 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
479 strerror(rc = errno));
485 unsigned int po_only_path:1;
486 unsigned int po_show_path:1;
487 unsigned int po_show_type:1;
488 unsigned int po_recursive:1;
489 unsigned int po_params2:1;
490 unsigned int po_delete:1;
493 /* Param set to single log file, used by all clients and servers.
494 * This should be loaded after the individual config logs.
495 * Called from set param with -P option.
497 static int jt_lcfg_mgsparam2(int argc, char **argv, struct param_opts *popt)
501 struct lustre_cfg_bufs bufs;
502 struct lustre_cfg *lcfg;
506 first_param = optind;
507 if (first_param < 0 || first_param >= argc)
510 for (i = first_param, rc = 0; i < argc; i++) {
511 lustre_cfg_bufs_reset(&bufs, NULL);
512 /* This same command would be executed on all nodes, many
513 * of which should fail (silently) because they don't have
514 * that proc file existing locally. There would be no
515 * preprocessing on the MGS to try to figure out which
516 * parameter files to add this to, there would be nodes
517 * processing on the cluster nodes to try to figure out
518 * if they are the intended targets. They will blindly
519 * try to set the parameter, and ENOTFOUND means it wasn't
521 * Target name "general" means call on all targets. It is
522 * left here in case some filtering will be added in
525 lustre_cfg_bufs_set_string(&bufs, 0, "general");
527 len = strlen(argv[i]);
529 /* put an '=' on the end in case it doesn't have one */
530 if (popt->po_delete && argv[i][len - 1] != '=') {
531 buf = malloc(len + 1);
532 sprintf(buf, "%s=", argv[i]);
536 lustre_cfg_bufs_set_string(&bufs, 1, buf);
538 lcfg = lustre_cfg_new(LCFG_SET_PARAM, &bufs);
540 fprintf(stderr, "error: allocating lcfg for %s: %s\n",
541 jt_cmdname(argv[0]), strerror(PTR_ERR(lcfg)));
545 int rc2 = lcfg_mgs_ioctl(argv[0], OBD_DEV_ID, lcfg);
547 fprintf(stderr, "error: executing %s: %s\n",
548 jt_cmdname(argv[0]), strerror(errno));
552 lustre_cfg_free(lcfg);
561 /* Param set in config log on MGS */
562 /* conf_param key=value */
563 /* Note we can actually send mgc conf_params from clients, but currently
564 * that's only done for default file striping (see ll_send_mgc_param),
566 /* After removal of a parameter (-d) Lustre will use the default
567 * AT NEXT REBOOT, not immediately. */
568 int jt_lcfg_mgsparam(int argc, char **argv)
572 struct lustre_cfg_bufs bufs;
573 struct lustre_cfg *lcfg;
576 #if LUSTRE_VERSION_CODE >= OBD_OCD_VERSION(2, 7, 53, 0)
577 fprintf(stderr, "warning: 'lctl conf_param' is deprecated, "
578 "use 'lctl set_param -P' instead\n");
581 /* mgs_setparam processes only lctl buf #1 */
582 if ((argc > 3) || (argc <= 1))
585 while ((rc = getopt(argc, argv, "d")) != -1) {
595 lustre_cfg_bufs_reset(&bufs, NULL);
599 /* for delete, make it "<param>=\0" */
600 buf = malloc(strlen(argv[optind]) + 2);
601 /* put an '=' on the end in case it doesn't have one */
602 sprintf(buf, "%s=", argv[optind]);
603 /* then truncate after the first '=' */
604 ptr = strchr(buf, '=');
606 lustre_cfg_bufs_set_string(&bufs, 1, buf);
608 lustre_cfg_bufs_set_string(&bufs, 1, argv[optind]);
611 /* We could put other opcodes here. */
612 lcfg = lustre_cfg_new(LCFG_PARAM, &bufs);
614 rc = lcfg_mgs_ioctl(argv[0], OBD_DEV_ID, lcfg);
615 lustre_cfg_free(lcfg);
619 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
620 strerror(rc = errno));
626 /* Display the path in the same format as sysctl
627 * For eg. obdfilter.lustre-OST0000.stats */
628 static char *display_name(char *filename, unsigned int po_show_type)
634 if (lstat(filename, &st) < 0)
638 filename += strlen("/proc/");
639 if (strncmp(filename, "fs/", strlen("fs/")) == 0)
640 filename += strlen("fs/");
642 filename += strlen("sys/");
644 if (strncmp(filename, "lustre/", strlen("lustre/")) == 0)
645 filename += strlen("lustre/");
646 else if (strncmp(filename, "lnet/", strlen("lnet/")) == 0)
647 filename += strlen("lnet/");
649 /* replace '/' with '.' to match conf_param and sysctl */
651 while ((tmp = strchr(tmp, '/')) != NULL)
654 /* append the indicator to entries */
656 if (S_ISDIR(st.st_mode))
657 strcat(filename, "/");
658 else if (S_ISLNK(st.st_mode))
659 strcat(filename, "@");
660 else if (st.st_mode & S_IWUSR)
661 strcat(filename, "=");
667 /* Find a character in a length limited string */
668 /* BEWARE - kernel definition of strnchr has args in different order! */
669 static char *strnchr(const char *p, char c, size_t n)
682 static char *globerrstr(int glob_rc)
686 return "Out of memory";
690 return "Found no match";
692 return "Unknown error";
695 static void clean_path(char *path)
699 /* If the input is in form Eg. obdfilter.*.stats */
700 if (strchr(path, '.')) {
702 while (*tmp != '\0') {
704 (tmp != path) && (*(tmp - 1) != '\\'))
709 /* get rid of '\', glob doesn't like it */
710 if ((tmp = strrchr(path, '\\')) != NULL) {
711 char *tail = path + strlen(path);
712 while (tmp != path) {
714 memmove(tmp, tmp + 1, tail - tmp);
722 /* Supporting file paths creates perilous behavoir: LU-888.
723 * Path support is deprecated.
724 * If a path is supplied it must begin with /proc. */
725 static void lprocfs_param_pattern(const char *cmd, const char *path, char *buf,
728 /* test path to see if it begins with '/proc/' */
729 if (strncmp(path, "/proc/", strlen("/proc/")) == 0) {
732 fprintf(stderr, "%s: specifying parameters via "
733 "full paths is deprecated.\n", cmd);
734 #if LUSTRE_VERSION_CODE >= OBD_OCD_VERSION(2, 6, 50, 0)
735 #warning "remove deprecated full path tunable access"
739 snprintf(buf, buf_size, "%s", path);
741 snprintf(buf, buf_size, "/proc/{fs,sys}/{lnet,lustre}/%s",
746 static int listparam_cmdline(int argc, char **argv, struct param_opts *popt)
750 popt->po_show_path = 1;
751 popt->po_only_path = 1;
752 popt->po_show_type = 0;
753 popt->po_recursive = 0;
755 while ((ch = getopt(argc, argv, "FR")) != -1) {
758 popt->po_show_type = 1;
761 popt->po_recursive = 1;
771 static int listparam_display(struct param_opts *popt, char *pattern)
776 char filename[PATH_MAX + 1]; /* extra 1 byte for file type */
778 rc = glob(pattern, GLOB_BRACE | (popt->po_recursive ? GLOB_MARK : 0),
781 fprintf(stderr, "error: list_param: %s: %s\n",
782 pattern, globerrstr(rc));
786 for (i = 0; i < glob_info.gl_pathc; i++) {
787 char *valuename = NULL;
790 /* Trailing '/' will indicate recursion into directory */
791 last = strlen(glob_info.gl_pathv[i]) - 1;
793 /* Remove trailing '/' or it will be converted to '.' */
794 if (last > 0 && glob_info.gl_pathv[i][last] == '/')
795 glob_info.gl_pathv[i][last] = '\0';
798 strcpy(filename, glob_info.gl_pathv[i]);
799 valuename = display_name(filename, popt->po_show_type);
801 printf("%s\n", valuename);
803 strcpy(filename, glob_info.gl_pathv[i]);
804 strcat(filename, "/*");
805 listparam_display(popt, filename);
809 globfree(&glob_info);
813 int jt_lcfg_listparam(int argc, char **argv)
816 struct param_opts popt;
817 char pattern[PATH_MAX];
820 rc = listparam_cmdline(argc, argv, &popt);
821 if (rc == argc && popt.po_recursive) {
822 rc--; /* we know at least "-R" is a parameter */
824 } else if (rc < 0 || rc >= argc) {
828 for (i = rc; i < argc; i++) {
833 lprocfs_param_pattern(argv[0], path, pattern, sizeof(pattern));
835 rc = listparam_display(&popt, pattern);
843 static int getparam_cmdline(int argc, char **argv, struct param_opts *popt)
847 popt->po_show_path = 1;
848 popt->po_only_path = 0;
849 popt->po_show_type = 0;
850 popt->po_recursive = 0;
852 while ((ch = getopt(argc, argv, "nNF")) != -1) {
855 popt->po_only_path = 1;
858 popt->po_show_path = 0;
860 popt->po_show_type = 1;
870 static int getparam_display(struct param_opts *popt, char *pattern)
877 char filename[PATH_MAX + 1]; /* extra 1 byte for file type */
879 rc = glob(pattern, GLOB_BRACE, NULL, &glob_info);
881 fprintf(stderr, "error: get_param: %s: %s\n",
882 pattern, globerrstr(rc));
886 buf = malloc(PAGE_CACHE_SIZE);
887 for (i = 0; i < glob_info.gl_pathc; i++) {
888 char *valuename = NULL;
890 memset(buf, 0, PAGE_CACHE_SIZE);
891 /* As listparam_display is used to show param name (with type),
892 * here "if (only_path)" is ignored.*/
893 if (popt->po_show_path) {
894 if (strlen(glob_info.gl_pathv[i]) >
895 sizeof(filename)-1) {
899 strncpy(filename, glob_info.gl_pathv[i],
901 valuename = display_name(filename, 0);
904 /* Write the contents of file to stdout */
905 fd = open(glob_info.gl_pathv[i], O_RDONLY);
908 "error: get_param: opening('%s') failed: %s\n",
909 glob_info.gl_pathv[i], strerror(errno));
914 rc = read(fd, buf, PAGE_CACHE_SIZE);
918 fprintf(stderr, "error: get_param: "
919 "read('%s') failed: %s\n",
920 glob_info.gl_pathv[i], strerror(errno));
923 /* Print the output in the format path=value if the
924 * value contains no new line character or cab be
925 * occupied in a line, else print value on new line */
926 if (valuename && popt->po_show_path) {
927 int longbuf = strnchr(buf, rc - 1, '\n') != NULL
929 printf("%s=%s", valuename, longbuf ? "\n" : buf);
935 rc = write(fileno(stdout), buf, rc);
937 fprintf(stderr, "error: get_param: "
938 "write to stdout failed: %s\n",
946 globfree(&glob_info);
951 int jt_lcfg_getparam(int argc, char **argv)
954 struct param_opts popt;
955 char pattern[PATH_MAX];
958 rc = getparam_cmdline(argc, argv, &popt);
959 if (rc < 0 || rc >= argc)
962 for (i = rc, rc = 0; i < argc; i++) {
969 lprocfs_param_pattern(argv[0], path, pattern, sizeof(pattern));
971 if (popt.po_only_path)
972 rc2 = listparam_display(&popt, pattern);
974 rc2 = getparam_display(&popt, pattern);
975 if (rc2 < 0 && rc == 0)
982 static int setparam_cmdline(int argc, char **argv, struct param_opts *popt)
986 popt->po_show_path = 1;
987 popt->po_only_path = 0;
988 popt->po_show_type = 0;
989 popt->po_recursive = 0;
990 popt->po_params2 = 0;
993 while ((ch = getopt(argc, argv, "nPd")) != -1) {
996 popt->po_show_path = 0;
999 popt->po_params2 = 1;
1002 popt->po_delete = 1;
1011 static int setparam_display(struct param_opts *popt, char *pattern, char *value)
1017 char filename[PATH_MAX + 1]; /* extra 1 byte for file type */
1019 rc = glob(pattern, GLOB_BRACE, NULL, &glob_info);
1021 fprintf(stderr, "error: set_param: %s: %s\n",
1022 pattern, globerrstr(rc));
1025 for (i = 0; i < glob_info.gl_pathc; i++) {
1026 char *valuename = NULL;
1028 if (popt->po_show_path) {
1029 if (strlen(glob_info.gl_pathv[i]) > sizeof(filename)-1)
1031 strncpy(filename, glob_info.gl_pathv[i],
1033 valuename = display_name(filename, 0);
1035 printf("%s=%s\n", valuename, value);
1037 /* Write the new value to the file */
1038 fd = open(glob_info.gl_pathv[i], O_WRONLY);
1040 rc = write(fd, value, strlen(value));
1042 fprintf(stderr, "error: set_param: setting "
1043 "%s=%s: %s\n", glob_info.gl_pathv[i],
1044 value, strerror(errno));
1049 fprintf(stderr, "error: set_param: %s opening %s\n",
1050 strerror(rc = errno), glob_info.gl_pathv[i]);
1054 globfree(&glob_info);
1058 int jt_lcfg_setparam(int argc, char **argv)
1061 struct param_opts popt;
1062 char pattern[PATH_MAX];
1063 char *path = NULL, *value = NULL;
1065 rc = setparam_cmdline(argc, argv, &popt);
1066 if (rc < 0 || rc >= argc)
1069 if (popt.po_params2)
1070 /* We can't delete parameters that were
1071 * set with old conf_param interface */
1072 return jt_lcfg_mgsparam2(argc, argv, &popt);
1074 for (i = rc, rc = 0; i < argc; i++) {
1077 if ((value = strchr(argv[i], '=')) != NULL) {
1078 /* format: set_param a=b */
1085 /* format: set_param a b */
1096 lprocfs_param_pattern(argv[0], path, pattern, sizeof(pattern));
1098 rc2 = setparam_display(&popt, pattern, value);
1101 if (rc2 < 0 && rc == 0)
1104 if (path != NULL && (value == NULL || *value == '\0'))
1105 fprintf(stderr, "error: %s: setting %s=: %s\n",
1106 jt_cmdname(argv[0]), path, strerror(rc = EINVAL));