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.
32 * Copyright (c) 2011, 2012, Whamcloud, Inc.
35 * This file is part of Lustre, http://www.lustre.org/
36 * Lustre is a trademark of Sun Microsystems, Inc.
38 * lustre/utils/lustre_cfg.c
40 * Author: Peter J. Braam <braam@clusterfs.com>
41 * Author: Phil Schwan <phil@clusterfs.com>
42 * Author: Andreas Dilger <adilger@clusterfs.com>
43 * Author: Robert Read <rread@clusterfs.com>
47 #include <sys/ioctl.h>
55 #include <liblustre.h>
57 #include <lustre_lib.h>
58 #include <lustre_cfg.h>
59 #include <lustre/lustre_idl.h>
60 #include <lustre_dlm.h>
61 #include <obd.h> /* for struct lov_stripe_md */
63 #include <lustre/lustre_build_version.h>
74 #include <lnet/lnetctl.h>
75 #include <libcfs/libcfsutil.h>
78 static char * lcfg_devname;
80 int lcfg_set_devname(char *name)
88 /* quietly strip the unnecessary '$' */
89 if (*name == '$' || *name == '%')
93 while (*ptr != '\0') {
102 /* We can't translate from dev # to name */
105 lcfg_devname = strdup(name);
113 char * lcfg_get_devname(void)
118 int jt_lcfg_device(int argc, char **argv)
120 return jt_obd_device(argc, argv);
123 int jt_lcfg_attach(int argc, char **argv)
125 struct lustre_cfg_bufs bufs;
126 struct lustre_cfg *lcfg;
132 lustre_cfg_bufs_reset(&bufs, NULL);
134 lustre_cfg_bufs_set_string(&bufs, 1, argv[1]);
135 lustre_cfg_bufs_set_string(&bufs, 0, argv[2]);
136 lustre_cfg_bufs_set_string(&bufs, 2, argv[3]);
138 lcfg = lustre_cfg_new(LCFG_ATTACH, &bufs);
139 rc = lcfg_ioctl(argv[0], OBD_DEV_ID, lcfg);
140 lustre_cfg_free(lcfg);
142 fprintf(stderr, "error: %s: LCFG_ATTACH %s\n",
143 jt_cmdname(argv[0]), strerror(rc = errno));
144 } else if (argc == 3) {
147 lcfg_set_devname(argv[2]);
148 if (strlen(argv[2]) > 128) {
149 printf("Name too long to set environment\n");
152 snprintf(name, 512, "LUSTRE_DEV_%s", argv[2]);
153 rc = setenv(name, argv[1], 1);
155 printf("error setting env variable %s\n", name);
158 lcfg_set_devname(argv[2]);
164 int jt_lcfg_setup(int argc, char **argv)
166 struct lustre_cfg_bufs bufs;
167 struct lustre_cfg *lcfg;
171 if (lcfg_devname == NULL) {
172 fprintf(stderr, "%s: please use 'device name' to set the "
173 "device name for config commands.\n",
174 jt_cmdname(argv[0]));
178 lustre_cfg_bufs_reset(&bufs, lcfg_devname);
183 for (i = 1; i < argc; i++) {
184 lustre_cfg_bufs_set_string(&bufs, i, argv[i]);
187 lcfg = lustre_cfg_new(LCFG_SETUP, &bufs);
188 rc = lcfg_ioctl(argv[0], OBD_DEV_ID, lcfg);
189 lustre_cfg_free(lcfg);
191 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
192 strerror(rc = errno));
197 int jt_obd_detach(int argc, char **argv)
199 struct lustre_cfg_bufs bufs;
200 struct lustre_cfg *lcfg;
203 if (lcfg_devname == NULL) {
204 fprintf(stderr, "%s: please use 'device name' to set the "
205 "device name for config commands.\n",
206 jt_cmdname(argv[0]));
210 lustre_cfg_bufs_reset(&bufs, lcfg_devname);
215 lcfg = lustre_cfg_new(LCFG_DETACH, &bufs);
216 rc = lcfg_ioctl(argv[0], OBD_DEV_ID, lcfg);
217 lustre_cfg_free(lcfg);
219 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
220 strerror(rc = errno));
225 int jt_obd_cleanup(int argc, char **argv)
227 struct lustre_cfg_bufs bufs;
228 struct lustre_cfg *lcfg;
231 char flags[3] = { 0 };
235 if (lcfg_devname == NULL) {
236 fprintf(stderr, "%s: please use 'device name' to set the "
237 "device name for config commands.\n",
238 jt_cmdname(argv[0]));
242 lustre_cfg_bufs_reset(&bufs, lcfg_devname);
244 if (argc < 1 || argc > 3)
247 /* we are protected from overflowing our buffer by the argc
250 for (n = 1; n < argc; n++) {
251 if (strcmp(argv[n], "force") == 0) {
252 flags[flag_cnt++] = force;
253 } else if (strcmp(argv[n], "failover") == 0) {
254 flags[flag_cnt++] = failover;
256 fprintf(stderr, "unknown option: %s", argv[n]);
262 lustre_cfg_bufs_set_string(&bufs, 1, flags);
265 lcfg = lustre_cfg_new(LCFG_CLEANUP, &bufs);
266 rc = lcfg_ioctl(argv[0], OBD_DEV_ID, lcfg);
267 lustre_cfg_free(lcfg);
269 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
270 strerror(rc = errno));
276 int do_add_uuid(char * func, char *uuid, lnet_nid_t nid)
279 struct lustre_cfg_bufs bufs;
280 struct lustre_cfg *lcfg;
282 lustre_cfg_bufs_reset(&bufs, lcfg_devname);
284 lustre_cfg_bufs_set_string(&bufs, 1, uuid);
286 lcfg = lustre_cfg_new(LCFG_ADD_UUID, &bufs);
287 lcfg->lcfg_nid = nid;
288 /* Poison NAL -- pre 1.4.6 will LASSERT on 0 NAL, this way it
289 doesn't work without crashing (bz 10130) */
290 lcfg->lcfg_nal = 0x5a;
293 fprintf(stderr, "adding\tnid: %d\tuuid: %s\n",
294 lcfg->lcfg_nid, uuid);
296 rc = lcfg_ioctl(func, OBD_DEV_ID, lcfg);
297 lustre_cfg_free(lcfg);
299 fprintf(stderr, "IOC_PORTAL_ADD_UUID failed: %s\n",
304 printf ("Added uuid %s: %s\n", uuid, libcfs_nid2str(nid));
308 int jt_lcfg_add_uuid(int argc, char **argv)
316 nid = libcfs_str2nid(argv[2]);
317 if (nid == LNET_NID_ANY) {
318 fprintf (stderr, "Can't parse NID %s\n", argv[2]);
322 return do_add_uuid(argv[0], argv[1], nid);
325 int obd_add_uuid(char *uuid, lnet_nid_t nid)
327 return do_add_uuid("obd_add_uuid", uuid, nid);
330 int jt_lcfg_del_uuid(int argc, char **argv)
333 struct lustre_cfg_bufs bufs;
334 struct lustre_cfg *lcfg;
337 fprintf(stderr, "usage: %s <uuid>\n", argv[0]);
341 lustre_cfg_bufs_reset(&bufs, lcfg_devname);
342 if (strcmp (argv[1], "_all_"))
343 lustre_cfg_bufs_set_string(&bufs, 1, argv[1]);
345 lcfg = lustre_cfg_new(LCFG_DEL_UUID, &bufs);
346 rc = lcfg_ioctl(argv[0], OBD_DEV_ID, lcfg);
347 lustre_cfg_free(lcfg);
349 fprintf(stderr, "IOC_PORTAL_DEL_UUID failed: %s\n",
356 int jt_lcfg_del_mount_option(int argc, char **argv)
359 struct lustre_cfg_bufs bufs;
360 struct lustre_cfg *lcfg;
365 lustre_cfg_bufs_reset(&bufs, lcfg_devname);
368 lustre_cfg_bufs_set_string(&bufs, 1, argv[1]);
370 lcfg = lustre_cfg_new(LCFG_DEL_MOUNTOPT, &bufs);
371 rc = lcfg_ioctl(argv[0], OBD_DEV_ID, lcfg);
372 lustre_cfg_free(lcfg);
374 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
375 strerror(rc = errno));
380 int jt_lcfg_set_timeout(int argc, char **argv)
383 struct lustre_cfg_bufs bufs;
384 struct lustre_cfg *lcfg;
386 fprintf(stderr, "%s has been deprecated. Use conf_param instead.\n"
387 "e.g. conf_param lustre-MDT0000 obd_timeout=50\n",
388 jt_cmdname(argv[0]));
395 lustre_cfg_bufs_reset(&bufs, lcfg_devname);
396 lcfg = lustre_cfg_new(LCFG_SET_TIMEOUT, &bufs);
397 lcfg->lcfg_num = atoi(argv[1]);
399 rc = lcfg_ioctl(argv[0], OBD_DEV_ID, lcfg);
400 //rc = lcfg_mgs_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));
410 int jt_lcfg_add_conn(int argc, char **argv)
412 struct lustre_cfg_bufs bufs;
413 struct lustre_cfg *lcfg;
424 if (lcfg_devname == NULL) {
425 fprintf(stderr, "%s: please use 'device name' to set the "
426 "device name for config commands.\n",
427 jt_cmdname(argv[0]));
431 lustre_cfg_bufs_reset(&bufs, lcfg_devname);
433 lustre_cfg_bufs_set_string(&bufs, 1, argv[1]);
435 lcfg = lustre_cfg_new(LCFG_ADD_CONN, &bufs);
436 lcfg->lcfg_num = priority;
438 rc = lcfg_ioctl(argv[0], OBD_DEV_ID, lcfg);
439 lustre_cfg_free (lcfg);
441 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
442 strerror(rc = errno));
448 int jt_lcfg_del_conn(int argc, char **argv)
450 struct lustre_cfg_bufs bufs;
451 struct lustre_cfg *lcfg;
457 if (lcfg_devname == NULL) {
458 fprintf(stderr, "%s: please use 'device name' to set the "
459 "device name for config commands.\n",
460 jt_cmdname(argv[0]));
464 lustre_cfg_bufs_reset(&bufs, lcfg_devname);
466 /* connection uuid */
467 lustre_cfg_bufs_set_string(&bufs, 1, argv[1]);
469 lcfg = lustre_cfg_new(LCFG_DEL_MOUNTOPT, &bufs);
471 rc = lcfg_ioctl(argv[0], OBD_DEV_ID, lcfg);
472 lustre_cfg_free(lcfg);
474 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
475 strerror(rc = errno));
481 /* Param set locally, directly on target */
482 int jt_lcfg_param(int argc, char **argv)
485 struct lustre_cfg_bufs bufs;
486 struct lustre_cfg *lcfg;
488 if (argc >= LUSTRE_CFG_MAX_BUFCOUNT)
491 lustre_cfg_bufs_reset(&bufs, NULL);
493 for (i = 1; i < argc; i++) {
494 lustre_cfg_bufs_set_string(&bufs, i, argv[i]);
497 lcfg = lustre_cfg_new(LCFG_PARAM, &bufs);
499 rc = lcfg_ioctl(argv[0], OBD_DEV_ID, lcfg);
500 lustre_cfg_free(lcfg);
502 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
503 strerror(rc = errno));
508 /* Param set in config log on MGS */
509 /* conf_param key=value */
510 /* Note we can actually send mgc conf_params from clients, but currently
511 * that's only done for default file striping (see ll_send_mgc_param),
513 /* After removal of a parameter (-d) Lustre will use the default
514 * AT NEXT REBOOT, not immediately. */
515 int jt_lcfg_mgsparam(int argc, char **argv)
519 struct lustre_cfg_bufs bufs;
520 struct lustre_cfg *lcfg;
523 /* mgs_setparam processes only lctl buf #1 */
524 if ((argc > 3) || (argc <= 1))
527 while ((rc = getopt(argc, argv, "d")) != -1) {
537 lustre_cfg_bufs_reset(&bufs, NULL);
541 /* for delete, make it "<param>=\0" */
542 buf = malloc(strlen(argv[optind]) + 2);
543 /* put an '=' on the end in case it doesn't have one */
544 sprintf(buf, "%s=", argv[optind]);
545 /* then truncate after the first '=' */
546 ptr = strchr(buf, '=');
548 lustre_cfg_bufs_set_string(&bufs, 1, buf);
550 lustre_cfg_bufs_set_string(&bufs, 1, argv[optind]);
553 /* We could put other opcodes here. */
554 lcfg = lustre_cfg_new(LCFG_PARAM, &bufs);
556 rc = lcfg_mgs_ioctl(argv[0], OBD_DEV_ID, lcfg);
557 lustre_cfg_free(lcfg);
561 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
562 strerror(rc = errno));
568 /* Display the path in the same format as sysctl
569 * For eg. obdfilter.lustre-OST0000.stats */
570 static char *display_name(char *filename, int show_type)
576 if (lstat(filename, &st) < 0)
580 filename += strlen("/proc/");
581 if (strncmp(filename, "fs/", strlen("fs/")) == 0)
582 filename += strlen("fs/");
584 filename += strlen("sys/");
586 if (strncmp(filename, "lustre/", strlen("lustre/")) == 0)
587 filename += strlen("lustre/");
588 else if (strncmp(filename, "lnet/", strlen("lnet/")) == 0)
589 filename += strlen("lnet/");
591 /* replace '/' with '.' to match conf_param and sysctl */
593 while ((tmp = strchr(tmp, '/')) != NULL)
596 /* append the indicator to entries */
598 if (S_ISDIR(st.st_mode))
599 strcat(filename, "/");
600 else if (S_ISLNK(st.st_mode))
601 strcat(filename, "@");
602 else if (st.st_mode & S_IWUSR)
603 strcat(filename, "=");
609 /* Find a character in a length limited string */
610 /* BEWARE - kernel definition of strnchr has args in different order! */
611 static char *strnchr(const char *p, char c, size_t n)
624 static char *globerrstr(int glob_rc)
628 return "Out of memory";
632 return "Found no match";
634 return "Unknown error";
637 static void clean_path(char *path)
641 /* If the input is in form Eg. obdfilter.*.stats */
642 if (strchr(path, '.')) {
644 while (*tmp != '\0') {
646 (tmp != path) && (*(tmp - 1) != '\\'))
651 /* get rid of '\', glob doesn't like it */
652 if ((tmp = strrchr(path, '\\')) != NULL) {
653 char *tail = path + strlen(path);
654 while (tmp != path) {
656 memmove(tmp, tmp + 1, tail - tmp);
664 /* Supporting file paths creates perilous behavoir: LU-888.
665 * Path support is deprecated.
666 * If a path is supplied it must begin with /proc. */
667 static void lprocfs_param_pattern(const char *cmd, const char *path, char *buf,
670 /* test path to see if it begins with '/proc/' */
671 if (strncmp(path, "/proc/", strlen("/proc/")) == 0) {
674 fprintf(stderr, "%s: specifying parameters via "
675 "full paths is deprecated.\n", cmd);
676 #if LUSTRE_VERSION_CODE >= OBD_OCD_VERSION(2,6,50,0)
677 #warning "remove deprecated full path tunable access"
681 snprintf(buf, buf_size, "%s", path);
683 snprintf(buf, buf_size, "/proc/{fs,sys}/{lnet,lustre}/%s",
695 static int listparam_cmdline(int argc, char **argv, struct param_opts *popt)
704 while ((ch = getopt(argc, argv, "FR")) != -1) {
720 static int listparam_display(struct param_opts *popt, char *pattern)
725 char filename[PATH_MAX + 1]; /* extra 1 byte for file type */
727 rc = glob(pattern, GLOB_BRACE | (popt->recursive ? GLOB_MARK : 0),
730 fprintf(stderr, "error: list_param: %s: %s\n",
731 pattern, globerrstr(rc));
735 for (i = 0; i < glob_info.gl_pathc; i++) {
736 char *valuename = NULL;
739 /* Trailing '/' will indicate recursion into directory */
740 last = strlen(glob_info.gl_pathv[i]) - 1;
742 /* Remove trailing '/' or it will be converted to '.' */
743 if (last > 0 && glob_info.gl_pathv[i][last] == '/')
744 glob_info.gl_pathv[i][last] = '\0';
747 strcpy(filename, glob_info.gl_pathv[i]);
748 valuename = display_name(filename, popt->show_type);
750 printf("%s\n", valuename);
752 strcpy(filename, glob_info.gl_pathv[i]);
753 strcat(filename, "/*");
754 listparam_display(popt, filename);
758 globfree(&glob_info);
762 int jt_lcfg_listparam(int argc, char **argv)
765 struct param_opts popt;
766 char pattern[PATH_MAX];
769 rc = listparam_cmdline(argc, argv, &popt);
770 if (rc == argc && popt.recursive) {
771 rc--; /* we know at least "-R" is a parameter */
773 } else if (rc < 0 || rc >= argc) {
777 for (i = rc; i < argc; i++) {
782 lprocfs_param_pattern(argv[0], path, pattern, sizeof(pattern));
784 rc = listparam_display(&popt, pattern);
792 static int getparam_cmdline(int argc, char **argv, struct param_opts *popt)
801 while ((ch = getopt(argc, argv, "nNF")) != -1) {
819 static int getparam_display(struct param_opts *popt, char *pattern)
826 char filename[PATH_MAX + 1]; /* extra 1 byte for file type */
828 rc = glob(pattern, GLOB_BRACE, NULL, &glob_info);
830 fprintf(stderr, "error: get_param: %s: %s\n",
831 pattern, globerrstr(rc));
835 buf = malloc(CFS_PAGE_SIZE);
836 for (i = 0; i < glob_info.gl_pathc; i++) {
837 char *valuename = NULL;
839 memset(buf, 0, CFS_PAGE_SIZE);
840 /* As listparam_display is used to show param name (with type),
841 * here "if (only_path)" is ignored.*/
842 if (popt->show_path) {
843 strcpy(filename, glob_info.gl_pathv[i]);
844 valuename = display_name(filename, 0);
847 /* Write the contents of file to stdout */
848 fd = open(glob_info.gl_pathv[i], O_RDONLY);
851 "error: get_param: opening('%s') failed: %s\n",
852 glob_info.gl_pathv[i], strerror(errno));
857 rc = read(fd, buf, CFS_PAGE_SIZE);
861 fprintf(stderr, "error: get_param: "
862 "read('%s') failed: %s\n",
863 glob_info.gl_pathv[i], strerror(errno));
866 /* Print the output in the format path=value if the
867 * value contains no new line character or cab be
868 * occupied in a line, else print value on new line */
869 if (valuename && popt->show_path) {
870 int longbuf = strnchr(buf, rc - 1, '\n') != NULL
872 printf("%s=%s", valuename, longbuf ? "\n" : buf);
878 rc = write(fileno(stdout), buf, rc);
880 fprintf(stderr, "error: get_param: "
881 "write to stdout failed: %s\n",
889 globfree(&glob_info);
894 int jt_lcfg_getparam(int argc, char **argv)
897 struct param_opts popt;
898 char pattern[PATH_MAX];
901 rc = getparam_cmdline(argc, argv, &popt);
902 if (rc < 0 || rc >= argc)
905 for (i = rc; i < argc; i++) {
910 lprocfs_param_pattern(argv[0], path, pattern, sizeof(pattern));
913 rc = listparam_display(&popt, pattern);
915 rc = getparam_display(&popt, pattern);
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; i < argc; i++) {
1000 if ((value = strchr(argv[i], '=')) != NULL) {
1001 /* format: set_param a=b */
1006 /* format: set_param a b */
1017 lprocfs_param_pattern(argv[0], path, pattern, sizeof(pattern));
1019 rc = setparam_display(&popt, pattern, value);