1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
6 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 only,
10 * as published by the Free Software Foundation.
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License version 2 for more details (a copy is included
16 * in the LICENSE file that accompanied this code).
18 * You should have received a copy of the GNU General Public License
19 * version 2 along with this program; If not, see
20 * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
22 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
23 * CA 95054 USA or visit www.sun.com if you need additional information or
29 * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
30 * Use is subject to license terms.
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)
83 /* quietly strip the unnecessary '$' */
84 if (*name == '$' || *name == '%')
87 /* We can't translate from dev # to name */
90 lcfg_devname = strdup(name);
98 char * lcfg_get_devname(void)
103 int jt_lcfg_device(int argc, char **argv)
105 return jt_obd_device(argc, argv);
108 int jt_lcfg_attach(int argc, char **argv)
110 struct lustre_cfg_bufs bufs;
111 struct lustre_cfg *lcfg;
117 lustre_cfg_bufs_reset(&bufs, NULL);
119 lustre_cfg_bufs_set_string(&bufs, 1, argv[1]);
120 lustre_cfg_bufs_set_string(&bufs, 0, argv[2]);
121 lustre_cfg_bufs_set_string(&bufs, 2, argv[3]);
123 lcfg = lustre_cfg_new(LCFG_ATTACH, &bufs);
124 rc = lcfg_ioctl(argv[0], OBD_DEV_ID, lcfg);
125 lustre_cfg_free(lcfg);
127 fprintf(stderr, "error: %s: LCFG_ATTACH %s\n",
128 jt_cmdname(argv[0]), strerror(rc = errno));
129 } else if (argc == 3) {
132 lcfg_set_devname(argv[2]);
133 if (strlen(argv[2]) > 128) {
134 printf("Name too long to set environment\n");
137 snprintf(name, 512, "LUSTRE_DEV_%s", argv[2]);
138 rc = setenv(name, argv[1], 1);
140 printf("error setting env variable %s\n", name);
143 lcfg_set_devname(argv[2]);
149 int jt_lcfg_setup(int argc, char **argv)
151 struct lustre_cfg_bufs bufs;
152 struct lustre_cfg *lcfg;
156 if (lcfg_devname == NULL) {
157 fprintf(stderr, "%s: please use 'device name' to set the "
158 "device name for config commands.\n",
159 jt_cmdname(argv[0]));
163 lustre_cfg_bufs_reset(&bufs, lcfg_devname);
168 for (i = 1; i < argc; i++) {
169 lustre_cfg_bufs_set_string(&bufs, i, argv[i]);
172 lcfg = lustre_cfg_new(LCFG_SETUP, &bufs);
173 rc = lcfg_ioctl(argv[0], OBD_DEV_ID, lcfg);
174 lustre_cfg_free(lcfg);
176 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
177 strerror(rc = errno));
182 int jt_obd_detach(int argc, char **argv)
184 struct lustre_cfg_bufs bufs;
185 struct lustre_cfg *lcfg;
188 if (lcfg_devname == NULL) {
189 fprintf(stderr, "%s: please use 'device name' to set the "
190 "device name for config commands.\n",
191 jt_cmdname(argv[0]));
195 lustre_cfg_bufs_reset(&bufs, lcfg_devname);
200 lcfg = lustre_cfg_new(LCFG_DETACH, &bufs);
201 rc = lcfg_ioctl(argv[0], OBD_DEV_ID, lcfg);
202 lustre_cfg_free(lcfg);
204 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
205 strerror(rc = errno));
210 int jt_obd_cleanup(int argc, char **argv)
212 struct lustre_cfg_bufs bufs;
213 struct lustre_cfg *lcfg;
216 char flags[3] = { 0 };
220 if (lcfg_devname == NULL) {
221 fprintf(stderr, "%s: please use 'device name' to set the "
222 "device name for config commands.\n",
223 jt_cmdname(argv[0]));
227 lustre_cfg_bufs_reset(&bufs, lcfg_devname);
229 if (argc < 1 || argc > 3)
232 /* we are protected from overflowing our buffer by the argc
235 for (n = 1; n < argc; n++) {
236 if (strcmp(argv[n], "force") == 0) {
237 flags[flag_cnt++] = force;
238 } else if (strcmp(argv[n], "failover") == 0) {
239 flags[flag_cnt++] = failover;
241 fprintf(stderr, "unknown option: %s", argv[n]);
247 lustre_cfg_bufs_set_string(&bufs, 1, flags);
250 lcfg = lustre_cfg_new(LCFG_CLEANUP, &bufs);
251 rc = lcfg_ioctl(argv[0], OBD_DEV_ID, lcfg);
252 lustre_cfg_free(lcfg);
254 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
255 strerror(rc = errno));
261 int do_add_uuid(char * func, char *uuid, lnet_nid_t nid)
264 struct lustre_cfg_bufs bufs;
265 struct lustre_cfg *lcfg;
267 lustre_cfg_bufs_reset(&bufs, lcfg_devname);
269 lustre_cfg_bufs_set_string(&bufs, 1, uuid);
271 lcfg = lustre_cfg_new(LCFG_ADD_UUID, &bufs);
272 lcfg->lcfg_nid = nid;
273 /* Poison NAL -- pre 1.4.6 will LASSERT on 0 NAL, this way it
274 doesn't work without crashing (bz 10130) */
275 lcfg->lcfg_nal = 0x5a;
278 fprintf(stderr, "adding\tnid: %d\tuuid: %s\n",
279 lcfg->lcfg_nid, uuid);
281 rc = lcfg_ioctl(func, OBD_DEV_ID, lcfg);
282 lustre_cfg_free(lcfg);
284 fprintf(stderr, "IOC_PORTAL_ADD_UUID failed: %s\n",
289 printf ("Added uuid %s: %s\n", uuid, libcfs_nid2str(nid));
293 int jt_lcfg_add_uuid(int argc, char **argv)
301 nid = libcfs_str2nid(argv[2]);
302 if (nid == LNET_NID_ANY) {
303 fprintf (stderr, "Can't parse NID %s\n", argv[2]);
307 return do_add_uuid(argv[0], argv[1], nid);
310 int obd_add_uuid(char *uuid, lnet_nid_t nid)
312 return do_add_uuid("obd_add_uuid", uuid, nid);
315 int jt_lcfg_del_uuid(int argc, char **argv)
318 struct lustre_cfg_bufs bufs;
319 struct lustre_cfg *lcfg;
322 fprintf(stderr, "usage: %s <uuid>\n", argv[0]);
326 lustre_cfg_bufs_reset(&bufs, lcfg_devname);
327 if (strcmp (argv[1], "_all_"))
328 lustre_cfg_bufs_set_string(&bufs, 1, argv[1]);
330 lcfg = lustre_cfg_new(LCFG_DEL_UUID, &bufs);
331 rc = lcfg_ioctl(argv[0], OBD_DEV_ID, lcfg);
332 lustre_cfg_free(lcfg);
334 fprintf(stderr, "IOC_PORTAL_DEL_UUID failed: %s\n",
341 int jt_lcfg_del_mount_option(int argc, char **argv)
344 struct lustre_cfg_bufs bufs;
345 struct lustre_cfg *lcfg;
350 lustre_cfg_bufs_reset(&bufs, lcfg_devname);
353 lustre_cfg_bufs_set_string(&bufs, 1, argv[1]);
355 lcfg = lustre_cfg_new(LCFG_DEL_MOUNTOPT, &bufs);
356 rc = lcfg_ioctl(argv[0], OBD_DEV_ID, lcfg);
357 lustre_cfg_free(lcfg);
359 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
360 strerror(rc = errno));
365 int jt_lcfg_set_timeout(int argc, char **argv)
367 fprintf(stderr, "%s has been deprecated. Use conf_param instead.\n"
368 "e.g. conf_param sys.testfs.obd_timeout=50\n",
369 jt_cmdname(argv[0]));
373 int jt_lcfg_add_conn(int argc, char **argv)
375 struct lustre_cfg_bufs bufs;
376 struct lustre_cfg *lcfg;
387 if (lcfg_devname == NULL) {
388 fprintf(stderr, "%s: please use 'device name' to set the "
389 "device name for config commands.\n",
390 jt_cmdname(argv[0]));
394 lustre_cfg_bufs_reset(&bufs, lcfg_devname);
396 lustre_cfg_bufs_set_string(&bufs, 1, argv[1]);
398 lcfg = lustre_cfg_new(LCFG_ADD_CONN, &bufs);
399 lcfg->lcfg_num = priority;
401 rc = lcfg_ioctl(argv[0], OBD_DEV_ID, lcfg);
402 lustre_cfg_free (lcfg);
404 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
405 strerror(rc = errno));
411 int jt_lcfg_del_conn(int argc, char **argv)
413 struct lustre_cfg_bufs bufs;
414 struct lustre_cfg *lcfg;
420 if (lcfg_devname == NULL) {
421 fprintf(stderr, "%s: please use 'device name' to set the "
422 "device name for config commands.\n",
423 jt_cmdname(argv[0]));
427 lustre_cfg_bufs_reset(&bufs, lcfg_devname);
429 /* connection uuid */
430 lustre_cfg_bufs_set_string(&bufs, 1, argv[1]);
432 lcfg = lustre_cfg_new(LCFG_DEL_MOUNTOPT, &bufs);
434 rc = lcfg_ioctl(argv[0], OBD_DEV_ID, lcfg);
435 lustre_cfg_free(lcfg);
437 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
438 strerror(rc = errno));
444 /* Param set locally, directly on target */
445 int jt_lcfg_param(int argc, char **argv)
448 struct lustre_cfg_bufs bufs;
449 struct lustre_cfg *lcfg;
451 if (argc >= LUSTRE_CFG_MAX_BUFCOUNT)
454 lustre_cfg_bufs_reset(&bufs, NULL);
456 for (i = 1; i < argc; i++) {
457 lustre_cfg_bufs_set_string(&bufs, i, argv[i]);
460 lcfg = lustre_cfg_new(LCFG_PARAM, &bufs);
462 rc = lcfg_ioctl(argv[0], OBD_DEV_ID, lcfg);
463 lustre_cfg_free(lcfg);
465 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
466 strerror(rc = errno));
471 /* Could this element of a parameter be an obd type?
474 static int element_could_be_obd(char *el)
478 /* Rather than try to enumerate known obd types and risk
479 * becoming stale, I'm just going to check for no wacky chars */
480 while ((*ptr != '\0') && (*ptr != '.')) {
481 if (!isalpha(*ptr++))
487 /* Convert set_param into conf_param format. Examples of differences:
488 * conf_param testfs.sys.at_max=1200
489 * set_param at_max=1200 -- no fsname, but conf_param needs a valid one
490 * conf_param lustre.llite.max_read_ahead_mb=16
491 * set_param llite.lustre-ffff81003f157000.max_read_ahead_mb=16
492 * conf_param lustre-MDT0000.lov.stripesize=2M
493 * set_param lov.lustre-MDT0000-mdtlov.stripesize=2M
494 * set_param lov.lustre-clilov-ffff81003f157000.stripesize=2M -- clilov
495 * conf_param lustre-OST0001.osc.active=0
496 * set_param osc.lustre-OST0000-osc-ffff81003f157000.active=0
497 * conf_param lustre-OST0000.osc.max_dirty_mb=29.15
498 * set_param osc.lustre-OST0000-osc-ffff81003f157000.max_dirty_mb=16
499 * conf_param lustre-OST0001.ost.client_cache_seconds=15
500 * set_param obdfilter.lustre-OST0001.client_cache_seconds=15 -- obdfilter/ost
501 * conf_param testfs-OST0000.failover.node=1.2.3.4@tcp1
502 * no proc, but osc.testfs-OST0000.failover.node -- would be appropriate
504 static int rearrange_setparam_syntax(char *in)
506 char buf[MGS_PARAM_MAXLEN];
515 value = strchr(in, '=');
520 /* Separate elements 0.1.all_the_rest */
521 element[elements++] = in;
522 for (ptr = in; *ptr != '\0' && (elements < 3); ptr++) {
525 element[elements++] = ++ptr;
529 fprintf(stderr, "error: Parameter format is "
530 "<obd>.<fsname|devname>.<param>.\n"
531 "Wildcards are not supported. Examples:\n"
532 "sys.testfs.at_max=1200\n"
533 "llite.testfs.max_read_ahead_mb=16\n"
534 "lov.testfs-MDT0000.qos_threshold_rr=30\n"
535 "mdc.testfs-MDT0000.max_rpcs_in_flight=6\n"
536 "osc.testfs-OST0000.active=0\n"
537 "osc.testfs-OST0000.max_dirty_mb=16\n"
538 "obdfilter.testfs-OST0001.client_cache_seconds=15\n"
539 "osc.testfs-OST0000.failover.node=1.2.3.4@tcp\n\n"
544 /* e.g. testfs-OST003f-junk.ost.param */
545 rc = libcfs_str2server(element[0], &type, &index, &ptr);
547 *ptr = '\0'; /* trunc the junk */
550 /* e.g. ost.testfs-OST003f-junk.param */
551 rc = libcfs_str2server(element[1], &type, &index, &ptr);
557 /* llite.fsname.param or fsname.obd.param */
558 if (!element_could_be_obd(element[0]) &&
559 element_could_be_obd(element[1]))
560 /* fsname-junk.obd.param */
562 if (element_could_be_obd(element[0]) &&
563 !element_could_be_obd(element[1]))
564 /* obd.fsname-junk.param */
566 if (!element_could_be_obd(element[0]) &&
567 !element_could_be_obd(element[1])) {
568 fprintf(stderr, "error: Parameter format is "
569 "<obd>.<fsname|devname>.<param>\n");
572 /* Either element could be obd. Assume set_param syntax
573 * (obd.fsname.param) */
584 /* Don't worry Mom, we'll check it out */
585 if (strncmp(element[2], "failover", 8) != 0) { /* no proc for this */
588 if (strcmp(element[obd], "sys") == 0)
589 sprintf(buf, "%s", element[2]);
591 sprintf(buf, "%s.%s*.%s", element[obd], element[dev],
595 rc = jt_lcfg_listparam(3, argt);
597 fprintf(stderr, "warning: can't find local param '%s'\n"
598 "(but that service may not be running locally)."
602 /* s/obdfilter/ost/ */
603 if (strcmp(element[obd], "obdfilter") == 0)
604 sprintf(element[obd], "ost");
606 sprintf(buf, "%s.%s.%s=%s", element[dev], element[obd],
607 element[2], value + 1);
613 /* Param set in config log on MGS */
614 /* conf_param key=value */
615 /* Note we can actually send mgc conf_params from clients, but currently
616 * that's only done for default file striping (see ll_send_mgc_param),
618 /* After removal of a parameter (-d) Lustre will use the default
619 * AT NEXT REBOOT, not immediately. */
620 int jt_lcfg_mgsparam(int argc, char **argv)
624 struct lustre_cfg_bufs bufs;
625 struct lustre_cfg *lcfg;
626 char buf[MGS_PARAM_MAXLEN];
628 /* mgs_setparam processes only lctl buf #1 */
629 if ((argc > 3) || (argc <= 1))
632 while ((rc = getopt(argc, argv, "d")) != -1) {
645 /* for delete, make it "<param>=\0" */
646 /* put an '=' on the end in case it doesn't have one */
647 sprintf(buf, "%s=", argv[optind]);
648 /* then truncate after the first '=' */
649 ptr = strchr(buf, '=');
652 sprintf(buf, "%s", argv[optind]);
655 rc = rearrange_setparam_syntax(buf);
659 lustre_cfg_bufs_reset(&bufs, NULL);
660 lustre_cfg_bufs_set_string(&bufs, 1, buf);
662 /* We could put other opcodes here. */
663 lcfg = lustre_cfg_new(LCFG_PARAM, &bufs);
665 rc = lcfg_mgs_ioctl(argv[0], OBD_DEV_ID, lcfg);
666 lustre_cfg_free(lcfg);
668 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
669 strerror(rc = errno));
672 fprintf(stderr, "Does this filesystem/target exist on "
674 printf("Known targets:\n");
675 sprintf(buf, "mgs.MGS.live.*");
678 jt_lcfg_getparam(3, argt);
685 /* Display the path in the same format as sysctl
686 * For eg. obdfilter.lustre-OST0000.stats */
687 static char *display_name(char *filename, int show_type)
693 if (lstat(filename, &st) < 0)
697 filename += strlen("/proc/");
698 if (strncmp(filename, "fs/", strlen("fs/")) == 0)
699 filename += strlen("fs/");
701 filename += strlen("sys/");
703 if (strncmp(filename, "lustre/", strlen("lustre/")) == 0)
704 filename += strlen("lustre/");
705 else if (strncmp(filename, "lnet/", strlen("lnet/")) == 0)
706 filename += strlen("lnet/");
708 /* replace '/' with '.' to match conf_param and sysctl */
710 while ((tmp = strchr(tmp, '/')) != NULL)
713 /* append the indicator to entries */
715 if (S_ISDIR(st.st_mode))
716 strcat(filename, "/");
717 else if (S_ISLNK(st.st_mode))
718 strcat(filename, "@");
719 else if (st.st_mode & S_IWUSR)
720 strcat(filename, "=");
726 /* Find a character in a length limited string */
727 /* BEWARE - kernel definition of strnchr has args in different order! */
728 static char *strnchr(const char *p, char c, size_t n)
741 static char *globerrstr(int glob_rc)
745 return "Out of memory";
749 return "Found no match";
751 return "Unknown error";
754 static void clean_path(char *path)
758 /* If the input is in form Eg. obdfilter.*.stats */
759 if (strchr(path, '.')) {
761 while (*tmp != '\0') {
763 (tmp != path) && (*(tmp - 1) != '\\'))
768 /* get rid of '\', glob doesn't like it */
769 if ((tmp = strrchr(path, '\\')) != NULL) {
770 char *tail = path + strlen(path);
771 while (tmp != path) {
773 memmove(tmp, tmp + 1, tail - tmp);
788 static int listparam_cmdline(int argc, char **argv, struct param_opts *popt)
797 while ((ch = getopt(argc, argv, "FRq")) != -1) {
816 static int listparam_display(struct param_opts *popt, char *pattern)
821 char filename[PATH_MAX + 1]; /* extra 1 byte for file type */
823 rc = glob(pattern, GLOB_BRACE | (popt->recursive ? GLOB_MARK : 0),
826 if (popt->show_path) /* when quiet, don't show errors */
827 fprintf(stderr, "error: list_param: %s: %s\n",
828 pattern, globerrstr(rc));
832 if (popt->show_path) {
833 for (i = 0; i < glob_info.gl_pathc; i++) {
834 char *valuename = NULL;
837 /* Trailing '/' will indicate recursion into directory */
838 last = strlen(glob_info.gl_pathv[i]) - 1;
840 /* Remove trailing '/' or it will be converted to '.' */
841 if (last > 0 && glob_info.gl_pathv[i][last] == '/')
842 glob_info.gl_pathv[i][last] = '\0';
845 strcpy(filename, glob_info.gl_pathv[i]);
846 valuename = display_name(filename, popt->show_type);
848 printf("%s\n", valuename);
850 strcpy(filename, glob_info.gl_pathv[i]);
851 strcat(filename, "/*");
852 listparam_display(popt, filename);
857 globfree(&glob_info);
861 int jt_lcfg_listparam(int argc, char **argv)
865 struct param_opts popt;
866 char pattern[PATH_MAX];
869 rc = listparam_cmdline(argc, argv, &popt);
870 if (rc == argc && popt.recursive) {
871 rc--; /* we know at least "-R" is a parameter */
873 } else if (rc < 0 || rc >= argc) {
877 for (i = rc; i < argc; i++) {
882 /* If the entire path is specified as input */
883 fp = open(path, O_RDONLY);
885 snprintf(pattern, PATH_MAX, "/proc/{fs,sys}/{lnet,lustre}/%s",
888 strcpy(pattern, path);
892 rc = listparam_display(&popt, pattern);
900 static int getparam_cmdline(int argc, char **argv, struct param_opts *popt)
909 while ((ch = getopt(argc, argv, "nNF")) != -1) {
927 static int getparam_display(struct param_opts *popt, char *pattern)
934 char filename[PATH_MAX + 1]; /* extra 1 byte for file type */
936 rc = glob(pattern, GLOB_BRACE, NULL, &glob_info);
938 fprintf(stderr, "error: get_param: %s: %s\n",
939 pattern, globerrstr(rc));
943 buf = malloc(CFS_PAGE_SIZE);
944 for (i = 0; i < glob_info.gl_pathc; i++) {
945 char *valuename = NULL;
947 memset(buf, 0, CFS_PAGE_SIZE);
948 /* As listparam_display is used to show param name (with type),
949 * here "if (only_path)" is ignored.*/
950 if (popt->show_path) {
951 strcpy(filename, glob_info.gl_pathv[i]);
952 valuename = display_name(filename, 0);
955 /* Write the contents of file to stdout */
956 fd = open(glob_info.gl_pathv[i], O_RDONLY);
959 "error: get_param: opening('%s') failed: %s\n",
960 glob_info.gl_pathv[i], strerror(errno));
965 rc = read(fd, buf, CFS_PAGE_SIZE);
969 fprintf(stderr, "error: get_param: "
970 "read('%s') failed: %s\n",
971 glob_info.gl_pathv[i], strerror(errno));
974 /* Print the output in the format path=value if the
975 * value contains no new line character or can be
976 * occupied in a line, else print value on new line */
977 if (valuename && popt->show_path) {
978 int longbuf = strnchr(buf, rc - 1, '\n') != NULL
980 printf("%s=%s", valuename, longbuf ? "\n" : buf);
986 rc = write(fileno(stdout), buf, rc);
988 fprintf(stderr, "error: get_param: "
989 "write to stdout failed: %s\n",
997 globfree(&glob_info);
1002 int jt_lcfg_getparam(int argc, char **argv)
1006 struct param_opts popt;
1007 char pattern[PATH_MAX];
1010 rc = getparam_cmdline(argc, argv, &popt);
1011 if (rc < 0 || rc >= argc)
1014 for (i = rc; i < argc; i++) {
1019 /* If the entire path is specified as input */
1020 fp = open(path, O_RDONLY);
1022 snprintf(pattern, PATH_MAX, "/proc/{fs,sys}/{lnet,lustre}/%s",
1025 strcpy(pattern, path);
1030 rc = listparam_display(&popt, pattern);
1032 rc = getparam_display(&popt, pattern);
1040 static int setparam_cmdline(int argc, char **argv, struct param_opts *popt)
1044 popt->show_path = 1;
1045 popt->only_path = 0;
1046 popt->show_type = 0;
1047 popt->recursive = 0;
1049 while ((ch = getopt(argc, argv, "n")) != -1) {
1052 popt->show_path = 0;
1061 static int setparam_display(struct param_opts *popt, char *pattern, char *value)
1067 char filename[PATH_MAX + 1]; /* extra 1 byte for file type */
1069 rc = glob(pattern, GLOB_BRACE, NULL, &glob_info);
1071 fprintf(stderr, "error: set_param: %s: %s\n",
1072 pattern, globerrstr(rc));
1075 for (i = 0; i < glob_info.gl_pathc; i++) {
1076 char *valuename = NULL;
1078 if (popt->show_path) {
1079 strcpy(filename, glob_info.gl_pathv[i]);
1080 valuename = display_name(filename, 0);
1082 printf("%s=%s\n", valuename, value);
1084 /* Write the new value to the file */
1085 fd = open(glob_info.gl_pathv[i], O_WRONLY);
1087 rc = write(fd, value, strlen(value));
1089 fprintf(stderr, "error: set_param: "
1090 "writing to file %s: %s\n",
1091 glob_info.gl_pathv[i], strerror(errno));
1096 fprintf(stderr, "error: set_param: %s opening %s\n",
1097 strerror(rc = errno), glob_info.gl_pathv[i]);
1101 globfree(&glob_info);
1105 int jt_lcfg_setparam(int argc, char **argv)
1109 struct param_opts popt;
1110 char pattern[PATH_MAX];
1111 char *path = NULL, *value = NULL;
1113 rc = setparam_cmdline(argc, argv, &popt);
1114 if (rc < 0 || rc >= argc)
1117 for (i = rc; i < argc; i++) {
1118 if ((value = strchr(argv[i], '=')) != NULL) {
1119 /* format: set_param a=b */
1124 /* format: set_param a b */
1135 /* If the entire path is specified as input */
1136 fp = open(path, O_RDONLY);
1138 snprintf(pattern, PATH_MAX, "/proc/{fs,sys}/{lnet,lustre}/%s",
1141 strcpy(pattern, path);
1145 rc = setparam_display(&popt, pattern, value);