X-Git-Url: https://git.whamcloud.com/?p=fs%2Flustre-release.git;a=blobdiff_plain;f=lustre%2Futils%2Fliblustreapi.c;h=44ac26c2766de9e9070aa84e242d04af9a22abb5;hp=c7a82812e26601321cf47c135a83161adafbd8cc;hb=08892438473f3188de3dc7f76b0ce433eaef4367;hpb=6d775021473e53b623cd78f35a4d51e67136918a diff --git a/lustre/utils/liblustreapi.c b/lustre/utils/liblustreapi.c index c7a8281..44ac26c 100644 --- a/lustre/utils/liblustreapi.c +++ b/lustre/utils/liblustreapi.c @@ -59,9 +59,11 @@ #include #include #include +#include #include #include #include /* for dirname() */ +#include #ifdef HAVE_LINUX_UNISTD_H #include #else @@ -69,6 +71,7 @@ #endif #include #include +#include #include #include @@ -78,23 +81,34 @@ #include #include #include "lustreapi_internal.h" +#include "lstddef.h" static int llapi_msg_level = LLAPI_MSG_MAX; const char *liblustreapi_cmd; char *mdt_hash_name[] = { "none", LMV_HASH_NAME_ALL_CHARS, - LMV_HASH_NAME_FNV_1A_64 }; + LMV_HASH_NAME_FNV_1A_64, + LMV_HASH_NAME_CRUSH, +}; + +struct lustre_foreign_type lu_foreign_types[] = { + {.lft_type = LU_FOREIGN_TYPE_NONE, .lft_name = "none"}, + {.lft_type = LU_FOREIGN_TYPE_DAOS, .lft_name = "daos"}, + /* must be the last element */ + {.lft_type = LU_FOREIGN_TYPE_UNKNOWN, .lft_name = NULL} + /* array max dimension must be <= UINT32_MAX */ +}; void llapi_msg_set_level(int level) { - /* ensure level is in the good range */ - if (level < LLAPI_MSG_OFF) - llapi_msg_level = LLAPI_MSG_OFF; - else if (level > LLAPI_MSG_MAX) - llapi_msg_level = LLAPI_MSG_MAX; - else - llapi_msg_level = level; + /* ensure level is in the good range */ + if (level < LLAPI_MSG_OFF) + llapi_msg_level = LLAPI_MSG_OFF; + else if (level > LLAPI_MSG_MAX) + llapi_msg_level = LLAPI_MSG_MAX; + else + llapi_msg_level = level; } int llapi_msg_get_level(void) @@ -115,16 +129,36 @@ void llapi_clear_command_name(void) static void error_callback_default(enum llapi_message_level level, int err, const char *fmt, va_list ap) { + bool has_nl = strchr(fmt, '\n') != NULL; + if (liblustreapi_cmd != NULL) fprintf(stderr, "%s %s: ", program_invocation_short_name, liblustreapi_cmd); else fprintf(stderr, "%s: ", program_invocation_short_name); - vfprintf(stderr, fmt, ap); - if (level & LLAPI_MSG_NO_ERRNO) - fprintf(stderr, "\n"); - else + + + if (level & LLAPI_MSG_NO_ERRNO) { + vfprintf(stderr, fmt, ap); + if (!has_nl) + fprintf(stderr, "\n"); + } else { + char *newfmt; + + /* + * Remove trailing linefeed so error string can be appended. + * @fmt is a const string, so we can't modify it directly. + */ + if (has_nl && (newfmt = strdup(fmt))) + *strrchr(newfmt, '\n') = '\0'; + else + newfmt = (char *)fmt; + + vfprintf(stderr, newfmt, ap); + if (newfmt != fmt) + free(newfmt); fprintf(stderr, ": %s (%d)\n", strerror(err), err); + } } static void info_callback_default(enum llapi_message_level level, int err, @@ -291,7 +325,7 @@ int llapi_ioctl_pack(struct obd_ioctl_data *data, char **pbuf, int max_len) if (*pbuf != NULL && data->ioc_len > max_len) { llapi_error(LLAPI_MSG_ERROR, -EINVAL, - "pbuf = %p, ioc_len = %u, max_len = %d\n", + "pbuf = %p, ioc_len = %u, max_len = %d", *pbuf, data->ioc_len, max_len); return -EINVAL; } @@ -376,45 +410,53 @@ int llapi_ioctl_unpack(struct obd_ioctl_data *data, char *pbuf, int max_len) int llapi_stripe_limit_check(unsigned long long stripe_size, int stripe_offset, int stripe_count, int stripe_pattern) { - int page_size, rc; + static int page_size; + int rc = 0; - /* 64 KB is the largest common page size I'm aware of (on ia64), but - * check the local page size just in case. */ - page_size = LOV_MIN_STRIPE_SIZE; - if (getpagesize() > page_size) { - page_size = getpagesize(); - llapi_err_noerrno(LLAPI_MSG_WARN, - "warning: your page size (%u) is " - "larger than expected (%u)", page_size, - LOV_MIN_STRIPE_SIZE); + if (page_size == 0) { + /* + * 64 KB is the largest common page size (on ia64/PPC/ARM), + * but check the local page size just in case. The page_size + * will not change for the lifetime of this process at least. + */ + page_size = LOV_MIN_STRIPE_SIZE; + if (getpagesize() > page_size) { + page_size = getpagesize(); + llapi_err_noerrno(LLAPI_MSG_WARN, + "warning: page size (%u) larger than expected (%u)", + page_size, LOV_MIN_STRIPE_SIZE); + } } if (!llapi_stripe_size_is_aligned(stripe_size)) { rc = -EINVAL; - llapi_error(LLAPI_MSG_ERROR, rc, "error: bad stripe_size %llu, " - "must be an even multiple of %d bytes", - stripe_size, page_size); - return rc; + llapi_error(LLAPI_MSG_ERROR, rc, + "error: bad stripe_size %llu, must be an even multiple of %d bytes", + (unsigned long long)stripe_size, page_size); + goto out; } if (!llapi_stripe_index_is_valid(stripe_offset)) { rc = -EINVAL; llapi_error(LLAPI_MSG_ERROR, rc, "error: bad stripe offset %d", stripe_offset); - return rc; + goto out; } if (!llapi_stripe_count_is_valid(stripe_count)) { rc = -EINVAL; llapi_error(LLAPI_MSG_ERROR, rc, "error: bad stripe count %d", stripe_count); - return rc; + goto out; } if (llapi_stripe_size_is_too_big(stripe_size)) { rc = -EINVAL; llapi_error(LLAPI_MSG_ERROR, rc, - "warning: stripe size 4G or larger " - "is not currently supported and would wrap"); - return rc; + "error: stripe size '%llu' over 4GB limit", + (unsigned long long)stripe_size); + goto out; } - return 0; + +out: + errno = -rc; + return rc; } int llapi_dir_stripe_limit_check(int stripe_offset, int stripe_count, @@ -498,23 +540,21 @@ static int get_param_lmv(const char *path, const char *param, 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); - int rc; - - rc = llapi_getname(path, inst, sizeof(inst)); - if (rc != 0) - return rc; - /* 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 rc; + /* + * Rather than open the file and do the ioctl to get the + * instance name and close the file and search for the param + * file and open the param file and read the param file and + * parse the value and close the param file, let's just return + * a large enough value. It's 2020, RAM is cheap and this is + * much faster. + */ - rc = atoi(buf); + if (md_size < XATTR_SIZE_MAX) + md_size = XATTR_SIZE_MAX; - return rc > 0 ? rc : md_size; + return md_size; } int llapi_get_agent_uuid(char *path, char *buf, size_t bufsize) @@ -522,87 +562,6 @@ 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 tgtname in target_obd - * if pool is not NULL: - * if pool not found returns errno < 0 - * if tgtname is NULL, returns 1 if pool is not empty and 0 if pool empty - * if tgtname is not NULL, returns 1 if OST is in pool and 0 if not - */ -int llapi_search_tgt(char *fsname, char *poolname, char *tgtname, bool is_mdt) -{ - char buffer[PATH_MAX]; - size_t len = 0; - glob_t param; - FILE *fd; - int rc; - - /* You need one or the other */ - if (poolname == NULL && fsname == NULL) - return -EINVAL; - - if (tgtname != NULL) - len = strlen(tgtname); - - 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(is_mdt ? "lmv" : "lov", fsname, - FILTER_BY_FS_NAME, - "target_obd", ¶m); - if (rc == 0) { - strncpy(buffer, param.gl_pathv[0], - sizeof(buffer)); - } - } else { - return -EINVAL; - } - cfs_free_param_data(¶m); - if (rc) - return rc; - - fd = fopen(buffer, "r"); - if (fd == NULL) - return -errno; - - while (fgets(buffer, sizeof(buffer), fd) != NULL) { - if (poolname == NULL) { - char *ptr; - /* Search for an tgtname in the list of targets - * Line format is IDX: fsname-OST/MDTxxxx_UUID STATUS */ - ptr = strchr(buffer, ' '); - if ((ptr != NULL) && - (strncmp(ptr + 1, tgtname, len) == 0)) { - fclose(fd); - return 1; - } - } else { - /* Search for an tgtname in a pool, - * (or an existing non-empty pool if no tgtname) */ - if ((tgtname == NULL) || - (strncmp(buffer, tgtname, len) == 0)) { - fclose(fd); - return 1; - } - } - } - fclose(fd); - return 0; -} - -int llapi_search_ost(char *fsname, char *poolname, char *ostname) -{ - return llapi_search_tgt(fsname, poolname, ostname, false); -} - /** * Open a Lustre file. * @@ -642,9 +601,12 @@ int llapi_file_open_param(const char *name, int flags, mode_t mode, /* Make sure we have a good pool */ if (pool_name != NULL) { - /* in case user gives the full pool name ., - * strip the fsname */ + /* + * in case user gives the full pool name ., + * strip the fsname + */ char *ptr = strchr(pool_name, '.'); + if (ptr != NULL) { *ptr = '\0'; if (strcmp(pool_name, fsname) != 0) { @@ -672,7 +634,7 @@ int llapi_file_open_param(const char *name, int flags, mode_t mode, /* sanity check of target list */ if (param->lsp_is_specific) { - char ostname[MAX_OBD_NAME + 1]; + char ostname[MAX_OBD_NAME + 64]; bool found = false; int i; @@ -698,8 +660,7 @@ int llapi_file_open_param(const char *name, int flags, mode_t mode, } if (!found) { llapi_error(LLAPI_MSG_ERROR, -EINVAL, - "%s: stripe offset '%d' is not in the " - "target list", + "%s: stripe offset '%d' is not in the target list", __func__, param->lsp_stripe_offset); return -EINVAL; } @@ -746,9 +707,11 @@ retry_open: lumv3->lmm_magic = LOV_USER_MAGIC_SPECIFIC; if (pool_name == NULL) { - /* LOV_USER_MAGIC_SPECIFIC uses v3 format plus specified + /* + * LOV_USER_MAGIC_SPECIFIC uses v3 format plus specified * OST list, therefore if pool is not specified we have - * to pack a null pool name for placeholder. */ + * to pack a null pool name for placeholder. + */ memset(lumv3->lmm_pool_name, 0, LOV_MAXPOOLNAME); } @@ -757,11 +720,15 @@ retry_open: } if (ioctl(fd, LL_IOC_LOV_SETSTRIPE, lum) != 0) { - char *errmsg = "stripe already set"; + char errmsg[512] = "stripe already set"; rc = -errno; if (errno != EEXIST && errno != EALREADY) - errmsg = strerror(errno); + strncpy(errmsg, strerror(errno), sizeof(errmsg) - 1); + if (rc == -EREMOTEIO) + snprintf(errmsg, sizeof(errmsg), + "inactive OST among your specified %d OST(s)", + param->lsp_stripe_count); llapi_err_noerrno(LLAPI_MSG_ERROR, "setstripe error for '%s': %s", name, errmsg); @@ -790,43 +757,117 @@ int llapi_file_open_pool(const char *name, int flags, int mode, } int llapi_file_open(const char *name, int flags, int mode, - unsigned long long stripe_size, int stripe_offset, - int stripe_count, int stripe_pattern) + unsigned long long stripe_size, int stripe_offset, + int stripe_count, int stripe_pattern) { - return llapi_file_open_pool(name, flags, mode, stripe_size, - stripe_offset, stripe_count, - stripe_pattern, NULL); + return llapi_file_open_pool(name, flags, mode, stripe_size, + stripe_offset, stripe_count, + stripe_pattern, NULL); +} + +int llapi_file_create_foreign(const char *name, mode_t mode, __u32 type, + __u32 flags, char *foreign_lov) +{ + size_t len; + struct lov_foreign_md *lfm; + int fd, rc; + + if (foreign_lov == NULL) { + rc = -EINVAL; + llapi_error(LLAPI_MSG_ERROR, rc, + "foreign LOV EA content must be provided"); + goto out_err; + } + + len = strlen(foreign_lov); + if (len > XATTR_SIZE_MAX - offsetof(struct lov_foreign_md, lfm_value) || + len <= 0) { + rc = -EINVAL; + llapi_error(LLAPI_MSG_ERROR, rc, + "foreign LOV EA size %zu (must be 0 < len < %zu)", + len, XATTR_SIZE_MAX - + offsetof(struct lov_foreign_md, lfm_value)); + goto out_err; + } + + lfm = malloc(len + offsetof(struct lov_foreign_md, lfm_value)); + if (lfm == NULL) { + rc = -ENOMEM; + llapi_error(LLAPI_MSG_ERROR, rc, + "failed to allocate lov_foreign_md"); + goto out_err; + } + + fd = open(name, O_WRONLY|O_CREAT|O_LOV_DELAY_CREATE, mode); + if (fd == -1) { + fd = -errno; + llapi_error(LLAPI_MSG_ERROR, fd, "open '%s' failed", name); + goto out_free; + } + + lfm->lfm_magic = LOV_USER_MAGIC_FOREIGN; + lfm->lfm_length = len; + lfm->lfm_type = type; + lfm->lfm_flags = flags; + memcpy(lfm->lfm_value, foreign_lov, len); + + if (ioctl(fd, LL_IOC_LOV_SETSTRIPE, lfm) != 0) { + char *errmsg = "stripe already set"; + + rc = -errno; + if (errno == ENOTTY) + errmsg = "not on a Lustre filesystem"; + else if (errno == EEXIST || errno == EALREADY) + errmsg = "stripe already set"; + else + errmsg = strerror(errno); + + llapi_err_noerrno(LLAPI_MSG_ERROR, + "setstripe error for '%s': %s", name, errmsg); + + close(fd); + fd = rc; + } + +out_free: + free(lfm); + + return fd; + +out_err: + errno = -rc; + return rc; } int llapi_file_create(const char *name, unsigned long long stripe_size, - int stripe_offset, int stripe_count, int stripe_pattern) + int stripe_offset, int stripe_count, int stripe_pattern) { - int fd; + int fd; - fd = llapi_file_open_pool(name, O_CREAT | O_WRONLY, 0644, stripe_size, - stripe_offset, stripe_count, stripe_pattern, - NULL); - if (fd < 0) - return fd; + fd = llapi_file_open_pool(name, O_CREAT | O_WRONLY, 0644, stripe_size, + stripe_offset, stripe_count, stripe_pattern, + NULL); + if (fd < 0) + return fd; - close(fd); - return 0; + close(fd); + return 0; } int llapi_file_create_pool(const char *name, unsigned long long stripe_size, - int stripe_offset, int stripe_count, - int stripe_pattern, char *pool_name) + int stripe_offset, int stripe_count, + int stripe_pattern, char *pool_name) { - int fd; + int fd; - fd = llapi_file_open_pool(name, O_CREAT | O_WRONLY, 0644, stripe_size, - stripe_offset, stripe_count, stripe_pattern, - pool_name); - if (fd < 0) - return fd; + fd = llapi_file_open_pool(name, O_CREAT | O_WRONLY, 0644, stripe_size, + stripe_offset, stripe_count, stripe_pattern, + pool_name); + if (fd < 0) + return fd; - close(fd); - return 0; + close(fd); + return 0; } static int verify_dir_param(const char *name, @@ -854,8 +895,10 @@ static int verify_dir_param(const char *name, /* Make sure we have a good pool */ if (pool_name != NULL) { - /* in case user gives the full pool name ., - * strip the fsname */ + /* + * in case user gives the full pool name ., + * strip the fsname + */ char *ptr = strchr(pool_name, '.'); if (ptr != NULL) { @@ -883,7 +926,7 @@ static int verify_dir_param(const char *name, /* sanity check of target list */ if (param->lsp_is_specific) { - char mdtname[MAX_OBD_NAME + 1]; + char mdtname[MAX_OBD_NAME + 64]; bool found = false; int i; @@ -909,8 +952,7 @@ static int verify_dir_param(const char *name, } if (!found) { llapi_error(LLAPI_MSG_ERROR, -EINVAL, - "%s: stripe offset '%d' is not in the " - "target list", + "%s: stripe offset '%d' is not in the target list", __func__, param->lsp_stripe_offset); return -EINVAL; } @@ -964,6 +1006,7 @@ int llapi_dir_set_default_lmv(const char *name, rc = ioctl(fd, LL_IOC_LMV_SET_DEFAULT_STRIPE, &lmu); if (rc < 0) { char *errmsg = "stripe already set"; + rc = -errno; if (errno != EEXIST && errno != EALREADY) errmsg = strerror(errno); @@ -1083,6 +1126,106 @@ out: return rc; } +/** + * Create a foreign directory. + * + * \param name the name of the directory to be created + * \param mode permission of the file if it is created, see mode in open(2) + * \param type foreign type to be set in LMV EA + * \param flags foreign flags to be set in LMV EA + * \param value foreign pattern to be set in LMV EA + * + * \retval 0 on success + * \retval negative errno on failure + */ +int llapi_dir_create_foreign(const char *name, mode_t mode, __u32 type, + __u32 flags, const char *value) +{ + struct lmv_foreign_md *lfm = NULL; + size_t lfm_size, len; + struct obd_ioctl_data data = { 0 }; + char rawbuf[8192]; + char *buf = rawbuf; + char *dirpath = NULL; + char *namepath = NULL; + char *dir; + char *filename; + int fd, rc; + + len = strlen(value); + if (len > XATTR_SIZE_MAX - offsetof(struct lmv_foreign_md, lfm_value) || + len <= 0) { + rc = -EINVAL; + llapi_error(LLAPI_MSG_ERROR, rc, + "invalid LOV EA length %zu (must be 0 < len < %zu)", + len, XATTR_SIZE_MAX - + offsetof(struct lmv_foreign_md, lfm_value)); + return rc; + } + lfm_size = len + offsetof(struct lmv_foreign_md, lfm_value); + lfm = calloc(1, lfm_size); + if (lfm == NULL) + return -ENOMEM; + + dirpath = strdup(name); + if (!dirpath) { + free(lfm); + return -ENOMEM; + } + + namepath = strdup(name); + if (!namepath) { + free(dirpath); + free(lfm); + return -ENOMEM; + } + + lfm->lfm_magic = LMV_MAGIC_FOREIGN; + lfm->lfm_length = len; + lfm->lfm_type = type; + lfm->lfm_flags = flags; + memcpy(lfm->lfm_value, value, len); + + filename = basename(namepath); + dir = dirname(dirpath); + + data.ioc_inlbuf1 = (char *)filename; + data.ioc_inllen1 = strlen(filename) + 1; + data.ioc_inlbuf2 = (char *)lfm; + data.ioc_inllen2 = lfm_size; + data.ioc_type = mode; + rc = llapi_ioctl_pack(&data, &buf, sizeof(rawbuf)); + if (rc) { + llapi_error(LLAPI_MSG_ERROR, rc, + "error: LL_IOC_LMV_SETSTRIPE pack failed '%s'.", + name); + goto out; + } + + fd = open(dir, O_DIRECTORY | O_RDONLY); + if (fd < 0) { + rc = -errno; + llapi_error(LLAPI_MSG_ERROR, rc, "unable to open '%s'", name); + goto out; + } + + if (ioctl(fd, LL_IOC_LMV_SETSTRIPE, buf)) { + char *errmsg = "stripe already set"; + + rc = -errno; + if (errno != EEXIST && errno != EALREADY) + errmsg = strerror(errno); + + llapi_err_noerrno(LLAPI_MSG_ERROR, + "dirstripe error on '%s': %s", name, errmsg); + } + close(fd); +out: + free(namepath); + free(dirpath); + free(lfm); + return rc; +} int llapi_dir_create_pool(const char *name, int mode, int stripe_offset, int stripe_count, int stripe_pattern, @@ -1124,13 +1267,10 @@ int llapi_direntry_remove(char *dname) goto out; } - if (ioctl(fd, LL_IOC_REMOVE_ENTRY, filename)) { - char *errmsg = strerror(errno); - llapi_err_noerrno(LLAPI_MSG_ERROR, - "error on ioctl %#jx for '%s' (%d): %s", - (uintmax_t)LL_IOC_LMV_SETSTRIPE, filename, - fd, errmsg); - } + if (ioctl(fd, LL_IOC_REMOVE_ENTRY, filename)) + llapi_error(LLAPI_MSG_ERROR, errno, + "error on ioctl %#lx for '%s' (%d)", + (long)LL_IOC_LMV_SETSTRIPE, filename, fd); out: free(dirpath); free(namepath); @@ -1149,10 +1289,11 @@ int get_root_path(int want, char *fsname, int *outfd, char *path, int index) char buf[PATH_MAX], mntdir[PATH_MAX]; char *ptr, *ptr_end; FILE *fp; - int idx = 0, len = 0, mntlen, fd; + int idx = 0, mntlen = 0, fd; int rc = -ENODEV; + int fsnamelen, mountlen; - /* get the mount point */ + /* get the mount point */ fp = setmntent(PROC_MOUNTS, "r"); if (fp == NULL) { rc = -EIO; @@ -1160,23 +1301,25 @@ int get_root_path(int want, char *fsname, int *outfd, char *path, int index) "cannot retrieve filesystem mount point"); return rc; } - while (1) { - if (getmntent_r(fp, &mnt, buf, sizeof(buf)) == NULL) - break; + while (1) { + if (getmntent_r(fp, &mnt, buf, sizeof(buf)) == NULL) + break; - if (!llapi_is_lustre_mnt(&mnt)) - continue; + if (!llapi_is_lustre_mnt(&mnt)) + continue; - if ((want & WANT_INDEX) && (idx++ != index)) - continue; + if ((want & WANT_INDEX) && (idx++ != index)) + continue; - mntlen = strlen(mnt.mnt_dir); + mntlen = strlen(mnt.mnt_dir); ptr = strchr(mnt.mnt_fsname, '/'); while (ptr && *ptr == '/') ptr++; - /* thanks to the call to llapi_is_lustre_mnt() above, + /* + * thanks to the call to llapi_is_lustre_mnt() above, * we are sure that mnt.mnt_fsname contains ":/", - * so ptr should never be NULL */ + * so ptr should never be NULL + */ if (ptr == NULL) continue; ptr_end = ptr; @@ -1184,32 +1327,37 @@ int get_root_path(int want, char *fsname, int *outfd, char *path, int index) ptr_end++; /* Check the fsname for a match, if given */ - if (!(want & WANT_FSNAME) && fsname != NULL && - (strlen(fsname) > 0) && - (strncmp(ptr, fsname, ptr_end - ptr) != 0)) - continue; + mountlen = ptr_end - ptr; + if (!(want & WANT_FSNAME) && fsname != NULL && + (fsnamelen = strlen(fsname)) > 0 && + (fsnamelen != mountlen || + (strncmp(ptr, fsname, mountlen) != 0))) + continue; - /* If the path isn't set return the first one we find */ + /* If the path isn't set return the first one we find */ if (path == NULL || strlen(path) == 0) { - strncpy(mntdir, mnt.mnt_dir, strlen(mnt.mnt_dir)); - mntdir[strlen(mnt.mnt_dir)] = '\0'; + strncpy(mntdir, mnt.mnt_dir, sizeof(mntdir) - 1); + mntdir[sizeof(mntdir) - 1] = '\0'; if ((want & WANT_FSNAME) && fsname != NULL) { - strncpy(fsname, ptr, ptr_end - ptr); - fsname[ptr_end - ptr] = '\0'; + strncpy(fsname, ptr, mountlen); + fsname[mountlen] = '\0'; } rc = 0; break; /* Otherwise find the longest matching path */ - } else if ((strlen(path) >= mntlen) && (mntlen >= len) && + } else if ((strlen(path) >= mntlen) && (strncmp(mnt.mnt_dir, path, mntlen) == 0)) { - strncpy(mntdir, mnt.mnt_dir, strlen(mnt.mnt_dir)); - mntdir[strlen(mnt.mnt_dir)] = '\0'; - len = mntlen; + /* check the path format */ + if (strlen(path) > mntlen && path[mntlen] != '/') + continue; + strncpy(mntdir, mnt.mnt_dir, sizeof(mntdir) - 1); + mntdir[sizeof(mntdir) - 1] = '\0'; if ((want & WANT_FSNAME) && fsname != NULL) { - strncpy(fsname, ptr, ptr_end - ptr); - fsname[ptr_end - ptr] = '\0'; + strncpy(fsname, ptr, mountlen); + fsname[mountlen] = '\0'; } rc = 0; + break; } } endmntent(fp); @@ -1217,16 +1365,15 @@ int get_root_path(int want, char *fsname, int *outfd, char *path, int index) /* Found it */ if (rc == 0) { if ((want & WANT_PATH) && path != NULL) { - strncpy(path, mntdir, strlen(mntdir)); - path[strlen(mntdir)] = '\0'; + strncpy(path, mntdir, mntlen); + path[mntlen] = '\0'; } if (want & WANT_FD) { fd = open(mntdir, O_RDONLY | O_DIRECTORY | O_NONBLOCK); if (fd < 0) { rc = -errno; llapi_error(LLAPI_MSG_ERROR, rc, - "cannot open '%s': %s", mntdir, - strerror(-rc)); + "cannot open '%s'", mntdir); } else { *outfd = fd; @@ -1252,29 +1399,30 @@ int get_root_path(int want, char *fsname, int *outfd, char *path, int index) * See function lfs_osts in lfs.c for an example of the index use. */ int llapi_search_mounts(const char *pathname, int index, char *mntdir, - char *fsname) + char *fsname) { - int want = WANT_PATH, idx = -1; + int want = WANT_PATH, idx = -1; - if (!pathname || pathname[0] == '\0') { - want |= WANT_INDEX; - idx = index; - } else - strcpy(mntdir, pathname); + if (!pathname || pathname[0] == '\0') { + want |= WANT_INDEX; + idx = index; + } else { + strcpy(mntdir, pathname); + } - if (fsname) - want |= WANT_FSNAME; - return get_root_path(want, fsname, NULL, mntdir, idx); + if (fsname) + want |= WANT_FSNAME; + return get_root_path(want, fsname, NULL, mntdir, idx); } /* Given a path, find the corresponding Lustre fsname */ int llapi_search_fsname(const char *pathname, char *fsname) { - char *path; - int rc; + char *path; + int rc; - path = realpath(pathname, NULL); - if (path == NULL) { + path = realpath(pathname, NULL); + if (path == NULL) { char tmp[PATH_MAX - 1]; char buf[PATH_MAX]; char *ptr; @@ -1282,10 +1430,12 @@ int llapi_search_fsname(const char *pathname, char *fsname) tmp[0] = '\0'; buf[0] = '\0'; if (pathname[0] != '/') { - /* Need an absolute path, but realpath() only works for + /* + * 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. */ + * case the relative pathname contains ".." in it. + */ char realpath[PATH_MAX - 1]; if (getcwd(realpath, sizeof(realpath) - 2) == NULL) { @@ -1340,41 +1490,12 @@ int llapi_search_fsname(const char *pathname, char *fsname) int llapi_search_rootpath(char *pathname, const char *fsname) { - return get_root_path(WANT_PATH, (char *)fsname, NULL, pathname, -1); -} - -int llapi_getname(const char *path, char *buf, size_t size) -{ - struct obd_uuid uuid_buf; - char *uuid = uuid_buf.uuid; - char *cfg_instance; - int rc, len, fsname_len; - - memset(&uuid_buf, 0, sizeof(uuid_buf)); - rc = llapi_file_get_lov_uuid(path, &uuid_buf); - if (rc) - return rc; - /* - * We want to turn testfs-clilov-ffff88002738bc00 into - * testfs-ffff88002738bc00 in a portable way that doesn't depend - * on what is after "-clilov-" as it may change in the future. - * Unfortunately, the "fsname" part may contain a dash, so we - * can't just skip to the first dash, and the "instance" may be a - * UUID in the future, so we can't necessarily go to the last dash. + * pathname can be used as an argument by get_root_path(), + * clear it for safety */ - cfg_instance = strstr(uuid, "-clilov-"); - if (!cfg_instance) - return -EINVAL; - - fsname_len = cfg_instance - uuid; - cfg_instance += strlen("-clilov-"); - len = snprintf(buf, size, "%.*s-%s", fsname_len, uuid, cfg_instance); - - if (len >= size) - rc = -ENAMETOOLONG; - - return rc; + pathname[0] = 0; + return get_root_path(WANT_PATH, (char *)fsname, NULL, pathname, -1); } /** @@ -1389,7 +1510,7 @@ int llapi_getname(const char *path, char *buf, size_t size) * \retval -error failure */ int llapi_get_poolmembers(const char *poolname, char **members, - int list_size, char *buffer, int buffer_size) + int list_size, char *buffer, int buffer_size) { char fsname[PATH_MAX]; char *pool, *tmp; @@ -1432,31 +1553,31 @@ int llapi_get_poolmembers(const char *poolname, char **members, return rc; } - rc = 0; - while (fgets(buf, sizeof(buf), fd) != NULL) { - if (nb_entries >= list_size) { - rc = -EOVERFLOW; - break; - } + rc = 0; + while (fgets(buf, sizeof(buf), fd) != NULL) { + if (nb_entries >= list_size) { + rc = -EOVERFLOW; + break; + } buf[sizeof(buf) - 1] = '\0'; - /* remove '\n' */ - tmp = strchr(buf, '\n'); - if (tmp != NULL) - *tmp='\0'; - if (used + strlen(buf) + 1 > buffer_size) { - rc = -EOVERFLOW; - break; - } - - strcpy(buffer + used, buf); - members[nb_entries] = buffer + used; - used += strlen(buf) + 1; - nb_entries++; - rc = nb_entries; - } - - fclose(fd); - return rc; + /* remove '\n' */ + tmp = strchr(buf, '\n'); + if (tmp != NULL) + *tmp = '\0'; + if (used + strlen(buf) + 1 > buffer_size) { + rc = -EOVERFLOW; + break; + } + + strcpy(buffer + used, buf); + members[nb_entries] = buffer + used; + used += strlen(buf) + 1; + nb_entries++; + rc = nb_entries; + } + + fclose(fd); + return rc; } /** @@ -1471,49 +1592,47 @@ int llapi_get_poolmembers(const char *poolname, char **members, * \retval -error failure */ int llapi_get_poollist(const char *name, char **poollist, int list_size, - char *buffer, int buffer_size) + char *buffer, int buffer_size) { - char rname[PATH_MAX]; glob_t pathname; char *fsname; - char *ptr; - DIR *dir; + char *ptr; + DIR *dir; struct dirent *pool; - int rc = 0; - unsigned int nb_entries = 0; - unsigned int used = 0; - unsigned int i; + int rc = 0; + unsigned int nb_entries = 0; + unsigned int used = 0; + unsigned int i; /* initialize output array */ - for (i = 0; i < list_size; i++) - poollist[i] = NULL; - - /* is name a pathname ? */ - ptr = strchr(name, '/'); - if (ptr != NULL) { - /* only absolute pathname is supported */ - if (*name != '/') - return -EINVAL; - - if (!realpath(name, rname)) { - rc = -errno; - llapi_error(LLAPI_MSG_ERROR, rc, "invalid path '%s'", - name); - return rc; - } - - fsname = strdup(rname); + for (i = 0; i < list_size; i++) + poollist[i] = NULL; + + /* is name a pathname ? */ + ptr = strchr(name, '/'); + if (ptr != NULL) { + char fsname_buf[MAXNAMLEN]; + + /* We will need fsname for printing later */ + rc = llapi_getname(name, fsname_buf, sizeof(fsname_buf)); + if (rc) + return rc; + + ptr = strrchr(fsname_buf, '-'); + if (ptr) + *ptr = '\0'; + + fsname = strdup(fsname_buf); if (!fsname) return -ENOMEM; - - rc = poolpath(&pathname, NULL, rname); } else { /* name is FSNAME */ fsname = strdup(name); if (!fsname) return -ENOMEM; - rc = poolpath(&pathname, fsname, NULL); } + + rc = poolpath(&pathname, fsname, NULL); if (rc != 0) { llapi_error(LLAPI_MSG_ERROR, rc, "Lustre filesystem '%s' not found", name); @@ -1537,17 +1656,17 @@ int llapi_get_poollist(const char *name, char **poollist, int list_size, goto free_dir; } - /* ignore . and .. */ + /* ignore . and .. */ if (!strcmp(pool->d_name, ".") || !strcmp(pool->d_name, "..")) - continue; + continue; - /* check output bounds */ + /* check output bounds */ if (nb_entries >= list_size) { rc = -EOVERFLOW; goto free_dir_no_msg; } - /* +2 for '.' and final '\0' */ + /* +2 for '.' and final '\0' */ if (used + strlen(pool->d_name) + strlen(fsname) + 2 > buffer_size) { rc = -EOVERFLOW; @@ -1555,9 +1674,9 @@ int llapi_get_poollist(const char *name, char **poollist, int list_size, } sprintf(buffer + used, "%s.%s", fsname, pool->d_name); - poollist[nb_entries] = buffer + used; + poollist[nb_entries] = buffer + used; used += strlen(pool->d_name) + strlen(fsname) + 2; - nb_entries++; + nb_entries++; } while (1); free_dir: @@ -1579,8 +1698,10 @@ free_path: /* 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) */ + /* + * 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; @@ -1606,40 +1727,42 @@ int llapi_poollist(const char *name) 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 - * allocated space. */ + /* + * Allocate space for each fsname-OST0000_UUID, 1 per OST, + * and also an array to store the pointers for all that + * allocated space. + */ retry_get_pools: - bufsize = sizeof(struct obd_uuid) * obdcount; - buffer = realloc(tmp, bufsize + sizeof(*list) * obdcount); - if (buffer == NULL) { - rc = -ENOMEM; - goto err; - } - list = (char **) (buffer + bufsize); - - if (!poolname) { - /* name is a path or fsname */ - nb = llapi_get_poollist(name, list, obdcount, - buffer, bufsize); - } else { - /* name is a pool name (.) */ - nb = llapi_get_poolmembers(name, list, obdcount, - buffer, bufsize); - } - - if (nb == -EOVERFLOW) { - obdcount *= 2; - tmp = buffer; - goto retry_get_pools; - } - - for (i = 0; i < nb; i++) - llapi_printf(LLAPI_MSG_NORMAL, "%s\n", list[i]); - rc = (nb < 0 ? nb : 0); + bufsize = sizeof(struct obd_uuid) * obdcount; + buffer = realloc(tmp, bufsize + sizeof(*list) * obdcount); + if (buffer == NULL) { + rc = -ENOMEM; + goto err; + } + list = (char **) (buffer + bufsize); + + if (!poolname) { + /* name is a path or fsname */ + nb = llapi_get_poollist(name, list, obdcount, + buffer, bufsize); + } else { + /* name is a pool name (.) */ + nb = llapi_get_poolmembers(name, list, obdcount, + buffer, bufsize); + } + + if (nb == -EOVERFLOW) { + obdcount *= 2; + tmp = buffer; + goto retry_get_pools; + } + + for (i = 0; i < nb; i++) + llapi_printf(LLAPI_MSG_NORMAL, "%s\n", list[i]); + rc = (nb < 0 ? nb : 0); err: - if (buffer) - free(buffer); + if (buffer) + free(buffer); if (fsname != NULL && type == FILTER_BY_FS_NAME) free(fsname); return rc; @@ -1648,7 +1771,28 @@ err: typedef int (semantic_func_t)(char *path, DIR *parent, DIR **d, void *data, struct dirent64 *de); -#define OBD_NOT_FOUND (-1) +#define OBD_NOT_FOUND (-1) + +static void find_param_fini(struct find_param *param) +{ + if (param->fp_migrate) + return; + + if (param->fp_obd_indexes) { + free(param->fp_obd_indexes); + param->fp_obd_indexes = NULL; + } + + if (param->fp_lmd) { + free(param->fp_lmd); + param->fp_lmd = NULL; + } + + if (param->fp_lmv_md) { + free(param->fp_lmv_md); + param->fp_lmv_md = NULL; + } +} static int common_param_init(struct find_param *param, char *path) { @@ -1665,10 +1809,11 @@ static int common_param_init(struct find_param *param, char *path) lum_size = PATH_MAX + 1; param->fp_lum_size = lum_size; - param->fp_lmd = calloc(1, sizeof(lstat_t) + lum_size); + param->fp_lmd = calloc(1, offsetof(typeof(*param->fp_lmd), lmd_lmm) + + lum_size); if (param->fp_lmd == NULL) { llapi_error(LLAPI_MSG_ERROR, -ENOMEM, - "error: allocation of %zu bytes for ioctl", + "error: allocate %zu bytes for layout failed", sizeof(lstat_t) + param->fp_lum_size); return -ENOMEM; } @@ -1682,6 +1827,7 @@ static int common_param_init(struct find_param *param, char *path) "error: allocation of %d bytes for ioctl", lmv_user_md_size(param->fp_lmv_stripe_count, LMV_USER_MAGIC_SPECIFIC)); + find_param_fini(param); return -ENOMEM; } @@ -1692,27 +1838,12 @@ static int common_param_init(struct find_param *param, char *path) return 0; } -static void find_param_fini(struct find_param *param) -{ - if (param->fp_migrate) - return; - - if (param->fp_obd_indexes) - free(param->fp_obd_indexes); - - if (param->fp_lmd) - free(param->fp_lmd); - - if (param->fp_lmv_md) - free(param->fp_lmv_md); -} - static int cb_common_fini(char *path, DIR *parent, DIR **dirp, void *data, struct dirent64 *de) { struct find_param *param = data; - param->fp_depth--; + param->fp_depth--; return 0; } @@ -1750,7 +1881,26 @@ again: int stripe_count; int lmv_size; - stripe_count = (__u32)param->fp_lmv_md->lum_stripe_count; + /* if foreign LMV case, fake stripes number */ + if (param->fp_lmv_md->lum_magic == LMV_MAGIC_FOREIGN) { + struct lmv_foreign_md *lfm; + + lfm = (struct lmv_foreign_md *)param->fp_lmv_md; + if (lfm->lfm_length < XATTR_SIZE_MAX - + offsetof(typeof(*lfm), lfm_value)) { + uint32_t size = lfm->lfm_length + + offsetof(typeof(*lfm), lfm_value); + + stripe_count = lmv_foreign_to_md_stripes(size); + } else { + llapi_error(LLAPI_MSG_ERROR, -EINVAL, + "error: invalid %d foreign size returned from ioctl", + lfm->lfm_length); + return -EINVAL; + } + } else { + stripe_count = param->fp_lmv_md->lum_stripe_count; + } if (stripe_count <= param->fp_lmv_stripe_count) return ret; @@ -1771,11 +1921,74 @@ again: return ret; } -int get_lmd_info_fd(char *path, int parent_fd, int dir_fd, +static void convert_lmd_statx(struct lov_user_mds_data *lmd_v2, lstat_t *st, + bool strict) +{ + memset(&lmd_v2->lmd_stx, 0, sizeof(lmd_v2->lmd_stx)); + lmd_v2->lmd_stx.stx_blksize = st->st_blksize; + lmd_v2->lmd_stx.stx_nlink = st->st_nlink; + lmd_v2->lmd_stx.stx_uid = st->st_uid; + lmd_v2->lmd_stx.stx_gid = st->st_gid; + lmd_v2->lmd_stx.stx_mode = st->st_mode; + lmd_v2->lmd_stx.stx_ino = st->st_ino; + lmd_v2->lmd_stx.stx_size = st->st_size; + lmd_v2->lmd_stx.stx_blocks = st->st_blocks; + lmd_v2->lmd_stx.stx_atime.tv_sec = st->st_atime; + lmd_v2->lmd_stx.stx_ctime.tv_sec = st->st_ctime; + lmd_v2->lmd_stx.stx_mtime.tv_sec = st->st_mtime; + lmd_v2->lmd_stx.stx_rdev_major = major(st->st_rdev); + lmd_v2->lmd_stx.stx_rdev_minor = minor(st->st_rdev); + lmd_v2->lmd_stx.stx_dev_major = major(st->st_dev); + lmd_v2->lmd_stx.stx_dev_minor = minor(st->st_dev); + lmd_v2->lmd_stx.stx_mask |= STATX_BASIC_STATS; + + lmd_v2->lmd_flags = 0; + if (strict) { + lmd_v2->lmd_flags |= OBD_MD_FLSIZE | OBD_MD_FLBLOCKS; + } else { + lmd_v2->lmd_stx.stx_mask &= ~(STATX_SIZE | STATX_BLOCKS); + if (lmd_v2->lmd_stx.stx_size) + lmd_v2->lmd_flags |= OBD_MD_FLLAZYSIZE; + if (lmd_v2->lmd_stx.stx_blocks) + lmd_v2->lmd_flags |= OBD_MD_FLLAZYBLOCKS; + } + lmd_v2->lmd_flags |= OBD_MD_FLATIME | OBD_MD_FLMTIME | OBD_MD_FLCTIME | + OBD_MD_FLBLKSZ | OBD_MD_FLMODE | OBD_MD_FLTYPE | + OBD_MD_FLUID | OBD_MD_FLGID | OBD_MD_FLNLINK | + OBD_MD_FLRDEV; + +} + +static int convert_lmdbuf_v1v2(void *lmdbuf, int lmdlen) +{ + struct lov_user_mds_data_v1 *lmd_v1 = lmdbuf; + struct lov_user_mds_data *lmd_v2 = lmdbuf; + lstat_t st; + int size; + + size = lov_comp_md_size((struct lov_comp_md_v1 *)&lmd_v1->lmd_lmm); + if (size < 0) + return size; + + if (lmdlen < sizeof(lmd_v1->lmd_st) + size) + return -EOVERFLOW; + + st = lmd_v1->lmd_st; + memmove(&lmd_v2->lmd_lmm, &lmd_v1->lmd_lmm, + lmdlen - (&lmd_v2->lmd_lmm - &lmd_v1->lmd_lmm)); + convert_lmd_statx(lmd_v2, &st, false); + lmd_v2->lmd_lmmsize = 0; + lmd_v2->lmd_padding = 0; + + return 0; +} + +int get_lmd_info_fd(const char *path, int parent_fd, int dir_fd, void *lmdbuf, int lmdlen, enum get_lmd_info_type type) { struct lov_user_mds_data *lmd = lmdbuf; - lstat_t *st = &lmd->lmd_st; + static bool use_old_ioctl; + unsigned long cmd; int ret = 0; if (parent_fd < 0 && dir_fd < 0) @@ -1784,17 +1997,32 @@ int get_lmd_info_fd(char *path, int parent_fd, int dir_fd, return -EINVAL; if (dir_fd >= 0) { - /* LL_IOC_MDC_GETINFO operates on the current directory inode + /* + * LL_IOC_MDC_GETINFO operates on the current directory inode * and returns struct lov_user_mds_data, while * LL_IOC_LOV_GETSTRIPE returns only struct lov_user_md. */ - ret = ioctl(dir_fd, type == GET_LMD_INFO ? LL_IOC_MDC_GETINFO : - LL_IOC_LOV_GETSTRIPE, - lmdbuf); + if (type == GET_LMD_INFO) + cmd = use_old_ioctl ? LL_IOC_MDC_GETINFO_OLD : + LL_IOC_MDC_GETINFO; + else + cmd = LL_IOC_LOV_GETSTRIPE; + +retry_getinfo: + ret = ioctl(dir_fd, cmd, lmdbuf); + if (ret < 0 && errno == ENOTTY && cmd == LL_IOC_MDC_GETINFO) { + cmd = LL_IOC_MDC_GETINFO_OLD; + use_old_ioctl = true; + goto retry_getinfo; + } + + if (cmd == LL_IOC_MDC_GETINFO_OLD && !ret) + ret = convert_lmdbuf_v1v2(lmdbuf, lmdlen); } else if (parent_fd >= 0) { - char *fname = strrchr(path, '/'); + const char *fname = strrchr(path, '/'); - /* IOC_MDC_GETFILEINFO takes as input the filename (relative to + /* + * IOC_MDC_GETFILEINFO takes as input the filename (relative to * the parent directory) and returns struct lov_user_mds_data, * while IOC_MDC_GETFILESTRIPE returns only struct lov_user_md. * @@ -1812,24 +2040,50 @@ int get_lmd_info_fd(char *path, int parent_fd, int dir_fd, errno = -ret; else if (ret >= lmdlen || ret++ == 0) errno = EINVAL; - else - ret = ioctl(parent_fd, type == GET_LMD_INFO ? - IOC_MDC_GETFILEINFO : - IOC_MDC_GETFILESTRIPE, lmdbuf); + else { + if (type == GET_LMD_INFO) + cmd = use_old_ioctl ? IOC_MDC_GETFILEINFO_OLD : + IOC_MDC_GETFILEINFO; + else + cmd = IOC_MDC_GETFILESTRIPE; + +retry_getfileinfo: + ret = ioctl(parent_fd, cmd, lmdbuf); + if (ret < 0 && errno == ENOTTY && + cmd == IOC_MDC_GETFILEINFO) { + cmd = IOC_MDC_GETFILEINFO_OLD; + use_old_ioctl = true; + goto retry_getfileinfo; + } + + if (cmd == IOC_MDC_GETFILEINFO_OLD && !ret) + ret = convert_lmdbuf_v1v2(lmdbuf, lmdlen); + } } if (ret && type == GET_LMD_INFO) { if (errno == ENOTTY) { - /* ioctl is not supported, it is not a lustre fs. + lstat_t st; + + /* + * ioctl is not supported, it is not a lustre fs. * Do the regular lstat(2) instead. */ - ret = lstat_f(path, st); + ret = lstat_f(path, &st); if (ret) { ret = -errno; llapi_error(LLAPI_MSG_ERROR, ret, "error: %s: lstat failed for %s", __func__, path); } + + convert_lmd_statx(lmd, &st, true); + /* + * It may be wrong to set use_old_ioctl with true as + * the file is not a lustre fs. So reset it with false + * directly here. + */ + use_old_ioctl = false; } else if (errno == ENOENT) { ret = -errno; llapi_error(LLAPI_MSG_WARN, ret, @@ -1873,20 +2127,20 @@ static int llapi_semantic_traverse(char *path, int size, DIR *parent, ret = 0; len = strlen(path); - d = opendir(path); - if (!d && errno != ENOTDIR) { - ret = -errno; - llapi_error(LLAPI_MSG_ERROR, ret, "%s: Failed to open '%s'", - __func__, path); - return ret; - } else if (!d && !parent) { - /* ENOTDIR. Open the parent dir. */ - p = opendir_parent(path); + d = opendir(path); + if (!d && errno != ENOTDIR) { + ret = -errno; + llapi_error(LLAPI_MSG_ERROR, ret, "%s: Failed to open '%s'", + __func__, path); + return ret; + } else if (!d && !parent) { + /* ENOTDIR. Open the parent dir. */ + p = opendir_parent(path); if (!p) { ret = -errno; goto out; } - } + } if (sem_init && (ret = sem_init(path, parent ?: p, &d, data, de))) goto err; @@ -1911,24 +2165,24 @@ static int llapi_semantic_traverse(char *path, int size, DIR *parent, strcat(path, dent->d_name); if (dent->d_type == DT_UNKNOWN) { - lstat_t *st = ¶m->fp_lmd->lmd_st; + struct lov_user_mds_data *lmd = param->fp_lmd; - rc = get_lmd_info(path, d, NULL, param->fp_lmd, + rc = get_lmd_info(path, d, NULL, lmd, param->fp_lum_size, GET_LMD_INFO); if (rc == 0) - dent->d_type = IFTODT(st->st_mode); + dent->d_type = IFTODT(lmd->lmd_stx.stx_mode); else if (ret == 0) ret = rc; if (rc == -ENOENT) continue; } - switch (dent->d_type) { - case DT_UNKNOWN: - llapi_err_noerrno(LLAPI_MSG_ERROR, - "error: %s: '%s' is UNKNOWN type %d", - __func__, dent->d_name, dent->d_type); - break; + switch (dent->d_type) { + case DT_UNKNOWN: + llapi_err_noerrno(LLAPI_MSG_ERROR, + "error: %s: '%s' is UNKNOWN type %d", + __func__, dent->d_name, dent->d_type); + break; case DT_DIR: rc = llapi_semantic_traverse(path, size, d, sem_init, sem_fini, data, dent); @@ -1946,52 +2200,52 @@ static int llapi_semantic_traverse(char *path, int size, DIR *parent, } if (sem_fini && rc == 0) sem_fini(path, d, NULL, data, dent); - } - } + } + } out: - path[len] = 0; + path[len] = 0; if (sem_fini) sem_fini(path, parent, &d, data, de); err: - if (d) - closedir(d); - if (p) - closedir(p); + if (d) + closedir(d); + if (p) + closedir(p); return ret; } static int param_callback(char *path, semantic_func_t sem_init, - semantic_func_t sem_fini, struct find_param *param) + semantic_func_t sem_fini, struct find_param *param) { - int ret, len = strlen(path); - char *buf; + int ret, len = strlen(path); + char *buf; - if (len > PATH_MAX) { - ret = -EINVAL; - llapi_error(LLAPI_MSG_ERROR, ret, - "Path name '%s' is too long", path); - return ret; - } + if (len > PATH_MAX) { + ret = -EINVAL; + llapi_error(LLAPI_MSG_ERROR, ret, + "Path name '%s' is too long", path); + return ret; + } - buf = (char *)malloc(PATH_MAX + 1); - if (!buf) - return -ENOMEM; + buf = (char *)malloc(PATH_MAX + 1); + if (!buf) + return -ENOMEM; snprintf(buf, PATH_MAX + 1, "%s", path); - ret = common_param_init(param, buf); - if (ret) - goto out; + ret = common_param_init(param, buf); + if (ret) + goto out; param->fp_depth = 0; - ret = llapi_semantic_traverse(buf, PATH_MAX + 1, NULL, sem_init, - sem_fini, param, NULL); + ret = llapi_semantic_traverse(buf, PATH_MAX + 1, NULL, sem_init, + sem_fini, param, NULL); out: - find_param_fini(param); - free(buf); - return ret < 0 ? ret : 0; + find_param_fini(param); + free(buf); + return ret < 0 ? ret : 0; } int llapi_file_fget_lov_uuid(int fd, struct obd_uuid *lov_name) @@ -2007,12 +2261,13 @@ int llapi_file_fget_lov_uuid(int fd, struct obd_uuid *lov_name) int llapi_file_fget_lmv_uuid(int fd, struct obd_uuid *lov_name) { - int rc = ioctl(fd, OBD_IOC_GETMDNAME, lov_name); - if (rc) { - rc = -errno; - llapi_error(LLAPI_MSG_ERROR, rc, "error: can't get lmv name."); - } - return rc; + int rc = ioctl(fd, OBD_IOC_GETMDNAME, lov_name); + + if (rc) { + rc = -errno; + llapi_error(LLAPI_MSG_ERROR, rc, "error: can't get lmv name."); + } + return rc; } int llapi_file_get_lov_uuid(const char *path, struct obd_uuid *lov_uuid) @@ -2050,8 +2305,8 @@ int llapi_file_get_lmv_uuid(const char *path, struct obd_uuid *lov_uuid) } enum tgt_type { - LOV_TYPE = 1, - LMV_TYPE + LOV_TYPE = 1, + LMV_TYPE }; /* @@ -2061,7 +2316,7 @@ enum tgt_type { * the ost_count set to number of available obd uuids. */ static int llapi_get_target_uuids(int fd, struct obd_uuid *uuidp, - int *ost_count, enum tgt_type type) + int *ost_count, enum tgt_type type) { char buf[PATH_MAX], format[32]; int rc = 0, index = 0; @@ -2096,15 +2351,15 @@ static int llapi_get_target_uuids(int fd, struct obd_uuid *uuidp, while (fgets(buf, sizeof(buf), fp) != NULL) { if (uuidp && (index < *ost_count)) { if (sscanf(buf, format, &index, uuidp[index].uuid) < 2) - break; - } - index++; - } + break; + } + index++; + } - fclose(fp); + fclose(fp); - if (uuidp && (index > *ost_count)) - rc = -EOVERFLOW; + if (uuidp && (index > *ost_count)) + rc = -EOVERFLOW; *ost_count = index; free_param: @@ -2114,7 +2369,7 @@ free_param: int llapi_lov_get_uuids(int fd, struct obd_uuid *uuidp, int *ost_count) { - return llapi_get_target_uuids(fd, uuidp, ost_count, LOV_TYPE); + return llapi_get_target_uuids(fd, uuidp, ost_count, LOV_TYPE); } int llapi_get_obd_count(char *mnt, int *count, int is_mdt) @@ -2138,31 +2393,36 @@ int llapi_get_obd_count(char *mnt, int *count, int is_mdt) return rc; } -/* Check if user specified value matches a real uuid. Ignore _UUID, +/* + * Check if user specified value matches a real uuid. Ignore _UUID, * -osc-4ba41334, other trailing gunk in comparison. * @param real_uuid ends in "_UUID" * @param search_uuid may or may not end in "_UUID" */ int llapi_uuid_match(char *real_uuid, char *search_uuid) { - int cmplen = strlen(real_uuid); - int searchlen = strlen(search_uuid); + int cmplen = strlen(real_uuid); + int searchlen = strlen(search_uuid); - if (cmplen > 5 && strcmp(real_uuid + cmplen - 5, "_UUID") == 0) - cmplen -= 5; - if (searchlen > 5 && strcmp(search_uuid + searchlen - 5, "_UUID") == 0) - searchlen -= 5; + if (cmplen > 5 && strcmp(real_uuid + cmplen - 5, "_UUID") == 0) + cmplen -= 5; + if (searchlen > 5 && strcmp(search_uuid + searchlen - 5, "_UUID") == 0) + searchlen -= 5; - /* The UUIDs may legitimately be different lengths, if - * the system was upgraded from an older version. */ - if (cmplen != searchlen) - return 0; + /* + * The UUIDs may legitimately be different lengths, if + * the system was upgraded from an older version. + */ + if (cmplen != searchlen) + return 0; - return (strncmp(search_uuid, real_uuid, cmplen) == 0); + return (strncmp(search_uuid, real_uuid, cmplen) == 0); } -/* Here, param->fp_obd_uuid points to a single obduuid, the index of which is - * returned in param->fp_obd_index */ +/* + * Here, param->fp_obd_uuid points to a single obduuid, the index of which is + * returned in param->fp_obd_index + */ static int setup_obd_uuid(int fd, char *dname, struct find_param *param) { struct obd_uuid obd_uuid; @@ -2234,7 +2494,7 @@ static int setup_obd_uuid(int fd, char *dname, struct find_param *param) } param->fp_obds_printed = 1; - fclose(fp); + fclose(fp); if (param->fp_obd_uuid && (param->fp_obd_index == OBD_NOT_FOUND)) { llapi_err_noerrno(LLAPI_MSG_ERROR, @@ -2247,18 +2507,20 @@ free_param: return rc; } -/* In this case, param->fp_obd_uuid will be an array of obduuids and +/* + * In this case, param->fp_obd_uuid will be an array of obduuids and * obd index for all these obduuids will be returned in - * param->fp_obd_indexes */ + * param->fp_obd_indexes + */ static int setup_indexes(DIR *dir, char *path, struct obd_uuid *obduuids, - int num_obds, int **obdindexes, int *obdindex, - enum tgt_type type) + int num_obds, int **obdindexes, int *obdindex, + enum tgt_type type) { int ret, obdcount, obd_valid = 0, obdnum; long i; - struct obd_uuid *uuids = NULL; - char buf[16]; - int *indexes; + struct obd_uuid *uuids = NULL; + char buf[16]; + int *indexes; if (type == LOV_TYPE) ret = get_param_lov(path, "numobd", buf, sizeof(buf)); @@ -2291,30 +2553,30 @@ retry_get_uuids: goto out_free; } - indexes = malloc(num_obds * sizeof(*obdindex)); - if (indexes == NULL) { - ret = -ENOMEM; - goto out_free; - } - - for (obdnum = 0; obdnum < num_obds; obdnum++) { - char *end = NULL; - - /* The user may have specified a simple index */ - i = strtol(obduuids[obdnum].uuid, &end, 0); - if (end && *end == '\0' && i < obdcount) { - indexes[obdnum] = i; - obd_valid++; - } else { - for (i = 0; i < obdcount; i++) { - if (llapi_uuid_match(uuids[i].uuid, - obduuids[obdnum].uuid)) { - indexes[obdnum] = i; - obd_valid++; - break; - } - } - } + indexes = malloc(num_obds * sizeof(*obdindex)); + if (indexes == NULL) { + ret = -ENOMEM; + goto out_free; + } + + for (obdnum = 0; obdnum < num_obds; obdnum++) { + char *end = NULL; + + /* The user may have specified a simple index */ + i = strtol(obduuids[obdnum].uuid, &end, 0); + if (end && *end == '\0' && i < obdcount) { + indexes[obdnum] = i; + obd_valid++; + } else { + for (i = 0; i < obdcount; i++) { + if (llapi_uuid_match(uuids[i].uuid, + obduuids[obdnum].uuid)) { + indexes[obdnum] = i; + obd_valid++; + break; + } + } + } if (i >= obdcount) { indexes[obdnum] = OBD_NOT_FOUND; llapi_err_noerrno(LLAPI_MSG_ERROR, @@ -2324,22 +2586,22 @@ retry_get_uuids: } } - if (obd_valid == 0) - *obdindex = OBD_NOT_FOUND; - else - *obdindex = obd_valid; + if (obd_valid == 0) + *obdindex = OBD_NOT_FOUND; + else + *obdindex = obd_valid; - *obdindexes = indexes; + *obdindexes = indexes; out_free: - if (uuids) - free(uuids); + if (uuids) + free(uuids); - return ret; + return ret; } static int setup_target_indexes(DIR *dir, char *path, struct find_param *param) { - int ret = 0; + int ret = 0; if (param->fp_mdt_uuid) { ret = setup_indexes(dir, path, param->fp_mdt_uuid, @@ -2385,9 +2647,9 @@ int llapi_ostlist(char *path, struct find_param *param) * using pathname. */ static int sattr_get_defaults(const char *const fsname, - unsigned int *scount, - unsigned int *ssize, - unsigned int *soffset) + unsigned int *scount, + unsigned int *ssize, + unsigned int *soffset) { char val[PATH_MAX]; int rc; @@ -2429,61 +2691,64 @@ int sattr_cache_get_defaults(const char *const fsname, const char *const pathname, unsigned int *scount, unsigned int *ssize, unsigned int *soffset) { - static struct { - char fsname[PATH_MAX + 1]; - unsigned int stripecount; - unsigned int stripesize; - unsigned int stripeoffset; - } cache = { - .fsname = {'\0'} - }; - - int rc; - char fsname_buf[PATH_MAX + 1]; - unsigned int tmp[3]; - - if (fsname == NULL) { - rc = llapi_search_fsname(pathname, fsname_buf); - if (rc) - return rc; - } else { + static struct { + char fsname[PATH_MAX + 1]; + unsigned int stripecount; + unsigned int stripesize; + unsigned int stripeoffset; + } cache = { + .fsname = {'\0'} + }; + + int rc; + char fsname_buf[PATH_MAX + 1]; + unsigned int tmp[3]; + + if (fsname == NULL) { + rc = llapi_search_fsname(pathname, fsname_buf); + if (rc) + return rc; + } else { snprintf(fsname_buf, sizeof(fsname_buf), "%s", fsname); - } + } 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 - * cache. - */ + /* + * Ensure all 3 sattrs (count, size, and offset) are + * successfully retrieved and stored in tmp before writing to + * cache. + */ rc = sattr_get_defaults(fsname_buf, &tmp[0], &tmp[1], &tmp[2]); - if (rc != 0) - return rc; + if (rc != 0) + return rc; - cache.stripecount = tmp[0]; - cache.stripesize = tmp[1]; - cache.stripeoffset = tmp[2]; + cache.stripecount = tmp[0]; + cache.stripesize = tmp[1]; + cache.stripeoffset = tmp[2]; snprintf(cache.fsname, sizeof(cache.fsname), "%s", fsname_buf); - } + } - if (scount) - *scount = cache.stripecount; - if (ssize) - *ssize = cache.stripesize; - if (soffset) - *soffset = cache.stripeoffset; + if (scount) + *scount = cache.stripecount; + if (ssize) + *ssize = cache.stripesize; + if (soffset) + *soffset = cache.stripeoffset; - return 0; + return 0; } static char *layout2name(__u32 layout_pattern) { - if (layout_pattern == LOV_PATTERN_MDT) + if (layout_pattern & LOV_PATTERN_F_RELEASED) + return "released"; + else if (layout_pattern == LOV_PATTERN_MDT) return "mdt"; else if (layout_pattern == LOV_PATTERN_RAID0) return "raid0"; - else if (layout_pattern == (LOV_PATTERN_RAID0 | LOV_PATTERN_F_RELEASED)) - return "released"; + else if (layout_pattern == + (LOV_PATTERN_RAID0 | LOV_PATTERN_OVERSTRIPING)) + return "raid0,overstriped"; else return "unknown"; } @@ -2494,6 +2759,7 @@ enum lov_dump_flags { LDF_INDENT = 0x0004, LDF_SKIP_OBJS = 0x0008, LDF_YAML = 0x0010, + LDF_EXTENSION = 0x0020, }; static void lov_dump_user_lmm_header(struct lov_user_md *lum, char *path, @@ -2507,6 +2773,7 @@ static void lov_dump_user_lmm_header(struct lov_user_md *lum, char *path, bool indent = flags & LDF_INDENT; bool yaml = flags & LDF_YAML; bool skip_objs = flags & LDF_SKIP_OBJS; + bool extension = flags & LDF_EXTENSION; char *prefix = is_dir ? "" : "lmm_"; char *separator = ""; char *space = indent ? " " : ""; @@ -2540,7 +2807,8 @@ static void lov_dump_user_lmm_header(struct lov_user_md *lum, char *path, if (verbose & ~VERBOSE_DFID) llapi_printf(LLAPI_MSG_NORMAL, "%slmm_fid: ", space); - /* This needs a bit of hand-holding since old 1.x lmm_oi + /* + * This needs a bit of hand-holding since old 1.x lmm_oi * have { oi.oi_id = mds_inum, oi.oi_seq = 0 } and 2.x lmm_oi * have { oi.oi_id = mds_oid, oi.oi_seq = mds_seq } instead of * a real FID. Ideally the 2.x code would have stored this @@ -2556,7 +2824,8 @@ static void lov_dump_user_lmm_header(struct lov_user_md *lum, char *path, * oi_fid fields are in the right order. This is why there are * separate lmm_oi_seq() and lmm_oi_id() routines for this. * - * For newer layout types hopefully this will be a real FID. */ + * For newer layout types hopefully this will be a real FID. + */ seq = lmm_oi_seq(&lum->lmm_oi) == 0 ? lmm_oi_id(&lum->lmm_oi) : lmm_oi_seq(&lum->lmm_oi); oid = lmm_oi_seq(&lum->lmm_oi) == 0 ? @@ -2564,10 +2833,10 @@ static void lov_dump_user_lmm_header(struct lov_user_md *lum, char *path, ver = (__u32)(lmm_oi_id(&lum->lmm_oi) >> 32); if (yaml) llapi_printf(LLAPI_MSG_NORMAL, DFID_NOBRACE"\n", - seq, oid, ver); + (unsigned long long)seq, oid, ver); else llapi_printf(LLAPI_MSG_NORMAL, DFID"\n", - seq, oid, ver); + (unsigned long long)seq, oid, ver); } if (verbose & VERBOSE_STRIPE_COUNT) { @@ -2578,6 +2847,7 @@ static void lov_dump_user_lmm_header(struct lov_user_md *lum, char *path, if (!is_raw && lum->lmm_stripe_count == 0 && lov_pattern(lum->lmm_pattern) != LOV_PATTERN_MDT) { unsigned int scount; + rc = sattr_cache_get_defaults(NULL, path, &scount, NULL, NULL); @@ -2586,16 +2856,15 @@ static void lov_dump_user_lmm_header(struct lov_user_md *lum, char *path, scount); else llapi_error(LLAPI_MSG_ERROR, rc, - "Cannot determine default" - " stripe count."); + "Cannot determine default stripe count."); } else { llapi_printf(LLAPI_MSG_NORMAL, "%d", - lum->lmm_stripe_count == - (typeof(lum->lmm_stripe_count))(-1) - ? -1 : lum->lmm_stripe_count); + extension ? 0 : + (__s16)lum->lmm_stripe_count); } } else { llapi_printf(LLAPI_MSG_NORMAL, "%hd", + extension ? 0 : (__s16)lum->lmm_stripe_count); } if (!yaml && is_dir) @@ -2604,24 +2873,31 @@ static void lov_dump_user_lmm_header(struct lov_user_md *lum, char *path, separator = "\n"; } - if (verbose & VERBOSE_STRIPE_SIZE) { + if (((verbose & VERBOSE_STRIPE_SIZE) && !extension) || + ((verbose & VERBOSE_EXT_SIZE) && extension)) { llapi_printf(LLAPI_MSG_NORMAL, "%s", separator); - if (verbose & ~VERBOSE_STRIPE_SIZE) + if (verbose & ~VERBOSE_EXT_SIZE && extension) + llapi_printf(LLAPI_MSG_NORMAL, "%s%sextension_size: ", + space, prefix); + if (verbose & ~VERBOSE_STRIPE_SIZE && !extension) llapi_printf(LLAPI_MSG_NORMAL, "%s%sstripe_size: ", space, prefix); if (is_dir && !is_raw && lum->lmm_stripe_size == 0) { unsigned int ssize; + rc = sattr_cache_get_defaults(NULL, path, NULL, &ssize, NULL); if (rc == 0) llapi_printf(LLAPI_MSG_NORMAL, "%u", ssize); else llapi_error(LLAPI_MSG_ERROR, rc, - "Cannot determine default" - " stripe size."); + "Cannot determine default stripe size."); } else { - llapi_printf(LLAPI_MSG_NORMAL, "%u", - lum->lmm_stripe_size); + /* Extension size is in KiB */ + llapi_printf(LLAPI_MSG_NORMAL, "%llu", + extension ? + (unsigned long long)(lum->lmm_stripe_size * SEL_UNIT_SIZE) : + (unsigned long long)lum->lmm_stripe_size); } if (!yaml && is_dir) separator = " "; @@ -2757,6 +3033,7 @@ void lov_dump_user_lmm_v1v3(struct lov_user_md *lum, char *pool_name, space, i, idx, PFID(&fid)); } else { char fmt[48]; + sprintf(fmt, "%s%s%s\n", "\t%6u\t%14llu\t%#13llx\t", (fid_seq_is_rsvd(gr) || @@ -2856,14 +3133,12 @@ void lmv_dump_user_lmm(struct lmv_user_md *lum, char *pool_name, if (flags & LMV_HASH_FLAG_MIGRATION) llapi_printf(LLAPI_MSG_NORMAL, ",migrating"); - if (flags & LMV_HASH_FLAG_DEAD) - llapi_printf(LLAPI_MSG_NORMAL, ",dead"); if (flags & LMV_HASH_FLAG_BAD_TYPE) llapi_printf(LLAPI_MSG_NORMAL, ",bad_type"); if (flags & LMV_HASH_FLAG_LOST_LMV) llapi_printf(LLAPI_MSG_NORMAL, ",lost_lmv"); - separator = "\n"; + separator = "\n"; } if (verbose & VERBOSE_OBJID && lum->lum_magic != LMV_USER_MAGIC) { @@ -2874,13 +3149,13 @@ void lmv_dump_user_lmm(struct lmv_user_md *lum, char *pool_name, 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, "%6u\t\t "DFID"\t\t%s\n", idx, PFID(fid), obdindex == idx ? " *" : ""); } - } if ((verbose & VERBOSE_POOL) && pool_name != NULL && @@ -3039,7 +3314,7 @@ static void lov_dump_comp_v1_entry(struct find_param *param, "%4slcme_timestamp: ", " "); if (yaml) { llapi_printf(LLAPI_MSG_NORMAL, "%llu", - entry->lcme_timestamp); + (unsigned long long)entry->lcme_timestamp); } else { time_t stamp = entry->lcme_timestamp; char *date_str = asctime(localtime(&stamp)); @@ -3057,7 +3332,7 @@ static void lov_dump_comp_v1_entry(struct find_param *param, llapi_printf(LLAPI_MSG_NORMAL, "%4slcme_extent.e_start: ", " "); llapi_printf(LLAPI_MSG_NORMAL, "%llu", - entry->lcme_extent.e_start); + (unsigned long long)entry->lcme_extent.e_start); separator = "\n"; } @@ -3070,7 +3345,7 @@ static void lov_dump_comp_v1_entry(struct find_param *param, llapi_printf(LLAPI_MSG_NORMAL, "%s", "EOF"); else llapi_printf(LLAPI_MSG_NORMAL, "%llu", - entry->lcme_extent.e_end); + (unsigned long long)entry->lcme_extent.e_end); separator = "\n"; } @@ -3089,7 +3364,8 @@ static void lov_dump_comp_v1_entry(struct find_param *param, } } -/* Check if the value matches 1 of the given criteria (e.g. --atime +/-N). +/* + * Check if the value matches 1 of the given criteria (e.g. --atime +/-N). * @mds indicates if this is MDS timestamps and there are attributes on OSTs. * * The result is -1 if it does not match, 0 if not yet clear, 1 if matches. @@ -3107,7 +3383,8 @@ static void lov_dump_comp_v1_entry(struct find_param *param, * 9 | file < limit; sign < 0 | ? / -1 | * -------------------------------------- * Note: 5th actually means that the value is within the interval - * (limit - margin, limit]. */ + * (limit - margin, limit]. + */ static int find_value_cmp(unsigned long long file, unsigned long long limit, int sign, int negopt, unsigned long long margin, bool mds) @@ -3258,7 +3535,7 @@ static void lov_dump_comp_v1(struct find_param *param, char *path, struct lov_user_md_v1 *v1; char pool_name[LOV_MAXPOOLNAME + 1]; int obdindex = param->fp_obd_index; - int i, j, match; + int i, j, match, ext; bool obdstripe = false; __u16 mirror_index = 0; __u16 mirror_id = 0; @@ -3355,8 +3632,15 @@ static void lov_dump_comp_v1(struct find_param *param, char *path, */ if (entry->lcme_flags & LCME_FL_INIT) continue; - else - break; + + if (param->fp_verbose & VERBOSE_EXT_SIZE) { + if (entry->lcme_flags & LCME_FL_EXTENSION) + /* moved back below */ + i++; + else + continue; + } + break; } if (entry->lcme_flags & LCME_FL_INIT) { @@ -3386,9 +3670,10 @@ static void lov_dump_comp_v1(struct find_param *param, char *path, objects = lov_v1v3_objects(v1); lov_v1v3_pool_name(v1, pool_name); + ext = entry->lcme_flags & LCME_FL_EXTENSION ? LDF_EXTENSION : 0; lov_dump_user_lmm_v1v3(v1, pool_name, objects, path, obdindex, param->fp_max_depth, param->fp_verbose, - flags); + flags | ext); } if (print_last_init_comp(param)) { /** @@ -3407,9 +3692,11 @@ static void lov_dump_comp_v1(struct find_param *param, char *path, objects = lov_v1v3_objects(v1); lov_v1v3_pool_name(v1, pool_name); + entry = &comp_v1->lcm_entries[i]; + ext = entry->lcme_flags & LCME_FL_EXTENSION ? LDF_EXTENSION : 0; lov_dump_user_lmm_v1v3(v1, pool_name, objects, path, obdindex, param->fp_max_depth, param->fp_verbose, - flags); + flags | ext); } } @@ -3444,13 +3731,14 @@ struct lov_user_mds_data *lov_forge_comp_v1(struct lov_user_mds_data *orig, int lum_size = lov_user_md_size(is_dir ? 0 : lum->lmm_stripe_count, lum->lmm_magic); - new = malloc(sizeof(lstat_t) + lum_off + lum_size); + new = malloc(offsetof(typeof(*new), lmd_lmm) + lum_off + lum_size); if (new == NULL) { llapi_printf(LLAPI_MSG_NORMAL, "out of memory\n"); return new; } - memcpy(new, orig, sizeof(lstat_t)); + memcpy(new, orig, sizeof(new->lmd_stx) + sizeof(new->lmd_flags) + + sizeof(new->lmd_lmmsize)); comp_v1 = (struct lov_comp_md_v1 *)&new->lmd_lmm; comp_v1->lcm_magic = lum->lmm_magic; @@ -3512,6 +3800,84 @@ static void lov_dump_plain_user_lmm(struct find_param *param, char *path, } } +static uint32_t check_foreign_type(uint32_t foreign_type) +{ + uint32_t i; + + for (i = 0; i < LU_FOREIGN_TYPE_UNKNOWN; i++) { + if (lu_foreign_types[i].lft_name == NULL) + break; + if (foreign_type == lu_foreign_types[i].lft_type) + return i; + } + + return LU_FOREIGN_TYPE_UNKNOWN; +} + +static void lov_dump_foreign_lmm(struct find_param *param, char *path, + enum lov_dump_flags flags) +{ + struct lov_foreign_md *lfm = (void *)¶m->fp_lmd->lmd_lmm; + bool yaml = flags & LDF_YAML; + + if (!yaml && param->fp_depth && path) + llapi_printf(LLAPI_MSG_NORMAL, "%s\n", path); + + if (param->fp_verbose & VERBOSE_DETAIL) { + uint32_t type = check_foreign_type(lfm->lfm_type); + + llapi_printf(LLAPI_MSG_NORMAL, "lfm_magic: 0x%08X\n", + lfm->lfm_magic); + llapi_printf(LLAPI_MSG_NORMAL, "lfm_length: %u\n", + lfm->lfm_length); + llapi_printf(LLAPI_MSG_NORMAL, "lfm_type: 0x%08X", + lfm->lfm_type); + if (type < LU_FOREIGN_TYPE_UNKNOWN) + llapi_printf(LLAPI_MSG_NORMAL, " (%s)\n", + lu_foreign_types[type].lft_name); + else + llapi_printf(LLAPI_MSG_NORMAL, " (unknown)\n"); + + llapi_printf(LLAPI_MSG_NORMAL, "lfm_flags: 0x%08X\n", + lfm->lfm_flags); + } + llapi_printf(LLAPI_MSG_NORMAL, "lfm_value: '%.*s'\n", + lfm->lfm_length, lfm->lfm_value); + llapi_printf(LLAPI_MSG_NORMAL, "\n"); +} + +static void lmv_dump_foreign_lmm(struct find_param *param, char *path, + enum lov_dump_flags flags) +{ + struct lmv_foreign_md *lfm = (struct lmv_foreign_md *)param->fp_lmv_md; + bool yaml = flags & LDF_YAML; + + if (!yaml && param->fp_depth && path) + llapi_printf(LLAPI_MSG_NORMAL, "%s\n", path); + + if (param->fp_verbose & VERBOSE_DETAIL) { + uint32_t type = check_foreign_type(lfm->lfm_type); + + llapi_printf(LLAPI_MSG_NORMAL, "lfm_magic: 0x%08X\n", + lfm->lfm_magic); + llapi_printf(LLAPI_MSG_NORMAL, "lfm_length: %u\n", + lfm->lfm_length); + llapi_printf(LLAPI_MSG_NORMAL, "lfm_type: 0x%08X", + lfm->lfm_type); + if (type < LU_FOREIGN_TYPE_UNKNOWN) + llapi_printf(LLAPI_MSG_NORMAL, " (%s)\n", + lu_foreign_types[type].lft_name); + else + llapi_printf(LLAPI_MSG_NORMAL, " (unknown)\n"); + + llapi_printf(LLAPI_MSG_NORMAL, "lfm_flags: 0x%08X\n", + lfm->lfm_flags); + } + llapi_printf(LLAPI_MSG_NORMAL, "lfm_value: '%.*s'\n", + lfm->lfm_length, lfm->lfm_value); + llapi_printf(LLAPI_MSG_NORMAL, "\n"); +} + static void llapi_lov_dump_user_lmm(struct find_param *param, char *path, enum lov_dump_flags flags) { @@ -3533,6 +3899,9 @@ static void llapi_lov_dump_user_lmm(struct find_param *param, char *path, case LOV_USER_MAGIC_SPECIFIC: lov_dump_plain_user_lmm(param, path, flags); break; + case LOV_USER_MAGIC_FOREIGN: + lov_dump_foreign_lmm(param, path, flags); + break; case LMV_MAGIC_V1: case LMV_USER_MAGIC: { char pool_name[LOV_MAXPOOLNAME + 1]; @@ -3549,9 +3918,12 @@ static void llapi_lov_dump_user_lmm(struct find_param *param, char *path, case LOV_USER_MAGIC_COMP_V1: lov_dump_comp_v1(param, path, flags); break; + case LMV_MAGIC_FOREIGN: + lmv_dump_foreign_lmm(param, path, flags); + break; default: - llapi_printf(LLAPI_MSG_NORMAL, "unknown lmm_magic: %#x " - "(expecting one of %#x %#x %#x %#x)\n", + llapi_printf(LLAPI_MSG_NORMAL, + "unknown lmm_magic: %#x (expecting one of %#x %#x %#x %#x)\n", *(__u32 *)¶m->fp_lmd->lmd_lmm, LOV_USER_MAGIC_V1, LOV_USER_MAGIC_V3, LMV_USER_MAGIC, LMV_MAGIC_V1); @@ -3586,8 +3958,7 @@ int llapi_file_get_stripe(const char *path, struct lov_user_md *lum) fd = open(dname, O_RDONLY | O_NONBLOCK); if (fd == -1) { rc = -errno; - free(dname); - return rc; + goto out_free; } strcpy((char *)lum, fname); @@ -3597,55 +3968,60 @@ int llapi_file_get_stripe(const char *path, struct lov_user_md *lum) if (close(fd) == -1 && rc == 0) rc = -errno; +out_free: free(dname); return rc; } int llapi_file_lookup(int dirfd, const char *name) { - struct obd_ioctl_data data = { 0 }; - char rawbuf[8192]; - char *buf = rawbuf; - int rc; + struct obd_ioctl_data data = { 0 }; + char rawbuf[8192]; + char *buf = rawbuf; + int rc; - if (dirfd < 0 || name == NULL) - return -EINVAL; + if (dirfd < 0 || name == NULL) + return -EINVAL; - data.ioc_version = OBD_IOCTL_VERSION; - data.ioc_len = sizeof(data); - data.ioc_inlbuf1 = (char *)name; - data.ioc_inllen1 = strlen(name) + 1; + data.ioc_version = OBD_IOCTL_VERSION; + data.ioc_len = sizeof(data); + data.ioc_inlbuf1 = (char *)name; + data.ioc_inllen1 = strlen(name) + 1; rc = llapi_ioctl_pack(&data, &buf, sizeof(rawbuf)); - if (rc) { - llapi_error(LLAPI_MSG_ERROR, rc, - "error: IOC_MDC_LOOKUP pack failed for '%s': rc %d", - name, rc); - return rc; - } + if (rc) { + llapi_error(LLAPI_MSG_ERROR, rc, + "error: IOC_MDC_LOOKUP pack failed for '%s': rc %d", + name, rc); + return rc; + } - rc = ioctl(dirfd, IOC_MDC_LOOKUP, buf); - if (rc < 0) - rc = -errno; - return rc; + rc = ioctl(dirfd, IOC_MDC_LOOKUP, buf); + if (rc < 0) + rc = -errno; + return rc; } -/* Check if the file time matches all the given criteria (e.g. --atime +/-N). +/* + * Check if the file time matches all the given criteria (e.g. --atime +/-N). * Return -1 or 1 if file timestamp does not or does match the given criteria * correspondingly. Return 0 if the MDS time is being checked and there are * attributes on OSTs and it is not yet clear if the timespamp matches. * * If 0 is returned, we need to do another RPC to the OSTs to obtain the - * updated timestamps. */ -static int find_time_check(lstat_t *st, struct find_param *param, int mds) + * updated timestamps. + */ +static int find_time_check(struct find_param *param, int mds) { + struct lov_user_mds_data *lmd = param->fp_lmd; 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, + rc2 = find_value_cmp(lmd->lmd_stx.stx_atime.tv_sec, + param->fp_atime, param->fp_asign, + param->fp_exclude_atime, param->fp_time_margin, mds); if (rc2 < 0) return rc2; @@ -3653,27 +4029,33 @@ static int find_time_check(lstat_t *st, struct find_param *param, int mds) } if (param->fp_mtime) { - rc2 = find_value_cmp(st->st_mtime, param->fp_mtime, - param->fp_msign, param->fp_exclude_mtime, + rc2 = find_value_cmp(lmd->lmd_stx.stx_mtime.tv_sec, + param->fp_mtime, param->fp_msign, + param->fp_exclude_mtime, param->fp_time_margin, 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 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 (param->fp_ctime) { - rc2 = find_value_cmp(st->st_ctime, param->fp_ctime, - param->fp_csign, param->fp_exclude_ctime, + rc2 = find_value_cmp(lmd->lmd_stx.stx_ctime.tv_sec, + param->fp_ctime, param->fp_csign, + param->fp_exclude_ctime, param->fp_time_margin, 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 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; } @@ -3681,6 +4063,79 @@ static int find_time_check(lstat_t *st, struct find_param *param, int mds) return rc; } +static int find_newerxy_check(struct find_param *param, int mds, bool from_mdt) +{ + struct lov_user_mds_data *lmd = param->fp_lmd; + int i; + int rc = 1; + int rc2; + + for (i = 0; i < 2; i++) { + /* Check if file is accepted. */ + if (param->fp_newery[NEWERXY_ATIME][i]) { + rc2 = find_value_cmp(lmd->lmd_stx.stx_atime.tv_sec, + param->fp_newery[NEWERXY_ATIME][i], + -1, i, 0, mds); + if (rc2 < 0) + return rc2; + rc = rc2; + } + + if (param->fp_newery[NEWERXY_MTIME][i]) { + rc2 = find_value_cmp(lmd->lmd_stx.stx_mtime.tv_sec, + param->fp_newery[NEWERXY_MTIME][i], + -1, i, 0, 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 (param->fp_newery[NEWERXY_CTIME][i]) { + rc2 = find_value_cmp(lmd->lmd_stx.stx_ctime.tv_sec, + param->fp_newery[NEWERXY_CTIME][i], + -1, i, 0, 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; + } + + /* + * File birth time (btime) can get from MDT directly. + * if @from_mdt is true, it means the input file attributs are + * obtained directly from MDT. + * Thus, if @from_mdt is false, we should skip the following + * btime check. + */ + if (!from_mdt) + continue; + + if (param->fp_newery[NEWERXY_BTIME][i]) { + if (!(lmd->lmd_stx.stx_mask & STATX_BTIME)) + return -EOPNOTSUPP; + + rc2 = find_value_cmp(lmd->lmd_stx.stx_btime.tv_sec, + param->fp_newery[NEWERXY_BTIME][i], + -1, i, 0, 0); + if (rc2 < 0) + return rc2; + } + } + + return rc; +} + /** * Check whether the stripes matches the indexes user provided * 1 : matched @@ -3690,18 +4145,24 @@ static int check_obd_match(struct find_param *param) { struct lov_user_ost_data_v1 *objects; struct lov_comp_md_v1 *comp_v1 = NULL; - struct lov_user_md_v1 *v1 = ¶m->fp_lmd->lmd_lmm; - lstat_t *st = ¶m->fp_lmd->lmd_st; + struct lov_user_mds_data *lmd = param->fp_lmd; + struct lov_user_md_v1 *v1 = &lmd->lmd_lmm; int i, j, k, count = 1; if (param->fp_obd_uuid && param->fp_obd_index == OBD_NOT_FOUND) return 0; - if (!S_ISREG(st->st_mode)) + if (!S_ISREG(lmd->lmd_stx.stx_mode)) return 0; - /* Only those files should be accepted, which have a - * stripe on the specified OST. */ + /* exclude foreign */ + if (v1->lmm_magic == LOV_USER_MAGIC_FOREIGN) + return param->fp_exclude_obd; + + /* + * Only those files should be accepted, which have a + * stripe on the specified OST. + */ if (v1->lmm_magic == LOV_USER_MAGIC_COMP_V1) { comp_v1 = (struct lov_comp_md_v1 *)v1; count = comp_v1->lcm_entry_count; @@ -3752,51 +4213,101 @@ static int check_mdt_match(struct find_param *param) * not active, just print the object affected by this * failed target **/ -static int print_failed_tgt(struct find_param *param, char *path, int type) +static void print_failed_tgt(struct find_param *param, char *path, int type) { - struct obd_statfs stat_buf; - struct obd_uuid uuid_buf; - int ret; - - if (type != LL_STATFS_LOV && type != LL_STATFS_LMV) - return -EINVAL; + struct obd_statfs stat_buf; + struct obd_uuid uuid_buf; + int tgt_nr, i, *indexes; + int ret = 0; - memset(&stat_buf, 0, sizeof(struct obd_statfs)); - memset(&uuid_buf, 0, sizeof(struct obd_uuid)); - ret = llapi_obd_statfs(path, type, - param->fp_obd_index, &stat_buf, - &uuid_buf); - if (ret) { - llapi_printf(LLAPI_MSG_NORMAL, - "obd_uuid: %s failed %s ", - param->fp_obd_uuid->uuid, - strerror(errno)); + if (type != LL_STATFS_LOV && type != LL_STATFS_LMV) { + llapi_error(LLAPI_MSG_NORMAL, ret, "%s: wrong statfs type(%d)", + __func__, type); + return; } - return ret; + tgt_nr = (type == LL_STATFS_LOV) ? param->fp_obd_index : + param->fp_mdt_index; + indexes = (type == LL_STATFS_LOV) ? param->fp_obd_indexes : + param->fp_mdt_indexes; + + for (i = 0; i < tgt_nr; i++) { + memset(&stat_buf, 0, sizeof(struct obd_statfs)); + memset(&uuid_buf, 0, sizeof(struct obd_uuid)); + + ret = llapi_obd_statfs(path, type, indexes[i], &stat_buf, + &uuid_buf); + if (ret) + llapi_error(LLAPI_MSG_NORMAL, ret, + "%s: obd_uuid: %s failed", + __func__, param->fp_obd_uuid->uuid); + } } static int find_check_stripe_size(struct find_param *param) { struct lov_comp_md_v1 *comp_v1 = NULL; struct lov_user_md_v1 *v1 = ¶m->fp_lmd->lmd_lmm; + __u32 stripe_size = 0; int ret, i, count = 1; + if (v1->lmm_magic == LOV_USER_MAGIC_FOREIGN) + return param->fp_exclude_stripe_size ? 1 : -1; + + ret = param->fp_exclude_stripe_size ? 1 : -1; if (v1->lmm_magic == LOV_USER_MAGIC_COMP_V1) { comp_v1 = (struct lov_comp_md_v1 *)v1; count = comp_v1->lcm_entry_count; - ret = param->fp_exclude_stripe_size ? 1 : -1; } for (i = 0; i < count; i++) { - if (comp_v1) + struct lov_comp_md_entry_v1 *ent; + + if (comp_v1) { v1 = lov_comp_entry(comp_v1, i); - ret = find_value_cmp(v1->lmm_stripe_size, param->fp_stripe_size, - param->fp_stripe_size_sign, - param->fp_exclude_stripe_size, - param->fp_stripe_size_units, 0); - /* If any stripe_size matches */ + ent = &comp_v1->lcm_entries[i]; + if (ent->lcme_flags & LCME_FL_EXTENSION) + continue; + if (!(ent->lcme_flags & LCME_FL_INIT)) + continue; + } + stripe_size = v1->lmm_stripe_size; + } + + ret = find_value_cmp(stripe_size, param->fp_stripe_size, + param->fp_stripe_size_sign, + param->fp_exclude_stripe_size, + param->fp_stripe_size_units, 0); + + return ret; +} + +static int find_check_ext_size(struct find_param *param) +{ + struct lov_comp_md_v1 *comp_v1; + struct lov_user_md_v1 *v1; + int ret, i; + + ret = param->fp_exclude_ext_size ? 1 : -1; + comp_v1 = (struct lov_comp_md_v1 *)¶m->fp_lmd->lmd_lmm; + if (comp_v1->lcm_magic != LOV_USER_MAGIC_COMP_V1) + return ret; + + for (i = 0; i < comp_v1->lcm_entry_count; i++) { + struct lov_comp_md_entry_v1 *ent; + + v1 = lov_comp_entry(comp_v1, i); + + ent = &comp_v1->lcm_entries[i]; + if (!(ent->lcme_flags & LCME_FL_EXTENSION)) + continue; + + ret = find_value_cmp(v1->lmm_stripe_size, param->fp_ext_size, + param->fp_ext_size_sign, + param->fp_exclude_ext_size, + param->fp_ext_size_units, 0); + /* If any ext_size matches */ if (ret != -1) break; } @@ -3811,15 +4322,28 @@ static __u32 find_get_stripe_count(struct find_param *param) int i, count = 1; __u32 stripe_count = 0; + if (v1->lmm_magic == LOV_USER_MAGIC_FOREIGN) + return 0; + if (v1->lmm_magic == LOV_USER_MAGIC_COMP_V1) { comp_v1 = (struct lov_comp_md_v1 *)v1; count = comp_v1->lcm_entry_count; } for (i = 0; i < count; i++) { - if (comp_v1) + if (comp_v1) { + struct lov_comp_md_entry_v1 *ent; + v1 = lov_comp_entry(comp_v1, i); - stripe_count += v1->lmm_stripe_count; + + ent = &comp_v1->lcm_entries[i]; + if (!(ent->lcme_flags & LCME_FL_INIT)) + continue; + + if (ent->lcme_flags & LCME_FL_EXTENSION) + continue; + } + stripe_count = v1->lmm_stripe_count; } return stripe_count; @@ -3843,6 +4367,10 @@ static int find_check_layout(struct find_param *param) if (comp_v1) v1 = lov_comp_entry(comp_v1, i); + /* foreign file have a special magic but no pattern field */ + if (v1->lmm_magic == LOV_USER_MAGIC_FOREIGN) + continue; + if (v1->lmm_pattern == LOV_PATTERN_INVALID) continue; @@ -3863,38 +4391,88 @@ static int find_check_layout(struct find_param *param) return -1; } +/* + * if no type specified, check/exclude all foreign + * if type specified, check all foreign&type and exclude !foreign + foreign&type + */ +static int find_check_foreign(struct find_param *param) +{ + if (S_ISREG(param->fp_lmd->lmd_stx.stx_mode)) { + struct lov_foreign_md *lfm; + + lfm = (void *)¶m->fp_lmd->lmd_lmm; + if (lfm->lfm_magic != LOV_USER_MAGIC_FOREIGN) { + if (param->fp_foreign_type == LU_FOREIGN_TYPE_UNKNOWN) + return param->fp_exclude_foreign ? 1 : -1; + return -1; + } + + if (param->fp_foreign_type == LU_FOREIGN_TYPE_UNKNOWN || + lfm->lfm_type == param->fp_foreign_type) + return param->fp_exclude_foreign ? -1 : 1; + return param->fp_exclude_foreign ? 1 : -1; + } + + if (S_ISDIR(param->fp_lmd->lmd_stx.stx_mode)) { + struct lmv_foreign_md *lfm; + + lfm = (void *)param->fp_lmv_md; + if (lfm->lfm_magic != LMV_MAGIC_FOREIGN) { + if (param->fp_foreign_type == LU_FOREIGN_TYPE_UNKNOWN) + return param->fp_exclude_foreign ? 1 : -1; + return -1; + } + + if (param->fp_foreign_type == LU_FOREIGN_TYPE_UNKNOWN || + lfm->lfm_type == param->fp_foreign_type) + return param->fp_exclude_foreign ? -1 : 1; + return param->fp_exclude_foreign ? 1 : -1; + } + return -1; +} + static int find_check_pool(struct find_param *param) { struct lov_comp_md_v1 *comp_v1 = NULL; - struct lov_user_md_v1 *v1 = ¶m->fp_lmd->lmd_lmm; - struct lov_user_md_v3 *v3 = (void *)v1; + struct lov_user_md_v3 *v3 = (void *)¶m->fp_lmd->lmd_lmm; int i, count = 1; bool found = false; - if (v1->lmm_magic == LOV_USER_MAGIC_COMP_V1) { - comp_v1 = (struct lov_comp_md_v1 *)v1; + if (v3->lmm_magic == LOV_USER_MAGIC_COMP_V1) { + comp_v1 = (struct lov_comp_md_v1 *)v3; count = comp_v1->lcm_entry_count; /* empty requested pool is taken as no pool search */ - if (count == 0 && param->fp_poolname[0] == '\0') + if (count == 0 && param->fp_poolname[0] == '\0') { found = true; + goto found; + } } for (i = 0; i < count; i++) { - if (comp_v1 != NULL) - v1 = lov_comp_entry(comp_v1, i); + if (comp_v1 != NULL) { + if (!(comp_v1->lcm_entries[i].lcme_flags & + LCME_FL_INIT)) + continue; + + v3 = (void *)lov_comp_entry(comp_v1, i); + } + + if (v3->lmm_magic == LOV_USER_MAGIC_FOREIGN) + continue; - if (((v1->lmm_magic == LOV_USER_MAGIC_V1) && + if (((v3->lmm_magic == LOV_USER_MAGIC_V1) && (param->fp_poolname[0] == '\0')) || - ((v1->lmm_magic == LOV_USER_MAGIC_V3) && + ((v3->lmm_magic == LOV_USER_MAGIC_V3) && (strncmp(v3->lmm_pool_name, param->fp_poolname, LOV_MAXPOOLNAME) == 0)) || - ((v1->lmm_magic == LOV_USER_MAGIC_V3) && + ((v3->lmm_magic == LOV_USER_MAGIC_V3) && (strcmp(param->fp_poolname, "*") == 0))) { found = true; break; } } +found: if ((found && !param->fp_exclude_pool) || (!found && param->fp_exclude_pool)) return 1; @@ -3904,12 +4482,15 @@ static int find_check_pool(struct find_param *param) static int find_check_comp_options(struct find_param *param) { - lstat_t *st = ¶m->fp_lmd->lmd_st; struct lov_comp_md_v1 *comp_v1, *forged_v1 = NULL; - struct lov_user_md_v1 *v1 = ¶m->fp_lmd->lmd_lmm; + struct lov_user_mds_data *lmd = param->fp_lmd; + struct lov_user_md_v1 *v1 = &lmd->lmd_lmm; struct lov_comp_md_entry_v1 *entry; int i, ret = 0; + if (v1->lmm_magic == LOV_USER_MAGIC_FOREIGN) + return -1; + if (v1->lmm_magic == LOV_USER_MAGIC_COMP_V1) { comp_v1 = (struct lov_comp_md_v1 *)v1; } else { @@ -3919,7 +4500,8 @@ static int find_check_comp_options(struct find_param *param) comp_v1 = forged_v1; comp_v1->lcm_entry_count = 1; entry = &comp_v1->lcm_entries[0]; - entry->lcme_flags = S_ISDIR(st->st_mode) ? 0 : LCME_FL_INIT; + entry->lcme_flags = S_ISDIR(lmd->lmd_stx.stx_mode) ? + 0 : LCME_FL_INIT; entry->lcme_extent.e_start = 0; entry->lcme_extent.e_end = LUSTRE_EOF; } @@ -3974,7 +4556,7 @@ static int find_check_comp_options(struct find_param *param) break; } out: - if (forged_v1 != NULL) + if (forged_v1) free(forged_v1); return ret; } @@ -4018,8 +4600,8 @@ static bool find_check_lmm_info(struct find_param *param) param->fp_check_stripe_size || param->fp_check_layout || param->fp_check_comp_count || param->fp_check_comp_end || param->fp_check_comp_start || param->fp_check_comp_flags || - param->fp_check_mirror_count || - param->fp_check_mirror_state || + param->fp_check_mirror_count || param->fp_check_foreign || + param->fp_check_mirror_state || param->fp_check_ext_size || param->fp_check_projid; } @@ -4033,7 +4615,7 @@ static int fget_projid(int fd, int *projid) struct fsxattr fsx; int rc; - rc = ioctl(fd, LL_IOC_FSGETXATTR, &fsx); + rc = ioctl(fd, FS_IOC_FSGETXATTR, &fsx); if (rc) return -errno; @@ -4045,13 +4627,14 @@ static int cb_find_init(char *path, DIR *parent, DIR **dirp, void *data, struct dirent64 *de) { struct find_param *param = (struct find_param *)data; + struct lov_user_mds_data *lmd = param->fp_lmd; DIR *dir = dirp == NULL ? NULL : *dirp; int decision = 1; /* 1 is accepted; -1 is rejected. */ - lstat_t *st = ¶m->fp_lmd->lmd_st; int lustre_fs = 1; int checked_type = 0; int ret = 0; __u32 stripe_count = 0; + __u64 flags; int fd = -2; if (parent == NULL && dir == NULL) @@ -4060,6 +4643,7 @@ static int cb_find_init(char *path, DIR *parent, DIR **dirp, /* If a regular expression is presented, make the initial decision */ if (param->fp_pattern != NULL) { char *fname = strrchr(path, '/'); + fname = (fname == NULL ? path : fname + 1); ret = fnmatch(param->fp_pattern, fname, 0); if ((ret == FNM_NOMATCH && !param->fp_exclude_pattern) || @@ -4082,10 +4666,13 @@ static int cb_find_init(char *path, DIR *parent, DIR **dirp, ret = 0; - /* Request MDS for the stat info if some of these parameters need - * to be compared. */ + /* + * Request MDS for the stat info if some of these parameters need + * to be compared. + */ if (param->fp_obd_uuid || param->fp_mdt_uuid || param->fp_check_uid || param->fp_check_gid || + param->fp_newerxy || param->fp_btime || param->fp_atime || param->fp_mtime || param->fp_ctime || param->fp_check_size || param->fp_check_blocks || find_check_lmm_info(param) || @@ -4093,14 +4680,26 @@ static int cb_find_init(char *path, DIR *parent, DIR **dirp, decision = 0; if (param->fp_type != 0 && checked_type == 0) - decision = 0; + decision = 0; if (decision == 0) { - if (param->fp_check_mdt_count || param->fp_check_hash_type) { + if (dir && (param->fp_check_mdt_count || + param->fp_check_hash_type || param->fp_check_foreign)) { param->fp_get_lmv = 1; ret = cb_get_dirstripe(path, dir, param); - if (ret != 0) + if (ret != 0) { + /* + * XXX this works to decide for foreign + * criterion only + */ + if (errno == ENODATA && + param->fp_check_foreign) { + if (param->fp_exclude_foreign) + goto foreign; + goto decided; + } return ret; + } } param->fp_lmd->lmd_lmm.lmm_magic = 0; @@ -4110,8 +4709,10 @@ static int cb_find_init(char *path, DIR *parent, DIR **dirp, find_check_lmm_info(param)) { struct lov_user_md *lmm = ¶m->fp_lmd->lmd_lmm; - /* We need to "fake" the "use the default" values - * since the lmm struct is zeroed out at this point. */ + /* + * We need to "fake" the "use the default" values + * since the lmm struct is zeroed out at this point. + */ lmm->lmm_magic = LOV_USER_MAGIC_V1; lmm->lmm_pattern = LOV_PATTERN_DEFAULT; if (!param->fp_raw) @@ -4125,13 +4726,15 @@ static int cb_find_init(char *path, DIR *parent, DIR **dirp, if (dir != NULL) { ret = llapi_file_fget_mdtidx(dirfd(dir), ¶m->fp_file_mdt_index); - } else if (S_ISREG(st->st_mode)) { - /* FIXME: we could get the MDT index from the + } else if (S_ISREG(lmd->lmd_stx.stx_mode)) { + /* + * FIXME: we could get the MDT index from the * file's FID in lmd->lmd_lmm.lmm_oi without * opening the file, once we are sure that * LFSCK2 (2.6) has fixed up pre-2.0 LOV EAs. * That would still be an ioctl() to map the - * FID to the MDT, but not an open RPC. */ + * FID to the MDT, but not an open RPC. + */ fd = open(path, O_RDONLY); if (fd > 0) { ret = llapi_file_fget_mdtidx(fd, @@ -4140,8 +4743,10 @@ static int cb_find_init(char *path, DIR *parent, DIR **dirp, ret = -errno; } } else { - /* For a special file, we assume it resides on - * the same MDT as the parent directory. */ + /* + * For a special file, we assume it resides on + * the same MDT as the parent directory. + */ ret = llapi_file_fget_mdtidx(dirfd(parent), ¶m->fp_file_mdt_index); } @@ -4159,7 +4764,7 @@ static int cb_find_init(char *path, DIR *parent, DIR **dirp, } if (param->fp_type && !checked_type) { - if ((st->st_mode & S_IFMT) == param->fp_type) { + if ((lmd->lmd_stx.stx_mode & S_IFMT) == param->fp_type) { if (param->fp_exclude_type) goto decided; } else { @@ -4168,10 +4773,11 @@ static int cb_find_init(char *path, DIR *parent, DIR **dirp, } } - /* Prepare odb. */ + /* Prepare odb. */ if (param->fp_obd_uuid || param->fp_mdt_uuid) { if (lustre_fs && param->fp_got_uuids && - param->fp_dev != st->st_dev) { + param->fp_dev != makedev(lmd->lmd_stx.stx_dev_major, + lmd->lmd_stx.stx_dev_minor)) { /* A lustre/lustre mount point is crossed. */ param->fp_got_uuids = 0; param->fp_obds_printed = 0; @@ -4185,14 +4791,21 @@ static int cb_find_init(char *path, DIR *parent, DIR **dirp, if (ret) goto out; - param->fp_dev = st->st_dev; + param->fp_dev = makedev(lmd->lmd_stx.stx_dev_major, + lmd->lmd_stx.stx_dev_minor); } else if (!lustre_fs && param->fp_got_uuids) { /* A lustre/non-lustre mount point is crossed. */ param->fp_got_uuids = 0; param->fp_mdt_index = OBD_NOT_FOUND; param->fp_obd_index = OBD_NOT_FOUND; - } - } + } + } + + if (param->fp_check_foreign) { + decision = find_check_foreign(param); + if (decision == -1) + goto decided; + } if (param->fp_check_stripe_size) { decision = find_check_stripe_size(param); @@ -4200,6 +4813,12 @@ static int cb_find_init(char *path, DIR *parent, DIR **dirp, goto decided; } + if (param->fp_check_ext_size) { + decision = find_check_ext_size(param); + if (decision == -1) + goto decided; + } + if (param->fp_check_stripe_count) { decision = find_value_cmp(stripe_count, param->fp_stripe_count, param->fp_stripe_count_sign, @@ -4209,6 +4828,11 @@ static int cb_find_init(char *path, DIR *parent, DIR **dirp, } if (param->fp_check_mdt_count) { + if (param->fp_lmv_md->lum_magic == LMV_MAGIC_FOREIGN) { + decision = -1; + goto decided; + } + decision = find_value_cmp( param->fp_lmv_md->lum_stripe_count, param->fp_mdt_count, @@ -4227,6 +4851,11 @@ static int cb_find_init(char *path, DIR *parent, DIR **dirp, if (param->fp_check_hash_type) { __u32 found; + if (param->fp_lmv_md->lum_magic == LMV_MAGIC_FOREIGN) { + decision = -1; + goto decided; + } + found = param->fp_lmv_md->lum_hash_type & param->fp_hash_type; if ((found && param->fp_exclude_hash_type) || (!found && !param->fp_exclude_hash_type)) { @@ -4240,15 +4869,19 @@ static int cb_find_init(char *path, DIR *parent, DIR **dirp, (param->fp_mdt_uuid && param->fp_mdt_index == OBD_NOT_FOUND)) goto decided; - /* If an OST or MDT UUID is given, and some OST matches, - * check it here. */ + /* + * If an OST or MDT UUID is given, and some OST matches, + * check it here. + */ if (param->fp_obd_index != OBD_NOT_FOUND || param->fp_mdt_index != OBD_NOT_FOUND) { if (param->fp_obd_uuid) { if (check_obd_match(param)) { - /* If no mdtuuid is given, we are done. + /* + * If no mdtuuid is given, we are done. * Otherwise, fall through to the mdtuuid - * check below. */ + * check below. + */ if (!param->fp_mdt_uuid) goto obd_matches; } else { @@ -4265,7 +4898,7 @@ static int cb_find_init(char *path, DIR *parent, DIR **dirp, obd_matches: if (param->fp_check_uid) { - if (st->st_uid == param->fp_uid) { + if (lmd->lmd_stx.stx_uid == param->fp_uid) { if (param->fp_exclude_uid) goto decided; } else { @@ -4275,7 +4908,7 @@ obd_matches: } if (param->fp_check_gid) { - if (st->st_gid == param->fp_gid) { + if (lmd->lmd_stx.stx_gid == param->fp_gid) { if (param->fp_exclude_gid) goto decided; } else { @@ -4327,63 +4960,119 @@ obd_matches: /* Check the time on mds. */ decision = 1; if (param->fp_atime || param->fp_mtime || param->fp_ctime) { - int for_mds; + int for_mds; + + for_mds = lustre_fs ? + (S_ISREG(lmd->lmd_stx.stx_mode) && stripe_count) : 0; + decision = find_time_check(param, for_mds); + if (decision == -1) + goto decided; + } + + if (param->fp_btime) { + if (!(lmd->lmd_stx.stx_mask & STATX_BTIME)) { + ret = -EOPNOTSUPP; + goto out; + } + + decision = find_value_cmp(lmd->lmd_stx.stx_btime.tv_sec, + param->fp_btime, param->fp_bsign, + param->fp_exclude_btime, + param->fp_time_margin, 0); + if (decision == -1) + goto decided; + } + + if (param->fp_newerxy) { + int for_mds; for_mds = lustre_fs ? - (S_ISREG(st->st_mode) && stripe_count) : 0; - decision = find_time_check(st, param, for_mds); - if (decision == -1) - goto decided; - } - - /* If file still fits the request, ask ost for updated info. - The regular stat is almost of the same speed as some new - 'glimpse-size-ioctl'. */ - - if ((param->fp_check_size || param->fp_check_blocks) && - ((S_ISREG(st->st_mode) && stripe_count) || S_ISDIR(st->st_mode))) + (S_ISREG(lmd->lmd_stx.stx_mode) && stripe_count) : 0; + decision = find_newerxy_check(param, for_mds, true); + if (decision == -1) + goto decided; + if (decision < 0) { + ret = decision; + goto out; + } + } + + flags = param->fp_lmd->lmd_flags; + if (param->fp_check_size && + ((S_ISREG(lmd->lmd_stx.stx_mode) && stripe_count) || + S_ISDIR(lmd->lmd_stx.stx_mode)) && + !(flags & OBD_MD_FLSIZE || + (param->fp_lazy && flags & OBD_MD_FLLAZYSIZE))) + decision = 0; + + if (param->fp_check_blocks && + ((S_ISREG(lmd->lmd_stx.stx_mode) && stripe_count) || + S_ISDIR(lmd->lmd_stx.stx_mode)) && + !(flags & OBD_MD_FLBLOCKS || + (param->fp_lazy && flags & OBD_MD_FLLAZYBLOCKS))) decision = 0; + /* + * If file still fits the request, ask ost for updated info. + * The regular stat is almost of the same speed as some new + * 'glimpse-size-ioctl'. + */ if (!decision) { - /* For regular files with the stripe the decision may have not - * been taken yet if *time or size is to be checked. */ + lstat_t st; + + /* + * For regular files with the stripe the decision may have not + * been taken yet if *time or size is to be checked. + */ if (param->fp_obd_index != OBD_NOT_FOUND) - print_failed_tgt(param, path, LL_STATFS_LOV); + print_failed_tgt(param, path, LL_STATFS_LOV); if (param->fp_mdt_index != OBD_NOT_FOUND) - print_failed_tgt(param, path, LL_STATFS_LMV); + print_failed_tgt(param, path, LL_STATFS_LMV); if (dir != NULL) - ret = fstat_f(dirfd(dir), st); + ret = fstat_f(dirfd(dir), &st); else if (de != NULL) - ret = fstatat_f(dirfd(parent), de->d_name, st, + ret = fstatat_f(dirfd(parent), de->d_name, &st, AT_SYMLINK_NOFOLLOW); else - ret = lstat_f(path, st); - - if (ret) { - if (errno == ENOENT) { - llapi_error(LLAPI_MSG_ERROR, -ENOENT, - "warning: %s: %s does not exist", - __func__, path); - goto decided; - } else { + ret = lstat_f(path, &st); + + if (ret) { + if (errno == ENOENT) { + llapi_error(LLAPI_MSG_ERROR, -ENOENT, + "warning: %s: %s does not exist", + __func__, path); + goto decided; + } else { ret = -errno; llapi_error(LLAPI_MSG_ERROR, ret, - "%s: IOC_LOV_GETINFO on %s failed", + "%s: stat on %s failed", __func__, path); goto out; } } + convert_lmd_statx(param->fp_lmd, &st, true); /* Check the time on osc. */ - decision = find_time_check(st, param, 0); + decision = find_time_check(param, 0); if (decision == -1) goto decided; + + if (param->fp_newerxy) { + decision = find_newerxy_check(param, 0, false); + if (decision == -1) + goto decided; + if (decision < 0) { + ret = decision; + goto out; + } + } } if (param->fp_check_size) { - decision = find_value_cmp(st->st_size, param->fp_size, + decision = find_value_cmp(lmd->lmd_stx.stx_size, + param->fp_size, param->fp_size_sign, param->fp_exclude_size, param->fp_size_units, 0); @@ -4392,7 +5081,8 @@ obd_matches: } if (param->fp_check_blocks) { /* convert st_blocks to bytes */ - decision = find_value_cmp(st->st_blocks * 512, param->fp_blocks, + decision = find_value_cmp(lmd->lmd_stx.stx_blocks * 512, + param->fp_blocks, param->fp_blocks_sign, param->fp_exclude_blocks, param->fp_blocks_units, 0); @@ -4400,6 +5090,7 @@ obd_matches: goto decided; } +foreign: llapi_printf(LLAPI_MSG_NORMAL, "%s", path); if (param->fp_zero_end) llapi_printf(LLAPI_MSG_NORMAL, "%c", '\0'); @@ -4468,7 +5159,7 @@ static int cb_migrate_mdt_init(char *path, DIR *parent, DIR **dirp, ret = llapi_ioctl_pack(&data, &rawbuf, sizeof(raw)); if (ret != 0) { llapi_error(LLAPI_MSG_ERROR, ret, - "llapi_obd_statfs: error packing ioctl data"); + "%s: error packing ioctl data", __func__); goto out; } @@ -4476,25 +5167,26 @@ migrate: ret = ioctl(fd, LL_IOC_MIGRATE, rawbuf); if (ret != 0) { if (errno == EBUSY && !retry) { - /* because migrate may not be able to lock all involved + /* + * because migrate may not be able to lock all involved * objects in order, for some of them it try lock, while * there may be conflicting COS locks and cause migrate * fail with EBUSY, hope a sync() could cause - * transaction commit and release these COS locks. */ + * transaction commit and release these COS locks. + */ sync(); retry = true; goto migrate; } else if (errno == EALREADY) { if (param->fp_verbose & VERBOSE_DETAIL) llapi_printf(LLAPI_MSG_NORMAL, - "%s was migrated to MDT%d already\n", + "%s migrated to MDT%d already\n", path, lmu->lum_stripe_offset); ret = 0; } else { ret = -errno; - llapi_error(LLAPI_MSG_ERROR, ret, - "%s migrate failed: %s (%d)\n", - path, strerror(-ret), ret); + llapi_error(LLAPI_MSG_ERROR, ret, "%s migrate failed", + path); goto out; } } else if (param->fp_verbose & VERBOSE_DETAIL) { @@ -4506,11 +5198,13 @@ migrate: out: if (dirp != NULL) { - /* If the directory is being migration, we need + /* + * 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 */ + * new directory handle + */ *dirp = opendir(path); if (*dirp == NULL) { ret = -errno; @@ -4571,7 +5265,8 @@ int llapi_mv(char *path, struct find_param *param) if (!printed) { llapi_error(LLAPI_MSG_ERROR, -ESTALE, - "llapi_mv() is deprecated, use llapi_migrate_mdt()\n"); + "%s() is deprecated, use llapi_migrate_mdt() instead", + __func__); printed = true; } #endif @@ -4580,7 +5275,7 @@ int llapi_mv(char *path, struct find_param *param) int llapi_find(char *path, struct find_param *param) { - return param_callback(path, cb_find_init, cb_common_fini, param); + return param_callback(path, cb_find_init, cb_common_fini, param); } /* @@ -4590,9 +5285,9 @@ int llapi_find(char *path, struct find_param *param) */ int llapi_file_fget_mdtidx(int fd, int *mdtidx) { - if (ioctl(fd, LL_IOC_GET_MDTIDX, mdtidx) < 0) - return -errno; - return 0; + if (ioctl(fd, LL_IOC_GET_MDTIDX, mdtidx) < 0) + return -errno; + return 0; } static int cb_get_mdt_index(char *path, DIR *parent, DIR **dirp, void *data, @@ -4662,9 +5357,9 @@ out: static int cb_getstripe(char *path, DIR *parent, DIR **dirp, void *data, struct dirent64 *de) { - struct find_param *param = (struct find_param *)data; + struct find_param *param = (struct find_param *)data; DIR *d = dirp == NULL ? NULL : *dirp; - int ret = 0; + int ret = 0; if (parent == NULL && d == NULL) return -EINVAL; @@ -4685,20 +5380,22 @@ static int cb_getstripe(char *path, DIR *parent, DIR **dirp, void *data, else return 0; - if (ret) { - if (errno == ENODATA && d != NULL) { - /* We need to "fake" the "use the default" values + if (ret) { + if (errno == ENODATA && d != NULL) { + /* + * We need to "fake" the "use the default" values * since the lmm struct is zeroed out at this point. * The magic needs to be set in order to satisfy * a check later on in the code path. * The object_seq needs to be set for the "(Default)" - * prefix to be displayed. */ + * prefix to be displayed. + */ if (param->fp_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; + lum->lum_stripe_offset = LMV_OFFSET_DEFAULT; goto dump; } else if (param->fp_get_lmv) { struct lmv_user_md *lum = param->fp_lmv_md; @@ -4724,23 +5421,23 @@ static int cb_getstripe(char *path, DIR *parent, DIR **dirp, void *data, lmm->lmm_stripe_offset = -1; goto dump; } - } else if (errno == ENODATA && parent != NULL) { + } else if (errno == ENODATA && parent != NULL) { if (!param->fp_obd_uuid && !param->fp_mdt_uuid) - llapi_printf(LLAPI_MSG_NORMAL, - "%s has no stripe info\n", path); - goto out; - } else if (errno == ENOENT) { - llapi_error(LLAPI_MSG_WARN, -ENOENT, - "warning: %s: %s does not exist", - __func__, path); - goto out; - } else if (errno == ENOTTY) { - ret = -errno; - llapi_error(LLAPI_MSG_ERROR, ret, - "%s: '%s' not on a Lustre fs?", - __func__, path); - } else { - ret = -errno; + llapi_printf(LLAPI_MSG_NORMAL, + "%s has no stripe info\n", path); + goto out; + } else if (errno == ENOENT) { + llapi_error(LLAPI_MSG_WARN, -ENOENT, + "warning: %s: %s does not exist", + __func__, path); + goto out; + } else if (errno == ENOTTY) { + ret = -errno; + llapi_error(LLAPI_MSG_ERROR, ret, + "%s: '%s' not on a Lustre fs?", + __func__, path); + } else { + ret = -errno; err_out: llapi_error(LLAPI_MSG_ERROR, ret, "error: %s: %s failed for %s", @@ -4748,8 +5445,8 @@ err_out: "IOC_MDC_GETFILESTRIPE", path); } - return ret; - } + return ret; + } dump: if (!(param->fp_verbose & VERBOSE_MDTINDEX)) @@ -4768,33 +5465,33 @@ out: int llapi_getstripe(char *path, struct find_param *param) { return param_callback(path, (param->fp_verbose & VERBOSE_MDTINDEX) ? - cb_get_mdt_index : cb_getstripe, - cb_common_fini, param); + cb_get_mdt_index : cb_getstripe, + cb_common_fini, param); } int llapi_obd_fstatfs(int fd, __u32 type, __u32 index, struct obd_statfs *stat_buf, struct obd_uuid *uuid_buf) { char raw[MAX_IOC_BUFLEN] = {'\0'}; - char *rawbuf = raw; - struct obd_ioctl_data data = { 0 }; - int rc = 0; - - data.ioc_inlbuf1 = (char *)&type; - data.ioc_inllen1 = sizeof(__u32); - data.ioc_inlbuf2 = (char *)&index; - data.ioc_inllen2 = sizeof(__u32); - data.ioc_pbuf1 = (char *)stat_buf; - data.ioc_plen1 = sizeof(struct obd_statfs); - data.ioc_pbuf2 = (char *)uuid_buf; - data.ioc_plen2 = sizeof(struct obd_uuid); + char *rawbuf = raw; + struct obd_ioctl_data data = { 0 }; + int rc = 0; + + data.ioc_inlbuf1 = (char *)&type; + data.ioc_inllen1 = sizeof(__u32); + data.ioc_inlbuf2 = (char *)&index; + data.ioc_inllen2 = sizeof(__u32); + data.ioc_pbuf1 = (char *)stat_buf; + data.ioc_plen1 = sizeof(struct obd_statfs); + data.ioc_pbuf2 = (char *)uuid_buf; + data.ioc_plen2 = sizeof(struct obd_uuid); rc = llapi_ioctl_pack(&data, &rawbuf, sizeof(raw)); - if (rc != 0) { - llapi_error(LLAPI_MSG_ERROR, rc, - "llapi_obd_statfs: error packing ioctl data"); - return rc; - } + if (rc != 0) { + llapi_error(LLAPI_MSG_ERROR, rc, + "%s: error packing ioctl data", __func__); + return rc; + } rc = ioctl(fd, IOC_OBD_STATFS, (void *)rawbuf); @@ -4812,8 +5509,10 @@ int llapi_obd_statfs(char *path, __u32 type, __u32 index, rc = -errno; 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. */ + /* + * 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; } @@ -4866,7 +5565,7 @@ failed: } int llapi_target_iterate(int type_num, char **obd_type, - void *args, llapi_cb_t cb) + void *args, llapi_cb_t cb) { int i, rc = 0; glob_t param; @@ -4931,23 +5630,22 @@ free_path: } static void do_target_check(char *obd_type_name, char *obd_name, - char *obd_uuid, void *args) + char *obd_uuid, void *args) { - int rc; + int rc; - rc = llapi_ping(obd_type_name, obd_name); - if (rc == ENOTCONN) { - llapi_printf(LLAPI_MSG_NORMAL, "%s inactive.\n", obd_name); - } else if (rc) { - llapi_error(LLAPI_MSG_ERROR, rc, "error: check '%s'", obd_name); - } else { - llapi_printf(LLAPI_MSG_NORMAL, "%s active.\n", obd_name); - } + rc = llapi_ping(obd_type_name, obd_name); + if (rc == ENOTCONN) + llapi_printf(LLAPI_MSG_NORMAL, "%s inactive.\n", obd_name); + else if (rc) + llapi_error(LLAPI_MSG_ERROR, rc, "error: check '%s'", obd_name); + else + llapi_printf(LLAPI_MSG_NORMAL, "%s active.\n", obd_name); } int llapi_target_check(int type_num, char **obd_type, char *dir) { - return llapi_target_iterate(type_num, obd_type, NULL, do_target_check); + return llapi_target_iterate(type_num, obd_type, NULL, do_target_check); } #undef MAX_STRING_SIZE @@ -4955,14 +5653,14 @@ int llapi_target_check(int type_num, char **obd_type, char *dir) /* Is this a lustre fs? */ int llapi_is_lustre_mnttype(const char *type) { - return (strcmp(type, "lustre") == 0 || strcmp(type,"lustre_lite") == 0); + return strcmp(type, "lustre") == 0 || strcmp(type, "lustre_tgt") == 0; } /* Is this a lustre client fs? */ int llapi_is_lustre_mnt(struct mntent *mnt) { - return (llapi_is_lustre_mnttype(mnt->mnt_type) && - strstr(mnt->mnt_fsname, ":/") != NULL); + return (llapi_is_lustre_mnttype(mnt->mnt_type) && + strstr(mnt->mnt_fsname, ":/") != NULL); } int llapi_quotactl(char *mnt, struct if_quotactl *qctl) @@ -4990,248 +5688,6 @@ int llapi_quotactl(char *mnt, struct if_quotactl *qctl) return rc; } -/* Print mdtname 'name' into 'buf' using 'format'. Add -MDT0000 if needed. - * format must have %s%s, buf must be > 16 - * Eg: if name = "lustre-MDT0000", "lustre", or "lustre-MDT0000_UUID" - * then buf = "lustre-MDT0000" - */ -static int get_mdtname(char *name, char *format, char *buf) -{ - char suffix[]="-MDT0000"; - int len = strlen(name); - - if ((len > 5) && (strncmp(name + len - 5, "_UUID", 5) == 0)) { - name[len - 5] = '\0'; - len -= 5; - } - - if (len > 8) { - if ((len <= 16) && strncmp(name + len - 8, "-MDT", 4) == 0) { - suffix[0] = '\0'; - } else { - /* Not enough room to add suffix */ - llapi_err_noerrno(LLAPI_MSG_ERROR, - "Invalid MDT name |%s|", name); - return -EINVAL; - } - } - - return sprintf(buf, format, name, suffix); -} - -/** ioctl on filsystem root, with mdtindex sent as data - * \param mdtname path, fsname, or mdtname (lutre-MDT0004) - * \param mdtidxp pointer to integer within data to be filled in with the - * mdt index (0 if no mdt is specified). NULL won't be filled. - */ -int root_ioctl(const char *mdtname, int opc, void *data, int *mdtidxp, - int want_error) -{ - char fsname[20]; - char *ptr; - int fd, rc; - long index; - - /* Take path, fsname, or MDTname. Assume MDT0000 in the former cases. - Open root and parse mdt index. */ - if (mdtname[0] == '/') { - index = 0; - rc = get_root_path(WANT_FD | want_error, NULL, &fd, - (char *)mdtname, -1); - } else { - if (get_mdtname((char *)mdtname, "%s%s", fsname) < 0) - return -EINVAL; - ptr = fsname + strlen(fsname) - 8; - *ptr = '\0'; - index = strtol(ptr + 4, NULL, 16); - rc = get_root_path(WANT_FD | want_error, fsname, &fd, NULL, -1); - } - if (rc < 0) { - if (want_error) - llapi_err_noerrno(LLAPI_MSG_ERROR, - "Can't open %s: %d\n", mdtname, rc); - return rc; - } - - if (mdtidxp) - *mdtidxp = index; - - rc = ioctl(fd, opc, data); - if (rc == -1) - rc = -errno; - else - rc = 0; - close(fd); - return rc; -} - -int llapi_fid2path(const char *device, const char *fidstr, char *buf, - int buflen, long long *recno, int *linkno) -{ - const char *fidstr_orig = fidstr; - struct lu_fid fid; - struct getinfo_fid2path *gf; - char *a; - char *b; - int rc; - - while (*fidstr == '[') - fidstr++; - - sscanf(fidstr, SFID, RFID(&fid)); - if (!fid_is_sane(&fid)) { - llapi_err_noerrno(LLAPI_MSG_ERROR, - "bad FID format '%s', should be [seq:oid:ver]" - " (e.g. "DFID")\n", fidstr_orig, - (unsigned long long)FID_SEQ_NORMAL, 2, 0); - return -EINVAL; - } - - gf = malloc(sizeof(*gf) + buflen); - if (gf == NULL) - return -ENOMEM; - - gf->gf_fid = fid; - gf->gf_recno = *recno; - gf->gf_linkno = *linkno; - gf->gf_pathlen = buflen; - - /* Take path or fsname */ - rc = root_ioctl(device, OBD_IOC_FID2PATH, gf, NULL, 0); - if (rc) - goto out_free; - - b = buf; - /* strip out instances of // */ - for (a = gf->gf_u.gf_path; *a != '\0'; a++) { - if ((*a == '/') && (*(a + 1) == '/')) - continue; - *b = *a; - b++; - } - *b = '\0'; - - if (buf[0] == '\0') { /* ROOT path */ - buf[0] = '/'; - buf[1] = '\0'; - } - - *recno = gf->gf_recno; - *linkno = gf->gf_linkno; - -out_free: - free(gf); - return rc; -} - -static int fid_from_lma(const char *path, int fd, struct lu_fid *fid) -{ - char buf[512]; - struct lustre_mdt_attrs *lma; - int rc; - - if (path == NULL) - rc = fgetxattr(fd, XATTR_NAME_LMA, buf, sizeof(buf)); - else - rc = lgetxattr(path, XATTR_NAME_LMA, buf, sizeof(buf)); - if (rc < 0) - return -errno; - lma = (struct lustre_mdt_attrs *)buf; - fid_le_to_cpu(fid, &lma->lma_self_fid); - return 0; -} - -int llapi_get_mdt_index_by_fid(int fd, const struct lu_fid *fid, - int *mdt_index) -{ - int rc; - - rc = ioctl(fd, LL_IOC_FID2MDTIDX, fid); - if (rc < 0) - return -errno; - - *mdt_index = rc; - - return rc; -} - -int llapi_fd2fid(int fd, struct lu_fid *fid) -{ - int rc; - - memset(fid, 0, sizeof(*fid)); - - rc = ioctl(fd, LL_IOC_PATH2FID, fid) < 0 ? -errno : 0; - if (rc == -EINVAL || rc == -ENOTTY) - rc = fid_from_lma(NULL, fd, fid); - - return rc; -} - -int llapi_path2fid(const char *path, struct lu_fid *fid) -{ - int fd, rc; - - memset(fid, 0, sizeof(*fid)); - fd = open(path, O_RDONLY | O_NONBLOCK | O_NOFOLLOW); - if (fd < 0) { - if (errno == ELOOP || errno == ENXIO) - return fid_from_lma(path, -1, fid); - return -errno; - } - - rc = llapi_fd2fid(fd, fid); - if (rc == -EINVAL || rc == -ENOTTY) - rc = fid_from_lma(path, -1, fid); - - close(fd); - return rc; -} - -int llapi_fd2parent(int fd, unsigned int linkno, struct lu_fid *parent_fid, - char *name, size_t name_size) -{ - struct getparent *gp; - int rc; - - gp = malloc(sizeof(*gp) + name_size); - if (gp == NULL) - return -ENOMEM; - - gp->gp_linkno = linkno; - gp->gp_name_size = name_size; - - rc = ioctl(fd, LL_IOC_GETPARENT, gp); - if (rc < 0) { - rc = -errno; - goto err_free; - } - - *parent_fid = gp->gp_fid; - - strncpy(name, gp->gp_name, name_size); - name[name_size - 1] = '\0'; - -err_free: - free(gp); - return rc; -} - -int llapi_path2parent(const char *path, unsigned int linkno, - struct lu_fid *parent_fid, char *name, size_t name_size) -{ - int fd; - int rc; - - fd = open(path, O_RDONLY | O_NONBLOCK | O_NOFOLLOW); - if (fd < 0) - return -errno; - - rc = llapi_fd2parent(fd, linkno, parent_fid, name, name_size); - close(fd); - return rc; -} - int llapi_get_connect_flags(const char *mnt, __u64 *flags) { int root; @@ -5559,32 +6015,6 @@ out: } /** - * Attempt to open a file with Lustre file identifier \a fid - * and return an open file descriptor. - * - * \param[in] lustre_dir path within Lustre filesystem containing \a fid - * \param[in] fid Lustre file identifier of file to open - * \param[in] flags open() flags - * - * \retval non-negative file descriptor on successful open - * \retval -1 if an error occurred - */ -int llapi_open_by_fid(const char *lustre_dir, const struct lu_fid *fid, - int flags) -{ - char mntdir[PATH_MAX]; - char path[PATH_MAX]; - int rc; - - rc = llapi_search_mounts(lustre_dir, 0, mntdir, NULL); - if (rc != 0) - return -1; - - snprintf(path, sizeof(path), "%s/.lustre/fid/"DFID, mntdir, PFID(fid)); - return open(path, flags); -} - -/** * Take group lock. * * \param fd File to lock.