X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;f=lustre%2Futils%2Flustre_cfg.c;h=d5edad2a4192a8dbbdd96ada46ddc0da25f61a2b;hb=0ee03999a24c3e5e2652155237809671414630b9;hp=69f734b6cf98025974e7427add4fbc75bc530fe0;hpb=0e660eab787c3b2857e4295f1ec554e016393885;p=fs%2Flustre-release.git diff --git a/lustre/utils/lustre_cfg.c b/lustre/utils/lustre_cfg.c index 69f734b..d5edad2 100644 --- a/lustre/utils/lustre_cfg.c +++ b/lustre/utils/lustre_cfg.c @@ -1,6 +1,4 @@ -/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*- - * vim:expandtab:shiftwidth=8:tabstop=8: - * +/* * GPL HEADER START * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. @@ -26,8 +24,10 @@ * GPL HEADER END */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved + * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. * Use is subject to license terms. + * + * Copyright (c) 2011, 2012, Whamcloud, Inc. */ /* * This file is part of Lustre, http://www.lustre.org/ @@ -43,6 +43,7 @@ #include #include +#include #include #include #include @@ -76,13 +77,26 @@ static char * lcfg_devname; int lcfg_set_devname(char *name) { + char *ptr; + int digit = 1; + if (name) { if (lcfg_devname) free(lcfg_devname); /* quietly strip the unnecessary '$' */ if (*name == '$' || *name == '%') name++; - if (isdigit(*name)) { + + ptr = name; + while (*ptr != '\0') { + if (!isdigit(*ptr)) { + digit = 0; + break; + } + ptr++; + } + + if (digit) { /* We can't translate from dev # to name */ lcfg_devname = NULL; } else { @@ -337,9 +351,6 @@ int jt_lcfg_del_uuid(int argc, char **argv) return 0; } - - - int jt_lcfg_del_mount_option(int argc, char **argv) { int rc; @@ -394,8 +405,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; @@ -495,19 +504,48 @@ int jt_lcfg_param(int argc, char **argv) } /* Param set in config log on MGS */ -/* conf_param key1=value1 [key2=value2...] */ +/* conf_param key=value */ +/* Note we can actually send mgc conf_params from clients, but currently + * that's only done for default file striping (see ll_send_mgc_param), + * and not here. */ +/* After removal of a parameter (-d) Lustre will use the default + * AT NEXT REBOOT, not immediately. */ int jt_lcfg_mgsparam(int argc, char **argv) { - int i, rc; + int rc; + int del = 0; struct lustre_cfg_bufs bufs; struct lustre_cfg *lcfg; + char *buf = NULL; - if ((argc >= LUSTRE_CFG_MAX_BUFCOUNT) || (argc <= 1)) + /* mgs_setparam processes only lctl buf #1 */ + if ((argc > 3) || (argc <= 1)) return CMD_HELP; + while ((rc = getopt(argc, argv, "d")) != -1) { + switch (rc) { + case 'd': + del = 1; + break; + default: + return CMD_HELP; + } + } + lustre_cfg_bufs_reset(&bufs, NULL); - for (i = 1; i < argc; i++) { - lustre_cfg_bufs_set_string(&bufs, i, argv[i]); + if (del) { + char *ptr; + + /* for delete, make it "=\0" */ + buf = malloc(strlen(argv[optind]) + 2); + /* put an '=' on the end in case it doesn't have one */ + sprintf(buf, "%s=", argv[optind]); + /* then truncate after the first '=' */ + ptr = strchr(buf, '='); + *(++ptr) = '\0'; + lustre_cfg_bufs_set_string(&bufs, 1, buf); + } else { + lustre_cfg_bufs_set_string(&bufs, 1, argv[optind]); } /* We could put other opcodes here. */ @@ -515,6 +553,8 @@ int jt_lcfg_mgsparam(int argc, char **argv) rc = lcfg_mgs_ioctl(argv[0], OBD_DEV_ID, lcfg); lustre_cfg_free(lcfg); + if (buf) + free(buf); if (rc < 0) { fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]), strerror(rc = errno)); @@ -525,9 +565,15 @@ int jt_lcfg_mgsparam(int argc, char **argv) /* Display the path in the same format as sysctl * For eg. obdfilter.lustre-OST0000.stats */ -static char *display_name(char *filename) +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) @@ -537,12 +583,24 @@ static char *display_name(char *filename) if (strncmp(filename, "lustre/", strlen("lustre/")) == 0) filename += strlen("lustre/"); + else if (strncmp(filename, "lnet/", strlen("lnet/")) == 0) + filename += strlen("lnet/"); /* 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; } @@ -561,51 +619,215 @@ static char *strnchr(const char *p, char c, size_t n) return (0); } -int jt_lcfg_getparam(int argc, char **argv) +static char *globerrstr(int glob_rc) { - int fp; - int rc = 0, i, show_path = 0, only_path = 0; - char pattern[PATH_MAX]; - char *path, *tmp, *buf; - glob_t glob_info; - - if (argc == 3 && (strcmp(argv[1], "-n") == 0 || strcmp(argv[1], "-N") == 0)) { - path = argv[2]; - if (strcmp(argv[1], "-N") == 0) { - only_path = 1; - show_path = 1; - } - } else if (argc == 2) { - show_path = 1; - path = argv[1]; - } else { - return CMD_HELP; + 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 == '.') + 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; + } + } +} + +/* Supporting file paths creates perilous behavoir: LU-888. + * Path support is deprecated. + * If a path is supplied it must begin with /proc. */ +static void lprocfs_param_pattern(const char *cmd, const char *path, char *buf, + size_t buf_size) +{ + /* test path to see if it begins with '/proc/' */ + if (strncmp(path, "/proc/", strlen("/proc/")) == 0) { + static int warned; + if (!warned) { + fprintf(stderr, "%s: specifying parameters via " + "full paths is deprecated.\n", cmd); +#if LUSTRE_VERSION_CODE >= OBD_OCD_VERSION(2, 6, 50, 0) +#warning "remove deprecated full path tunable access" +#endif + warned = 1; + } + snprintf(buf, buf_size, "%s", path); + } else { + snprintf(buf, buf_size, "/proc/{fs,sys}/{lnet,lustre}/%s", + path); + } +} + +struct param_opts { + int only_path:1; + int show_path:1; + int show_type:1; + int recursive:1; +}; - /* 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); +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; + popt->recursive = 0; + + while ((ch = getopt(argc, argv, "FR")) != -1) { + switch (ch) { + case 'F': + popt->show_type = 1; + break; + case 'R': + popt->recursive = 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 | (popt->recursive ? GLOB_MARK : 0), + 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; + int last; + + /* Trailing '/' will indicate recursion into directory */ + last = strlen(glob_info.gl_pathv[i]) - 1; + + /* Remove trailing '/' or it will be converted to '.' */ + if (last > 0 && glob_info.gl_pathv[i][last] == '/') + glob_info.gl_pathv[i][last] = '\0'; + else + last = 0; + strcpy(filename, glob_info.gl_pathv[i]); + valuename = display_name(filename, popt->show_type); + if (valuename) + printf("%s\n", valuename); + if (last) { + strcpy(filename, glob_info.gl_pathv[i]); + strcat(filename, "/*"); + listparam_display(popt, filename); + } + } + + globfree(&glob_info); + return rc; +} + +int jt_lcfg_listparam(int argc, char **argv) +{ + int rc = 0, i; + struct param_opts popt; + char pattern[PATH_MAX]; + char *path; + + rc = listparam_cmdline(argc, argv, &popt); + if (rc == argc && popt.recursive) { + rc--; /* we know at least "-R" is a parameter */ + argv[rc] = "*"; + } else if (rc < 0 || rc >= argc) { + return CMD_HELP; + } + + for (i = rc; i < argc; i++) { + path = argv[i]; + + clean_path(path); + + lprocfs_param_pattern(argv[0], path, pattern, sizeof(pattern)); + + 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; + popt->recursive = 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 : glob %s: %s \n", pattern,strerror(rc)); - return rc; + fprintf(stderr, "error: get_param: %s: %s\n", + pattern, globerrstr(rc)); + return -ESRCH; } buf = malloc(CFS_PAGE_SIZE); @@ -613,39 +835,36 @@ int jt_lcfg_getparam(int argc, char **argv) char *valuename = NULL; memset(buf, 0, CFS_PAGE_SIZE); - if (show_path) { - char *filename; - filename = strdup(glob_info.gl_pathv[i]); - valuename = display_name(filename); - if (valuename && only_path) { - printf("%s\n", valuename); - continue; - } + /* 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 */ - fp = open(glob_info.gl_pathv[i], O_RDONLY); - if (fp < 0) { - fprintf(stderr, "error: %s: opening('%s') failed: %s\n", - jt_cmdname(argv[0]), glob_info.gl_pathv[i], - strerror(errno)); + 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(fp, buf, CFS_PAGE_SIZE); + rc = read(fd, buf, CFS_PAGE_SIZE); if (rc == 0) break; if (rc < 0) { - fprintf(stderr, "error: %s: read('%s') " - "failed: %s\n", jt_cmdname(argv[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 && show_path) { + if (valuename && popt->show_path) { int longbuf = strnchr(buf, rc - 1, '\n') != NULL || rc > 60; printf("%s=%s", valuename, longbuf ? "\n" : buf); @@ -656,13 +875,13 @@ int jt_lcfg_getparam(int argc, char **argv) } rc = write(fileno(stdout), buf, rc); if (rc < 0) { - fprintf(stderr, "error: %s: write to stdout " - "failed: %s\n", jt_cmdname(argv[0]), + fprintf(stderr, "error: get_param: " + "write to stdout failed: %s\n", strerror(errno)); break; } } while (1); - close(fp); + close(fd); } globfree(&glob_info); @@ -670,96 +889,142 @@ int jt_lcfg_getparam(int argc, char **argv) return rc; } - -int jt_lcfg_setparam(int argc, char **argv) +int jt_lcfg_getparam(int argc, char **argv) { int rc = 0, i; - int fp, show_path = 0; + struct param_opts popt; char pattern[PATH_MAX]; - char *path, *value, *tmp; - glob_t glob_info; + char *path; - path = argv[1]; - if (argc == 4 && (strcmp(argv[1], "-n") == 0)) { - /* Format: lctl set_param -n param value */ - path = argv[2]; - value = argv[3]; - } else if (argc == 3) { - if (strcmp(argv[1], "-n") != 0) { - /* Format: lctl set_param param value */ - show_path = 1; - value = argv[2]; - } else if ((value = strchr(argv[2], '=')) != NULL) { - /* Format: lctl set_param -n param=value */ - path = argv[2]; - *value = '\0'; - value ++; - } else { - fprintf(stderr, "error: %s Incorrect arguments." - "See Usage\n", - jt_cmdname(argv[0])); - return CMD_HELP; - } - } else if (argc == 2 && ((value = strchr(argv[1], '=')) != NULL)) { - /* Format: lctl set_param param=value */ - show_path = 1; - *value = '\0'; - value++; - } else { - fprintf(stderr, "error: %s Incorrect arguments. See Usage\n", - jt_cmdname(argv[0])); + rc = getparam_cmdline(argc, argv, &popt); + if (rc < 0 || rc >= argc) return CMD_HELP; - } - /* If the input is in form Eg. obdfilter.*.stats */ - if (strchr(path, '.')) { - tmp = path; - while (*tmp != '\0') { - if (*tmp == '.') - *tmp = '/'; - tmp ++; + for (i = rc, rc = 0; i < argc; i++) { + int rc2; + + path = argv[i]; + + clean_path(path); + + lprocfs_param_pattern(argv[0], path, pattern, sizeof(pattern)); + + if (popt.only_path) + rc2 = listparam_display(&popt, pattern); + else + rc2 = getparam_display(&popt, pattern); + if (rc2 < 0 && rc == 0) + rc = rc2; + } + + return rc; +} + +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; + popt->recursive = 0; + + while ((ch = getopt(argc, argv, "n")) != -1) { + switch (ch) { + case 'n': + popt->show_path = 0; + break; + default: + return -1; } } + return optind; +} - 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); - } +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 : glob %s: %s \n", pattern,strerror(rc)); - return rc; + fprintf(stderr, "error: set_param: %s: %s\n", + pattern, globerrstr(rc)); + return -ESRCH; } for (i = 0; i < glob_info.gl_pathc; i++) { - if (show_path) { - char *valuename, *filename; - filename = strdup(glob_info.gl_pathv[i]); - valuename = display_name(filename); - printf("%s=%s\n", valuename, value); + 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 */ - fp = open(glob_info.gl_pathv[i], O_WRONLY); - if (fp > 0) { - rc = write(fp, value, strlen(value)); + fd = open(glob_info.gl_pathv[i], O_WRONLY); + if (fd > 0) { + rc = write(fd, value, strlen(value)); if (rc < 0) - fprintf(stderr, - "error writing to file %s\n", - glob_info.gl_pathv[i]); + fprintf(stderr, "error: set_param: " + "writing to file %s: %s\n", + glob_info.gl_pathv[i], strerror(errno)); else rc = 0; - close(fp); + close(fd); } else { - fprintf(stderr, "error: %s: %s opening %s\n", - jt_cmdname(argv[0]), strerror(rc = errno), - glob_info.gl_pathv[i]); + 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 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, rc = 0; i < argc; i++) { + int rc2; + + 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); + + lprocfs_param_pattern(argv[0], path, pattern, sizeof(pattern)); + + rc2 = setparam_display(&popt, pattern, value); + path = NULL; + value = NULL; + if (rc2 < 0 && rc == 0) + rc = rc2; + } + + return rc; +} +