diff --git a/lustre/utils/lctl.c b/lustre/utils/lctl.c index 4d8b7cfb5e5a76040218ac2407aceec010a68a73..85e41055c23bce88336f5e87dc6907898dcc1f6e 100644 --- a/lustre/utils/lctl.c +++ b/lustre/utils/lctl.c @@ -119,6 +119,14 @@ command_t cmdlist[] = { "usage: conf_param <target.keyword=val> ...\n"}, {"local_param", jt_lcfg_param, 0, "set a temporary, local param\n" "usage: local_param <target.keyword=val> ...\n"}, + {"get_param", jt_lcfg_getparam, 0, "get the Lustre or LNET parameter\n" + "usage: get_param [-n] path/to/param/file \n" + "Get the value of Lustre or LNET parameter from the specified path\n" + "Use '-n' to disable printing of the key name when printing values."}, + {"set_param", jt_lcfg_setparam, 0, "set the Lustre or LNET parameter\n" + "usage: set_param [-n] path/to/param/file value\n" + "Set the value of the Lustre or LNET parameter at the specified path\n" + "Use '-n' to disable printing of the key name when printing values."}, /* Debug commands */ {"==== debugging control ===", jt_noop, 0, "debug"}, diff --git a/lustre/utils/lustre_cfg.c b/lustre/utils/lustre_cfg.c index 9af3ed6387a47e54abd316fb0794f4a0057c4ee1..55836d7afa70d0b84ebdf8081c0cc4e72bf96b19 100644 --- a/lustre/utils/lustre_cfg.c +++ b/lustre/utils/lustre_cfg.c @@ -29,6 +29,7 @@ #include <stdio.h> #include <stdarg.h> #include <ctype.h> +#include <glob.h> #ifndef __KERNEL__ #include <liblustre.h> @@ -506,4 +507,231 @@ int jt_lcfg_mgsparam(int argc, char **argv) return rc; } +/* Display the path in the same format as sysctl + * For eg. obdfilter.lustre-OST0000.stats */ +static char *display_name(char *filename) +{ + char *tmp; + + 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 = '.'; + + return filename; +} + +/* Find a character in a length limited string */ +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); +} + +int jt_lcfg_getparam(int argc, char **argv) +{ + int fp; + int rc = 0, i, show_path = 0; + char buf[CFS_PAGE_SIZE] = {'\0'}, pattern[PATH_MAX]; + char *path, *tmp; + glob_t glob_info; + + if (argc == 3 && strcmp(argv[1], "-n") == 0) { + path = argv[2]; + } else if (argc == 2) { + show_path = 1; + path = argv[1]; + } else { + return CMD_HELP; + } + + /* If the input is in form Eg. obdfilter.*.stats */ + if (strchr(path, '.')) { + tmp = path; + while (*tmp != '\0') { + if (*tmp == '.') + *tmp = '/'; + tmp ++; + } + } + + /* 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 = glob(pattern, GLOB_BRACE, NULL, &glob_info); + if (rc) { + fprintf(stderr, "error : glob %s: %s \n", pattern,strerror(rc)); + return rc; + } + + for (i = 0; i < glob_info.gl_pathc; i++) { + char *valuename = NULL; + if (show_path) { + char *filename; + filename = strdup(glob_info.gl_pathv[i]); + valuename = display_name(filename); + } + + /* 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)); + continue; + } + + do { + rc = read(fp, buf, sizeof(buf)); + if (rc == 0) + break; + if (rc < 0) { + fprintf(stderr, "error: %s: read('%s') " + "failed: %s\n", jt_cmdname(argv[0]), + 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) { + 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: %s: write to stdout " + "failed: %s\n", jt_cmdname(argv[0]), + strerror(errno)); + break; + } + } while (1); + memset(buf, 0, sizeof(buf)); + close(fp); + } + + globfree(&glob_info); + return rc; +} + + +int jt_lcfg_setparam(int argc, char **argv) +{ + int rc = 0, i; + int fp, show_path = 0; + char pattern[PATH_MAX]; + char *path, *value, *tmp; + glob_t glob_info; + + 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])); + return CMD_HELP; + } + /* If the input is in form Eg. obdfilter.*.stats */ + if (strchr(path, '.')) { + tmp = path; + while (*tmp != '\0') { + if (*tmp == '.') + *tmp = '/'; + tmp ++; + } + } + + 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 = glob(pattern, GLOB_BRACE, NULL, &glob_info); + if (rc) { + fprintf(stderr, "error : glob %s: %s \n", pattern,strerror(rc)); + return rc; + } + 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); + } + /* 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)); + if (rc < 0) + fprintf(stderr, + "error writing to file %s\n", + glob_info.gl_pathv[i]); + else + rc = 0; + close(fp); + } else { + fprintf(stderr, "error: %s: %s opening %s\n", + jt_cmdname(argv[0]), strerror(rc = errno), + glob_info.gl_pathv[i]); + } + } + + globfree(&glob_info); + return rc; +} diff --git a/lustre/utils/obdctl.h b/lustre/utils/obdctl.h index 03b42586dab17cbf1ea727a22c97264ba518ad68..3f2bf77420b93a95a299b5363172ee1fbfd9bc8e 100644 --- a/lustre/utils/obdctl.h +++ b/lustre/utils/obdctl.h @@ -79,6 +79,8 @@ int jt_lcfg_add_conn(int argc, char **argv); int jt_lcfg_del_conn(int argc, char **argv); int jt_lcfg_param(int argc, char **argv); int jt_lcfg_mgsparam(int argc, char **argv); +int jt_lcfg_getparam(int argc, char **argv); +int jt_lcfg_setparam(int argc, char **argv); int obd_add_uuid(char *uuid, lnet_nid_t nid);