X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;f=lustre%2Futils%2Flustre_cfg.c;h=3d8806584764e563435e69d175a088753424e5f5;hb=dfd8433e6f6376bf5f7a50020bb484adfe48ce2c;hp=b973113a4736e667e7009110f0d36c59b2eb75b2;hpb=113303973ec9f8484eb2355a1a6ef3c4c7fd6a56;p=fs%2Flustre-release.git diff --git a/lustre/utils/lustre_cfg.c b/lustre/utils/lustre_cfg.c index b973113..3d88065 100644 --- a/lustre/utils/lustre_cfg.c +++ b/lustre/utils/lustre_cfg.c @@ -1,35 +1,53 @@ /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*- * vim:expandtab:shiftwidth=8:tabstop=8: * - * Copyright (C) 2002 Cluster File Systems, Inc. - * Author: Peter J. Braam - * Author: Phil Schwan - * Author: Andreas Dilger - * Author: Robert Read + * GPL HEADER START * - * This file is part of Lustre, http://www.lustre.org. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * - * Lustre is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 only, + * as published by the Free Software Foundation. * - * Lustre is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License version 2 for more details (a copy is included + * in the LICENSE file that accompanied this code). * - * You should have received a copy of the GNU General Public License - * along with Lustre; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * You should have received a copy of the GNU General Public License + * version 2 along with this program; If not, see + * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + * GPL HEADER END + */ +/* + * Copyright 2008 Sun Microsystems, Inc. All rights reserved + * Use is subject to license terms. + */ +/* + * This file is part of Lustre, http://www.lustre.org/ + * Lustre is a trademark of Sun Microsystems, Inc. + * + * lustre/utils/lustre_cfg.c + * + * Author: Peter J. Braam + * Author: Phil Schwan + * Author: Andreas Dilger + * Author: Robert Read */ - #include #include +#include #include #include #include +#include #ifndef __KERNEL__ #include @@ -40,7 +58,7 @@ #include #include /* for struct lov_stripe_md */ #include -#include +#include #include #include @@ -52,7 +70,7 @@ #include "obdctl.h" #include -#include "parser.h" +#include #include static char * lcfg_devname; @@ -65,7 +83,7 @@ int lcfg_set_devname(char *name) /* quietly strip the unnecessary '$' */ if (*name == '$' || *name == '%') name++; - if (isdigit(*name)) { + if (isdigit(*name)) { /* We can't translate from dev # to name */ lcfg_devname = NULL; } else { @@ -73,7 +91,7 @@ int lcfg_set_devname(char *name) } } else { lcfg_devname = NULL; - } + } return 0; } @@ -137,8 +155,8 @@ int jt_lcfg_setup(int argc, char **argv) if (lcfg_devname == NULL) { fprintf(stderr, "%s: please use 'device name' to set the " - "device name for config commands.\n", - jt_cmdname(argv[0])); + "device name for config commands.\n", + jt_cmdname(argv[0])); return -EINVAL; } @@ -169,8 +187,8 @@ int jt_obd_detach(int argc, char **argv) if (lcfg_devname == NULL) { fprintf(stderr, "%s: please use 'device name' to set the " - "device name for config commands.\n", - jt_cmdname(argv[0])); + "device name for config commands.\n", + jt_cmdname(argv[0])); return -EINVAL; } @@ -201,8 +219,8 @@ int jt_obd_cleanup(int argc, char **argv) if (lcfg_devname == NULL) { fprintf(stderr, "%s: please use 'device name' to set the " - "device name for config commands.\n", - jt_cmdname(argv[0])); + "device name for config commands.\n", + jt_cmdname(argv[0])); return -EINVAL; } @@ -239,8 +257,8 @@ int jt_obd_cleanup(int argc, char **argv) return rc; } -static -int do_add_uuid(char * func, char *uuid, lnet_nid_t nid) +static +int do_add_uuid(char * func, char *uuid, lnet_nid_t nid) { int rc; struct lustre_cfg_bufs bufs; @@ -252,7 +270,7 @@ int do_add_uuid(char * func, char *uuid, lnet_nid_t nid) lcfg = lustre_cfg_new(LCFG_ADD_UUID, &bufs); lcfg->lcfg_nid = nid; - /* Poison NAL -- pre 1.4.6 will LASSERT on 0 NAL, this way it + /* Poison NAL -- pre 1.4.6 will LASSERT on 0 NAL, this way it doesn't work without crashing (bz 10130) */ lcfg->lcfg_nal = 0x5a; @@ -275,8 +293,8 @@ int do_add_uuid(char * func, char *uuid, lnet_nid_t nid) int jt_lcfg_add_uuid(int argc, char **argv) { lnet_nid_t nid; - - if (argc != 3) { + + if (argc != 3) { return CMD_HELP; } @@ -308,7 +326,7 @@ int jt_lcfg_del_uuid(int argc, char **argv) lustre_cfg_bufs_reset(&bufs, lcfg_devname); if (strcmp (argv[1], "_all_")) lustre_cfg_bufs_set_string(&bufs, 1, argv[1]); - + lcfg = lustre_cfg_new(LCFG_DEL_UUID, &bufs); rc = lcfg_ioctl(argv[0], OBD_DEV_ID, lcfg); lustre_cfg_free(lcfg); @@ -320,9 +338,6 @@ int jt_lcfg_del_uuid(int argc, char **argv) return 0; } - - - int jt_lcfg_del_mount_option(int argc, char **argv) { int rc; @@ -365,7 +380,7 @@ int jt_lcfg_set_timeout(int argc, char **argv) lustre_cfg_bufs_reset(&bufs, lcfg_devname); lcfg = lustre_cfg_new(LCFG_SET_TIMEOUT, &bufs); lcfg->lcfg_num = atoi(argv[1]); - + rc = lcfg_ioctl(argv[0], OBD_DEV_ID, lcfg); //rc = lcfg_mgs_ioctl(argv[0], OBD_DEV_ID, lcfg); @@ -377,8 +392,6 @@ int jt_lcfg_set_timeout(int argc, char **argv) return rc; } - - int jt_lcfg_add_conn(int argc, char **argv) { struct lustre_cfg_bufs bufs; @@ -395,8 +408,8 @@ int jt_lcfg_add_conn(int argc, char **argv) if (lcfg_devname == NULL) { fprintf(stderr, "%s: please use 'device name' to set the " - "device name for config commands.\n", - jt_cmdname(argv[0])); + "device name for config commands.\n", + jt_cmdname(argv[0])); return -EINVAL; } @@ -428,8 +441,8 @@ int jt_lcfg_del_conn(int argc, char **argv) if (lcfg_devname == NULL) { fprintf(stderr, "%s: please use 'device name' to set the " - "device name for config commands.\n", - jt_cmdname(argv[0])); + "device name for config commands.\n", + jt_cmdname(argv[0])); return -EINVAL; } @@ -460,14 +473,14 @@ int jt_lcfg_param(int argc, char **argv) if (argc >= LUSTRE_CFG_MAX_BUFCOUNT) return CMD_HELP; - lustre_cfg_bufs_reset(&bufs, lcfg_devname); + lustre_cfg_bufs_reset(&bufs, NULL); for (i = 1; i < argc; i++) { lustre_cfg_bufs_set_string(&bufs, i, argv[i]); } lcfg = lustre_cfg_new(LCFG_PARAM, &bufs); - + rc = lcfg_ioctl(argv[0], OBD_DEV_ID, lcfg); lustre_cfg_free(lcfg); if (rc < 0) { @@ -478,28 +491,19 @@ int jt_lcfg_param(int argc, char **argv) } /* Param set in config log on MGS */ -/* conf_param key1=value1 [key2=value2...] */ +/* conf_param key1=value1 [key2=value2...] */ int jt_lcfg_mgsparam(int argc, char **argv) { - int i, rc, index_offset = 0; + int i, rc; struct lustre_cfg_bufs bufs; struct lustre_cfg *lcfg; if ((argc >= LUSTRE_CFG_MAX_BUFCOUNT) || (argc <= 1)) return CMD_HELP; - if (!strchr(argv[1], '=')) { - /* Not key=val, assume */ - rc = jt_obd_device(2, argv); - if (rc) - return rc; - index_offset = 1; - } - - lustre_cfg_bufs_reset(&bufs, lcfg_devname); - - for (i = 1; i < (argc - index_offset); i++) { - lustre_cfg_bufs_set_string(&bufs, i, argv[i + index_offset]); + lustre_cfg_bufs_reset(&bufs, NULL); + for (i = 1; i < argc; i++) { + lustre_cfg_bufs_set_string(&bufs, i, argv[i]); } /* We could put other opcodes here. */ @@ -511,8 +515,442 @@ int jt_lcfg_mgsparam(int argc, char **argv) fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]), strerror(rc = errno)); } - + + return rc; +} + +/* Display the path in the same format as sysctl + * For eg. obdfilter.lustre-OST0000.stats */ +static char *display_name(char *filename, int show_type) +{ + char *tmp; + struct stat st; + + if (show_type) { + if (lstat(filename, &st) < 0) + return NULL; + } + + filename += strlen("/proc/"); + if (strncmp(filename, "fs/", strlen("fs/")) == 0) + filename += strlen("fs/"); + else + filename += strlen("sys/"); + + if (strncmp(filename, "lustre/", strlen("lustre/")) == 0) + filename += strlen("lustre/"); + + /* replace '/' with '.' to match conf_param and sysctl */ + tmp = filename; + while ((tmp = strchr(tmp, '/')) != NULL) + *tmp = '.'; + + /* append the indicator to entries */ + if (show_type) { + if (S_ISDIR(st.st_mode)) + strcat(filename, "/"); + else if (S_ISLNK(st.st_mode)) + strcat(filename, "@"); + else if (st.st_mode & S_IWUSR) + strcat(filename, "="); + } + + return filename; +} + +/* Find a character in a length limited string */ +/* BEWARE - kernel definition of strnchr has args in different order! */ +static char *strnchr(const char *p, char c, size_t n) +{ + if (!p) + return (0); + + while (n-- > 0) { + if (*p == c) + return ((char *)p); + p++; + } + return (0); +} + +static char *globerrstr(int glob_rc) +{ + switch(glob_rc) { + case GLOB_NOSPACE: + return "Out of memory"; + case GLOB_ABORTED: + return "Read error"; + case GLOB_NOMATCH: + return "Found no match"; + } + return "Unknown error"; +} + +static void clean_path(char *path) +{ + char *tmp; + + /* If the input is in form Eg. obdfilter.*.stats */ + if (strchr(path, '.')) { + tmp = path; + while (*tmp != '\0') { + if ((*tmp == '.') && + (tmp != path) && (*(tmp - 1) != '\\')) + *tmp = '/'; + tmp ++; + } + } + /* get rid of '\', glob doesn't like it */ + if ((tmp = strrchr(path, '\\')) != NULL) { + char *tail = path + strlen(path); + while (tmp != path) { + if (*tmp == '\\') { + memmove(tmp, tmp + 1, tail - tmp); + --tail; + } + --tmp; + } + } +} + +struct param_opts { + int only_path; + int show_path; + int show_type; +}; + +static int listparam_cmdline(int argc, char **argv, struct param_opts *popt) +{ + int ch; + + popt->show_path = 1; + popt->only_path = 1; + popt->show_type = 0; + + while ((ch = getopt(argc, argv, "F")) != -1) { + switch (ch) { + case 'F': + popt->show_type = 1; + break; + default: + return -1; + } + } + + return optind; +} + +static int listparam_display(struct param_opts *popt, char *pattern) +{ + int rc; + int i; + glob_t glob_info; + char filename[PATH_MAX + 1]; /* extra 1 byte for file type */ + + rc = glob(pattern, GLOB_BRACE, NULL, &glob_info); + if (rc) { + fprintf(stderr, "error: list_param: %s: %s\n", + pattern, globerrstr(rc)); + return -ESRCH; + } + + for (i = 0; i < glob_info.gl_pathc; i++) { + char *valuename = NULL; + + strcpy(filename, glob_info.gl_pathv[i]); + valuename = display_name(filename, popt->show_type); + if (valuename) + printf("%s\n", valuename); + } + + globfree(&glob_info); return rc; } +int jt_lcfg_listparam(int argc, char **argv) +{ + int fp; + int rc = 0, i; + struct param_opts popt; + char pattern[PATH_MAX]; + char *path; + + rc = listparam_cmdline(argc, argv, &popt); + if (rc < 0 || rc >= argc) + return CMD_HELP; + + for (i = rc; i < argc; i++) { + path = argv[i]; + + clean_path(path); + + /* If the entire path is specified as input */ + fp = open(path, O_RDONLY); + if (fp < 0) { + snprintf(pattern, PATH_MAX, "/proc/{fs,sys}/{lnet,lustre}/%s", + path); + } else { + strcpy(pattern, path); + close(fp); + } + rc = listparam_display(&popt, pattern); + if (rc < 0) + return rc; + } + + return 0; +} + +static int getparam_cmdline(int argc, char **argv, struct param_opts *popt) +{ + int ch; + + popt->show_path = 1; + popt->only_path = 0; + popt->show_type = 0; + + while ((ch = getopt(argc, argv, "nNF")) != -1) { + switch (ch) { + case 'N': + popt->only_path = 1; + break; + case 'n': + popt->show_path = 0; + case 'F': + popt->show_type = 1; + break; + default: + return -1; + } + } + + return optind; +} + +static int getparam_display(struct param_opts *popt, char *pattern) +{ + int rc; + int fd; + int i; + char *buf; + glob_t glob_info; + char filename[PATH_MAX + 1]; /* extra 1 byte for file type */ + + rc = glob(pattern, GLOB_BRACE, NULL, &glob_info); + if (rc) { + fprintf(stderr, "error: get_param: %s: %s\n", + pattern, globerrstr(rc)); + return -ESRCH; + } + + buf = malloc(CFS_PAGE_SIZE); + for (i = 0; i < glob_info.gl_pathc; i++) { + char *valuename = NULL; + + memset(buf, 0, CFS_PAGE_SIZE); + /* As listparam_display is used to show param name (with type), + * here "if (only_path)" is ignored.*/ + if (popt->show_path) { + strcpy(filename, glob_info.gl_pathv[i]); + valuename = display_name(filename, 0); + } + + /* Write the contents of file to stdout */ + fd = open(glob_info.gl_pathv[i], O_RDONLY); + if (fd < 0) { + fprintf(stderr, + "error: get_param: opening('%s') failed: %s\n", + glob_info.gl_pathv[i], strerror(errno)); + continue; + } + + do { + rc = read(fd, buf, CFS_PAGE_SIZE); + if (rc == 0) + break; + if (rc < 0) { + fprintf(stderr, "error: get_param: " + "read('%s') failed: %s\n", + glob_info.gl_pathv[i], strerror(errno)); + break; + } + /* Print the output in the format path=value if the + * value contains no new line character or cab be + * occupied in a line, else print value on new line */ + if (valuename && popt->show_path) { + int longbuf = strnchr(buf, rc - 1, '\n') != NULL + || rc > 60; + printf("%s=%s", valuename, longbuf ? "\n" : buf); + valuename = NULL; + if (!longbuf) + continue; + fflush(stdout); + } + rc = write(fileno(stdout), buf, rc); + if (rc < 0) { + fprintf(stderr, "error: get_param: " + "write to stdout failed: %s\n", + strerror(errno)); + break; + } + } while (1); + close(fd); + } + + globfree(&glob_info); + free(buf); + return rc; +} + +int jt_lcfg_getparam(int argc, char **argv) +{ + int fp; + int rc = 0, i; + struct param_opts popt; + char pattern[PATH_MAX]; + char *path; + + rc = getparam_cmdline(argc, argv, &popt); + if (rc < 0 || rc >= argc) + return CMD_HELP; + + for (i = rc; i < argc; i++) { + path = argv[i]; + + clean_path(path); + + /* If the entire path is specified as input */ + fp = open(path, O_RDONLY); + if (fp < 0) { + snprintf(pattern, PATH_MAX, "/proc/{fs,sys}/{lnet,lustre}/%s", + path); + } else { + strcpy(pattern, path); + close(fp); + } + + if (popt.only_path) + rc = listparam_display(&popt, pattern); + else + rc = getparam_display(&popt, pattern); + if (rc < 0) + return rc; + } + + return 0; +} + +static int setparam_cmdline(int argc, char **argv, struct param_opts *popt) +{ + int ch; + + popt->show_path = 1; + popt->only_path = 0; + popt->show_type = 0; + + while ((ch = getopt(argc, argv, "n")) != -1) { + switch (ch) { + case 'n': + popt->show_path = 0; + break; + default: + return -1; + } + } + return optind; +} + +static int setparam_display(struct param_opts *popt, char *pattern, char *value) +{ + int rc; + int fd; + int i; + glob_t glob_info; + char filename[PATH_MAX + 1]; /* extra 1 byte for file type */ + + rc = glob(pattern, GLOB_BRACE, NULL, &glob_info); + if (rc) { + fprintf(stderr, "error: set_param: %s: %s\n", + pattern, globerrstr(rc)); + return -ESRCH; + } + for (i = 0; i < glob_info.gl_pathc; i++) { + char *valuename = NULL; + + if (popt->show_path) { + strcpy(filename, glob_info.gl_pathv[i]); + valuename = display_name(filename, 0); + if (valuename) + printf("%s=%s\n", valuename, value); + } + /* Write the new value to the file */ + fd = open(glob_info.gl_pathv[i], O_WRONLY); + if (fd > 0) { + rc = write(fd, value, strlen(value)); + if (rc < 0) + fprintf(stderr, "error: set_param: " + "writing to file %s: %s\n", + glob_info.gl_pathv[i], strerror(errno)); + else + rc = 0; + close(fd); + } else { + fprintf(stderr, "error: set_param: %s opening %s\n", + strerror(rc = errno), glob_info.gl_pathv[i]); + } + } + + globfree(&glob_info); + return rc; +} + +int jt_lcfg_setparam(int argc, char **argv) +{ + int fp; + int rc = 0, i; + struct param_opts popt; + char pattern[PATH_MAX]; + char *path = NULL, *value = NULL; + + rc = setparam_cmdline(argc, argv, &popt); + if (rc < 0 || rc >= argc) + return CMD_HELP; + + for (i = rc; i < argc; i++) { + if ((value = strchr(argv[i], '=')) != NULL) { + /* format: set_param a=b */ + *value = '\0'; + value ++; + path = argv[i]; + } else { + /* format: set_param a b */ + if (path == NULL) { + path = argv[i]; + continue; + } else { + value = argv[i]; + } + } + + clean_path(path); + + /* If the entire path is specified as input */ + fp = open(path, O_RDONLY); + if (fp < 0) { + snprintf(pattern, PATH_MAX, "/proc/{fs,sys}/{lnet,lustre}/%s", + path); + } else { + strcpy(pattern, path); + close(fp); + } + + rc = setparam_display(&popt, pattern, value); + path = NULL; + value = NULL; + if (rc < 0) + return rc; + } + + return 0; +}