From 8813fdf2a4f2055e4867df653644f12ac4c78b15 Mon Sep 17 00:00:00 2001 From: James Simmons Date: Thu, 14 Jan 2016 15:15:18 -0500 Subject: [PATCH] LU-5030 util: migrate liblustreapi to use cfs_get_paths() Move liblustreapi library to use cfs_get_paths() so it can be used with the upstream client as well. Change-Id: I7c2ee3ded74dec0827f1aeaa631b1c334d39c917 Signed-off-by: Dmitry Eremin Signed-off-by: James Simmons Signed-off-by: Wang Chao Reviewed-on: http://review.whamcloud.com/17468 Reviewed-by: Ben Evans Tested-by: Jenkins Reviewed-by: Andreas Dilger Tested-by: Maloo Reviewed-by: Oleg Drokin --- lustre/utils/Makefile.am | 6 +- lustre/utils/liblustreapi.c | 892 ++++++++++++------------------------ lustre/utils/liblustreapi_hsm.c | 1 - lustre/utils/liblustreapi_nodemap.c | 13 +- lustre/utils/liblustreapi_param.c | 175 +++++++ lustre/utils/lustreapi_internal.h | 41 +- 6 files changed, 523 insertions(+), 605 deletions(-) create mode 100644 lustre/utils/liblustreapi_param.c diff --git a/lustre/utils/Makefile.am b/lustre/utils/Makefile.am index e4b8e1b..4c68926 100644 --- a/lustre/utils/Makefile.am +++ b/lustre/utils/Makefile.am @@ -79,13 +79,13 @@ llverfs_LDADD := $(EXT2FSLIB) $(E2PLIB) llverdev_LDADD := $(EXT2FSLIB) $(BLKIDLIB) -L_STRING := $(top_builddir)/libcfs/libcfs/util/string.c liblustreapitmp_a_SOURCES = liblustreapi.c liblustreapi_hsm.c \ liblustreapi_nodemap.c lustreapi_internal.h \ liblustreapi_json.c liblustreapi_layout.c \ liblustreapi_lease.c liblustreapi_util.c \ - liblustreapi_kernelconn.c $(L_STRING) - + liblustreapi_kernelconn.c liblustreapi_param.c \ + $(top_builddir)/libcfs/libcfs/util/string.c \ + $(top_builddir)/libcfs/libcfs/util/param.c if UTILS # build static and shared lib lustreapi liblustreapi.a : liblustreapitmp.a diff --git a/lustre/utils/liblustreapi.c b/lustre/utils/liblustreapi.c index 1f9c35f..bac6a68 100644 --- a/lustre/utils/liblustreapi.c +++ b/lustre/utils/liblustreapi.c @@ -62,7 +62,6 @@ #include #include #include -#include #include /* for dirname() */ #ifdef HAVE_LINUX_UNISTD_H #include @@ -71,6 +70,7 @@ #endif #include +#include #include #include #include @@ -296,67 +296,6 @@ int llapi_stripe_limit_check(unsigned long long stripe_size, int stripe_offset, return 0; } -/* return the first file matching this pattern */ -static int first_match(char *pattern, char *buffer) -{ - glob_t glob_info; - - if (glob(pattern, GLOB_BRACE, NULL, &glob_info)) - return -ENOENT; - - if (glob_info.gl_pathc < 1) { - globfree(&glob_info); - return -ENOENT; - } - - strcpy(buffer, glob_info.gl_pathv[0]); - - globfree(&glob_info); - return 0; -} - -static int find_target_obdpath(char *fsname, char *path) -{ - glob_t glob_info; - char pattern[PATH_MAX + 1]; - int rc; - - snprintf(pattern, PATH_MAX, - "/proc/fs/lustre/lov/%s-*/target_obd", - fsname); - rc = glob(pattern, GLOB_BRACE, NULL, &glob_info); - if (rc == GLOB_NOMATCH) - return -ENODEV; - else if (rc) - return -EINVAL; - - strcpy(path, glob_info.gl_pathv[0]); - globfree(&glob_info); - return 0; -} - -static int find_poolpath(char *fsname, char *poolname, char *poolpath) -{ - glob_t glob_info; - char pattern[PATH_MAX + 1]; - int rc; - - snprintf(pattern, PATH_MAX, - "/proc/fs/lustre/lov/%s-*/pools/%s", - fsname, poolname); - rc = glob(pattern, GLOB_BRACE, NULL, &glob_info); - /* If no pools, make sure the lov is available */ - if ((rc == GLOB_NOMATCH) && - (find_target_obdpath(fsname, poolpath) == -ENODEV)) - return -ENODEV; - if (rc) - return -EINVAL; - - strcpy(poolpath, glob_info.gl_pathv[0]); - globfree(&glob_info); - return 0; -} - /* * Trim a trailing newline from a string, if it exists. */ @@ -375,200 +314,11 @@ int llapi_chomp_string(char *buf) return '\n'; } -/** - * return a parameter string for a specific device type or mountpoint - * - * \param param_path the path to the file containing parameter data - * \param result buffer for parameter value string - * \param result_size size of buffer for return value - * - * The \param param_path is appended to /proc/{fs,sys}/{lnet,lustre} to - * complete the absolute path to the file containing the parameter data - * the user is requesting. If that file exist then the data is read from - * the file and placed into the \param result buffer that is passed by - * the user. Data is only copied up to the \param result_size to prevent - * overflow of the array. - * - * Return 0 for success, with a NUL-terminated string in \param result. - * Return -ve value for error. - */ -int get_param(const char *param_path, char *result, - unsigned int result_size) -{ - char file[PATH_MAX + 1], pattern[PATH_MAX + 1], buf[result_size]; - FILE *fp = NULL; - int rc = 0; - - snprintf(pattern, PATH_MAX, "/proc/{fs,sys}/{lnet,lustre}/%s", - param_path); - rc = first_match(pattern, file); - if (rc != 0 || result == NULL) - return rc; - - fp = fopen(file, "r"); - if (fp != NULL) { - while (fgets(buf, result_size, fp) != NULL) - strcpy(result, buf); - fclose(fp); - } else { - rc = -errno; - } - return rc; -} - -#define DEVICES_LIST "/proc/fs/lustre/devices" - -/** - * return a parameter string for a specific device type or mountpoint - * - * \param fsname Lustre filesystem name (optional) - * \param file_path path to file in filesystem (optional, if fsname unset) - * \param obd_type Lustre OBD device type - * \param param_name parameter name to fetch - * \param value return buffer for parameter value string - * \param val_len size of buffer for return value - * - * If fsname is specified then the parameter will be from that filesystem - * (if it exists). If file_path is given and it is in a mounted Lustre - * filesystem, then the parameter will be otherwise the value may be - * from any mounted filesystem (if there is more than one). - * - * If "obd_type" matches a Lustre device then the first matching device - * (as with "lctl dl", constrained by \param fsname or \param mount_path) - * will be used to provide the return value, otherwise the first such - * device found will be used. - * - * Return 0 for success, with a NUL-terminated string in \param buffer. - * Return -ve value for error. - */ -static int get_param_obdvar(const char *fsname, const char *file_path, - const char *obd_type, const char *param_name, - char *value, unsigned int val_len) -{ - char devices[PATH_MAX]; - char dev[PATH_MAX] = "*"; - char fs[PATH_MAX]; - FILE *fp = NULL; - int rc = 0; - - fp = fopen(DEVICES_LIST, "r"); - if (fp == NULL) { - rc = -errno; - llapi_error(LLAPI_MSG_ERROR, rc, "error: opening "DEVICES_LIST); - goto out; - } - - if (fsname == NULL && file_path != NULL) { - rc = llapi_search_fsname(file_path, fs); - if (rc) { - llapi_error(LLAPI_MSG_ERROR, rc, - "'%s' is not on a Lustre filesystem", - file_path); - goto out; - } - } else if (fsname != NULL) { - rc = strlcpy(fs, fsname, sizeof(fs)); - if (rc >= sizeof(fs)) { - rc = -E2BIG; - goto out; - } - } - - while (fgets(devices, sizeof(devices) - 1, fp) != NULL) { - char *bufp = devices, *tmp; - - devices[sizeof(devices) - 1] = '\0'; - while (bufp[0] == ' ') - ++bufp; - - tmp = strstr(bufp, obd_type); - if (tmp != NULL) { - tmp += strlen(obd_type) + 1; - if (strcmp(tmp, fs)) - continue; - rc = strlcpy(dev, tmp, sizeof(dev)); - if (rc >= sizeof(dev)) { - rc = -E2BIG; - goto out; - } - - tmp = strchr(dev, ' '); - if (tmp != NULL) - *tmp = '\0'; - break; - } - } - - if (dev[0] == '*' && strlen(fs)) { - rc = snprintf(dev, sizeof(dev), "%s-*", fs); - if (rc >= sizeof(dev)) { - rc = -E2BIG; - goto out; - } - } - rc = snprintf(devices, sizeof(devices), "%s/%s/%s", obd_type, dev, - param_name); - if (rc >= sizeof(devices)) { - rc = -E2BIG; - goto out; - } - - fclose(fp); - return get_param(devices, value, val_len); -out: - if (fp != NULL) - fclose(fp); - return rc; -} - /* - * TYPE one of llite, lmv, lov. - * /proc/fs/lustre/TYPE/INST the directory of interest. + * Wrapper to grab parameter settings for lov.*-clilov-*.* values */ -static int get_param_cli(const char *type, const char *inst, - const char *param, char *buf, size_t buf_size) -{ - char param_path[PATH_MAX + 1]; - FILE *param_file = NULL; - int rc; - - snprintf(param_path, sizeof(param_path), - "/proc/fs/lustre/%s/%s/%s", type, inst, param); - - param_file = fopen(param_path, "r"); - if (param_file == NULL) { - rc = -errno; - goto out; - } - - if (fgets(buf, buf_size, param_file) == NULL) { - rc = -errno; - goto out; - } - - rc = 0; -out: - if (param_file != NULL) - fclose(param_file); - - return rc; -} - -static int get_param_llite(const char *path, - const char *param, char *buf, size_t buf_size) -{ - char inst[80]; - int rc; - - rc = llapi_getname(path, inst, sizeof(inst)); - if (rc != 0) - return rc; - - return get_param_cli("llite", inst, param, buf, buf_size); -} - -static int get_param_lov(const char *path, - const char *param, char *buf, size_t buf_size) +static int get_param_lov(const char *path, const char *param, + char *buf, size_t buf_size) { struct obd_uuid uuid; int rc; @@ -577,11 +327,15 @@ static int get_param_lov(const char *path, if (rc != 0) return rc; - return get_param_cli("lov", uuid.uuid, param, buf, buf_size); + return get_lustre_param_value("lov", uuid.uuid, FILTER_BY_EXACT, param, + buf, buf_size); } -static int get_param_lmv(const char *path, - const char *param, char *buf, size_t buf_size) +/* + * Wrapper to grab parameter settings for lmv.*-clilov-*.* values + */ +static int get_param_lmv(const char *path, const char *param, + char *buf, size_t buf_size) { struct obd_uuid uuid; int rc; @@ -590,26 +344,29 @@ static int get_param_lmv(const char *path, if (rc != 0) return rc; - return get_param_cli("lmv", uuid.uuid, param, buf, buf_size); + return get_lustre_param_value("lmv", uuid.uuid, FILTER_BY_EXACT, param, + buf, buf_size); } static int get_mds_md_size(const char *path) { + char buf[PATH_MAX], inst[PATH_MAX]; int md_size = lov_user_md_size(LOV_MAX_STRIPE_COUNT, LOV_USER_MAGIC_V3); - char buf[80]; int rc; - /* Get the max ea size from llite proc. */ - rc = get_param_llite(path, "max_easize", buf, sizeof(buf)); + rc = llapi_getname(path, inst, sizeof(inst)); if (rc != 0) - goto out; + return md_size; + + /* Get the max ea size from llite parameters. */ + rc = get_lustre_param_value("llite", inst, FILTER_BY_EXACT, + "max_easize", buf, sizeof(buf)); + if (rc != 0) + return md_size; rc = atoi(buf); - if (rc > 0) - md_size = rc; -out: - return md_size; + return rc > 0 ? rc : md_size; } int llapi_get_agent_uuid(char *path, char *buf, size_t bufsize) @@ -626,23 +383,43 @@ int llapi_get_agent_uuid(char *path, char *buf, size_t bufsize) */ int llapi_search_ost(char *fsname, char *poolname, char *ostname) { - FILE *fd; - char buffer[PATH_MAX + 1]; - int len = 0, rc; + char buffer[PATH_MAX]; + size_t len = 0; + glob_t param; + FILE *fd; + int rc; - if (ostname != NULL) - len = strlen(ostname); + /* You need one or the other */ + if (poolname == NULL && fsname == NULL) + return -EINVAL; - if (poolname == NULL) { - if (len == 0) - rc = -EINVAL; - else - rc = find_target_obdpath(fsname, buffer); + if (ostname != NULL) + len = strlen(ostname); + + if (poolname == NULL && len == 0) + return -EINVAL; + + /* Search by poolname and fsname if is not NULL */ + if (poolname != NULL) { + rc = poolpath(¶m, fsname, NULL); + if (rc == 0) { + snprintf(buffer, sizeof(buffer), "%s/%s", + param.gl_pathv[0], poolname); + } + } else if (fsname != NULL) { + rc = get_lustre_param_path("lov", fsname, + FILTER_BY_FS_NAME, + "target_obd", ¶m); + if (rc == 0) { + strncpy(buffer, param.gl_pathv[0], + sizeof(buffer)); + } } else { - rc = find_poolpath(fsname, poolname, buffer); + return -EINVAL; } - if (rc) - return rc; + cfs_free_param_data(¶m); + if (rc) + return rc; fd = fopen(buffer, "r"); if (fd == NULL) @@ -1251,37 +1028,6 @@ int llapi_getname(const char *path, char *buf, size_t size) return rc; } - -/* - * find the pool directory path under /proc - * (can be also used to test if a fsname is known) - */ -static int poolpath(char *fsname, char *pathname, char *pool_pathname) -{ - int rc = 0; - char pattern[PATH_MAX + 1]; - char buffer[PATH_MAX]; - - if (fsname == NULL) { - rc = llapi_search_fsname(pathname, buffer); - if (rc != 0) - return rc; - fsname = buffer; - strcpy(pathname, fsname); - } - - snprintf(pattern, PATH_MAX, "/proc/fs/lustre/lov/%s-*/pools", fsname); - rc = first_match(pattern, buffer); - if (rc) - return rc; - - /* in fsname test mode, pool_pathname is NULL */ - if (pool_pathname != NULL) - strcpy(pool_pathname, buffer); - - return 0; -} - /** * Get the list of pool members. * \param poolname string of format \.\ @@ -1298,43 +1044,43 @@ int llapi_get_poolmembers(const char *poolname, char **members, { char fsname[PATH_MAX]; char *pool, *tmp; - char pathname[PATH_MAX]; - char path[PATH_MAX]; - char buf[1024]; - FILE *fd; - int rc = 0; - int nb_entries = 0; - int used = 0; + glob_t pathname; + char buf[PATH_MAX]; + FILE *fd; + int rc = 0; + int nb_entries = 0; + int used = 0; - /* name is FSNAME.POOLNAME */ + /* name is FSNAME.POOLNAME */ if (strlen(poolname) >= sizeof(fsname)) return -EOVERFLOW; strlcpy(fsname, poolname, sizeof(fsname)); - pool = strchr(fsname, '.'); - if (pool == NULL) - return -EINVAL; + pool = strchr(fsname, '.'); + if (pool == NULL) + return -EINVAL; - *pool = '\0'; - pool++; + *pool = '\0'; + pool++; - rc = poolpath(fsname, NULL, pathname); - if (rc != 0) { - llapi_error(LLAPI_MSG_ERROR, rc, - "Lustre filesystem '%s' not found", - fsname); - return rc; - } + rc = poolpath(&pathname, fsname, NULL); + if (rc != 0) { + llapi_error(LLAPI_MSG_ERROR, rc, + "Lustre filesystem '%s' not found", + fsname); + return rc; + } - llapi_printf(LLAPI_MSG_NORMAL, "Pool: %s.%s\n", fsname, pool); - rc = snprintf(path, sizeof(path), "%s/%s", pathname, pool); - if (rc >= sizeof(path)) + llapi_printf(LLAPI_MSG_NORMAL, "Pool: %s.%s\n", fsname, pool); + rc = snprintf(buf, sizeof(buf), "%s/%s", pathname.gl_pathv[0], pool); + cfs_free_param_data(&pathname); + if (rc >= sizeof(buf)) return -EOVERFLOW; - fd = fopen(path, "r"); - if (fd == NULL) { - rc = -errno; - llapi_error(LLAPI_MSG_ERROR, rc, "Cannot open %s", path); - return rc; - } + fd = fopen(buf, "r"); + if (fd == NULL) { + rc = -errno; + llapi_error(LLAPI_MSG_ERROR, rc, "cannot open %s", buf); + return rc; + } rc = 0; while (fgets(buf, sizeof(buf), fd) != NULL) { @@ -1377,7 +1123,9 @@ int llapi_get_poolmembers(const char *poolname, char **members, int llapi_get_poollist(const char *name, char **poollist, int list_size, char *buffer, int buffer_size) { - char fsname[PATH_MAX + 1], rname[PATH_MAX + 1], pathname[PATH_MAX + 1]; + char rname[PATH_MAX]; + glob_t pathname; + char *fsname; char *ptr; DIR *dir; struct dirent pool; @@ -1405,50 +1153,45 @@ int llapi_get_poollist(const char *name, char **poollist, int list_size, return rc; } - rc = poolpath(NULL, rname, pathname); - if (rc != 0) { - llapi_error(LLAPI_MSG_ERROR, rc, "'%s' is not" - " a Lustre filesystem", name); - return rc; - } - if (strlen(rname) > sizeof(fsname)-1) - return -E2BIG; - strncpy(fsname, rname, sizeof(fsname)); - } else { - /* name is FSNAME */ - if (strlen(name) > sizeof(fsname)-1) - return -E2BIG; - strncpy(fsname, name, sizeof(fsname)); - rc = poolpath(fsname, NULL, pathname); - } - if (rc != 0) { - llapi_error(LLAPI_MSG_ERROR, rc, - "Lustre filesystem '%s' not found", name); - return rc; - } + fsname = strdup(rname); + if (!fsname) + return -ENOMEM; - llapi_printf(LLAPI_MSG_NORMAL, "Pools from %s:\n", fsname); - dir = opendir(pathname); - if (dir == NULL) { - rc = -errno; - llapi_error(LLAPI_MSG_ERROR, rc, - "Could not open pool list for '%s'", - name); - return rc; - } + rc = poolpath(&pathname, NULL, rname); + } else { + /* name is FSNAME */ + fsname = strdup(name); + if (!fsname) + return -ENOMEM; + rc = poolpath(&pathname, fsname, NULL); + } + if (rc != 0) { + llapi_error(LLAPI_MSG_ERROR, rc, + "Lustre filesystem '%s' not found", name); + goto free_path; + } - while(1) { - rc = readdir_r(dir, &pool, &cookie); + llapi_printf(LLAPI_MSG_NORMAL, "Pools from %s:\n", fsname); + dir = opendir(pathname.gl_pathv[0]); + if (dir == NULL) { + rc = -errno; + llapi_error(LLAPI_MSG_ERROR, rc, + "Could not open pool list for '%s'", + name); + goto free_path; + } - if (rc != 0) { - rc = -errno; - llapi_error(LLAPI_MSG_ERROR, rc, - "Error reading pool list for '%s'", name); - goto out; - } else if ((rc == 0) && (cookie == NULL)) { - /* end of directory */ - break; - } + while(1) { + rc = readdir_r(dir, &pool, &cookie); + if (rc != 0) { + rc = -errno; + llapi_error(LLAPI_MSG_ERROR, rc, + "Error reading pool list for '%s'", name); + goto free_path; + } else if ((rc == 0) && (cookie == NULL)) { + /* end of directory */ + break; + } /* ignore . and .. */ if (!strcmp(pool.d_name, ".") || !strcmp(pool.d_name, "..")) @@ -1457,14 +1200,14 @@ int llapi_get_poollist(const char *name, char **poollist, int list_size, /* check output bounds */ if (nb_entries >= list_size) { rc = -EOVERFLOW; - goto out; + goto free_dir; } /* +2 for '.' and final '\0' */ if (used + strlen(pool.d_name) + strlen(fsname) + 2 > buffer_size) { rc = -EOVERFLOW; - goto out; + goto free_dir; } sprintf(buffer + used, "%s.%s", fsname, pool.d_name); @@ -1473,19 +1216,24 @@ int llapi_get_poollist(const char *name, char **poollist, int list_size, nb_entries++; } -out: - closedir(dir); - return ((rc != 0) ? rc : nb_entries); +free_dir: + closedir(dir); +free_path: + cfs_free_param_data(&pathname); + if (fsname) + free(fsname); + return rc != 0 ? rc : nb_entries; } /* wrapper for lfs.c and obd.c */ int llapi_poollist(const char *name) { - /* list of pool names (assume that pool count is smaller - than OST count) */ - char **list, *buffer = NULL, *path = NULL, *fsname = NULL; - int obdcount, bufsize, rc, nb, i; - char *poolname = NULL, *tmp = NULL, data[16]; + /* list of pool names (assume that pool count is smaller + than OST count) */ + char **list, *buffer = NULL, *fsname = (char *)name; + char *poolname = NULL, *tmp = NULL, data[16]; + enum param_filter type = FILTER_BY_PATH; + int obdcount, bufsize, rc, nb, i; if (name == NULL) return -EINVAL; @@ -1495,18 +1243,17 @@ int llapi_poollist(const char *name) if (fsname == NULL) return -ENOMEM; - poolname = strchr(fsname, '.'); - if (poolname) - *poolname = '\0'; - } else { - path = (char *) name; - } + poolname = strchr(fsname, '.'); + if (poolname) + *poolname = '\0'; + type = FILTER_BY_FS_NAME; + } - rc = get_param_obdvar(fsname, path, "lov", "numobd", - data, sizeof(data)); - if (rc < 0) - goto err; - obdcount = atoi(data); + rc = get_lustre_param_value("lov", fsname, type, "numobd", + data, sizeof(data)); + if (rc < 0) + goto err; + obdcount = atoi(data); /* Allocate space for each fsname-OST0000_UUID, 1 per OST, * and also an array to store the pointers for all that @@ -1542,9 +1289,9 @@ retry_get_pools: err: if (buffer) free(buffer); - if (fsname) - free(fsname); - return rc; + if (fsname != NULL && type == FILTER_BY_FS_NAME) + free(fsname); + return rc; } typedef int (semantic_func_t)(char *path, DIR *parent, DIR **d, @@ -1915,6 +1662,7 @@ enum tgt_type { LOV_TYPE = 1, LMV_TYPE }; + /* * If uuidp is NULL, return the number of available obd uuids. * If uuidp is non-NULL, then it will return the uuids of the obds. If @@ -1924,32 +1672,33 @@ enum tgt_type { static int llapi_get_target_uuids(int fd, struct obd_uuid *uuidp, int *ost_count, enum tgt_type type) { + char buf[PATH_MAX], format[32]; + int rc = 0, index = 0; struct obd_uuid name; - char buf[1024]; - char format[32]; + glob_t param; FILE *fp; - int rc = 0, index = 0; - /* Get the lov name */ - if (type == LOV_TYPE) { - rc = llapi_file_fget_lov_uuid(fd, &name); - if (rc) - return rc; - } else { - rc = llapi_file_fget_lmv_uuid(fd, &name); - if (rc) - return rc; - } + /* Get the lov name */ + if (type == LOV_TYPE) + rc = llapi_file_fget_lov_uuid(fd, &name); + else + rc = llapi_file_fget_lmv_uuid(fd, &name); + if (rc != 0) + return rc; - /* Now get the ost uuids from /proc */ - snprintf(buf, sizeof(buf), "/proc/fs/lustre/%s/%s/target_obd", - type == LOV_TYPE ? "lov" : "lmv", name.uuid); - fp = fopen(buf, "r"); - if (fp == NULL) { - rc = -errno; - llapi_error(LLAPI_MSG_ERROR, rc, "error: opening '%s'", buf); - return rc; - } + /* Now get the ost uuids */ + rc = get_lustre_param_path(type == LOV_TYPE ? "lov" : "lmv", name.uuid, + FILTER_BY_EXACT, "target_obd", ¶m); + if (rc != 0) + return -ENOENT; + + fp = fopen(param.gl_pathv[0], "r"); + if (fp == NULL) { + rc = -errno; + llapi_error(LLAPI_MSG_ERROR, rc, "error: opening '%s'", + param.gl_pathv[0]); + goto free_param; + } snprintf(format, sizeof(format), "%%d: %%%zus", sizeof(uuidp[0].uuid) - 1); @@ -1966,8 +1715,10 @@ static int llapi_get_target_uuids(int fd, struct obd_uuid *uuidp, if (uuidp && (index > *ost_count)) rc = -EOVERFLOW; - *ost_count = index; - return rc; + *ost_count = index; +free_param: + cfs_free_param_data(¶m); + return rc; } int llapi_lov_get_uuids(int fd, struct obd_uuid *uuidp, int *ost_count) @@ -2024,44 +1775,52 @@ int llapi_uuid_match(char *real_uuid, char *search_uuid) static int setup_obd_uuid(DIR *dir, char *dname, struct find_param *param) { struct obd_uuid obd_uuid; - char buf[1024]; + char buf[PATH_MAX]; + glob_t param_data; char format[32]; - FILE *fp; int rc = 0; + FILE *fp; if (param->fp_got_uuids) - return rc; + return rc; - /* Get the lov/lmv name */ + /* Get the lov/lmv name */ if (param->fp_get_lmv) - rc = llapi_file_fget_lmv_uuid(dirfd(dir), &obd_uuid); - else - rc = llapi_file_fget_lov_uuid(dirfd(dir), &obd_uuid); - if (rc) { - if (rc != -ENOTTY) { - llapi_error(LLAPI_MSG_ERROR, rc, - "error: can't get lov name: %s", dname); - } else { - rc = 0; - } - return rc; - } + rc = llapi_file_fget_lmv_uuid(dirfd(dir), &obd_uuid); + else + rc = llapi_file_fget_lov_uuid(dirfd(dir), &obd_uuid); + if (rc) { + if (rc != -ENOTTY) { + llapi_error(LLAPI_MSG_ERROR, rc, + "error: can't get %s name: %s", + param->fp_get_lmv ? "lmv" : "lov", + dname); + } else { + rc = 0; + } + return rc; + } param->fp_got_uuids = 1; - /* Now get the ost uuids from /proc */ - snprintf(buf, sizeof(buf), "/proc/fs/lustre/%s/%s/target_obd", - param->fp_get_lmv ? "lmv" : "lov", obd_uuid.uuid); - fp = fopen(buf, "r"); - if (fp == NULL) { - rc = -errno; - llapi_error(LLAPI_MSG_ERROR, rc, "error: opening '%s'", buf); - return rc; - } + /* Now get the ost uuids */ + rc = get_lustre_param_path(param->fp_get_lmv ? "lmv" : "lov", + obd_uuid.uuid, FILTER_BY_EXACT, + "target_obd", ¶m_data); + if (rc != 0) + return -ENOENT; + + fp = fopen(param_data.gl_pathv[0], "r"); + if (fp == NULL) { + rc = -errno; + llapi_error(LLAPI_MSG_ERROR, rc, "error: opening '%s'", + param_data.gl_pathv[0]); + goto free_param; + } if (!param->fp_obd_uuid && !param->fp_quiet && !param->fp_obds_printed) llapi_printf(LLAPI_MSG_NORMAL, "%s:\n", - param->fp_get_lmv ? "MDTS" : "OBDS:"); + param->fp_get_lmv ? "MDTS" : "OBDS"); snprintf(format, sizeof(format), "%%d: %%%zus", sizeof(obd_uuid.uuid) - 1); @@ -2092,8 +1851,9 @@ static int setup_obd_uuid(DIR *dir, char *dname, struct find_param *param) __func__, param->fp_obd_uuid->uuid); rc = -EINVAL; } - - return (rc); +free_param: + cfs_free_param_data(¶m_data); + return rc; } /* In this case, param->fp_obd_uuid will be an array of obduuids and @@ -2116,27 +1876,26 @@ static int setup_indexes(DIR *dir, char *path, struct obd_uuid *obduuids, if (ret != 0) return ret; - obdcount = atoi(buf); - uuids = (struct obd_uuid *)malloc(obdcount * - sizeof(struct obd_uuid)); - if (uuids == NULL) - return -ENOMEM; + obdcount = atoi(buf); + uuids = malloc(obdcount * sizeof(struct obd_uuid)); + if (uuids == NULL) + return -ENOMEM; retry_get_uuids: - ret = llapi_get_target_uuids(dirfd(dir), uuids, &obdcount, type); - if (ret) { - struct obd_uuid *uuids_temp; + ret = llapi_get_target_uuids(dirfd(dir), uuids, &obdcount, type); + if (ret) { + if (ret == -EOVERFLOW) { + struct obd_uuid *uuids_temp; - if (ret == -EOVERFLOW) { - uuids_temp = realloc(uuids, obdcount * - sizeof(struct obd_uuid)); + uuids_temp = realloc(uuids, obdcount * + sizeof(struct obd_uuid)); if (uuids_temp != NULL) { + free(uuids); uuids = uuids_temp; - goto retry_get_uuids; + goto retry_get_uuids; } - else - ret = -ENOMEM; - } + ret = -ENOMEM; + } llapi_error(LLAPI_MSG_ERROR, ret, "get ost uuid failed"); goto out_free; @@ -2231,109 +1990,43 @@ int llapi_ostlist(char *path, struct find_param *param) } /* - * Given a filesystem name, or a pathname of a file on a lustre filesystem, - * tries to determine the path to the filesystem's clilov directory under /proc - * - * fsname is limited to MTI_NAME_MAXLEN in lustre_idl.h - * The NUL terminator is compensated by the additional "%s" bytes. */ -#define LOV_LEN (sizeof("/proc/fs/lustre/lov/%s-clilov-*") + MTI_NAME_MAXLEN) -static int clilovpath(const char *fsname, const char *const pathname, - char *clilovpath) -{ - int rc; - char pattern[LOV_LEN]; - char buffer[PATH_MAX + 1]; - - if (fsname == NULL) { - rc = llapi_search_fsname(pathname, buffer); - if (rc != 0) - return rc; - fsname = buffer; - } - - snprintf(pattern, sizeof(pattern), "/proc/fs/lustre/lov/%s-clilov-*", - fsname); - - rc = first_match(pattern, buffer); - if (rc != 0) - return rc; - - strlcpy(clilovpath, buffer, sizeof(buffer)); - - return 0; -} - -/* - * Given the path to a stripe attribute proc file, tries to open and - * read the attribute and return the value using the attr parameter - */ -static int sattr_read_attr(const char *const fpath, - unsigned int *attr) -{ - - FILE *f; - char line[PATH_MAX + 1]; - int rc = 0; - - f = fopen(fpath, "r"); - if (f == NULL) { - rc = -errno; - llapi_error(LLAPI_MSG_ERROR, rc, "Cannot open '%s'", fpath); - return rc; - } - - if (fgets(line, sizeof(line), f) != NULL) { - *attr = atoi(line); - } else { - llapi_error(LLAPI_MSG_ERROR, errno, "Cannot read from '%s'", fpath); - rc = 1; - } - - fclose(f); - return rc; -} - -/* * Tries to determine the default stripe attributes for a given filesystem. The * filesystem to check should be specified by fsname, or will be determined * using pathname. */ static int sattr_get_defaults(const char *const fsname, - const char *const pathname, unsigned int *scount, unsigned int *ssize, unsigned int *soffset) { - int rc; - char dpath[PATH_MAX + 1]; - char fpath[PATH_MAX + 1]; - - rc = clilovpath(fsname, pathname, dpath); - if (rc != 0) - return rc; + char val[PATH_MAX]; + int rc; - if (scount) { - snprintf(fpath, PATH_MAX, "%s/stripecount", dpath); - rc = sattr_read_attr(fpath, scount); - if (rc != 0) - return rc; - } + if (scount) { + rc = get_lustre_param_value("lov", fsname, FILTER_BY_FS_NAME, + "stripecount", val, sizeof(val)); + if (rc != 0) + return rc; + *scount = atoi(val); + } - if (ssize) { - snprintf(fpath, PATH_MAX, "%s/stripesize", dpath); - rc = sattr_read_attr(fpath, ssize); - if (rc != 0) - return rc; - } + if (ssize) { + rc = get_lustre_param_value("lov", fsname, FILTER_BY_FS_NAME, + "stripesize", val, sizeof(val)); + if (rc != 0) + return rc; + *ssize = atoi(val); + } - if (soffset) { - snprintf(fpath, PATH_MAX, "%s/stripeoffset", dpath); - rc = sattr_read_attr(fpath, soffset); - if (rc != 0) - return rc; - } + if (soffset) { + rc = get_lustre_param_value("lov", fsname, FILTER_BY_FS_NAME, + "stripeoffset", val, sizeof(val)); + if (rc != 0) + return rc; + *soffset = atoi(val); + } - return 0; + return 0; } /* @@ -2375,8 +2068,7 @@ static int sattr_cache_get_defaults(const char *const fsname, * successfully retrieved and stored in tmp before writing to * cache. */ - rc = sattr_get_defaults(fsname_buf, NULL, &tmp[0], &tmp[1], - &tmp[2]); + rc = sattr_get_defaults(fsname_buf, &tmp[0], &tmp[1], &tmp[2]); if (rc != 0) return rc; @@ -3661,44 +3353,56 @@ int llapi_obd_statfs(char *path, __u32 type, __u32 index, int llapi_ping(char *obd_type, char *obd_name) { - char path[MAX_STRING_SIZE]; - char buf[1]; - int rc, fd; + glob_t path; + char buf[1]; + int rc, fd; - snprintf(path, MAX_STRING_SIZE, "/proc/fs/lustre/%s/%s/ping", - obd_type, obd_name); + rc = cfs_get_param_paths(&path, "%s/%s/ping", + obd_type, obd_name); + if (rc != 0) + return -errno; - fd = open(path, O_WRONLY); - if (fd < 0) { - rc = -errno; - llapi_error(LLAPI_MSG_ERROR, rc, "error opening %s", path); - return rc; - } + fd = open(path.gl_pathv[0], O_WRONLY); + if (fd < 0) { + rc = -errno; + llapi_error(LLAPI_MSG_ERROR, rc, "error opening %s", + path.gl_pathv[0]); + goto failed; + } /* The purpose is to send a byte as a ping, whatever this byte is. */ /* coverity[uninit_use_in_call] */ - rc = write(fd, buf, 1); - if (rc < 0) - rc = -errno; - close(fd); + rc = write(fd, buf, 1); + if (rc < 0) + rc = -errno; + close(fd); - if (rc == 1) - return 0; - return rc; + if (rc == 1) + rc = 0; +failed: + cfs_free_param_data(&path); + return rc; } int llapi_target_iterate(int type_num, char **obd_type, void *args, llapi_cb_t cb) { - char buf[MAX_STRING_SIZE]; - FILE *fp = fopen(DEVICES_LIST, "r"); - int i, rc = 0; + char buf[MAX_STRING_SIZE]; + int i, rc = 0; + glob_t param; + FILE *fp; - if (fp == NULL) { - rc = -errno; - llapi_error(LLAPI_MSG_ERROR, rc, "error: opening "DEVICES_LIST); - return rc; - } + rc = cfs_get_param_paths(¶m, "devices"); + if (rc != 0) + return -ENOENT; + + fp = fopen(param.gl_pathv[0], "r"); + if (fp == NULL) { + rc = -errno; + llapi_error(LLAPI_MSG_ERROR, rc, "error: opening '%s'", + param.gl_pathv[0]); + goto free_path; + } while (fgets(buf, sizeof(buf), fp) != NULL) { char *obd_type_name = NULL; @@ -3724,9 +3428,11 @@ int llapi_target_iterate(int type_num, char **obd_type, cb(obd_type_name, obd_name, obd_uuid, args); } - } - fclose(fp); - return 0; + } + fclose(fp); +free_path: + cfs_free_param_data(¶m); + return 0; } static void do_target_check(char *obd_type_name, char *obd_name, diff --git a/lustre/utils/liblustreapi_hsm.c b/lustre/utils/liblustreapi_hsm.c index 60475f8..8033b03 100644 --- a/lustre/utils/liblustreapi_hsm.c +++ b/lustre/utils/liblustreapi_hsm.c @@ -48,7 +48,6 @@ #include #include #include -#include #include #ifdef HAVE_LINUX_UNISTD_H #include diff --git a/lustre/utils/liblustreapi_nodemap.c b/lustre/utils/liblustreapi_nodemap.c index a79fc85..5e25fff 100644 --- a/lustre/utils/liblustreapi_nodemap.c +++ b/lustre/utils/liblustreapi_nodemap.c @@ -24,17 +24,18 @@ * Author: Joshua Walgenbach */ +#include #include #include #include -#include -#include "lustreapi_internal.h" +#include int llapi_nodemap_exists(const char *nodemap) { - char mapname[PATH_MAX + 1]; + glob_t param; + int rc; - snprintf(mapname, sizeof(mapname), "nodemap/%s", nodemap); - - return get_param(mapname, NULL, 0); + rc = cfs_get_param_paths(¶m, "nodemap/%s", nodemap); + cfs_free_param_data(¶m); + return rc != 0 ? 1 : 0; } diff --git a/lustre/utils/liblustreapi_param.c b/lustre/utils/liblustreapi_param.c new file mode 100644 index 0000000..65cad29 --- /dev/null +++ b/lustre/utils/liblustreapi_param.c @@ -0,0 +1,175 @@ +/* + * LGPL HEADER START + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the GNU Lesser General Public License + * (LGPL) version 2.1 or (at your discretion) any later version. + * (LGPL) version 2.1 accompanies this distribution, and is available at + * http://www.gnu.org/licenses/lgpl-2.1.html + * + * This library 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 + * Lesser General Public License for more details. + * + * LGPL HEADER END + */ +/* + * lustre/utils/liblustreapi_param.c + * + * This code handles user interaction with the configuration interface + * to the Lustre file system to fine tune it. + */ +#include +#include + +#include +#include +#include +#include "lustreapi_internal.h" + +/** + * return the parameter's path for a specific device type or mountpoint + * + * \param param the results returned to the caller + * \param obd_type Lustre OBD device type + * + * \param filter filter combined with the type agrument allow the + * \param type caller to limit the scope of the search for the + * parameter's path. Typical options are search by + * Lustre filesystem name or by the path to a file + * or directory in the filesystem. + * + * \param param_name parameter name to fetch + * + * Using filter and the type argument we can limit the scope of the + * search to either the parameter belonging to a specific lustre filesystem + * (if it exists) or using a given file or directory path located on a + * mounted Lustre filesystem. The last case it can do is a special search + * based on exactly what the user passed instead of scanning file paths + * or specific file systems. + * + * If "obd_type" matches a Lustre device then the first matching device + * (as with "lctl dl", constrained by \param filter and \param type) + * will be used to provide the return value, otherwise the first such + * device found will be used. + * + * Return 0 for success, with the results stored in \param param. + * Return -ve value for error. + */ +int +get_lustre_param_path(const char *obd_type, const char *filter, + enum param_filter type, const char *param_name, + glob_t *param) +{ + char pattern[PATH_MAX]; + int rc = 0; + + if (filter == NULL || obd_type == NULL) + return -EINVAL; + + switch (type) { + case FILTER_BY_PATH: + rc = llapi_search_fsname(filter, pattern); + if (rc) { + llapi_error(LLAPI_MSG_ERROR, rc, + "'%s' is not on a Lustre filesystem", + filter); + return rc; + } + if (strlen(pattern) + 3 > sizeof(pattern)) + return -E2BIG; + strncat(pattern, "-*", sizeof(pattern)); + break; + case FILTER_BY_FS_NAME: + rc = snprintf(pattern, sizeof(pattern) - 1, "%s-*", filter); + if (rc < 0) + return rc; + else if (rc >= sizeof(pattern)) + return -EINVAL; + rc = 0; + break; + default: + if (strlen(filter) + 1 > sizeof(pattern)) + return -E2BIG; + strncpy(pattern, filter, sizeof(pattern)); + break; + } + + if (param_name != NULL) { + if (cfs_get_param_paths(param, "%s/%s/%s", + obd_type, pattern, param_name) != 0) + rc = -errno; + } else { + if (cfs_get_param_paths(param, "%s/%s", + obd_type, pattern) != 0) + rc = -errno; + } + + return rc; +} + +/** + * return a parameter of a single line value for a specific device type + * or mountpoint + * + * \param obd_type Lustre OBD device type + * + * \param filter filter combined with the type agruments allow the + * \param type caller to limit the scope of the search for the + * parameter's path. Typical options are search by + * Lustre filesystem name or by the path to a file + * or directory in the filesystem. + * + * \param param_name parameter name to fetch + * \param value return buffer for parameter value string + * \param val_len size of buffer for return value + * + * Using filter and the type argument we can limit the scope of the + * search to either the parameter belonging to a specific lustre filesystem + * (if it exists) or using a given file or directory path located on a + * mounted Lustre filesystem. The last case it can do is a special search + * based on exactly what the user passed instead of scanning file paths + * or specific file systems. + * + * If "obd_type" matches a Lustre device then the first matching device + * (as with "lctl dl", constrained by \param filter and \param type) + * will be used to provide the return value, otherwise the first such + * device found will be used. + * + * Return 0 for success, with a NUL-terminated string in \param value. + * Return negative errno value for error. + */ +int +get_lustre_param_value(const char *obd_type, const char *filter, + enum param_filter type, const char *param_name, + char *value, size_t val_len) +{ + glob_t param; + FILE *fp; + int rc; + + rc = get_lustre_param_path(obd_type, filter, type, param_name, ¶m); + if (rc != 0) + return -ENOENT; + + fp = fopen(param.gl_pathv[0], "r"); + if (fp == NULL) { + rc = -errno; + llapi_error(LLAPI_MSG_ERROR, rc, "error: opening '%s'", + param.gl_pathv[0]); + goto err; + } + + if (fgets(value, val_len, fp) == NULL) { + if (!feof(fp)) + rc = -ferror(fp); + } + fclose(fp); +err: + cfs_free_param_data(¶m); + + return rc; +} diff --git a/lustre/utils/lustreapi_internal.h b/lustre/utils/lustreapi_internal.h index a5d7ac1..00a66e3 100644 --- a/lustre/utils/lustreapi_internal.h +++ b/lustre/utils/lustreapi_internal.h @@ -35,6 +35,7 @@ #ifndef _LUSTREAPI_INTERNAL_H_ #define _LUSTREAPI_INTERNAL_H_ +#include #include #define WANT_PATH 0x1 @@ -45,8 +46,44 @@ int get_root_path(int want, char *fsname, int *outfd, char *path, int index); int root_ioctl(const char *mdtname, int opc, void *data, int *mdtidxp, int want_error); -int get_param(const char *param_path, char *result, - unsigned int result_size); + +/** + * Often when determining the parameter path in sysfs/procfs we + * are often only interest set of data. This enum gives use the + * ability to return data of parameters for: + * + * FILTER_BY_FS_NAME: a specific file system mount + * FILTER_BY_PATH: Using a Lustre file path to determine which + * file system is of interest + * FILTER_BY_EXACT: The default behavior. Search the parameter + * path as is. + */ +enum param_filter { + FILTER_BY_EXACT, + FILTER_BY_FS_NAME, + FILTER_BY_PATH +}; + +int get_lustre_param_path(const char *obd_type, const char *filter, + enum param_filter type, const char *param_name, + glob_t *param); +int get_lustre_param_value(const char *obd_type, const char *filter, + enum param_filter type, const char *param_name, + char *value, size_t val_len); + +static inline int +poolpath(glob_t *pool_path, const char *fsname, char *pathname) +{ + int rc; + + if (fsname != NULL) + rc = get_lustre_param_path("lov", fsname, FILTER_BY_FS_NAME, + "pools", pool_path); + else + rc = get_lustre_param_path("lov", pathname, FILTER_BY_PATH, + "pools", pool_path); + return rc; +} #define LLAPI_LAYOUT_MAGIC 0x11AD1107 /* LLAPILOT */ -- 1.8.3.1