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 2008 Sun Microsystems, Inc. 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>
52 #include <liblustre.h>
54 #include <lustre_lib.h>
55 #include <lustre_cfg.h>
56 #include <lustre/lustre_idl.h>
57 #include <lustre_dlm.h>
58 #include <obd.h> /* for struct lov_stripe_md */
60 #include <lustre/lustre_build_version.h>
71 #include <lnet/lnetctl.h>
72 #include <libcfs/libcfsutil.h>
75 static char * lcfg_devname;
77 int lcfg_set_devname(char *name)
82 /* quietly strip the unnecessary '$' */
83 if (*name == '$' || *name == '%')
86 /* We can't translate from dev # to name */
89 lcfg_devname = strdup(name);
97 char * lcfg_get_devname(void)
102 int jt_lcfg_device(int argc, char **argv)
104 return jt_obd_device(argc, argv);
107 int jt_lcfg_attach(int argc, char **argv)
109 struct lustre_cfg_bufs bufs;
110 struct lustre_cfg *lcfg;
116 lustre_cfg_bufs_reset(&bufs, NULL);
118 lustre_cfg_bufs_set_string(&bufs, 1, argv[1]);
119 lustre_cfg_bufs_set_string(&bufs, 0, argv[2]);
120 lustre_cfg_bufs_set_string(&bufs, 2, argv[3]);
122 lcfg = lustre_cfg_new(LCFG_ATTACH, &bufs);
123 rc = lcfg_ioctl(argv[0], OBD_DEV_ID, lcfg);
124 lustre_cfg_free(lcfg);
126 fprintf(stderr, "error: %s: LCFG_ATTACH %s\n",
127 jt_cmdname(argv[0]), strerror(rc = errno));
128 } else if (argc == 3) {
131 lcfg_set_devname(argv[2]);
132 if (strlen(argv[2]) > 128) {
133 printf("Name too long to set environment\n");
136 snprintf(name, 512, "LUSTRE_DEV_%s", argv[2]);
137 rc = setenv(name, argv[1], 1);
139 printf("error setting env variable %s\n", name);
142 lcfg_set_devname(argv[2]);
148 int jt_lcfg_setup(int argc, char **argv)
150 struct lustre_cfg_bufs bufs;
151 struct lustre_cfg *lcfg;
155 if (lcfg_devname == NULL) {
156 fprintf(stderr, "%s: please use 'device name' to set the "
157 "device name for config commands.\n",
158 jt_cmdname(argv[0]));
162 lustre_cfg_bufs_reset(&bufs, lcfg_devname);
167 for (i = 1; i < argc; i++) {
168 lustre_cfg_bufs_set_string(&bufs, i, argv[i]);
171 lcfg = lustre_cfg_new(LCFG_SETUP, &bufs);
172 rc = lcfg_ioctl(argv[0], OBD_DEV_ID, lcfg);
173 lustre_cfg_free(lcfg);
175 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
176 strerror(rc = errno));
181 int jt_obd_detach(int argc, char **argv)
183 struct lustre_cfg_bufs bufs;
184 struct lustre_cfg *lcfg;
187 if (lcfg_devname == NULL) {
188 fprintf(stderr, "%s: please use 'device name' to set the "
189 "device name for config commands.\n",
190 jt_cmdname(argv[0]));
194 lustre_cfg_bufs_reset(&bufs, lcfg_devname);
199 lcfg = lustre_cfg_new(LCFG_DETACH, &bufs);
200 rc = lcfg_ioctl(argv[0], OBD_DEV_ID, lcfg);
201 lustre_cfg_free(lcfg);
203 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
204 strerror(rc = errno));
209 int jt_obd_cleanup(int argc, char **argv)
211 struct lustre_cfg_bufs bufs;
212 struct lustre_cfg *lcfg;
215 char flags[3] = { 0 };
219 if (lcfg_devname == NULL) {
220 fprintf(stderr, "%s: please use 'device name' to set the "
221 "device name for config commands.\n",
222 jt_cmdname(argv[0]));
226 lustre_cfg_bufs_reset(&bufs, lcfg_devname);
228 if (argc < 1 || argc > 3)
231 /* we are protected from overflowing our buffer by the argc
234 for (n = 1; n < argc; n++) {
235 if (strcmp(argv[n], "force") == 0) {
236 flags[flag_cnt++] = force;
237 } else if (strcmp(argv[n], "failover") == 0) {
238 flags[flag_cnt++] = failover;
240 fprintf(stderr, "unknown option: %s", argv[n]);
246 lustre_cfg_bufs_set_string(&bufs, 1, flags);
249 lcfg = lustre_cfg_new(LCFG_CLEANUP, &bufs);
250 rc = lcfg_ioctl(argv[0], OBD_DEV_ID, lcfg);
251 lustre_cfg_free(lcfg);
253 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
254 strerror(rc = errno));
260 int do_add_uuid(char * func, char *uuid, lnet_nid_t nid)
263 struct lustre_cfg_bufs bufs;
264 struct lustre_cfg *lcfg;
266 lustre_cfg_bufs_reset(&bufs, lcfg_devname);
268 lustre_cfg_bufs_set_string(&bufs, 1, uuid);
270 lcfg = lustre_cfg_new(LCFG_ADD_UUID, &bufs);
271 lcfg->lcfg_nid = nid;
272 /* Poison NAL -- pre 1.4.6 will LASSERT on 0 NAL, this way it
273 doesn't work without crashing (bz 10130) */
274 lcfg->lcfg_nal = 0x5a;
277 fprintf(stderr, "adding\tnid: %d\tuuid: %s\n",
278 lcfg->lcfg_nid, uuid);
280 rc = lcfg_ioctl(func, OBD_DEV_ID, lcfg);
281 lustre_cfg_free(lcfg);
283 fprintf(stderr, "IOC_PORTAL_ADD_UUID failed: %s\n",
288 printf ("Added uuid %s: %s\n", uuid, libcfs_nid2str(nid));
292 int jt_lcfg_add_uuid(int argc, char **argv)
300 nid = libcfs_str2nid(argv[2]);
301 if (nid == LNET_NID_ANY) {
302 fprintf (stderr, "Can't parse NID %s\n", argv[2]);
306 return do_add_uuid(argv[0], argv[1], nid);
309 int obd_add_uuid(char *uuid, lnet_nid_t nid)
311 return do_add_uuid("obd_add_uuid", uuid, nid);
314 int jt_lcfg_del_uuid(int argc, char **argv)
317 struct lustre_cfg_bufs bufs;
318 struct lustre_cfg *lcfg;
321 fprintf(stderr, "usage: %s <uuid>\n", argv[0]);
325 lustre_cfg_bufs_reset(&bufs, lcfg_devname);
326 if (strcmp (argv[1], "_all_"))
327 lustre_cfg_bufs_set_string(&bufs, 1, argv[1]);
329 lcfg = lustre_cfg_new(LCFG_DEL_UUID, &bufs);
330 rc = lcfg_ioctl(argv[0], OBD_DEV_ID, lcfg);
331 lustre_cfg_free(lcfg);
333 fprintf(stderr, "IOC_PORTAL_DEL_UUID failed: %s\n",
340 int jt_lcfg_del_mount_option(int argc, char **argv)
343 struct lustre_cfg_bufs bufs;
344 struct lustre_cfg *lcfg;
349 lustre_cfg_bufs_reset(&bufs, lcfg_devname);
352 lustre_cfg_bufs_set_string(&bufs, 1, argv[1]);
354 lcfg = lustre_cfg_new(LCFG_DEL_MOUNTOPT, &bufs);
355 rc = lcfg_ioctl(argv[0], OBD_DEV_ID, lcfg);
356 lustre_cfg_free(lcfg);
358 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
359 strerror(rc = errno));
364 int jt_lcfg_set_timeout(int argc, char **argv)
367 struct lustre_cfg_bufs bufs;
368 struct lustre_cfg *lcfg;
370 fprintf(stderr, "%s has been deprecated. Use conf_param instead.\n"
371 "e.g. conf_param lustre-MDT0000 obd_timeout=50\n",
372 jt_cmdname(argv[0]));
379 lustre_cfg_bufs_reset(&bufs, lcfg_devname);
380 lcfg = lustre_cfg_new(LCFG_SET_TIMEOUT, &bufs);
381 lcfg->lcfg_num = atoi(argv[1]);
383 rc = lcfg_ioctl(argv[0], OBD_DEV_ID, lcfg);
384 //rc = lcfg_mgs_ioctl(argv[0], OBD_DEV_ID, lcfg);
386 lustre_cfg_free(lcfg);
388 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
389 strerror(rc = errno));
394 int jt_lcfg_add_conn(int argc, char **argv)
396 struct lustre_cfg_bufs bufs;
397 struct lustre_cfg *lcfg;
408 if (lcfg_devname == NULL) {
409 fprintf(stderr, "%s: please use 'device name' to set the "
410 "device name for config commands.\n",
411 jt_cmdname(argv[0]));
415 lustre_cfg_bufs_reset(&bufs, lcfg_devname);
417 lustre_cfg_bufs_set_string(&bufs, 1, argv[1]);
419 lcfg = lustre_cfg_new(LCFG_ADD_CONN, &bufs);
420 lcfg->lcfg_num = priority;
422 rc = lcfg_ioctl(argv[0], OBD_DEV_ID, lcfg);
423 lustre_cfg_free (lcfg);
425 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
426 strerror(rc = errno));
432 int jt_lcfg_del_conn(int argc, char **argv)
434 struct lustre_cfg_bufs bufs;
435 struct lustre_cfg *lcfg;
441 if (lcfg_devname == NULL) {
442 fprintf(stderr, "%s: please use 'device name' to set the "
443 "device name for config commands.\n",
444 jt_cmdname(argv[0]));
448 lustre_cfg_bufs_reset(&bufs, lcfg_devname);
450 /* connection uuid */
451 lustre_cfg_bufs_set_string(&bufs, 1, argv[1]);
453 lcfg = lustre_cfg_new(LCFG_DEL_MOUNTOPT, &bufs);
455 rc = lcfg_ioctl(argv[0], OBD_DEV_ID, lcfg);
456 lustre_cfg_free(lcfg);
458 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
459 strerror(rc = errno));
465 /* Param set locally, directly on target */
466 int jt_lcfg_param(int argc, char **argv)
469 struct lustre_cfg_bufs bufs;
470 struct lustre_cfg *lcfg;
472 if (argc >= LUSTRE_CFG_MAX_BUFCOUNT)
475 lustre_cfg_bufs_reset(&bufs, NULL);
477 for (i = 1; i < argc; i++) {
478 lustre_cfg_bufs_set_string(&bufs, i, argv[i]);
481 lcfg = lustre_cfg_new(LCFG_PARAM, &bufs);
483 rc = lcfg_ioctl(argv[0], OBD_DEV_ID, lcfg);
484 lustre_cfg_free(lcfg);
486 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
487 strerror(rc = errno));
492 /* Param set in config log on MGS */
493 /* conf_param key1=value1 [key2=value2...] */
494 int jt_lcfg_mgsparam(int argc, char **argv)
497 struct lustre_cfg_bufs bufs;
498 struct lustre_cfg *lcfg;
500 if ((argc >= LUSTRE_CFG_MAX_BUFCOUNT) || (argc <= 1))
503 lustre_cfg_bufs_reset(&bufs, NULL);
504 for (i = 1; i < argc; i++) {
505 lustre_cfg_bufs_set_string(&bufs, i, argv[i]);
508 /* We could put other opcodes here. */
509 lcfg = lustre_cfg_new(LCFG_PARAM, &bufs);
511 rc = lcfg_mgs_ioctl(argv[0], OBD_DEV_ID, lcfg);
512 lustre_cfg_free(lcfg);
514 fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]),
515 strerror(rc = errno));
521 /* Display the path in the same format as sysctl
522 * For eg. obdfilter.lustre-OST0000.stats */
523 static char *display_name(char *filename)
527 filename += strlen("/proc/");
528 if (strncmp(filename, "fs/", strlen("fs/")) == 0)
529 filename += strlen("fs/");
531 filename += strlen("sys/");
533 if (strncmp(filename, "lustre/", strlen("lustre/")) == 0)
534 filename += strlen("lustre/");
536 /* replace '/' with '.' to match conf_param and sysctl */
538 while ((tmp = strchr(tmp, '/')) != NULL)
544 /* Find a character in a length limited string */
545 /* BEWARE - kernel definition of strnchr has args in different order! */
546 static char *strnchr(const char *p, char c, size_t n)
559 static char *globerrstr(int glob_rc)
563 return "Out of memory";
567 return "Found no match";
569 return "Unknow error";
572 static void clean_path(char *path)
576 /* If the input is in form Eg. obdfilter.*.stats */
577 if (strchr(path, '.')) {
579 while (*tmp != '\0') {
581 (tmp != path) && (*(tmp - 1) != '\\'))
586 /* get rid of '\', glob doesn't like it */
587 if ((tmp = strrchr(path, '\\')) != NULL) {
588 char *tail = path + strlen(path);
589 while (tmp != path) {
591 memmove(tmp, tmp + 1, tail - tmp);
599 int jt_lcfg_getparam(int argc, char **argv)
602 int rc = 0, i, show_path = 0, only_path = 0;
603 char pattern[PATH_MAX];
607 if (argc == 3 && (strcmp(argv[1], "-n") == 0 || strcmp(argv[1], "-N") == 0)) {
609 if (strcmp(argv[1], "-N") == 0) {
613 } else if (argc == 2) {
622 /* If the entire path is specified as input */
623 fp = open(path, O_RDONLY);
625 snprintf(pattern, PATH_MAX, "/proc/{fs,sys}/{lnet,lustre}/%s",
628 strcpy(pattern, path);
632 rc = glob(pattern, GLOB_BRACE, NULL, &glob_info);
634 fprintf(stderr, "error : glob %s: %s \n", pattern,
639 buf = malloc(CFS_PAGE_SIZE);
640 for (i = 0; i < glob_info.gl_pathc; i++) {
641 char *valuename = NULL;
643 memset(buf, 0, CFS_PAGE_SIZE);
646 filename = strdup(glob_info.gl_pathv[i]);
647 valuename = display_name(filename);
648 if (valuename && only_path) {
649 printf("%s\n", valuename);
654 /* Write the contents of file to stdout */
655 fp = open(glob_info.gl_pathv[i], O_RDONLY);
657 fprintf(stderr, "error: %s: opening('%s') failed: %s\n",
658 jt_cmdname(argv[0]), glob_info.gl_pathv[i],
664 rc = read(fp, buf, CFS_PAGE_SIZE);
668 fprintf(stderr, "error: %s: read('%s') "
669 "failed: %s\n", jt_cmdname(argv[0]),
670 glob_info.gl_pathv[i], strerror(errno));
673 /* Print the output in the format path=value if the
674 * value contains no new line character or cab be
675 * occupied in a line, else print value on new line */
676 if (valuename && show_path) {
677 int longbuf = strnchr(buf, rc - 1, '\n') != NULL
679 printf("%s=%s", valuename, longbuf ? "\n" : buf);
685 rc = write(fileno(stdout), buf, rc);
687 fprintf(stderr, "error: %s: write to stdout "
688 "failed: %s\n", jt_cmdname(argv[0]),
696 globfree(&glob_info);
701 int jt_lcfg_setparam(int argc, char **argv)
704 int fp, show_path = 0;
705 char pattern[PATH_MAX];
710 if (argc == 4 && (strcmp(argv[1], "-n") == 0)) {
711 /* Format: lctl set_param -n param value */
714 } else if (argc == 3) {
715 if (strcmp(argv[1], "-n") != 0) {
716 /* Format: lctl set_param param value */
719 } else if ((value = strchr(argv[2], '=')) != NULL) {
720 /* Format: lctl set_param -n param=value */
725 fprintf(stderr, "error: %s Incorrect arguments."
727 jt_cmdname(argv[0]));
730 } else if (argc == 2 && ((value = strchr(argv[1], '=')) != NULL)) {
731 /* Format: lctl set_param param=value */
736 fprintf(stderr, "error: %s Incorrect arguments. See Usage\n",
737 jt_cmdname(argv[0]));
743 fp = open(path, O_RDONLY);
745 snprintf(pattern, PATH_MAX, "/proc/{fs,sys}/{lnet,lustre}/%s",
748 strcpy(pattern, path);
752 rc = glob(pattern, GLOB_BRACE, NULL, &glob_info);
754 fprintf(stderr, "error : glob %s: %s \n", pattern,
758 for (i = 0; i < glob_info.gl_pathc; i++) {
760 char *valuename, *filename;
761 filename = strdup(glob_info.gl_pathv[i]);
762 valuename = display_name(filename);
763 printf("%s=%s\n", valuename, value);
765 /* Write the new value to the file */
766 fp = open(glob_info.gl_pathv[i], O_WRONLY);
768 rc = write(fp, value, strlen(value));
771 "error writing to file %s\n",
772 glob_info.gl_pathv[i]);
777 fprintf(stderr, "error: %s: %s opening %s\n",
778 jt_cmdname(argv[0]), strerror(rc = errno),
779 glob_info.gl_pathv[i]);
783 globfree(&glob_info);