X-Git-Url: https://git.whamcloud.com/?p=fs%2Flustre-release.git;a=blobdiff_plain;f=lustre%2Futils%2Fliblustreapi.c;h=f7f8e69d52ab9b3090145c7bf883d072d4d73772;hp=461af1eb0e6aef4ee20f0bd5b40a19d906a1b222;hb=35b3a429d1915ec147f01a42c4ec0526b887d1c7;hpb=d5a07cd08ad07fe0de0c5bda2b3b65c36461f601 diff --git a/lustre/utils/liblustreapi.c b/lustre/utils/liblustreapi.c index 461af1e..f7f8e69 100644 --- a/lustre/utils/liblustreapi.c +++ b/lustre/utils/liblustreapi.c @@ -69,54 +69,12 @@ #endif #include -#include +#include #include -#include -#include #include +#include #include "lustreapi_internal.h" -static unsigned llapi_dir_filetype_table[] = { - [DT_UNKNOWN]= 0, - [DT_FIFO]= S_IFIFO, - [DT_CHR] = S_IFCHR, - [DT_DIR] = S_IFDIR, - [DT_BLK] = S_IFBLK, - [DT_REG] = S_IFREG, - [DT_LNK] = S_IFLNK, - [DT_SOCK]= S_IFSOCK, -#if defined(DT_DOOR) && defined(S_IFDOOR) - [DT_DOOR]= S_IFDOOR, -#endif -}; - -#if defined(DT_DOOR) && defined(S_IFDOOR) -static const int DT_MAX = DT_DOOR; -#else -static const int DT_MAX = DT_SOCK; -#endif - -static unsigned llapi_filetype_dir_table[] = { - [0]= DT_UNKNOWN, - [S_IFIFO]= DT_FIFO, - [S_IFCHR] = DT_CHR, - [S_IFDIR] = DT_DIR, - [S_IFBLK] = DT_BLK, - [S_IFREG] = DT_REG, - [S_IFLNK] = DT_LNK, - [S_IFSOCK]= DT_SOCK, -#if defined(DT_DOOR) && defined(S_IFDOOR) - [S_IFDOOR]= DT_DOOR, -#endif -}; - -#if defined(DT_DOOR) && defined(S_IFDOOR) -static const int S_IFMAX = DT_DOOR; -#else -static const int S_IFMAX = DT_SOCK; -#endif - -/* liblustreapi message level */ static int llapi_msg_level = LLAPI_MSG_MAX; void llapi_msg_set_level(int level) @@ -297,7 +255,7 @@ int llapi_stripe_limit_check(unsigned long long stripe_size, int stripe_offset, stripe_size, page_size); return rc; } - if (stripe_offset < -1 || stripe_offset > MAX_OBD_DEVICES) { + if (stripe_offset < -1) { rc = -EINVAL; llapi_error(LLAPI_MSG_ERROR, rc, "error: bad stripe offset %d", stripe_offset); @@ -380,6 +338,24 @@ static int find_poolpath(char *fsname, char *poolname, char *poolpath) return 0; } +/* + * Trim a trailing newline from a string, if it exists. + */ +int llapi_chomp_string(char *buf) +{ + if (!buf || !*buf) + return 0; + + while (buf[1]) + buf++; + + if (*buf != '\n') + return 0; + + *buf = '\0'; + return '\n'; +} + /** * return a parameter string for a specific device type or mountpoint * @@ -397,7 +373,7 @@ static int find_poolpath(char *fsname, char *poolname, char *poolpath) * Return 0 for success, with a NUL-terminated string in \param result. * Return -ve value for error. */ -static int get_param(const char *param_path, char *result, +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]; @@ -407,7 +383,7 @@ static int get_param(const char *param_path, char *result, snprintf(pattern, PATH_MAX, "/proc/{fs,sys}/{lnet,lustre}/%s", param_path); rc = first_match(pattern, file); - if (rc) + if (rc != 0 || result == NULL) return rc; fp = fopen(file, "r"); @@ -450,63 +426,70 @@ 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 + 1], dev[PATH_MAX + 1] = "*", fs[PATH_MAX + 1]; - FILE *fp = fopen(DEVICES_LIST, "r"); - int rc = 0; - - if (!fsname && file_path) { - rc = llapi_search_fsname(file_path, fs); - if (rc) { - llapi_error(LLAPI_MSG_ERROR, rc, - "'%s' is not on a Lustre filesystem", - file_path); - if (fp != NULL) - fclose(fp); - return rc; - } - } else if (fsname) { - if (strlen(fsname) > sizeof(fs)-1) { - if (fp != NULL) - fclose(fp); - return -E2BIG; - } - strncpy(fs, fsname, sizeof(fs)); - } - - if (fp == NULL) { - rc = -errno; - llapi_error(LLAPI_MSG_ERROR, rc, "error: opening "DEVICES_LIST); - return rc; - } + char devices[PATH_MAX]; + char dev[PATH_MAX] = "*"; + char fs[PATH_MAX]; + FILE *fp = NULL; + int rc = 0; - while (fgets(devices, sizeof(devices), fp) != NULL) { - char *bufp = devices, *tmp; + fp = fopen(DEVICES_LIST, "r"); + if (fp == NULL) { + rc = -errno; + llapi_error(LLAPI_MSG_ERROR, rc, "error: opening "DEVICES_LIST); + GOTO(out, rc); + } - while (bufp[0] == ' ') - ++bufp; + 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, rc); + } + } else if (fsname != NULL) { + rc = strlcpy(fs, fsname, sizeof(fs)); + if (rc >= sizeof(fs)) + GOTO(out, rc = -E2BIG); + } - tmp = strstr(bufp, obd_type); - if (tmp) { - tmp += strlen(obd_type) + 1; - if (strcmp(tmp, fs)) - continue; - if (strlen(tmp) > sizeof(dev)-1) { - fclose(fp); - return -E2BIG; - } - strncpy(dev, tmp, sizeof(dev)); - tmp = strchr(dev, ' '); + 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)) + GOTO(out, rc = -E2BIG); + tmp = strchr(dev, ' '); if (tmp != NULL) *tmp = '\0'; - break; - } - } + break; + } + } - if (dev[0] == '*' && strlen(fs)) - snprintf(dev, PATH_MAX, "%s-*", fs); - snprintf(devices, PATH_MAX, "%s/%s/%s", obd_type, dev, param_name); - fclose(fp); - return get_param(devices, value, val_len); + if (dev[0] == '*' && strlen(fs)) { + rc = snprintf(dev, sizeof(dev), "%s-*", fs); + if (rc >= sizeof(dev)) + GOTO(out, rc = -E2BIG); + } + rc = snprintf(devices, sizeof(devices), "%s/%s/%s", obd_type, dev, + param_name); + if (rc >= sizeof(devices)) + GOTO(out, rc = -E2BIG); + fclose(fp); + return get_param(devices, value, val_len); +out: + if (fp != NULL) + fclose(fp); + return rc; } /* @@ -600,6 +583,11 @@ out: return md_size; } +int llapi_get_agent_uuid(char *path, char *buf, size_t bufsize) +{ + return get_param_lmv(path, "uuid", buf, bufsize); +} + /* * if pool is NULL, search ostname in target_obd * if pool is not NULL: @@ -657,12 +645,11 @@ int llapi_search_ost(char *fsname, char *poolname, char *ostname) } int llapi_file_open_pool(const char *name, int flags, int mode, - unsigned long long stripe_size, int stripe_offset, - int stripe_count, int stripe_pattern, char *pool_name) + unsigned long long stripe_size, int stripe_offset, + int stripe_count, int stripe_pattern, char *pool_name) { - struct lov_user_md_v3 lum = { 0 }; - int fd, rc = 0; - int isdir = 0; + struct lov_user_md_v3 lum = { 0 }; + int fd, rc = 0; /* Make sure we have a good pool */ if (pool_name != NULL) { @@ -701,11 +688,14 @@ int llapi_file_open_pool(const char *name, int flags, int mode, } } - fd = open(name, flags | O_LOV_DELAY_CREATE, mode); - if (fd < 0 && errno == EISDIR) { - fd = open(name, O_DIRECTORY | O_RDONLY); - isdir++; - } +retry_open: + fd = open(name, flags | O_LOV_DELAY_CREATE, mode); + if (fd < 0) { + if (errno == EISDIR && !(flags & O_DIRECTORY)) { + flags = O_DIRECTORY | O_RDONLY; + goto retry_open; + } + } if (fd < 0) { rc = -errno; @@ -725,7 +715,8 @@ int llapi_file_open_pool(const char *name, int flags, int mode, lum.lmm_stripe_count = stripe_count; lum.lmm_stripe_offset = stripe_offset; if (pool_name != NULL) { - strncpy(lum.lmm_pool_name, pool_name, LOV_MAXPOOLNAME); + strlcpy(lum.lmm_pool_name, pool_name, + sizeof(lum.lmm_pool_name)); } else { /* If no pool is specified at all, use V1 request */ lum.lmm_magic = LOV_USER_MAGIC_V1; @@ -790,12 +781,54 @@ int llapi_file_create_pool(const char *name, unsigned long long stripe_size, return 0; } -/** - * In DNE phase I, only stripe_offset will be used in this function. - * stripe_count, stripe_pattern and pool_name will be supported later. - */ -int llapi_dir_create_pool(const char *name, int flags, int stripe_offset, - int stripe_count, int stripe_pattern, char *pool_name) +int llapi_dir_set_default_lmv_stripe(const char *name, int stripe_offset, + int stripe_count, int stripe_pattern, + const char *pool_name) +{ + struct lmv_user_md lum = { 0 }; + int fd; + int rc = 0; + + lum.lum_magic = LMV_USER_MAGIC; + lum.lum_stripe_offset = stripe_offset; + lum.lum_stripe_count = stripe_count; + lum.lum_hash_type = stripe_pattern; + if (pool_name != NULL) { + if (strlen(pool_name) >= sizeof(lum.lum_pool_name)) { + llapi_err_noerrno(LLAPI_MSG_ERROR, + "error LL_IOC_LMV_SET_DEFAULT_STRIPE '%s'" + ": too large pool name: %s", name, pool_name); + return -E2BIG; + } + strncpy(lum.lum_pool_name, pool_name, + sizeof(lum.lum_pool_name)); + } + + fd = open(name, O_DIRECTORY | O_RDONLY); + if (fd < 0) { + rc = -errno; + llapi_error(LLAPI_MSG_ERROR, rc, "unable to open '%s'", name); + return rc; + } + + rc = ioctl(fd, LL_IOC_LMV_SET_DEFAULT_STRIPE, &lum); + if (rc < 0) { + char *errmsg = "stripe already set"; + rc = -errno; + if (errno != EEXIST && errno != EALREADY) + errmsg = strerror(errno); + + llapi_err_noerrno(LLAPI_MSG_ERROR, + "error on LL_IOC_LMV_SETSTRIPE '%s' (%d): %s", + name, fd, errmsg); + } + close(fd); + return rc; +} + +int llapi_dir_create_pool(const char *name, int mode, int stripe_offset, + int stripe_count, int stripe_pattern, + const char *pool_name) { struct lmv_user_md lmu = { 0 }; struct obd_ioctl_data data = { 0 }; @@ -829,13 +862,13 @@ int llapi_dir_create_pool(const char *name, int flags, int stripe_offset, } filename = basename(namepath); - lmu.lum_type = LMV_STRIPE_TYPE; dir = dirname(dirpath); data.ioc_inlbuf1 = (char *)filename; data.ioc_inllen1 = strlen(filename) + 1; data.ioc_inlbuf2 = (char *)&lmu; data.ioc_inllen2 = sizeof(struct lmv_user_md); + data.ioc_type = mode; rc = obd_ioctl_pack(&data, &buf, sizeof(rawbuf)); if (rc) { llapi_error(LLAPI_MSG_ERROR, rc, @@ -1031,19 +1064,23 @@ int llapi_search_fsname(const char *pathname, char *fsname) path = realpath(pathname, NULL); if (path == NULL) { - char buf[PATH_MAX + 1], *ptr; - - buf[0] = 0; - if (pathname[0] != '/') { - /* Need an absolute path, but realpath() only works for - * pathnames that actually exist. We go through the - * extra hurdle of dirname(getcwd() + pathname) in - * case the relative pathname contains ".." in it. */ - if (getcwd(buf, sizeof(buf) - 1) == NULL) - return -errno; - strcat(buf, "/"); - } - strncat(buf, pathname, sizeof(buf) - strlen(buf)); + char buf[PATH_MAX], *ptr; + + buf[0] = '\0'; + if (pathname[0] != '/') { + /* Need an absolute path, but realpath() only works for + * pathnames that actually exist. We go through the + * extra hurdle of dirname(getcwd() + pathname) in + * case the relative pathname contains ".." in it. */ + if (getcwd(buf, sizeof(buf) - 2) == NULL) + return -errno; + rc = strlcat(buf, "/", sizeof(buf)); + if (rc >= sizeof(buf)) + return -E2BIG; + } + rc = strlcat(buf, pathname, sizeof(buf)); + if (rc >= sizeof(buf)) + return -E2BIG; path = realpath(buf, NULL); if (path == NULL) { ptr = strrchr(buf, '/'); @@ -1139,20 +1176,20 @@ static int poolpath(char *fsname, char *pathname, char *pool_pathname) int llapi_get_poolmembers(const char *poolname, char **members, int list_size, char *buffer, int buffer_size) { - char fsname[PATH_MAX + 1]; - char *pool, *tmp; - char pathname[PATH_MAX + 1]; - char path[PATH_MAX + 1]; - char buf[1024]; + 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; /* name is FSNAME.POOLNAME */ - if (strlen(poolname) > PATH_MAX) - return -EOVERFLOW; - strcpy(fsname, poolname); + if (strlen(poolname) >= sizeof(fsname)) + return -EOVERFLOW; + strlcpy(fsname, poolname, sizeof(fsname)); pool = strchr(fsname, '.'); if (pool == NULL) return -EINVAL; @@ -1169,7 +1206,9 @@ int llapi_get_poolmembers(const char *poolname, char **members, } llapi_printf(LLAPI_MSG_NORMAL, "Pool: %s.%s\n", fsname, pool); - sprintf(path, "%s/%s", pathname, pool); + rc = snprintf(path, sizeof(path), "%s/%s", pathname, pool); + if (rc >= sizeof(path)) + return -EOVERFLOW; fd = fopen(path, "r"); if (fd == NULL) { rc = -errno; @@ -1183,6 +1222,7 @@ int llapi_get_poolmembers(const char *poolname, char **members, rc = -EOVERFLOW; break; } + buf[sizeof(buf) - 1] = '\0'; /* remove '\n' */ tmp = strchr(buf, '\n'); if (tmp != NULL) @@ -1327,8 +1367,14 @@ int llapi_poollist(const char *name) int obdcount, bufsize, rc, nb, i; char *poolname = NULL, *tmp = NULL, data[16]; - if (name[0] != '/') { - fsname = strdup(name); + if (name == NULL) + return -EINVAL; + + if (name[0] != '/') { + fsname = strdup(name); + if (fsname == NULL) + return -ENOMEM; + poolname = strchr(fsname, '.'); if (poolname) *poolname = '\0'; @@ -1381,7 +1427,7 @@ err: return rc; } -typedef int (semantic_func_t)(char *path, DIR *parent, DIR *d, +typedef int (semantic_func_t)(char *path, DIR *parent, DIR **d, void *data, struct dirent64 *de); #define OBD_NOT_FOUND (-1) @@ -1414,7 +1460,8 @@ static int common_param_init(struct find_param *param, char *path) param->got_uuids = 0; param->obdindexes = NULL; param->obdindex = OBD_NOT_FOUND; - param->mdtindex = OBD_NOT_FOUND; + if (!param->migrate) + param->mdtindex = OBD_NOT_FOUND; return 0; } @@ -1430,12 +1477,13 @@ static void find_param_fini(struct find_param *param) free(param->fp_lmv_md); } -static int cb_common_fini(char *path, DIR *parent, DIR *d, void *data, +static int cb_common_fini(char *path, DIR *parent, DIR **dirp, void *data, struct dirent64 *de) { - struct find_param *param = (struct find_param *)data; - param->depth--; - return 0; + struct find_param *param = data; + param->fp_depth--; + + return 0; } /* set errno upon failure */ @@ -1462,8 +1510,12 @@ static int cb_get_dirstripe(char *path, DIR *d, struct find_param *param) int ret = 0; lmv->lum_stripe_count = param->fp_lmv_count; - lmv->lum_magic = LMV_MAGIC_V1; + if (param->get_default_lmv) + lmv->lum_magic = LMV_USER_MAGIC; + else + lmv->lum_magic = LMV_MAGIC_V1; ret = ioctl(dirfd(d), LL_IOC_LMV_GETSTRIPE, lmv); + return ret; } @@ -1483,7 +1535,7 @@ static int get_lmd_info(char *path, DIR *parent, DIR *dir, fname = (fname == NULL ? path : fname + 1); /* retrieve needed file info */ - strncpy((char *)lmd, fname, lumlen); + strlcpy((char *)lmd, fname, lumlen); ret = ioctl(dirfd(parent), IOC_MDC_GETFILEINFO, (void *)lmd); } @@ -1529,8 +1581,8 @@ static int llapi_semantic_traverse(char *path, int size, DIR *parent, int len, ret; DIR *d, *p = NULL; - ret = 0; - len = strlen(path); + ret = 0; + len = strlen(path); d = opendir(path); if (!d && errno != ENOTDIR) { @@ -1547,15 +1599,15 @@ static int llapi_semantic_traverse(char *path, int size, DIR *parent, } } - if (sem_init && (ret = sem_init(path, parent ?: p, d, data, de))) - goto err; + if (sem_init && (ret = sem_init(path, parent ?: p, &d, data, de))) + goto err; - if (!d || (param->get_lmv && !param->recursive)) { - ret = 0; + if (d == NULL) goto out; - } while ((dent = readdir64(d)) != NULL) { + int rc; + param->have_fileinfo = 0; if (!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, "..")) @@ -1578,15 +1630,15 @@ static int llapi_semantic_traverse(char *path, int size, DIR *parent, if (dent->d_type == DT_UNKNOWN) { lstat_t *st = ¶m->lmd->lmd_st; - ret = get_lmd_info(path, d, NULL, param->lmd, + rc = get_lmd_info(path, d, NULL, param->lmd, param->lumlen); - if (ret == 0) { - dent->d_type = - llapi_filetype_dir_table[st->st_mode & - S_IFMT]; - } - if (ret == -ENOENT) - continue; + if (rc == 0) + dent->d_type = IFTODT(st->st_mode); + else if (ret == 0) + ret = rc; + + if (rc == -ENOENT) + continue; } switch (dent->d_type) { case DT_UNKNOWN: @@ -1594,35 +1646,35 @@ static int llapi_semantic_traverse(char *path, int size, DIR *parent, "error: %s: '%s' is UNKNOWN type %d", __func__, dent->d_name, dent->d_type); break; - case DT_DIR: - ret = llapi_semantic_traverse(path, size, d, sem_init, - sem_fini, data, dent); - if (ret < 0) - goto out; - break; - default: - ret = 0; - if (sem_init) { - ret = sem_init(path, d, NULL, data, dent); - if (ret < 0) - goto out; - } - if (sem_fini && ret == 0) - sem_fini(path, d, NULL, data, dent); + case DT_DIR: + rc = llapi_semantic_traverse(path, size, d, sem_init, + sem_fini, data, dent); + if (rc != 0 && ret == 0) + ret = rc; + break; + default: + rc = 0; + if (sem_init) { + rc = sem_init(path, d, NULL, data, dent); + if (rc < 0 && ret == 0) + ret = rc; + } + if (sem_fini && rc == 0) + sem_fini(path, d, NULL, data, dent); } } out: path[len] = 0; - if (sem_fini) - sem_fini(path, parent, d, data, de); + if (sem_fini) + sem_fini(path, parent, &d, data, de); err: if (d) closedir(d); if (p) closedir(p); - return ret; + return ret; } static int param_callback(char *path, semantic_func_t sem_init, @@ -1642,11 +1694,12 @@ static int param_callback(char *path, semantic_func_t sem_init, if (!buf) return -ENOMEM; - strncpy(buf, path, PATH_MAX + 1); + strlcpy(buf, path, PATH_MAX + 1); ret = common_param_init(param, buf); if (ret) goto out; - param->depth = 0; + + param->fp_depth = 0; ret = llapi_semantic_traverse(buf, PATH_MAX + 1, NULL, sem_init, sem_fini, param, NULL); @@ -1723,10 +1776,11 @@ enum tgt_type { static int llapi_get_target_uuids(int fd, struct obd_uuid *uuidp, int *ost_count, enum tgt_type type) { - struct obd_uuid name; - char buf[1024]; - FILE *fp; - int rc = 0, index = 0; + struct obd_uuid name; + char buf[1024]; + char format[32]; + FILE *fp; + int rc = 0, index = 0; /* Get the lov name */ if (type == LOV_TYPE) { @@ -1749,9 +1803,11 @@ static int llapi_get_target_uuids(int fd, struct obd_uuid *uuidp, return rc; } - while (fgets(buf, sizeof(buf), fp) != NULL) { - if (uuidp && (index < *ost_count)) { - if (sscanf(buf, "%d: %s", &index, uuidp[index].uuid) <2) + snprintf(format, sizeof(format), + "%%d: %%%zus", sizeof(uuidp[0].uuid) - 1); + while (fgets(buf, sizeof(buf), fp) != NULL) { + if (uuidp && (index < *ost_count)) { + if (sscanf(buf, format, &index, uuidp[index].uuid) < 2) break; } index++; @@ -1819,11 +1875,11 @@ int llapi_uuid_match(char *real_uuid, char *search_uuid) * returned in param->obdindex */ static int setup_obd_uuid(DIR *dir, char *dname, struct find_param *param) { - struct obd_uuid obd_uuid; - char uuid[sizeof(struct obd_uuid)]; - char buf[1024]; - FILE *fp; - int rc = 0, index; + struct obd_uuid obd_uuid; + char buf[1024]; + char format[32]; + FILE *fp; + int rc = 0; if (param->got_uuids) return rc; @@ -1859,12 +1915,17 @@ static int setup_obd_uuid(DIR *dir, char *dname, struct find_param *param) llapi_printf(LLAPI_MSG_NORMAL, "%s:\n", param->get_lmv ? "MDTS" : "OBDS:"); - while (fgets(buf, sizeof(buf), fp) != NULL) { - if (sscanf(buf, "%d: %s", &index, uuid) < 2) - break; + snprintf(format, sizeof(format), + "%%d: %%%zus", sizeof(obd_uuid.uuid) - 1); + while (fgets(buf, sizeof(buf), fp) != NULL) { + int index; - if (param->obduuid) { - if (llapi_uuid_match(uuid, param->obduuid->uuid)) { + if (sscanf(buf, format, &index, obd_uuid.uuid) < 2) + break; + + if (param->obduuid) { + if (llapi_uuid_match(obd_uuid.uuid, + param->obduuid->uuid)) { param->obdindex = index; break; } @@ -2042,7 +2103,7 @@ static int clilovpath(const char *fsname, const char *const pathname, if (rc != 0) return rc; - strncpy(clilovpath, buffer, sizeof(buffer)); + strlcpy(clilovpath, buffer, sizeof(buffer)); return 0; } @@ -2150,10 +2211,10 @@ static int sattr_cache_get_defaults(const char *const fsname, if (rc) return rc; } else { - strncpy(fsname_buf, fsname, PATH_MAX); + strlcpy(fsname_buf, fsname, sizeof(fsname_buf)); } - if (strncmp(fsname_buf, cache.fsname, PATH_MAX) != 0) { + if (strncmp(fsname_buf, cache.fsname, sizeof(fsname_buf) - 1) != 0) { /* * Ensure all 3 sattrs (count, size, and offset) are * successfully retrieved and stored in tmp before writing to @@ -2167,7 +2228,7 @@ static int sattr_cache_get_defaults(const char *const fsname, cache.stripecount = tmp[0]; cache.stripesize = tmp[1]; cache.stripeoffset = tmp[2]; - strncpy(cache.fsname, fsname_buf, PATH_MAX); + strlcpy(cache.fsname, fsname_buf, sizeof(cache.fsname)); } if (scount) @@ -2359,20 +2420,30 @@ void lmv_dump_user_lmm(struct lmv_user_md *lum, char *pool_name, struct lmv_user_mds_data *objects = lum->lum_objects; char *prefix = lum->lum_magic == LMV_USER_MAGIC ? "(Default)" : ""; int i, obdstripe = 0; + char *separator = ""; if (obdindex != OBD_NOT_FOUND) { - for (i = 0; i < lum->lum_stripe_count; i++) { - if (obdindex == objects[i].lum_mds) { - llapi_printf(LLAPI_MSG_NORMAL, "%s%s\n", prefix, - path); + if (lum->lum_stripe_count == 0) { + if (obdindex == lum->lum_stripe_offset) obdstripe = 1; - break; + } else { + for (i = 0; i < lum->lum_stripe_count; i++) { + if (obdindex == objects[i].lum_mds) { + llapi_printf(LLAPI_MSG_NORMAL, + "%s%s\n", prefix, + path); + obdstripe = 1; + break; + } } } } else { obdstripe = 1; } + if (!obdstripe) + return; + /* show all information default */ if (!verbose) { if (lum->lum_magic == LMV_USER_MAGIC) @@ -2381,36 +2452,41 @@ void lmv_dump_user_lmm(struct lmv_user_md *lum, char *pool_name, verbose = VERBOSE_OBJID; } - if (lum->lum_magic == LMV_USER_MAGIC) - verbose &= ~VERBOSE_OBJID; - if (depth && path && ((verbose != VERBOSE_OBJID))) - llapi_printf(LLAPI_MSG_NORMAL, "%s\n", path); + llapi_printf(LLAPI_MSG_NORMAL, "%s%s\n", prefix, path); if (verbose & VERBOSE_COUNT) { + llapi_printf(LLAPI_MSG_NORMAL, "%s", separator); if (verbose & ~VERBOSE_COUNT) llapi_printf(LLAPI_MSG_NORMAL, "lmv_stripe_count: "); - llapi_printf(LLAPI_MSG_NORMAL, "%u\n", + llapi_printf(LLAPI_MSG_NORMAL, "%u", (int)lum->lum_stripe_count); + if (verbose & VERBOSE_OFFSET) + separator = " "; + else + separator = "\n"; } if (verbose & VERBOSE_OFFSET) { + llapi_printf(LLAPI_MSG_NORMAL, "%s", separator); if (verbose & ~VERBOSE_OFFSET) llapi_printf(LLAPI_MSG_NORMAL, "lmv_stripe_offset: "); - llapi_printf(LLAPI_MSG_NORMAL, "%d\n", + llapi_printf(LLAPI_MSG_NORMAL, "%d", (int)lum->lum_stripe_offset); + separator = "\n"; } - if (verbose & VERBOSE_OBJID) { - if ((obdstripe == 1)) + if (verbose & VERBOSE_OBJID && lum->lum_magic != LMV_USER_MAGIC) { + llapi_printf(LLAPI_MSG_NORMAL, "%s", separator); + if (obdstripe == 1 && lum->lum_stripe_count > 0) llapi_printf(LLAPI_MSG_NORMAL, - "\tmdtidx\t\t FID[seq:oid:ver]\n"); + "mdtidx\t\t FID[seq:oid:ver]\n"); for (i = 0; i < lum->lum_stripe_count; i++) { int idx = objects[i].lum_mds; struct lu_fid *fid = &objects[i].lum_fid; if ((obdindex == OBD_NOT_FOUND) || (obdindex == idx)) llapi_printf(LLAPI_MSG_NORMAL, - "\t%6u\t\t "DFID"\t\t%s\n", + "%6u\t\t "DFID"\t\t%s\n", idx, PFID(fid), obdindex == idx ? " *" : ""); } @@ -2418,19 +2494,23 @@ void lmv_dump_user_lmm(struct lmv_user_md *lum, char *pool_name, } if ((verbose & VERBOSE_POOL) && (pool_name[0] != '\0')) { + llapi_printf(LLAPI_MSG_NORMAL, "%s", separator); if (verbose & ~VERBOSE_POOL) llapi_printf(LLAPI_MSG_NORMAL, "%slmv_pool: ", prefix); llapi_printf(LLAPI_MSG_NORMAL, "%s%c ", pool_name, ' '); + separator = "\n"; } - llapi_printf(LLAPI_MSG_NORMAL, "\n"); + + if (!(verbose & VERBOSE_OBJID) || lum->lum_magic == LMV_USER_MAGIC) + llapi_printf(LLAPI_MSG_NORMAL, "\n"); } void llapi_lov_dump_user_lmm(struct find_param *param, char *path, int is_dir) { __u32 magic; - if (param->get_lmv) + if (param->get_lmv || param->get_default_lmv) magic = (__u32)param->fp_lmv_md->lum_magic; else magic = *(__u32 *)¶m->lmd->lmd_lmm; /* lum->lmm_magic */ @@ -2440,7 +2520,7 @@ void llapi_lov_dump_user_lmm(struct find_param *param, char *path, int is_dir) lov_dump_user_lmm_v1v3(¶m->lmd->lmd_lmm, NULL, param->lmd->lmd_lmm.lmm_objects, path, is_dir, - param->obdindex, param->maxdepth, + param->obdindex, param->fp_max_depth, param->verbose, param->raw); break; case LOV_USER_MAGIC_V3: { @@ -2448,12 +2528,11 @@ void llapi_lov_dump_user_lmm(struct find_param *param, char *path, int is_dir) struct lov_user_ost_data_v1 *objects; struct lov_user_md_v3 *lmmv3 = (void *)¶m->lmd->lmd_lmm; - strncpy(pool_name, lmmv3->lmm_pool_name, LOV_MAXPOOLNAME); - pool_name[LOV_MAXPOOLNAME] = '\0'; + strlcpy(pool_name, lmmv3->lmm_pool_name, sizeof(pool_name)); objects = lmmv3->lmm_objects; lov_dump_user_lmm_v1v3(¶m->lmd->lmd_lmm, pool_name, objects, path, is_dir, - param->obdindex, param->maxdepth, + param->obdindex, param->fp_max_depth, param->verbose, param->raw); break; } @@ -2463,9 +2542,9 @@ void llapi_lov_dump_user_lmm(struct find_param *param, char *path, int is_dir) struct lmv_user_md *lum; lum = (struct lmv_user_md *)param->fp_lmv_md; - strncpy(pool_name, lum->lum_pool_name, LOV_MAXPOOLNAME); + strlcpy(pool_name, lum->lum_pool_name, sizeof(pool_name)); lmv_dump_user_lmm(lum, pool_name, path, - param->obdindex, param->maxdepth, + param->obdindex, param->fp_max_depth, param->verbose); break; } @@ -2603,46 +2682,46 @@ static int find_value_cmp(unsigned long long file, unsigned long long limit, * updated timestamps. */ static int find_time_check(lstat_t *st, struct find_param *param, int mds) { - int ret; - int rc = 1; - - /* Check if file is accepted. */ - if (param->atime) { - ret = find_value_cmp(st->st_atime, param->atime, - param->asign, param->exclude_atime, - 24 * 60 * 60, mds); - if (ret < 0) - return ret; - rc = ret; - } - - if (param->mtime) { - ret = find_value_cmp(st->st_mtime, param->mtime, - param->msign, param->exclude_mtime, - 24 * 60 * 60, mds); - if (ret < 0) - return ret; - - /* If the previous check matches, but this one is not yet clear, - * we should return 0 to do an RPC on OSTs. */ - if (rc == 1) - rc = ret; - } + int rc = 1; + int rc2; + + /* Check if file is accepted. */ + if (param->fp_atime) { + rc2 = find_value_cmp(st->st_atime, param->fp_atime, + param->fp_asign, param->fp_exclude_atime, + 24 * 60 * 60, mds); + if (rc2 < 0) + return rc2; + rc = rc2; + } - if (param->ctime) { - ret = find_value_cmp(st->st_ctime, param->ctime, - param->csign, param->exclude_ctime, - 24 * 60 * 60, mds); - if (ret < 0) - return ret; + if (param->fp_mtime) { + rc2 = find_value_cmp(st->st_mtime, param->fp_mtime, + param->fp_msign, param->fp_exclude_mtime, + 24 * 60 * 60, mds); + if (rc2 < 0) + return rc2; + + /* If the previous check matches, but this one is not yet clear, + * we should return 0 to do an RPC on OSTs. */ + if (rc == 1) + rc = rc2; + } - /* If the previous check matches, but this one is not yet clear, - * we should return 0 to do an RPC on OSTs. */ - if (rc == 1) - rc = ret; - } + if (param->fp_ctime) { + rc2 = find_value_cmp(st->st_ctime, param->fp_ctime, + param->fp_csign, param->fp_exclude_ctime, + 24 * 60 * 60, mds); + if (rc2 < 0) + return rc2; + + /* If the previous check matches, but this one is not yet clear, + * we should return 0 to do an RPC on OSTs. */ + if (rc == 1) + rc = rc2; + } - return rc; + return rc; } /** @@ -2741,10 +2820,11 @@ static int print_failed_tgt(struct find_param *param, char *path, int type) return ret; } -static int cb_find_init(char *path, DIR *parent, DIR *dir, +static int cb_find_init(char *path, DIR *parent, DIR **dirp, void *data, struct dirent64 *de) { struct find_param *param = (struct find_param *)data; + DIR *dir = dirp == NULL ? NULL : *dirp; int decision = 1; /* 1 is accepted; -1 is rejected. */ lstat_t *st = ¶m->lmd->lmd_st; int lustre_fs = 1; @@ -2766,31 +2846,32 @@ static int cb_find_init(char *path, DIR *parent, DIR *dir, goto decided; } - /* See if we can check the file type from the dirent. */ - if (param->type && de != NULL && de->d_type != DT_UNKNOWN && - de->d_type < DT_MAX) { - checked_type = 1; - if (llapi_dir_filetype_table[de->d_type] == param->type) { - if (param->exclude_type) - goto decided; - } else { - if (!param->exclude_type) - goto decided; - } - } + /* See if we can check the file type from the dirent. */ + if (param->fp_type != 0 && de != NULL && de->d_type != DT_UNKNOWN) { + checked_type = 1; + + if (DTTOIF(de->d_type) == param->fp_type) { + if (param->fp_exclude_type) + goto decided; + } else { + if (!param->fp_exclude_type) + goto decided; + } + } ret = 0; /* Request MDS for the stat info if some of these parameters need * to be compared. */ - if (param->obduuid || param->mdtuuid || param->check_uid || - param->check_gid || param->check_pool || param->atime || - param->ctime || param->mtime || param->check_size || + if (param->obduuid || param->mdtuuid || + param->fp_check_uid || param->fp_check_gid || + param->fp_atime || param->fp_mtime || param->fp_ctime || + param->check_pool || param->check_size || param->check_stripecount || param->check_stripesize || param->check_layout) decision = 0; - if (param->type && checked_type == 0) + if (param->fp_type != 0 && checked_type == 0) decision = 0; if (param->have_fileinfo == 0 && decision == 0) { @@ -2840,20 +2921,20 @@ static int cb_find_init(char *path, DIR *parent, DIR *dir, } } - if (param->type && !checked_type) { - if ((st->st_mode & S_IFMT) == param->type) { - if (param->exclude_type) - goto decided; - } else { - if (!param->exclude_type) - goto decided; - } - } + if (param->fp_type && !checked_type) { + if ((st->st_mode & S_IFMT) == param->fp_type) { + if (param->fp_exclude_type) + goto decided; + } else { + if (!param->fp_exclude_type) + goto decided; + } + } /* Prepare odb. */ if (param->obduuid || param->mdtuuid) { if (lustre_fs && param->got_uuids && - param->st_dev != st->st_dev) { + param->fp_dev != st->st_dev) { /* A lustre/lustre mount point is crossed. */ param->got_uuids = 0; param->obds_printed = 0; @@ -2866,7 +2947,7 @@ static int cb_find_init(char *path, DIR *parent, DIR *dir, if (ret) return ret; - param->st_dev = st->st_dev; + param->fp_dev = st->st_dev; } else if (!lustre_fs && param->got_uuids) { /* A lustre/non-lustre mount point is crossed. */ param->got_uuids = 0; @@ -2932,25 +3013,25 @@ static int cb_find_init(char *path, DIR *parent, DIR *dir, } } obd_matches: - if (param->check_uid) { - if (st->st_uid == param->uid) { - if (param->exclude_uid) - goto decided; - } else { - if (!param->exclude_uid) - goto decided; + if (param->fp_check_uid) { + if (st->st_uid == param->fp_uid) { + if (param->fp_exclude_uid) + goto decided; + } else { + if (!param->fp_exclude_uid) + goto decided; } } - if (param->check_gid) { - if (st->st_gid == param->gid) { - if (param->exclude_gid) - goto decided; - } else { - if (!param->exclude_gid) - goto decided; - } - } + if (param->fp_check_gid) { + if (st->st_gid == param->fp_gid) { + if (param->fp_exclude_gid) + goto decided; + } else { + if (!param->fp_exclude_gid) + goto decided; + } + } if (param->check_pool) { struct lov_user_md_v3 *lmmv3 = (void *)¶m->lmd->lmd_lmm; @@ -2971,9 +3052,9 @@ obd_matches: } } - /* Check the time on mds. */ - decision = 1; - if (param->atime || param->ctime || param->mtime) { + /* Check the time on mds. */ + decision = 1; + if (param->fp_atime || param->fp_mtime || param->fp_ctime) { int for_mds; for_mds = lustre_fs ? (S_ISREG(st->st_mode) && @@ -3051,11 +3132,89 @@ obd_matches: decided: /* Do not get down anymore? */ - if (param->depth == param->maxdepth) - return 1; + if (param->fp_depth == param->fp_max_depth) + return 1; - param->depth++; - return 0; + param->fp_depth++; + + return 0; +} + +static int cb_mv_init(char *path, DIR *parent, DIR **dirp, + void *param_data, struct dirent64 *de) +{ + struct find_param *param = (struct find_param *)param_data; + DIR *dir = parent; + char raw[OBD_MAX_IOCTL_BUFFER] = {'\0'}; + char *rawbuf = raw; + struct obd_ioctl_data data = { 0 }; + int fd; + int ret; + char *filename; + + LASSERT(parent != NULL || dirp != NULL); + if (dirp != NULL) + closedir(*dirp); + + if (parent == NULL) { + dir = opendir_parent(path); + if (dir == NULL) { + *dirp = NULL; + ret = -errno; + llapi_error(LLAPI_MSG_ERROR, ret, + "can not open %s\n", path); + return ret; + } + } + + fd = dirfd(dir); + + filename = basename(path); + data.ioc_inlbuf1 = (char *)filename; + data.ioc_inllen1 = strlen(filename) + 1; + data.ioc_inlbuf2 = (char *)¶m->mdtindex; + data.ioc_inllen2 = sizeof(param->mdtindex); + ret = obd_ioctl_pack(&data, &rawbuf, sizeof(raw)); + if (ret != 0) { + llapi_error(LLAPI_MSG_ERROR, ret, + "llapi_obd_statfs: error packing ioctl data"); + goto out; + } + + ret = ioctl(fd, LL_IOC_MIGRATE, rawbuf); + if (ret != 0) { + ret = -errno; + fprintf(stderr, "%s migrate failed %d\n", path, ret); + goto out; + } else if (param->verbose & VERBOSE_DETAIL) { + fprintf(stdout, "migrate %s to MDT%d\n", path, param->mdtindex); + } + +out: + if (dirp != NULL) { + /* If the directory is being migration, we need + * close the directory after migration, + * so the old directory cache will be cleanup + * on the client side, and re-open to get the + * new directory handle */ + *dirp = opendir(path); + if (dirp == NULL) { + ret = -errno; + llapi_error(LLAPI_MSG_ERROR, ret, + "%s: Failed to open '%s'", __func__, path); + return ret; + } + } + + if (parent == NULL) + closedir(dir); + + return ret; +} + +int llapi_mv(char *path, struct find_param *param) +{ + return param_callback(path, cb_mv_init, cb_common_fini, param); } int llapi_find(char *path, struct find_param *param) @@ -3075,10 +3234,11 @@ int llapi_file_fget_mdtidx(int fd, int *mdtidx) return 0; } -static int cb_get_mdt_index(char *path, DIR *parent, DIR *d, void *data, +static int cb_get_mdt_index(char *path, DIR *parent, DIR **dirp, void *data, struct dirent64 *de) { struct find_param *param = (struct find_param *)data; + DIR *d = dirp == NULL ? NULL : *dirp; int ret = 0; int mdtidx; @@ -3134,18 +3294,20 @@ static int cb_get_mdt_index(char *path, DIR *parent, DIR *d, void *data, path, mdtidx); out: - /* Do not get down anymore? */ - if (param->depth == param->maxdepth) - return 1; + /* Do not get down anymore? */ + if (param->fp_depth == param->fp_max_depth) + return 1; - param->depth++; - return 0; + param->fp_depth++; + + return 0; } -static int cb_getstripe(char *path, DIR *parent, DIR *d, void *data, +static int cb_getstripe(char *path, DIR *parent, DIR **dirp, void *data, struct dirent64 *de) { struct find_param *param = (struct find_param *)data; + DIR *d = dirp == NULL ? NULL : *dirp; int ret = 0; LASSERT(parent != NULL || d != NULL); @@ -3158,25 +3320,18 @@ static int cb_getstripe(char *path, DIR *parent, DIR *d, void *data, } if (d) { - if (param->get_lmv) { + if (param->get_lmv || param->get_default_lmv) { ret = cb_get_dirstripe(path, d, param); } else { ret = ioctl(dirfd(d), LL_IOC_LOV_GETSTRIPE, (void *)¶m->lmd->lmd_lmm); } - } else if (parent) { + } else if (parent && !param->get_lmv && !param->get_default_lmv) { char *fname = strrchr(path, '/'); fname = (fname == NULL ? path : fname + 1); - if (param->get_lmv) { - llapi_printf(LLAPI_MSG_NORMAL, - "%s get dirstripe information for file\n", - path); - goto out; - } - - strncpy((char *)¶m->lmd->lmd_lmm, fname, param->lumlen); + strlcpy((char *)¶m->lmd->lmd_lmm, fname, param->lumlen); ret = ioctl(dirfd(parent), IOC_MDC_GETFILESTRIPE, (void *)¶m->lmd->lmd_lmm); @@ -3190,15 +3345,35 @@ static int cb_getstripe(char *path, DIR *parent, DIR *d, void *data, * a check later on in the code path. * The object_seq needs to be set for the "(Default)" * prefix to be displayed. */ - struct lov_user_md *lmm = ¶m->lmd->lmd_lmm; - lmm->lmm_magic = LOV_USER_MAGIC_V1; - if (!param->raw) - ostid_set_seq(&lmm->lmm_oi, - FID_SEQ_LOV_DEFAULT); - lmm->lmm_stripe_count = 0; - lmm->lmm_stripe_size = 0; - lmm->lmm_stripe_offset = -1; - goto dump; + if (param->get_default_lmv) { + struct lmv_user_md *lum = param->fp_lmv_md; + + lum->lum_magic = LMV_USER_MAGIC; + lum->lum_stripe_count = 0; + lum->lum_stripe_offset = -1; + goto dump; + } else if (param->get_lmv) { + struct lmv_user_md *lum = param->fp_lmv_md; + int mdtidx; + + ret = llapi_file_fget_mdtidx(dirfd(d), &mdtidx); + if (ret != 0) + goto err_out; + lum->lum_magic = LMV_MAGIC_V1; + lum->lum_stripe_count = 0; + lum->lum_stripe_offset = mdtidx; + goto dump; + } else { + struct lov_user_md *lmm = ¶m->lmd->lmd_lmm; + lmm->lmm_magic = LOV_USER_MAGIC_V1; + if (!param->raw) + ostid_set_seq(&lmm->lmm_oi, + FID_SEQ_LOV_DEFAULT); + lmm->lmm_stripe_count = 0; + lmm->lmm_stripe_size = 0; + lmm->lmm_stripe_offset = -1; + goto dump; + } } else if (errno == ENODATA && parent != NULL) { if (!param->obduuid && !param->mdtuuid) llapi_printf(LLAPI_MSG_NORMAL, @@ -3216,11 +3391,12 @@ static int cb_getstripe(char *path, DIR *parent, DIR *d, void *data, __func__, path); } else { ret = -errno; - llapi_error(LLAPI_MSG_ERROR, ret, - "error: %s: %s failed for %s", - __func__, d ? "LL_IOC_LOV_GETSTRIPE" : - "IOC_MDC_GETFILESTRIPE", path); - } +err_out: + llapi_error(LLAPI_MSG_ERROR, ret, + "error: %s: %s failed for %s", + __func__, d ? "LL_IOC_LOV_GETSTRIPE" : + "IOC_MDC_GETFILESTRIPE", path); + } return ret; } @@ -3230,12 +3406,13 @@ dump: llapi_lov_dump_user_lmm(param, path, d ? 1 : 0); out: - /* Do not get down anymore? */ - if (param->depth == param->maxdepth) - return 1; + /* Do not get down anymore? */ + if (param->fp_depth == param->fp_max_depth) + return 1; - param->depth++; - return 0; + param->fp_depth++; + + return 0; } int llapi_getstripe(char *path, struct find_param *param) @@ -3275,18 +3452,20 @@ int llapi_obd_statfs(char *path, __u32 type, __u32 index, if (errno == EISDIR) fd = open(path, O_DIRECTORY | O_RDONLY); - if (fd < 0) { - rc = errno ? -errno : -EBADF; - llapi_error(LLAPI_MSG_ERROR, rc, "error: %s: opening '%s'", - __func__, path); - return rc; - } - rc = ioctl(fd, IOC_OBD_STATFS, (void *)rawbuf); - if (rc) - rc = errno ? -errno : -EINVAL; + if (fd < 0) { + rc = errno ? -errno : -EBADF; + llapi_error(LLAPI_MSG_ERROR, rc, "error: %s: opening '%s'", + __func__, path); + /* If we can't even open a file on the filesystem (e.g. with + * -ESHUTDOWN), force caller to exit or it will loop forever. */ + return -ENODEV; + } + rc = ioctl(fd, IOC_OBD_STATFS, (void *)rawbuf); + if (rc) + rc = errno ? -errno : -EINVAL; - close(fd); - return rc; + close(fd); + return rc; } #define MAX_STRING_SIZE 128 @@ -3408,7 +3587,7 @@ int llapi_quotacheck(char *mnt, int check_type) return rc; } - rc = ioctl(dirfd(root), LL_IOC_QUOTACHECK, check_type); + rc = ioctl(dirfd(root), OBD_IOC_QUOTACHECK, check_type); if (rc < 0) rc = -errno; @@ -3430,7 +3609,7 @@ int llapi_poll_quotacheck(char *mnt, struct if_quotacheck *qchk) } while (1) { - rc = ioctl(dirfd(root), LL_IOC_POLL_QUOTACHECK, qchk); + rc = ioctl(dirfd(root), OBD_IOC_POLL_QUOTACHECK, qchk); if (!rc) break; sleep(poll_intvl); @@ -3454,7 +3633,7 @@ int llapi_quotactl(char *mnt, struct if_quotactl *qctl) return rc; } - rc = ioctl(dirfd(root), LL_IOC_QUOTACTL, qctl); + rc = ioctl(dirfd(root), OBD_IOC_QUOTACTL, qctl); if (rc < 0) rc = -errno; @@ -3462,10 +3641,11 @@ int llapi_quotactl(char *mnt, struct if_quotactl *qctl) return rc; } -static int cb_quotachown(char *path, DIR *parent, DIR *d, void *data, +static int cb_quotachown(char *path, DIR *parent, DIR **dirp, void *data, struct dirent64 *de) { struct find_param *param = (struct find_param *)data; + DIR *d = dirp == NULL ? NULL : *dirp; lstat_t *st; int rc; @@ -3950,7 +4130,7 @@ int llapi_changelog_start(void **priv, int flags, const char *device, cp->flags = flags; /* Set up the receiver */ - rc = libcfs_ukuc_start(&cp->kuc, 0 /* no group registration */); + rc = libcfs_ukuc_start(&cp->kuc, 0 /* no group registration */, 0); if (rc < 0) goto out_free; @@ -4140,9 +4320,13 @@ int llapi_fid2path(const char *device, const char *fidstr, char *buf, if (rc != -ENOENT) llapi_error(LLAPI_MSG_ERROR, rc, "ioctl err %d", rc); } else { - memcpy(buf, gf->gf_path, gf->gf_pathlen); - *recno = gf->gf_recno; - *linkno = gf->gf_linkno; + memcpy(buf, gf->gf_path, gf->gf_pathlen); + if (buf[0] == '\0') { /* ROOT path */ + buf[0] = '/'; + buf[1] = '\0'; + } + *recno = gf->gf_recno; + *linkno = gf->gf_linkno; } free(gf); @@ -4283,19 +4467,26 @@ int llapi_get_data_version(int fd, __u64 *data_version, __u64 flags) } /* - * Create a volatile file and open it for write: - * - file is created as a standard file in the directory - * - file does not appears in directory and directory mtime does not change - * - file is removed at close - * - file modes are rw-------, if user wants another one it must use fchmod() - * \param directory Directory where the file is created - * \param idx MDT index on which the file is created - * \param flags Std open flags + * Create a file without any name open it for read/write + * + * - file is created as if it were a standard file in the given \a directory + * - file does not appear in \a directory and mtime does not change because + * the filename is handled specially by the Lustre MDS. + * - file is removed at final close + * - file modes are rw------- since it doesn't make sense to have a read-only + * or write-only file that cannot be opened again. + * - if user wants another mode it must use fchmod() on the open file, no + * security problems arise because it cannot be opened by another process. + * + * \param[in] directory directory from which to inherit layout/MDT idx + * \param[in] idx MDT index on which the file is created, + * \a idx == -1 means no specific MDT is requested + * \param[in] open_flags standard open(2) flags * * \retval 0 on success. * \retval -errno on error. */ -int llapi_create_volatile_idx(char *directory, int idx, int mode) +int llapi_create_volatile_idx(char *directory, int idx, int open_flags) { char file_path[PATH_MAX]; char filename[PATH_MAX]; @@ -4329,14 +4520,19 @@ int llapi_create_volatile_idx(char *directory, int idx, int mode) if (rc >= sizeof(file_path)) return -E2BIG; - fd = open(file_path, (O_RDWR | O_CREAT | mode), (S_IRUSR | S_IWUSR)); + fd = open(file_path, O_RDWR | O_CREAT | open_flags, S_IRUSR | S_IWUSR); if (fd < 0) { llapi_error(LLAPI_MSG_ERROR, errno, - "Cannot create volatile file %s in %s\n", + "Cannot create volatile file '%s' in '%s'\n", filename + LUSTRE_VOLATILE_HDR_LEN, directory); return -errno; } + /* unlink file in case this wasn't a Lustre filesystem, and the + * magic volatile filename wasn't handled as intended. The effect + * is the same. */ + unlink(file_path); + return fd; } @@ -4374,28 +4570,29 @@ int llapi_swap_layouts(const char *path1, const char *path2, fd1 = open(path1, O_WRONLY | O_LOV_DELAY_CREATE); if (fd1 < 0) { - llapi_error(LLAPI_MSG_ERROR, -errno, - "error: cannot open for write %s", - path1); - return -errno; + rc = -errno; + llapi_error(LLAPI_MSG_ERROR, rc, + "error: cannot open '%s' for write", path1); + goto out; } fd2 = open(path2, O_WRONLY | O_LOV_DELAY_CREATE); if (fd2 < 0) { - llapi_error(LLAPI_MSG_ERROR, -errno, - "error: cannot open for write %s", - path2); - close(fd1); - return -errno; + rc = -errno; + llapi_error(LLAPI_MSG_ERROR, rc, + "error: cannot open '%s' for write", path2); + goto out_close; } rc = llapi_fswap_layouts(fd1, fd2, dv1, dv2, flags); if (rc < 0) llapi_error(LLAPI_MSG_ERROR, rc, - "error: cannot swap layouts between %s and %s\n", - path1, path2); + "error: cannot swap layout between '%s' and '%s'\n", + path1, path2); - close(fd1); close(fd2); +out_close: + close(fd1); +out: return rc; }