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, Whamcloud, Inc.
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));
506 /* Param set in config log on MGS */
507 /* conf_param key=value */
508 /* Note we can actually send mgc conf_params from clients, but currently
509 * that's only done for default file striping (see ll_send_mgc_param),
511 /* After removal of a parameter (-d) Lustre will use the default
512 * AT NEXT REBOOT, not immediately. */
513 int jt_lcfg_mgsparam(int argc, char **argv)
517 struct lustre_cfg_bufs bufs;
518 struct lustre_cfg *lcfg;
521 /* mgs_setparam processes only lctl buf #1 */
522 if ((argc > 3) || (argc <= 1))
525 while ((rc = getopt(argc, argv, "d")) != -1) {
535 lustre_cfg_bufs_reset(&bufs, NULL);
539 /* for delete, make it "<param>=\0" */
540 buf = malloc(strlen(argv[optind]) + 2);
541 /* put an '=' on the end in case it doesn't have one */
542 sprintf(buf, "%s=", argv[optind]);
543 /* then truncate after the first '=' */
544 ptr = strchr(buf, '=');
546 lustre_cfg_bufs_set_string(&bufs, 1, buf);
548 lustre_cfg_bufs_set_string(&bufs, 1, argv[optind]);
551 /* We could put other opcodes here. */
552 lcfg = lustre_cfg_new(LCFG_PARAM, &bufs);
554 rc = lcfg_mgs_ioctl(argv[0], OBD_DEV_ID, lcfg);
555 lustre_cfg_free(lcfg);
559 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
560 strerror(rc = errno));
566 /* Display the path in the same format as sysctl
567 * For eg. obdfilter.lustre-OST0000.stats */
568 static char *display_name(char *filename, int show_type)
574 if (lstat(filename, &st) < 0)
578 filename += strlen("/proc/");
579 if (strncmp(filename, "fs/", strlen("fs/")) == 0)
580 filename += strlen("fs/");
582 filename += strlen("sys/");
584 if (strncmp(filename, "lustre/", strlen("lustre/")) == 0)
585 filename += strlen("lustre/");
586 else if (strncmp(filename, "lnet/", strlen("lnet/")) == 0)
587 filename += strlen("lnet/");
589 /* replace '/' with '.' to match conf_param and sysctl */
591 while ((tmp = strchr(tmp, '/')) != NULL)
594 /* append the indicator to entries */
596 if (S_ISDIR(st.st_mode))
597 strcat(filename, "/");
598 else if (S_ISLNK(st.st_mode))
599 strcat(filename, "@");
600 else if (st.st_mode & S_IWUSR)
601 strcat(filename, "=");
607 /* Find a character in a length limited string */
608 /* BEWARE - kernel definition of strnchr has args in different order! */
609 static char *strnchr(const char *p, char c, size_t n)
622 static char *globerrstr(int glob_rc)
626 return "Out of memory";
630 return "Found no match";
632 return "Unknown error";
635 static void clean_path(char *path)
639 /* If the input is in form Eg. obdfilter.*.stats */
640 if (strchr(path, '.')) {
642 while (*tmp != '\0') {
644 (tmp != path) && (*(tmp - 1) != '\\'))
649 /* get rid of '\', glob doesn't like it */
650 if ((tmp = strrchr(path, '\\')) != NULL) {
651 char *tail = path + strlen(path);
652 while (tmp != path) {
654 memmove(tmp, tmp + 1, tail - tmp);
662 /* Supporting file paths creates perilous behavoir: LU-888.
663 * Path support is deprecated.
664 * If a path is supplied it must begin with /proc. */
665 static void lprocfs_param_pattern(const char *cmd, const char *path, char *buf,
668 /* test path to see if it begins with '/proc/' */
669 if (strncmp(path, "/proc/", strlen("/proc/")) == 0) {
672 fprintf(stderr, "%s: specifying parameters via "
673 "full paths is deprecated.\n", cmd);
674 #if LUSTRE_VERSION_CODE >= OBD_OCD_VERSION(2, 6, 50, 0)
675 #warning "remove deprecated full path tunable access"
679 snprintf(buf, buf_size, "%s", path);
681 snprintf(buf, buf_size, "/proc/{fs,sys}/{lnet,lustre}/%s",
693 static int listparam_cmdline(int argc, char **argv, struct param_opts *popt)
702 while ((ch = getopt(argc, argv, "FR")) != -1) {
718 static int listparam_display(struct param_opts *popt, char *pattern)
723 char filename[PATH_MAX + 1]; /* extra 1 byte for file type */
725 rc = glob(pattern, GLOB_BRACE | (popt->recursive ? GLOB_MARK : 0),
728 fprintf(stderr, "error: list_param: %s: %s\n",
729 pattern, globerrstr(rc));
733 for (i = 0; i < glob_info.gl_pathc; i++) {
734 char *valuename = NULL;
737 /* Trailing '/' will indicate recursion into directory */
738 last = strlen(glob_info.gl_pathv[i]) - 1;
740 /* Remove trailing '/' or it will be converted to '.' */
741 if (last > 0 && glob_info.gl_pathv[i][last] == '/')
742 glob_info.gl_pathv[i][last] = '\0';
745 strcpy(filename, glob_info.gl_pathv[i]);
746 valuename = display_name(filename, popt->show_type);
748 printf("%s\n", valuename);
750 strcpy(filename, glob_info.gl_pathv[i]);
751 strcat(filename, "/*");
752 listparam_display(popt, filename);
756 globfree(&glob_info);
760 int jt_lcfg_listparam(int argc, char **argv)
763 struct param_opts popt;
764 char pattern[PATH_MAX];
767 rc = listparam_cmdline(argc, argv, &popt);
768 if (rc == argc && popt.recursive) {
769 rc--; /* we know at least "-R" is a parameter */
771 } else if (rc < 0 || rc >= argc) {
775 for (i = rc; i < argc; i++) {
780 lprocfs_param_pattern(argv[0], path, pattern, sizeof(pattern));
782 rc = listparam_display(&popt, pattern);
790 static int getparam_cmdline(int argc, char **argv, struct param_opts *popt)
799 while ((ch = getopt(argc, argv, "nNF")) != -1) {
817 static int getparam_display(struct param_opts *popt, char *pattern)
824 char filename[PATH_MAX + 1]; /* extra 1 byte for file type */
826 rc = glob(pattern, GLOB_BRACE, NULL, &glob_info);
828 fprintf(stderr, "error: get_param: %s: %s\n",
829 pattern, globerrstr(rc));
833 buf = malloc(CFS_PAGE_SIZE);
834 for (i = 0; i < glob_info.gl_pathc; i++) {
835 char *valuename = NULL;
837 memset(buf, 0, CFS_PAGE_SIZE);
838 /* As listparam_display is used to show param name (with type),
839 * here "if (only_path)" is ignored.*/
840 if (popt->show_path) {
841 strcpy(filename, glob_info.gl_pathv[i]);
842 valuename = display_name(filename, 0);
845 /* Write the contents of file to stdout */
846 fd = open(glob_info.gl_pathv[i], O_RDONLY);
849 "error: get_param: opening('%s') failed: %s\n",
850 glob_info.gl_pathv[i], strerror(errno));
855 rc = read(fd, buf, CFS_PAGE_SIZE);
859 fprintf(stderr, "error: get_param: "
860 "read('%s') failed: %s\n",
861 glob_info.gl_pathv[i], strerror(errno));
864 /* Print the output in the format path=value if the
865 * value contains no new line character or cab be
866 * occupied in a line, else print value on new line */
867 if (valuename && popt->show_path) {
868 int longbuf = strnchr(buf, rc - 1, '\n') != NULL
870 printf("%s=%s", valuename, longbuf ? "\n" : buf);
876 rc = write(fileno(stdout), buf, rc);
878 fprintf(stderr, "error: get_param: "
879 "write to stdout failed: %s\n",
887 globfree(&glob_info);
892 int jt_lcfg_getparam(int argc, char **argv)
895 struct param_opts popt;
896 char pattern[PATH_MAX];
899 rc = getparam_cmdline(argc, argv, &popt);
900 if (rc < 0 || rc >= argc)
903 for (i = rc, rc = 0; i < argc; i++) {
910 lprocfs_param_pattern(argv[0], path, pattern, sizeof(pattern));
913 rc2 = listparam_display(&popt, pattern);
915 rc2 = getparam_display(&popt, pattern);
916 if (rc2 < 0 && rc == 0)
923 static int setparam_cmdline(int argc, char **argv, struct param_opts *popt)
932 while ((ch = getopt(argc, argv, "n")) != -1) {
944 static int setparam_display(struct param_opts *popt, char *pattern, char *value)
950 char filename[PATH_MAX + 1]; /* extra 1 byte for file type */
952 rc = glob(pattern, GLOB_BRACE, NULL, &glob_info);
954 fprintf(stderr, "error: set_param: %s: %s\n",
955 pattern, globerrstr(rc));
958 for (i = 0; i < glob_info.gl_pathc; i++) {
959 char *valuename = NULL;
961 if (popt->show_path) {
962 strcpy(filename, glob_info.gl_pathv[i]);
963 valuename = display_name(filename, 0);
965 printf("%s=%s\n", valuename, value);
967 /* Write the new value to the file */
968 fd = open(glob_info.gl_pathv[i], O_WRONLY);
970 rc = write(fd, value, strlen(value));
972 fprintf(stderr, "error: set_param: "
973 "writing to file %s: %s\n",
974 glob_info.gl_pathv[i], strerror(errno));
979 fprintf(stderr, "error: set_param: %s opening %s\n",
980 strerror(rc = errno), glob_info.gl_pathv[i]);
984 globfree(&glob_info);
988 int jt_lcfg_setparam(int argc, char **argv)
991 struct param_opts popt;
992 char pattern[PATH_MAX];
993 char *path = NULL, *value = NULL;
995 rc = setparam_cmdline(argc, argv, &popt);
996 if (rc < 0 || rc >= argc)
999 for (i = rc, rc = 0; i < argc; i++) {
1002 if ((value = strchr(argv[i], '=')) != NULL) {
1003 /* format: set_param a=b */
1008 /* format: set_param a b */
1019 lprocfs_param_pattern(argv[0], path, pattern, sizeof(pattern));
1021 rc2 = setparam_display(&popt, pattern, value);
1024 if (rc2 < 0 && rc == 0)