From 85cbe1a3ee6940f7468884bca43cd736a5365694 Mon Sep 17 00:00:00 2001 From: James Simmons Date: Thu, 28 Jan 2016 11:08:48 -0500 Subject: [PATCH] LU-5030 util: migrate lctl params functions to use cfs_get_paths() Make the normal lctl set_param,list_param, and get_param operations to use the new cfs_get_paths() function which enables sysfs support along side procfs. Change-Id: I5817e96c3172de53930776f0891f2a642907bfde Signed-off-by: Dmitry Eremin Signed-off-by: James Simmons Signed-off-by: Wang Chao Reviewed-on: http://review.whamcloud.com/17466 Reviewed-by: Ryan Haasken Tested-by: Jenkins Tested-by: Maloo Reviewed-by: John L. Hammond Reviewed-by: Andreas Dilger Reviewed-by: Oleg Drokin --- lustre/tests/sanity.sh | 8 +- lustre/tests/test-framework.sh | 4 +- lustre/utils/lustre_cfg.c | 812 ++++++++++++++++++++++---------------- lustre/utils/lustreapi_internal.h | 2 +- 4 files changed, 480 insertions(+), 346 deletions(-) diff --git a/lustre/tests/sanity.sh b/lustre/tests/sanity.sh index d150cf3..52d1f3a 100755 --- a/lustre/tests/sanity.sh +++ b/lustre/tests/sanity.sh @@ -9429,7 +9429,8 @@ run_test 133e "Verifying OST {read,write}_bytes nid stats =================" proc_dirs="" for dir in /proc/fs/lustre/ /proc/sys/lnet/ /proc/sys/lustre/ \ - /sys/fs/lustre/ /sys/fs/lnet/ /sys/kernel/debug/lustre/; do + /sys/fs/lustre/ /sys/fs/lnet/ /sys/kernel/debug/lnet/ \ + /sys/kernel/debug/lustre/; do [[ -d $dir ]] && proc_dirs+=" $dir" done @@ -9440,7 +9441,7 @@ test_133f() { find $proc_dirs -exec cat '{}' \; &> /dev/null # Second verifying readability. - $LCTL get_param -R &> /dev/null || error "proc file read failed" + $LCTL get_param -R '*' &> /dev/null || error "proc file read failed" # eventually, this can also be replaced with "lctl get_param -R", # but not until that option is always available on the server @@ -14311,7 +14312,8 @@ test_401() { #LU-7437 #count the number of parameters by "list_param -R" local params=$($LCTL list_param -R '*' 2>/dev/null | wc -l) #count the number of parameters by listing proc files - local procs=$(find -L $proc_dirs -mindepth 1 2>/dev/null | wc -l) + local procs=$(find -L $proc_dirs -mindepth 1 -printf '%P\n' 2>/dev/null | + sort -u | wc -l) [ $params -eq $procs ] || error "found $params parameters vs. $procs proc files" diff --git a/lustre/tests/test-framework.sh b/lustre/tests/test-framework.sh index 780f901..43b17e9 100755 --- a/lustre/tests/test-framework.sh +++ b/lustre/tests/test-framework.sh @@ -1116,7 +1116,7 @@ get_osd_param() { local name=$3 do_nodes $nodes "$LCTL get_param -n obdfilter.$device.$name \ - osd-*.$device.$name 2>&1" | grep -v 'Found no match' + osd-*.$device.$name 2>&1" | grep -v 'error:' } set_osd_param() { @@ -1126,7 +1126,7 @@ set_osd_param() { local value=$4 do_nodes $nodes "$LCTL set_param -n obdfilter.$device.$name=$value \ - osd-*.$device.$name=$value 2>&1" | grep -v 'Found no match' + osd-*.$device.$name=$value 2>&1" | grep -v 'error:' } set_debug_size () { diff --git a/lustre/utils/lustre_cfg.c b/lustre/utils/lustre_cfg.c index 8ddd97f..29d3631 100644 --- a/lustre/utils/lustre_cfg.c +++ b/lustre/utils/lustre_cfg.c @@ -51,9 +51,9 @@ #include #include #include -#include #include +#include #include #include #include @@ -67,7 +67,6 @@ #include #include - #include "obdctl.h" #include #include @@ -665,54 +664,66 @@ 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 */ +/** + * Display a parameter path in the same format as sysctl. + * E.g. obdfilter.lustre-OST0000.stats + * + * \param[in] filename file name of the parameter + * \param[in] st parameter file stats + * \param[in] popt set/get param options + * + * \retval allocated pointer containing modified filename + */ static char * -display_name(char *filename, size_t filename_size, struct param_opts *popt) +display_name(const char *filename, struct stat *st, struct param_opts *popt) { - struct stat st; - char *tmp; + size_t suffix_len = 0; char *suffix = NULL; + char *param_name; + char *tmp; - if (popt->po_show_type || popt->po_only_dir) { - if (lstat(filename, &st) == -1) + if (popt->po_show_type) { + if (S_ISDIR(st->st_mode)) + suffix = "/"; + else if (S_ISLNK(st->st_mode)) + suffix = "@"; + else if (st->st_mode & S_IWUSR) + suffix = "="; + + if (suffix != NULL) + suffix_len = strlen(suffix); + } else if (popt->po_only_dir) { + if (!S_ISDIR(st->st_mode)) return NULL; - - if (popt->po_show_type) { - if (S_ISDIR(st.st_mode)) - suffix = "/"; - else if (S_ISLNK(st.st_mode)) - suffix = "@"; - else if (st.st_mode & S_IWUSR) - suffix = "="; - } else if (popt->po_only_dir) { - if (!S_ISDIR(st.st_mode)) - return NULL; - } } - filename += strlen("/proc/"); - if (strncmp(filename, "fs/", strlen("fs/")) == 0) - filename += strlen("fs/"); - else - filename += strlen("sys/"); + /* Take the original filename string and chop off the glob addition */ + tmp = strstr(filename, "/lustre/"); + if (tmp == NULL) { + tmp = strstr(filename, "/lnet/"); + if (tmp != NULL) + tmp += strlen("/lnet/"); + } else + tmp += strlen("/lustre/"); - if (strncmp(filename, "lustre/", strlen("lustre/")) == 0) - filename += strlen("lustre/"); - else if (strncmp(filename, "lnet/", strlen("lnet/")) == 0) - filename += strlen("lnet/"); + /* Allocate return string */ + param_name = strdup(tmp); + if (param_name == NULL) + return NULL; /* replace '/' with '.' to match conf_param and sysctl */ - tmp = filename; - while ((tmp = strchr(tmp, '/')) != NULL) + for (tmp = strchr(param_name, '/'); tmp != NULL; tmp = strchr(tmp, '/')) *tmp = '.'; - /* Append the indicator to entries. We know there is enough space - * for the suffix, since the path prefix was deleted. */ - if (popt->po_show_type && suffix != NULL) - strncat(filename, suffix, filename_size); + /* Append the indicator to entries if needed. */ + if (popt->po_show_type && suffix != NULL) { + param_name = realloc(param_name, + suffix_len + strlen(param_name) + 1); + if (param_name != NULL) + strncat(param_name, suffix, suffix_len); + } - return filename; + return param_name; } /* Find a character in a length limited string */ @@ -730,60 +741,407 @@ static char *strnchr(const char *p, char c, size_t n) return (0); } -static char *globerrstr(int glob_rc) +/** + * Turns a lctl parameter string into a procfs/sysfs subdirectory path pattern. + * + * \param[in] popt Used to control parameter usage. For this + * function it is used to see if the path has + * a added suffix. + * \param[in,out] path lctl parameter string that is turned into + * the subdirectory path pattern that is used + * to search the procfs/sysfs tree. + * + * \retval -errno on error. + */ +static int +clean_path(struct param_opts *popt, char *path) { - 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"; + char *nidstr = NULL; + char *tmp; + + if (popt == NULL || path == NULL || strlen(path) == 0) + return -EINVAL; + + /* If path contains a suffix we need to remove it */ + if (popt->po_show_type) { + size_t path_end = strlen(path) - 1; + + tmp = path + path_end; + switch (*tmp) { + case '@': + case '=': + case '/': + *tmp = '\0'; + default: + break; + } + } + + /* get rid of '\', glob doesn't like it */ + tmp = strrchr(path, '\\'); + if (tmp != NULL) { + char *tail = path + strlen(path); + + while (tmp != path) { + if (*tmp == '\\') { + memmove(tmp, tmp + 1, tail - tmp); + --tail; + } + --tmp; + } + } + + /* Does this path contain a NID string ? */ + tmp = strchr(path, '@'); + if (tmp != NULL) { + char *find_nid = strdup(path); + lnet_nid_t nid; + + if (find_nid == NULL) + return -ENOMEM; + + /* First we need to chop off rest after nid string. + * Since find_nid is a clone of path it better have + * '@' */ + tmp = strchr(find_nid, '@'); + tmp = strchr(tmp, '.'); + if (tmp != NULL) + *tmp = '\0'; + + /* Now chop off the front. */ + for (tmp = strchr(find_nid, '.'); tmp != NULL; + tmp = strchr(tmp, '.')) { + /* Remove MGC to make it NID format */ + if (!strncmp(++tmp, "MGC", 3)) + tmp += 3; + + nid = libcfs_str2nid(tmp); + if (nid != LNET_NID_ANY) { + nidstr = libcfs_nid2str(nid); + if (nidstr == NULL) + return -EINVAL; + break; + } + } + free(find_nid); + } + + /* replace param '.' with '/' */ + for (tmp = strchr(path, '.'); tmp != NULL; tmp = strchr(tmp, '.')) { + *tmp++ = '/'; + + /* Remove MGC to make it NID format */ + if (!strncmp(tmp, "MGC", 3)) + tmp += 3; + + /* There exist cases where some of the subdirectories of the + * the parameter tree has embedded in its name a NID string. + * This means that it is possible that these subdirectories + * could have actual '.' in its name. If this is the case we + * don't want to blindly replace the '.' with '/'. */ + if (nidstr != NULL) { + char *match = strstr(tmp, nidstr); + + if (tmp == match) + tmp += strlen(nidstr); + } + } + + return 0; } -static void clean_path(char *path) +/** + * The application lctl can perform three operations for lustre + * tunables. This enum defines those three operations which are + * + * 1) LIST_PARAM - list available tunables + * 2) GET_PARAM - report the current setting of a tunable + * 3) SET_PARAM - set the tunable to a new value + */ +enum parameter_operation { + LIST_PARAM, + GET_PARAM, + SET_PARAM, +}; + +/** + * Read the value of parameter + * + * \param[in] path full path to the parameter + * \param[in] param_name lctl parameter format of the + * parameter path + * \param[in] popt set/get param options + * + * \retval 0 on success. + * \retval -errno on error. + */ +static int +read_param(const char *path, const char *param_name, struct param_opts *popt) { - 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; - } - } + bool display_path = popt->po_show_path; + long page_size = sysconf(_SC_PAGESIZE); + int rc = 0; + char *buf; + int fd; + + /* Read the contents of file to stdout */ + fd = open(path, O_RDONLY); + if (fd < 0) { + rc = -errno; + fprintf(stderr, + "error: get_param: opening('%s') failed: %s\n", + path, strerror(errno)); + return rc; + } + + buf = calloc(1, page_size); + if (buf == NULL) { + close(fd); + return -ENOMEM; + } + + while (1) { + ssize_t count = read(fd, buf, page_size); + + if (count == 0) + break; + if (count < 0) { + rc = -errno; + if (errno != EIO) { + fprintf(stderr, "error: get_param: " + "read('%s') failed: %s\n", + param_name, strerror(errno)); + } + break; + } + + /* Print the output in the format path=value if the value does + * not contain a new line character and the output can fit in + * a single line, else print value on new line */ + if (display_path) { + bool longbuf; + + longbuf = strnchr(buf, count - 1, '\n') != NULL || + count + strlen(param_name) >= 80; + printf("%s=%s", param_name, longbuf ? "\n" : buf); + + /* Make sure it doesn't print again while looping */ + display_path = false; + + if (!longbuf) + continue; + } + + if (fwrite(buf, 1, count, stdout) != count) { + rc = -errno; + fprintf(stderr, "error: get_param: " + "write to stdout failed: %s\n", + strerror(errno)); + break; + } + } + close(fd); + free(buf); + + return rc; } -/* Take a parameter name and turn it into a pathname glob. - * Disallow relative pathnames to avoid potential problems. */ -static int lprocfs_param_pattern(const char *pattern, char *buf, size_t bufsize) +/** + * Set a parameter to a specified value + * + * \param[in] path full path to the parameter + * \param[in] param_name lctl parameter format of the parameter path + * \param[in] popt set/get param options + * \param[in] value value to set the parameter to + * + * \retval number of bytes written on success. + * \retval -errno on error. + */ +static int +write_param(const char *path, const char *param_name, struct param_opts *popt, + const char *value) { - int rc; + int fd, rc = 0; + ssize_t count; + + if (value == NULL) + return -EINVAL; - rc = snprintf(buf, bufsize, "/proc/{fs,sys}/{lnet,lustre}/%s", pattern); - if (rc < 0) { + /* Write the new value to the file */ + fd = open(path, O_WRONLY); + if (fd < 0) { rc = -errno; - } else if (rc >= bufsize) { - fprintf(stderr, "error: parameter '%s' too long\n", pattern); - rc = -E2BIG; + fprintf(stderr, "error: set_param: opening %s: %s\n", + path, strerror(errno)); + return rc; } + count = write(fd, value, strlen(value)); + if (count < 0) { + rc = -errno; + if (errno != EIO) { + fprintf(stderr, "error: set_param: setting " + "%s=%s: %s\n", path, value, + strerror(errno)); + } + } else if (count < strlen(value)) { /* Truncate case */ + rc = -EINVAL; + fprintf(stderr, "error: set_param: setting " + "%s=%s: wrote only %zd\n", path, value, count); + } else if (popt->po_show_path) { + printf("%s=%s\n", param_name, value); + } + close(fd); + return rc; +} + +/** + * Perform a read, write or just a listing of a parameter + * + * \param[in] popt list,set,get parameter options + * \param[in] pattern search filter for the path of the parameter + * \param[in] value value to set the parameter if write operation + * \param[in] mode what operation to perform with the parameter + * + * \retval number of bytes written on success. + * \retval -errno on error. + */ +static int +param_display(struct param_opts *popt, char *pattern, char *value, + enum parameter_operation mode) +{ + int dir_count = 0; + char **dir_cache; + glob_t paths; + int rc, i; + + rc = cfs_get_param_paths(&paths, "%s", pattern); + if (rc != 0) { + rc = -errno; + if (!popt->po_recursive) { + fprintf(stderr, "error: '%s': %s\n", + pattern, strerror(errno)); + } + return rc; + } + + dir_cache = calloc(paths.gl_pathc, sizeof(char *)); + if (dir_cache == NULL) { + rc = -ENOMEM; + goto out_param; + } + + for (i = 0; i < paths.gl_pathc; i++) { + char *param_name = NULL, *tmp; + char pathname[PATH_MAX]; + struct stat st; + + if (stat(paths.gl_pathv[i], &st) == -1) { + rc = -errno; + break; + } + + param_name = display_name(paths.gl_pathv[i], &st, popt); + if (param_name == NULL) { + rc = -ENOMEM; + break; + } + + /** + * For the upstream client the parameter files locations + * are split between under both /sys/kernel/debug/lustre + * and /sys/fs/lustre. The parameter files containing + * small amounts of data, less than a page in size, are + * located under /sys/fs/lustre and in the case of large + * parameter data files, think stats for example, are + * located in the debugfs tree. Since the files are split + * across two trees the directories are often duplicated + * which means these directories are listed twice which + * leads to duplicate output to the user. To avoid scanning + * a directory twice we have to cache any directory and + * check if a search has been requested twice. + */ + if (S_ISDIR(st.st_mode)) { + int j; + + for (j = 0; j < dir_count; j++) { + if (!strcmp(dir_cache[j], param_name)) + break; + } + if (j != dir_count) { + free(param_name); + param_name = NULL; + continue; + } + dir_cache[dir_count++] = strdup(param_name); + } + + switch (mode) { + case GET_PARAM: + /* Read the contents of file to stdout */ + if (S_ISREG(st.st_mode)) + read_param(paths.gl_pathv[i], param_name, popt); + break; + case SET_PARAM: + if (S_ISREG(st.st_mode)) { + rc = write_param(paths.gl_pathv[i], param_name, + popt, value); + } + break; + case LIST_PARAM: + default: + if (popt->po_show_path) + printf("%s\n", param_name); + break; + } + + /* Only directories are searched recursively if + * requested by the user */ + if (!S_ISDIR(st.st_mode) || !popt->po_recursive) { + free(param_name); + param_name = NULL; + continue; + } + + /* Turn param_name into file path format */ + rc = clean_path(popt, param_name); + if (rc < 0) { + free(param_name); + param_name = NULL; + break; + } + + /* Use param_name to grab subdirectory tree from full path */ + tmp = strstr(paths.gl_pathv[i], param_name); + + /* cleanup paramname now that we are done with it */ + free(param_name); + param_name = NULL; + + /* Shouldn't happen but just in case */ + if (tmp == NULL) { + rc = -EINVAL; + break; + } + + rc = snprintf(pathname, sizeof(pathname), "%s/*", tmp); + if (rc < 0) { + break; + } else if (rc >= sizeof(pathname)) { + rc = -EINVAL; + break; + } + + rc = param_display(popt, pathname, value, mode); + if (rc != 0 && rc != -ENOENT) + break; + } + + for (i = 0; i < dir_count; i++) + free(dir_cache[i]); + free(dir_cache); +out_param: + cfs_free_param_data(&paths); return rc; } @@ -813,80 +1171,30 @@ static int listparam_cmdline(int argc, char **argv, struct param_opts *popt) return optind; } -static int listparam_display(struct param_opts *popt, char *pattern) -{ - glob_t glob_info; - int rc; - int i; - - rc = glob(pattern, /* GLOB_ONLYDIR doesn't guarantee, only a hint */ - GLOB_BRACE | (popt->po_only_dir ? GLOB_ONLYDIR : 0) | - (popt->po_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 pathname[PATH_MAX + 1]; /* extra 1 byte for file type */ - int len = sizeof(pathname), last; - char *paramname = NULL; - - /* 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; - strlcpy(pathname, glob_info.gl_pathv[i], len); - paramname = display_name(pathname, len, popt); - if (paramname) - printf("%s\n", paramname); - if (last) { - strlcpy(pathname, glob_info.gl_pathv[i], len); - strlcat(pathname, "/*", len); - listparam_display(popt, pathname); - } - } - - globfree(&glob_info); - return rc; -} - int jt_lcfg_listparam(int argc, char **argv) { - int rc = 0, i; + int rc = 0, index, i; struct param_opts popt; - char pattern[PATH_MAX]; char *path; memset(&popt, 0, sizeof(popt)); - rc = listparam_cmdline(argc, argv, &popt); - if (rc == argc && popt.po_recursive) { - rc--; /* we know at least "-R" is a parameter */ - argv[rc] = "*"; - } else if (rc < 0 || rc >= argc) { + index = listparam_cmdline(argc, argv, &popt); + if (index < 0 || index >= argc) return CMD_HELP; - } - for (i = rc; i < argc; i++) { + for (i = index; i < argc; i++) { path = argv[i]; - clean_path(path); - rc = lprocfs_param_pattern(path, pattern, sizeof(pattern)); + rc = clean_path(&popt, path); if (rc < 0) - return rc; + break; - rc = listparam_display(&popt, pattern); + rc = param_display(&popt, path, NULL, LIST_PARAM); if (rc < 0) - return rc; + break; } - return 0; + return rc; } static int getparam_cmdline(int argc, char **argv, struct param_opts *popt) @@ -917,143 +1225,28 @@ static int getparam_cmdline(int argc, char **argv, struct param_opts *popt) return optind; } -static int getparam_display(struct param_opts *popt, char *pattern) -{ - long page_size = sysconf(_SC_PAGESIZE); - glob_t glob_info; - char *buf; - int rc; - int fd; - int i; - - rc = glob(pattern, GLOB_BRACE | (popt->po_recursive ? GLOB_MARK : 0), - NULL, &glob_info); - if (rc) { - fprintf(stderr, "error: get_param: %s: %s\n", - pattern, globerrstr(rc)); - return -ESRCH; - } - - buf = malloc(page_size); - if (buf == NULL) - return -ENOMEM; - - for (i = 0; i < glob_info.gl_pathc; i++) { - char pathname[PATH_MAX + 1]; /* extra 1 byte for file type */ - int len = sizeof(pathname), last; - char *paramname = NULL; - - memset(buf, 0, page_size); - /* 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; - - if (last) { - strlcpy(pathname, glob_info.gl_pathv[i], len); - strlcat(pathname, "/*", len); - getparam_display(popt, pathname); - continue; - } - - if (popt->po_show_path) { - if (strlen(glob_info.gl_pathv[i]) > - sizeof(pathname) - 1) { - free(buf); - return -E2BIG; - } - strncpy(pathname, glob_info.gl_pathv[i], - sizeof(pathname)); - paramname = display_name(pathname, sizeof(pathname), - popt); - } - - /* 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, 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 can be - * occupied in a line, else print value on new line */ - if (paramname && popt->po_show_path) { - int longbuf; - - longbuf = strnchr(buf, rc - 1, '\n') != NULL || - rc + strlen(paramname) >= 80; - printf("%s=%s", paramname, - longbuf ? "\n" : buf); - paramname = 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 rc = 0, i; + int rc = 0, index, i; struct param_opts popt; - char pattern[PATH_MAX]; char *path; memset(&popt, 0, sizeof(popt)); - rc = getparam_cmdline(argc, argv, &popt); - if (rc == argc && popt.po_recursive) { - rc--; /* we know at least "-R" is a parameter */ - argv[rc] = "*"; - } else if (rc < 0 || rc >= argc) { + index = getparam_cmdline(argc, argv, &popt); + if (index < 0 || index >= argc) return CMD_HELP; - } - - for (i = rc, rc = 0; i < argc; i++) { - int rc2; + for (i = index; i < argc; i++) { path = argv[i]; - clean_path(path); - - rc2 = lprocfs_param_pattern(path, pattern, sizeof(pattern)); - if (rc2 < 0) - return rc2; - - if (popt.po_only_path) - rc2 = listparam_display(&popt, pattern); - else - rc2 = getparam_display(&popt, pattern); - if (rc2 < 0 && rc == 0) - rc = rc2; + + rc = clean_path(&popt, path); + if (rc < 0) + break; + + rc = param_display(&popt, path, NULL, + popt.po_only_path ? LIST_PARAM : GET_PARAM); + if (rc < 0) + break; } return rc; @@ -1088,14 +1281,14 @@ int jt_nodemap_info(int argc, char **argv) if (argc == 1 || strcmp("list", argv[1]) == 0) { popt.po_only_path = 1; popt.po_only_dir = 1; - rc = listparam_display(&popt, "nodemap/*"); + rc = param_display(&popt, "nodemap/*", NULL, LIST_PARAM); } else if (strcmp("all", argv[1]) == 0) { - rc = getparam_display(&popt, "nodemap/*/*"); + rc = param_display(&popt, "nodemap/*/*", NULL, LIST_PARAM); } else { char pattern[PATH_MAX]; snprintf(pattern, sizeof(pattern), "nodemap/%s/*", argv[1]); - rc = getparam_display(&popt, pattern); + rc = param_display(&popt, pattern, NULL, LIST_PARAM); if (rc == -ESRCH) fprintf(stderr, "error: nodemap_info: cannot find" "nodemap %s\n", argv[1]); @@ -1103,7 +1296,6 @@ int jt_nodemap_info(int argc, char **argv) return rc; } - static int setparam_cmdline(int argc, char **argv, struct param_opts *popt) { int ch; @@ -1133,70 +1325,15 @@ static int setparam_cmdline(int argc, char **argv, struct param_opts *popt) return optind; } -static int setparam_display(struct param_opts *popt, char *pattern, char *value) -{ - glob_t glob_info; - int rc; - int fd; - int i; - - 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 pathname[PATH_MAX + 1]; /* extra 1 byte for file type */ - char *paramname = NULL; - - if (popt->po_show_path) { - if (strlen(glob_info.gl_pathv[i]) > - sizeof(pathname) - 1) - return -E2BIG; - strncpy(pathname, glob_info.gl_pathv[i], - sizeof(pathname)); - paramname = display_name(pathname, sizeof(pathname), - popt); - if (paramname) - printf("%s=%s\n", paramname, value); - } - /* Write the new value to the file */ - fd = open(glob_info.gl_pathv[i], O_WRONLY); - if (fd >= 0) { - int rc2; - - rc2 = write(fd, value, strlen(value)); - if (rc2 < 0) { - if (rc == 0) - rc = -errno; - fprintf(stderr, "error: set_param: setting " - "%s=%s: %s\n", glob_info.gl_pathv[i], - value, strerror(errno)); - } - close(fd); - } else { - if (rc == 0) - rc = -errno; - fprintf(stderr, "error: set_param: opening %s: %s\n", - strerror(errno), glob_info.gl_pathv[i]); - } - } - - globfree(&glob_info); - return rc; -} - int jt_lcfg_setparam(int argc, char **argv) { - int rc = 0, i; + int rc = 0, index, i; struct param_opts popt; - char pattern[PATH_MAX]; char *path = NULL, *value = NULL; memset(&popt, 0, sizeof(popt)); - rc = setparam_cmdline(argc, argv, &popt); - if (rc < 0 || rc >= argc) + index = setparam_cmdline(argc, argv, &popt); + if (index < 0 || index >= argc) return CMD_HELP; if (popt.po_params2) @@ -1204,9 +1341,7 @@ int jt_lcfg_setparam(int argc, char **argv) * set with old conf_param interface */ return jt_lcfg_mgsparam2(argc, argv, &popt); - for (i = rc, rc = 0; i < argc; i++) { - int rc2; - + for (i = index; i < argc; i++) { value = strchr(argv[i], '='); if (value != NULL) { /* format: set_param a=b */ @@ -1225,20 +1360,17 @@ int jt_lcfg_setparam(int argc, char **argv) } } - clean_path(path); - rc2 = lprocfs_param_pattern(path, pattern, sizeof(pattern)); - if (rc2 < 0) - return rc2; + rc = clean_path(&popt, path); + if (rc < 0) + break; - rc2 = setparam_display(&popt, pattern, value); + rc = param_display(&popt, path, value, SET_PARAM); path = NULL; value = NULL; - if (rc2 < 0 && rc == 0) - rc = rc2; } if (path != NULL && (value == NULL || *value == '\0')) fprintf(stderr, "error: %s: setting %s=: %s\n", - jt_cmdname(argv[0]), pattern, strerror(rc = EINVAL)); + jt_cmdname(argv[0]), path, strerror(rc = EINVAL)); return rc; } diff --git a/lustre/utils/lustreapi_internal.h b/lustre/utils/lustreapi_internal.h index 00a66e3..2166c1e 100644 --- a/lustre/utils/lustreapi_internal.h +++ b/lustre/utils/lustreapi_internal.h @@ -35,7 +35,7 @@ #ifndef _LUSTREAPI_INTERNAL_H_ #define _LUSTREAPI_INTERNAL_H_ -#include +#include #include #define WANT_PATH 0x1 -- 1.8.3.1