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);
131 rc = lcfg_ioctl(argv[0], OBD_DEV_ID, lcfg);
132 lustre_cfg_free(lcfg);
134 fprintf(stderr, "error: %s: LCFG_ATTACH %s\n",
135 jt_cmdname(argv[0]), strerror(rc = errno));
137 lcfg_set_devname(argv[2]);
143 int jt_lcfg_setup(int argc, char **argv)
145 struct lustre_cfg_bufs bufs;
146 struct lustre_cfg *lcfg;
150 if (lcfg_devname == NULL) {
151 fprintf(stderr, "%s: please use 'device name' to set the "
152 "device name for config commands.\n",
153 jt_cmdname(argv[0]));
157 lustre_cfg_bufs_reset(&bufs, lcfg_devname);
162 for (i = 1; i < argc; i++) {
163 lustre_cfg_bufs_set_string(&bufs, i, argv[i]);
166 lcfg = lustre_cfg_new(LCFG_SETUP, &bufs);
167 rc = lcfg_ioctl(argv[0], OBD_DEV_ID, lcfg);
168 lustre_cfg_free(lcfg);
170 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
171 strerror(rc = errno));
176 int jt_obd_detach(int argc, char **argv)
178 struct lustre_cfg_bufs bufs;
179 struct lustre_cfg *lcfg;
182 if (lcfg_devname == NULL) {
183 fprintf(stderr, "%s: please use 'device name' to set the "
184 "device name for config commands.\n",
185 jt_cmdname(argv[0]));
189 lustre_cfg_bufs_reset(&bufs, lcfg_devname);
194 lcfg = lustre_cfg_new(LCFG_DETACH, &bufs);
195 rc = lcfg_ioctl(argv[0], OBD_DEV_ID, lcfg);
196 lustre_cfg_free(lcfg);
198 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
199 strerror(rc = errno));
204 int jt_obd_cleanup(int argc, char **argv)
206 struct lustre_cfg_bufs bufs;
207 struct lustre_cfg *lcfg;
210 char flags[3] = { 0 };
214 if (lcfg_devname == NULL) {
215 fprintf(stderr, "%s: please use 'device name' to set the "
216 "device name for config commands.\n",
217 jt_cmdname(argv[0]));
221 lustre_cfg_bufs_reset(&bufs, lcfg_devname);
223 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", argv[n]);
241 lustre_cfg_bufs_set_string(&bufs, 1, flags);
244 lcfg = lustre_cfg_new(LCFG_CLEANUP, &bufs);
245 rc = lcfg_ioctl(argv[0], OBD_DEV_ID, lcfg);
246 lustre_cfg_free(lcfg);
248 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
249 strerror(rc = errno));
255 int do_add_uuid(char * func, char *uuid, lnet_nid_t nid)
258 struct lustre_cfg_bufs bufs;
259 struct lustre_cfg *lcfg;
261 lustre_cfg_bufs_reset(&bufs, lcfg_devname);
263 lustre_cfg_bufs_set_string(&bufs, 1, uuid);
265 lcfg = lustre_cfg_new(LCFG_ADD_UUID, &bufs);
266 lcfg->lcfg_nid = nid;
267 /* Poison NAL -- pre 1.4.6 will LASSERT on 0 NAL, this way it
268 doesn't work without crashing (bz 10130) */
269 lcfg->lcfg_nal = 0x5a;
272 fprintf(stderr, "adding\tnid: %d\tuuid: %s\n",
273 lcfg->lcfg_nid, uuid);
275 rc = lcfg_ioctl(func, OBD_DEV_ID, lcfg);
276 lustre_cfg_free(lcfg);
278 fprintf(stderr, "IOC_PORTAL_ADD_UUID failed: %s\n",
283 printf ("Added uuid %s: %s\n", uuid, libcfs_nid2str(nid));
287 int jt_lcfg_add_uuid(int argc, char **argv)
295 nid = libcfs_str2nid(argv[2]);
296 if (nid == LNET_NID_ANY) {
297 fprintf (stderr, "Can't parse NID %s\n", argv[2]);
301 return do_add_uuid(argv[0], argv[1], nid);
304 int jt_lcfg_del_uuid(int argc, char **argv)
307 struct lustre_cfg_bufs bufs;
308 struct lustre_cfg *lcfg;
311 fprintf(stderr, "usage: %s <uuid>\n", argv[0]);
315 lustre_cfg_bufs_reset(&bufs, lcfg_devname);
316 if (strcmp (argv[1], "_all_"))
317 lustre_cfg_bufs_set_string(&bufs, 1, argv[1]);
319 lcfg = lustre_cfg_new(LCFG_DEL_UUID, &bufs);
320 rc = lcfg_ioctl(argv[0], OBD_DEV_ID, lcfg);
321 lustre_cfg_free(lcfg);
323 fprintf(stderr, "IOC_PORTAL_DEL_UUID failed: %s\n",
330 int jt_lcfg_del_mount_option(int argc, char **argv)
333 struct lustre_cfg_bufs bufs;
334 struct lustre_cfg *lcfg;
339 lustre_cfg_bufs_reset(&bufs, lcfg_devname);
342 lustre_cfg_bufs_set_string(&bufs, 1, argv[1]);
344 lcfg = lustre_cfg_new(LCFG_DEL_MOUNTOPT, &bufs);
345 rc = lcfg_ioctl(argv[0], OBD_DEV_ID, lcfg);
346 lustre_cfg_free(lcfg);
348 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
349 strerror(rc = errno));
354 int jt_lcfg_set_timeout(int argc, char **argv)
357 struct lustre_cfg_bufs bufs;
358 struct lustre_cfg *lcfg;
360 fprintf(stderr, "%s has been deprecated. Use conf_param instead.\n"
361 "e.g. conf_param lustre-MDT0000 obd_timeout=50\n",
362 jt_cmdname(argv[0]));
369 lustre_cfg_bufs_reset(&bufs, lcfg_devname);
370 lcfg = lustre_cfg_new(LCFG_SET_TIMEOUT, &bufs);
371 lcfg->lcfg_num = atoi(argv[1]);
373 rc = lcfg_ioctl(argv[0], OBD_DEV_ID, lcfg);
374 //rc = lcfg_mgs_ioctl(argv[0], OBD_DEV_ID, lcfg);
376 lustre_cfg_free(lcfg);
378 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
379 strerror(rc = errno));
384 int jt_lcfg_add_conn(int argc, char **argv)
386 struct lustre_cfg_bufs bufs;
387 struct lustre_cfg *lcfg;
398 if (lcfg_devname == NULL) {
399 fprintf(stderr, "%s: please use 'device name' to set the "
400 "device name for config commands.\n",
401 jt_cmdname(argv[0]));
405 lustre_cfg_bufs_reset(&bufs, lcfg_devname);
407 lustre_cfg_bufs_set_string(&bufs, 1, argv[1]);
409 lcfg = lustre_cfg_new(LCFG_ADD_CONN, &bufs);
410 lcfg->lcfg_num = priority;
412 rc = lcfg_ioctl(argv[0], OBD_DEV_ID, lcfg);
413 lustre_cfg_free (lcfg);
415 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
416 strerror(rc = errno));
422 int jt_lcfg_del_conn(int argc, char **argv)
424 struct lustre_cfg_bufs bufs;
425 struct lustre_cfg *lcfg;
431 if (lcfg_devname == NULL) {
432 fprintf(stderr, "%s: please use 'device name' to set the "
433 "device name for config commands.\n",
434 jt_cmdname(argv[0]));
438 lustre_cfg_bufs_reset(&bufs, lcfg_devname);
440 /* connection uuid */
441 lustre_cfg_bufs_set_string(&bufs, 1, argv[1]);
443 lcfg = lustre_cfg_new(LCFG_DEL_MOUNTOPT, &bufs);
445 rc = lcfg_ioctl(argv[0], OBD_DEV_ID, lcfg);
446 lustre_cfg_free(lcfg);
448 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
449 strerror(rc = errno));
455 /* Param set locally, directly on target */
456 int jt_lcfg_param(int argc, char **argv)
459 struct lustre_cfg_bufs bufs;
460 struct lustre_cfg *lcfg;
462 if (argc >= LUSTRE_CFG_MAX_BUFCOUNT)
465 lustre_cfg_bufs_reset(&bufs, NULL);
467 for (i = 1; i < argc; i++) {
468 lustre_cfg_bufs_set_string(&bufs, i, argv[i]);
471 lcfg = lustre_cfg_new(LCFG_PARAM, &bufs);
473 rc = lcfg_ioctl(argv[0], OBD_DEV_ID, lcfg);
474 lustre_cfg_free(lcfg);
476 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
477 strerror(rc = errno));
483 unsigned int po_only_path:1;
484 unsigned int po_show_path:1;
485 unsigned int po_show_type:1;
486 unsigned int po_recursive:1;
487 unsigned int po_params2:1;
488 unsigned int po_delete:1;
491 /* Param set to single log file, used by all clients and servers.
492 * This should be loaded after the individual config logs.
493 * Called from set param with -P option.
495 static int jt_lcfg_mgsparam2(int argc, char **argv, struct param_opts *popt)
499 struct lustre_cfg_bufs bufs;
500 struct lustre_cfg *lcfg;
504 first_param = optind;
505 if (first_param < 0 || first_param >= argc)
508 for (i = first_param, rc = 0; i < argc; i++) {
509 lustre_cfg_bufs_reset(&bufs, NULL);
510 /* This same command would be executed on all nodes, many
511 * of which should fail (silently) because they don't have
512 * that proc file existing locally. There would be no
513 * preprocessing on the MGS to try to figure out which
514 * parameter files to add this to, there would be nodes
515 * processing on the cluster nodes to try to figure out
516 * if they are the intended targets. They will blindly
517 * try to set the parameter, and ENOTFOUND means it wasn't
519 * Target name "general" means call on all targets. It is
520 * left here in case some filtering will be added in
523 lustre_cfg_bufs_set_string(&bufs, 0, "general");
525 len = strlen(argv[i]);
527 /* put an '=' on the end in case it doesn't have one */
528 if (popt->po_delete && argv[i][len - 1] != '=') {
529 buf = malloc(len + 1);
530 sprintf(buf, "%s=", argv[i]);
534 lustre_cfg_bufs_set_string(&bufs, 1, buf);
536 lcfg = lustre_cfg_new(LCFG_SET_PARAM, &bufs);
538 fprintf(stderr, "error: allocating lcfg for %s: %s\n",
539 jt_cmdname(argv[0]), strerror(PTR_ERR(lcfg)));
543 int rc2 = lcfg_mgs_ioctl(argv[0], OBD_DEV_ID, lcfg);
545 fprintf(stderr, "error: executing %s: %s\n",
546 jt_cmdname(argv[0]), strerror(errno));
550 lustre_cfg_free(lcfg);
559 /* Param set in config log on MGS */
560 /* conf_param key=value */
561 /* Note we can actually send mgc conf_params from clients, but currently
562 * that's only done for default file striping (see ll_send_mgc_param),
564 /* After removal of a parameter (-d) Lustre will use the default
565 * AT NEXT REBOOT, not immediately. */
566 int jt_lcfg_mgsparam(int argc, char **argv)
570 struct lustre_cfg_bufs bufs;
571 struct lustre_cfg *lcfg;
574 #if LUSTRE_VERSION_CODE >= OBD_OCD_VERSION(2, 7, 53, 0)
575 fprintf(stderr, "warning: 'lctl conf_param' is deprecated, "
576 "use 'lctl set_param -P' instead\n");
579 /* mgs_setparam processes only lctl buf #1 */
580 if ((argc > 3) || (argc <= 1))
583 while ((rc = getopt(argc, argv, "d")) != -1) {
593 lustre_cfg_bufs_reset(&bufs, NULL);
597 /* for delete, make it "<param>=\0" */
598 buf = malloc(strlen(argv[optind]) + 2);
599 /* put an '=' on the end in case it doesn't have one */
600 sprintf(buf, "%s=", argv[optind]);
601 /* then truncate after the first '=' */
602 ptr = strchr(buf, '=');
604 lustre_cfg_bufs_set_string(&bufs, 1, buf);
606 lustre_cfg_bufs_set_string(&bufs, 1, argv[optind]);
609 /* We could put other opcodes here. */
610 lcfg = lustre_cfg_new(LCFG_PARAM, &bufs);
612 rc = lcfg_mgs_ioctl(argv[0], OBD_DEV_ID, lcfg);
613 lustre_cfg_free(lcfg);
617 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
618 strerror(rc = errno));
624 /* Display the path in the same format as sysctl
625 * For eg. obdfilter.lustre-OST0000.stats */
626 static char *display_name(char *filename, unsigned int po_show_type)
632 if (lstat(filename, &st) < 0)
636 filename += strlen("/proc/");
637 if (strncmp(filename, "fs/", strlen("fs/")) == 0)
638 filename += strlen("fs/");
640 filename += strlen("sys/");
642 if (strncmp(filename, "lustre/", strlen("lustre/")) == 0)
643 filename += strlen("lustre/");
644 else if (strncmp(filename, "lnet/", strlen("lnet/")) == 0)
645 filename += strlen("lnet/");
647 /* replace '/' with '.' to match conf_param and sysctl */
649 while ((tmp = strchr(tmp, '/')) != NULL)
652 /* append the indicator to entries */
654 if (S_ISDIR(st.st_mode))
655 strcat(filename, "/");
656 else if (S_ISLNK(st.st_mode))
657 strcat(filename, "@");
658 else if (st.st_mode & S_IWUSR)
659 strcat(filename, "=");
665 /* Find a character in a length limited string */
666 /* BEWARE - kernel definition of strnchr has args in different order! */
667 static char *strnchr(const char *p, char c, size_t n)
680 static char *globerrstr(int glob_rc)
684 return "Out of memory";
688 return "Found no match";
690 return "Unknown error";
693 static void clean_path(char *path)
697 /* If the input is in form Eg. obdfilter.*.stats */
698 if (strchr(path, '.')) {
700 while (*tmp != '\0') {
702 (tmp != path) && (*(tmp - 1) != '\\'))
707 /* get rid of '\', glob doesn't like it */
708 if ((tmp = strrchr(path, '\\')) != NULL) {
709 char *tail = path + strlen(path);
710 while (tmp != path) {
712 memmove(tmp, tmp + 1, tail - tmp);
720 /* Supporting file paths creates perilous behavoir: LU-888.
721 * Path support is deprecated.
722 * If a path is supplied it must begin with /proc. */
723 static void lprocfs_param_pattern(const char *cmd, const char *path, char *buf,
726 /* test path to see if it begins with '/proc/' */
727 if (strncmp(path, "/proc/", strlen("/proc/")) == 0) {
730 fprintf(stderr, "%s: specifying parameters via "
731 "full paths is deprecated.\n", cmd);
732 #if LUSTRE_VERSION_CODE >= OBD_OCD_VERSION(2, 6, 50, 0)
733 #warning "remove deprecated full path tunable access"
737 snprintf(buf, buf_size, "%s", path);
739 snprintf(buf, buf_size, "/proc/{fs,sys}/{lnet,lustre}/%s",
744 static int listparam_cmdline(int argc, char **argv, struct param_opts *popt)
748 popt->po_show_path = 1;
749 popt->po_only_path = 1;
750 popt->po_show_type = 0;
751 popt->po_recursive = 0;
753 while ((ch = getopt(argc, argv, "FR")) != -1) {
756 popt->po_show_type = 1;
759 popt->po_recursive = 1;
769 static int listparam_display(struct param_opts *popt, char *pattern)
774 char filename[PATH_MAX + 1]; /* extra 1 byte for file type */
776 rc = glob(pattern, GLOB_BRACE | (popt->po_recursive ? GLOB_MARK : 0),
779 fprintf(stderr, "error: list_param: %s: %s\n",
780 pattern, globerrstr(rc));
784 for (i = 0; i < glob_info.gl_pathc; i++) {
785 char *valuename = NULL;
788 /* Trailing '/' will indicate recursion into directory */
789 last = strlen(glob_info.gl_pathv[i]) - 1;
791 /* Remove trailing '/' or it will be converted to '.' */
792 if (last > 0 && glob_info.gl_pathv[i][last] == '/')
793 glob_info.gl_pathv[i][last] = '\0';
796 strcpy(filename, glob_info.gl_pathv[i]);
797 valuename = display_name(filename, popt->po_show_type);
799 printf("%s\n", valuename);
801 strcpy(filename, glob_info.gl_pathv[i]);
802 strcat(filename, "/*");
803 listparam_display(popt, filename);
807 globfree(&glob_info);
811 int jt_lcfg_listparam(int argc, char **argv)
814 struct param_opts popt;
815 char pattern[PATH_MAX];
818 rc = listparam_cmdline(argc, argv, &popt);
819 if (rc == argc && popt.po_recursive) {
820 rc--; /* we know at least "-R" is a parameter */
822 } else if (rc < 0 || rc >= argc) {
826 for (i = rc; i < argc; i++) {
831 lprocfs_param_pattern(argv[0], path, pattern, sizeof(pattern));
833 rc = listparam_display(&popt, pattern);
841 static int getparam_cmdline(int argc, char **argv, struct param_opts *popt)
845 popt->po_show_path = 1;
846 popt->po_only_path = 0;
847 popt->po_show_type = 0;
848 popt->po_recursive = 0;
850 while ((ch = getopt(argc, argv, "nNF")) != -1) {
853 popt->po_only_path = 1;
856 popt->po_show_path = 0;
858 popt->po_show_type = 1;
868 static int getparam_display(struct param_opts *popt, char *pattern)
875 char filename[PATH_MAX + 1]; /* extra 1 byte for file type */
877 rc = glob(pattern, GLOB_BRACE, NULL, &glob_info);
879 fprintf(stderr, "error: get_param: %s: %s\n",
880 pattern, globerrstr(rc));
884 buf = malloc(PAGE_CACHE_SIZE);
885 for (i = 0; i < glob_info.gl_pathc; i++) {
886 char *valuename = NULL;
888 memset(buf, 0, PAGE_CACHE_SIZE);
889 /* As listparam_display is used to show param name (with type),
890 * here "if (only_path)" is ignored.*/
891 if (popt->po_show_path) {
892 if (strlen(glob_info.gl_pathv[i]) >
893 sizeof(filename)-1) {
897 strncpy(filename, glob_info.gl_pathv[i],
899 valuename = display_name(filename, 0);
902 /* Write the contents of file to stdout */
903 fd = open(glob_info.gl_pathv[i], O_RDONLY);
906 "error: get_param: opening('%s') failed: %s\n",
907 glob_info.gl_pathv[i], strerror(errno));
912 rc = read(fd, buf, PAGE_CACHE_SIZE);
916 fprintf(stderr, "error: get_param: "
917 "read('%s') failed: %s\n",
918 glob_info.gl_pathv[i], strerror(errno));
921 /* Print the output in the format path=value if the
922 * value contains no new line character or cab be
923 * occupied in a line, else print value on new line */
924 if (valuename && popt->po_show_path) {
925 int longbuf = strnchr(buf, rc - 1, '\n') != NULL
927 printf("%s=%s", valuename, longbuf ? "\n" : buf);
933 rc = write(fileno(stdout), buf, rc);
935 fprintf(stderr, "error: get_param: "
936 "write to stdout failed: %s\n",
944 globfree(&glob_info);
949 int jt_lcfg_getparam(int argc, char **argv)
952 struct param_opts popt;
953 char pattern[PATH_MAX];
956 rc = getparam_cmdline(argc, argv, &popt);
957 if (rc < 0 || rc >= argc)
960 for (i = rc, rc = 0; i < argc; i++) {
967 lprocfs_param_pattern(argv[0], path, pattern, sizeof(pattern));
969 if (popt.po_only_path)
970 rc2 = listparam_display(&popt, pattern);
972 rc2 = getparam_display(&popt, pattern);
973 if (rc2 < 0 && rc == 0)
980 static int setparam_cmdline(int argc, char **argv, struct param_opts *popt)
984 popt->po_show_path = 1;
985 popt->po_only_path = 0;
986 popt->po_show_type = 0;
987 popt->po_recursive = 0;
988 popt->po_params2 = 0;
991 while ((ch = getopt(argc, argv, "nPd")) != -1) {
994 popt->po_show_path = 0;
997 popt->po_params2 = 1;
1000 popt->po_delete = 1;
1009 static int setparam_display(struct param_opts *popt, char *pattern, char *value)
1015 char filename[PATH_MAX + 1]; /* extra 1 byte for file type */
1017 rc = glob(pattern, GLOB_BRACE, NULL, &glob_info);
1019 fprintf(stderr, "error: set_param: %s: %s\n",
1020 pattern, globerrstr(rc));
1023 for (i = 0; i < glob_info.gl_pathc; i++) {
1024 char *valuename = NULL;
1026 if (popt->po_show_path) {
1027 if (strlen(glob_info.gl_pathv[i]) > sizeof(filename)-1)
1029 strncpy(filename, glob_info.gl_pathv[i],
1031 valuename = display_name(filename, 0);
1033 printf("%s=%s\n", valuename, value);
1035 /* Write the new value to the file */
1036 fd = open(glob_info.gl_pathv[i], O_WRONLY);
1038 rc = write(fd, value, strlen(value));
1040 fprintf(stderr, "error: set_param: setting "
1041 "%s=%s: %s\n", glob_info.gl_pathv[i],
1042 value, strerror(errno));
1047 fprintf(stderr, "error: set_param: %s opening %s\n",
1048 strerror(rc = errno), glob_info.gl_pathv[i]);
1052 globfree(&glob_info);
1056 int jt_lcfg_setparam(int argc, char **argv)
1059 struct param_opts popt;
1060 char pattern[PATH_MAX];
1061 char *path = NULL, *value = NULL;
1063 rc = setparam_cmdline(argc, argv, &popt);
1064 if (rc < 0 || rc >= argc)
1067 if (popt.po_params2)
1068 /* We can't delete parameters that were
1069 * set with old conf_param interface */
1070 return jt_lcfg_mgsparam2(argc, argv, &popt);
1072 for (i = rc, rc = 0; i < argc; i++) {
1075 if ((value = strchr(argv[i], '=')) != NULL) {
1076 /* format: set_param a=b */
1083 /* format: set_param a b */
1094 lprocfs_param_pattern(argv[0], path, pattern, sizeof(pattern));
1096 rc2 = setparam_display(&popt, pattern, value);
1099 if (rc2 < 0 && rc == 0)
1102 if (path != NULL && (value == NULL || *value == '\0'))
1103 fprintf(stderr, "error: %s: setting %s=: %s\n",
1104 jt_cmdname(argv[0]), path, strerror(rc = EINVAL));