X-Git-Url: https://git.whamcloud.com/?p=fs%2Flustre-release.git;a=blobdiff_plain;f=lustre%2Futils%2Fliblustreapi.c;h=ca5debe6f3bfeb0d840eca9d6ad0d47bce68dd3d;hp=0f85d294b7891abcb953eb6b833b6b1d16b602ae;hb=9b0b7264a8d7a6a2abe681d15fefc88c27d20c1e;hpb=0f38a0b9db4f7c6c101ee55fe7b94d49a32eabe9 diff --git a/lustre/utils/liblustreapi.c b/lustre/utils/liblustreapi.c index 0f85d29..ca5debe 100644 --- a/lustre/utils/liblustreapi.c +++ b/lustre/utils/liblustreapi.c @@ -400,9 +400,54 @@ int llapi_ioctl_unpack(struct obd_ioctl_data *data, char *pbuf, int max_len) /* XXX: llapi_xxx() functions return negative values upon failure */ -int llapi_stripe_limit_check(unsigned long long stripe_size, int stripe_offset, - int stripe_count, int stripe_pattern) +int llapi_layout_search_ost(__u32 ost, char *pname, char *fsname) { + char ostname[MAX_OBD_NAME + 64]; + char *pool_name = pname; + int rc = 0; + + /** + * The current policy is that the pool does not have to exist at the + * setstripe time, see sanity-pfl/-flr tests. + * If this logic will change, re-enable it. + * + * if (pname && strlen(pname) == 0) + */ + pool_name = NULL; + + snprintf(ostname, sizeof(ostname), "%s-OST%04x_UUID", + fsname, ost); + rc = llapi_search_ost(fsname, pool_name, ostname); + if (rc <= 0) { + if (rc == 0) + rc = -ENODEV; + + llapi_error(LLAPI_MSG_ERROR, rc, + "%s: cannot find OST %s in %s", __func__, ostname, + pool_name != NULL ? "pool" : "system"); + return rc; + } + + return 0; +} + +/** + * Verify the setstripe parameters before using. + * This is a pair method for comp_args_to_layout()/llapi_layout_sanity_cb() + * when just 1 component or a non-PFL layout is given. + * + * \param[in] param stripe parameters + * \param[in] pool_name pool name + * \param[in] fsname lustre FS name + * + * \retval 0, success + * < 0, error code on failre + */ +static int llapi_stripe_param_verify(const struct llapi_stripe_param *param, + char **pool_name, + char *fsname) +{ + int count; static int page_size; int rc = 0; @@ -420,33 +465,94 @@ int llapi_stripe_limit_check(unsigned long long stripe_size, int stripe_offset, page_size, LOV_MIN_STRIPE_SIZE); } } - if (!llapi_stripe_size_is_aligned(stripe_size)) { + if (!llapi_stripe_size_is_aligned(param->lsp_stripe_size)) { rc = -EINVAL; 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); + param->lsp_stripe_size, page_size); goto out; } - if (!llapi_stripe_index_is_valid(stripe_offset)) { + if (!llapi_stripe_index_is_valid(param->lsp_stripe_offset)) { rc = -EINVAL; llapi_error(LLAPI_MSG_ERROR, rc, "error: bad stripe offset %d", - stripe_offset); + param->lsp_stripe_offset); goto out; } - if (!llapi_stripe_count_is_valid(stripe_count)) { + if (llapi_stripe_size_is_too_big(param->lsp_stripe_size)) { rc = -EINVAL; - llapi_error(LLAPI_MSG_ERROR, rc, "error: bad stripe count %d", - stripe_count); + llapi_error(LLAPI_MSG_ERROR, rc, + "error: stripe size '%llu' over 4GB limit", + param->lsp_stripe_size); goto out; } - if (llapi_stripe_size_is_too_big(stripe_size)) { + + count = param->lsp_stripe_count; + if (param->lsp_stripe_pattern == LOV_PATTERN_MDT) { rc = -EINVAL; llapi_error(LLAPI_MSG_ERROR, rc, - "error: stripe size '%llu' over 4GB limit", - (unsigned long long)stripe_size); + "Invalid pattern: %d, must be specified with -E\n", + param->lsp_stripe_pattern); goto out; + } else { + if (!llapi_stripe_count_is_valid(count)) { + rc = -EINVAL; + llapi_error(LLAPI_MSG_ERROR, rc, + "Invalid stripe count %d\n", count); + goto out; + } } + /* Make sure we have a good pool */ + if (*pool_name != NULL) { + if (!llapi_pool_name_is_valid(pool_name, fsname)) { + rc = -EINVAL; + llapi_error(LLAPI_MSG_ERROR, rc, + "Pool '%s' is not on filesystem '%s'", + *pool_name, fsname); + goto out; + } + + /* Make sure the pool exists and is non-empty */ + rc = llapi_search_ost(fsname, *pool_name, NULL); + if (rc < 1) { + char *err = rc == 0 ? "has no OSTs" : "does not exist"; + + rc = -EINVAL; + llapi_error(LLAPI_MSG_ERROR, rc, "pool '%s.%s' %s", + fsname, *pool_name, err); + goto out; + } + rc = 0; + } + + /* sanity check of target list */ + if (param->lsp_is_specific) { + bool found = false; + int i; + + for (i = 0; i < count; i++) { + rc = llapi_layout_search_ost(param->lsp_osts[i], + *pool_name, fsname); + if (rc) + goto out; + + /* Make sure stripe offset is in OST list. */ + if (param->lsp_osts[i] == param->lsp_stripe_offset) + found = true; + } + if (!found) { + rc = -EINVAL; + llapi_error(LLAPI_MSG_ERROR, rc, + "%s: stripe offset '%d' is not in the target list", + __func__, param->lsp_stripe_offset); + goto out; + } + } else if (param->lsp_stripe_offset != -1) { + rc = llapi_layout_search_ost(param->lsp_stripe_offset, + *pool_name, fsname); + if (rc) + goto out; + } out: errno = -rc; return rc; @@ -570,9 +676,9 @@ int llapi_file_open_param(const char *name, int flags, mode_t mode, const struct llapi_stripe_param *param) { char fsname[MAX_OBD_NAME + 1] = { 0 }; - char *pool_name = param->lsp_pool; struct lov_user_md *lum = NULL; - size_t lum_size = sizeof(*lum); + char *pool_name = param->lsp_pool; + size_t lum_size; int fd, rc; /* Make sure we are on a Lustre file system */ @@ -585,82 +691,17 @@ int llapi_file_open_param(const char *name, int flags, mode_t mode, } /* Check if the stripe pattern is sane. */ - rc = llapi_stripe_limit_check(param->lsp_stripe_size, - param->lsp_stripe_offset, - param->lsp_stripe_count, - param->lsp_stripe_pattern); + rc = llapi_stripe_param_verify(param, &pool_name, fsname); if (rc != 0) return rc; - /* Make sure we have a good pool */ - if (pool_name != NULL) { - /* - * 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) { - *ptr = '.'; - llapi_err_noerrno(LLAPI_MSG_ERROR, - "Pool '%s' is not on filesystem '%s'", - pool_name, fsname); - return -EINVAL; - } - pool_name = ptr + 1; - } - - /* Make sure the pool exists and is non-empty */ - rc = llapi_search_ost(fsname, pool_name, NULL); - if (rc < 1) { - char *err = rc == 0 ? "has no OSTs" : "does not exist"; - - llapi_err_noerrno(LLAPI_MSG_ERROR, "pool '%s.%s' %s", - fsname, pool_name, err); - return -EINVAL; - } - - lum_size = sizeof(struct lov_user_md_v3); - } - - /* sanity check of target list */ - if (param->lsp_is_specific) { - char ostname[MAX_OBD_NAME + 64]; - bool found = false; - int i; - - for (i = 0; i < param->lsp_stripe_count; i++) { - snprintf(ostname, sizeof(ostname), "%s-OST%04x_UUID", - fsname, param->lsp_osts[i]); - rc = llapi_search_ost(fsname, pool_name, ostname); - if (rc <= 0) { - if (rc == 0) - rc = -ENODEV; - - llapi_error(LLAPI_MSG_ERROR, rc, - "%s: cannot find OST %s in %s", - __func__, ostname, - pool_name != NULL ? - "pool" : "system"); - return rc; - } - - /* Make sure stripe offset is in OST list. */ - if (param->lsp_osts[i] == param->lsp_stripe_offset) - found = true; - } - if (!found) { - llapi_error(LLAPI_MSG_ERROR, -EINVAL, - "%s: stripe offset '%d' is not in the target list", - __func__, param->lsp_stripe_offset); - return -EINVAL; - } - + if (param->lsp_is_specific) lum_size = lov_user_md_size(param->lsp_stripe_count, LOV_USER_MAGIC_SPECIFIC); - } + else if (pool_name) + lum_size = sizeof(struct lov_user_md_v3); + else + lum_size = sizeof(*lum); lum = calloc(1, lum_size); if (lum == NULL) @@ -735,6 +776,18 @@ retry_open: return fd; } +int llapi_file_is_encrypted(int fd) +{ + unsigned long flags; + int rc; + + rc = ioctl(fd, FS_IOC_GETFLAGS, &flags); + if (rc == -1) + return -errno; + + return !!(flags & LUSTRE_ENCRYPT_FL); +} + int llapi_file_open_pool(const char *name, int flags, int mode, unsigned long long stripe_size, int stripe_offset, int stripe_count, int stripe_pattern, char *pool_name) @@ -962,6 +1015,8 @@ static inline void param2lmu(struct lmv_user_md *lmu, lmu->lum_stripe_count = param->lsp_stripe_count; lmu->lum_stripe_offset = param->lsp_stripe_offset; lmu->lum_hash_type = param->lsp_stripe_pattern; + lmu->lum_max_inherit = param->lsp_max_inherit; + lmu->lum_max_inherit_rr = param->lsp_max_inherit_rr; if (param->lsp_pool != NULL) strncpy(lmu->lum_pool_name, param->lsp_pool, LOV_MAXPOOLNAME); if (param->lsp_is_specific) { @@ -1086,6 +1141,9 @@ int llapi_dir_create(const char *name, mode_t mode, data.ioc_inlbuf2 = (char *)lmu; data.ioc_inllen2 = lmu_size; data.ioc_type = mode; + if (param->lsp_is_create) + /* borrow obdo1.o_flags to store this flag */ + data.ioc_obdo1.o_flags = OBD_FL_OBDMDEXISTS; rc = llapi_ioctl_pack(&data, &buf, sizeof(rawbuf)); if (rc) { llapi_error(LLAPI_MSG_ERROR, rc, @@ -1653,6 +1711,34 @@ free_path: /* wrapper for lfs.c and obd.c */ int llapi_poollist(const char *name) { + int poolcount, rc, i; + char *buf, **pools; + + rc = llapi_get_poolbuf(name, &buf, &pools, &poolcount); + if (rc) + return rc; + + for (i = 0; i < poolcount; i++) + llapi_printf(LLAPI_MSG_NORMAL, "%s\n", pools[i]); + free(buf); + + return 0; +} + +/** + * Get buffer that holds uuids and the list of pools in a filesystem. + * + * \param name filesystem name or path + * \param buf bufffer that has to be freed if function returns 0 + * \param pools pointer to the list of pools in buffer + * \param poolcount number of pools + * + * \return 0 when found at least 1 pool, i.e. poolcount > 0 + * \retval -error failure + */ +int llapi_get_poolbuf(const char *name, char **buf, + char ***pools, int *poolcount) +{ /* * list of pool names (assume that pool count is smaller * than OST count) @@ -1660,7 +1746,7 @@ int llapi_poollist(const char *name) char **list, *buffer = NULL, *fsname = (char *)name; char *poolname = NULL, *tmp = NULL, data[16]; enum param_filter type = FILTER_BY_PATH; - int obdcount, bufsize, rc, nb, i; + int obdcount, bufsize, rc, nb; if (name == NULL) return -EINVAL; @@ -1712,11 +1798,15 @@ retry_get_pools: goto retry_get_pools; } - for (i = 0; i < nb; i++) - llapi_printf(LLAPI_MSG_NORMAL, "%s\n", list[i]); rc = (nb < 0 ? nb : 0); + if (!rc) { + *buf = buffer; + *pools = list; + *poolcount = nb; + } err: - if (buffer) + /* Don't free buffer, it will be used later */ + if (rc && buffer) free(buffer); if (fsname != NULL && type == FILTER_BY_FS_NAME) free(fsname); @@ -1728,6 +1818,11 @@ typedef int (semantic_func_t)(char *path, int p, int *d, #define OBD_NOT_FOUND (-1) +static bool lmv_is_foreign(__u32 magic) +{ + return magic == LMV_MAGIC_FOREIGN; +} + static void find_param_fini(struct find_param *param) { if (param->fp_migrate) @@ -1825,6 +1920,8 @@ static int cb_get_dirstripe(char *path, int *d, struct find_param *param) int ret; bool did_nofollow = false; + if (!d || *d < 0) + return -ENOTDIR; again: param->fp_lmv_md->lum_stripe_count = param->fp_lmv_stripe_count; if (param->fp_get_default_lmv) @@ -1867,7 +1964,7 @@ again: int lmv_size; /* if foreign LMV case, fake stripes number */ - if (param->fp_lmv_md->lum_magic == LMV_MAGIC_FOREIGN) { + if (lmv_is_foreign(param->fp_lmv_md->lum_magic)) { struct lmv_foreign_md *lfm; lfm = (struct lmv_foreign_md *)param->fp_lmv_md; @@ -1903,6 +2000,7 @@ again: } goto again; } + return ret; } @@ -2873,7 +2971,8 @@ static void lov_dump_user_lmm_header(struct lov_user_md *lum, char *path, space, prefix, (uintmax_t)lmm_oi_id(&lum->lmm_oi)); } - if ((verbose & (VERBOSE_DETAIL | VERBOSE_DFID)) && !is_dir) { + + if (verbose & (VERBOSE_DETAIL | VERBOSE_DFID)) { __u64 seq; __u32 oid; __u32 ver; @@ -2881,30 +2980,51 @@ 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 - * 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 - * like a FID with { oi_id = mds_seq, oi_seq = mds_oid } so the - * ostid union lu_fid { f_seq = mds_seq, f_oid = mds_oid } - * worked properly (especially since IGIF FIDs use mds_inum as - * the FID SEQ), but unfortunately that didn't happen. - * - * Print it to look like an IGIF FID, even though the fields - * are reversed on disk, so that it makes sense to userspace. - * - * Don't use ostid_id() and ostid_seq(), since they assume the - * 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. - */ - 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 ? - 0 : (__u32)lmm_oi_id(&lum->lmm_oi); - ver = (__u32)(lmm_oi_id(&lum->lmm_oi) >> 32); + + if (is_dir) { + struct lu_fid dir_fid; + + rc = llapi_path2fid(path, &dir_fid); + if (rc) + llapi_error(LLAPI_MSG_ERROR, rc, + "Cannot determine directory fid."); + + seq = dir_fid.f_seq; + oid = dir_fid.f_oid; + ver = dir_fid.f_ver; + } else { + /* + * 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 like a + * FID with { oi_id = mds_seq, oi_seq = mds_oid } so + * the ostid union lu_fid { f_seq = mds_seq, + * f_oid = mds_oid } worked properly (especially since + * IGIF FIDs use mds_inum as the FID SEQ), but + * unfortunately that didn't happen. + * + * Print it to look like an IGIF FID, even though the + * fields are reversed on disk, so that it makes sense + * to userspace. + * + * Don't use ostid_id() and ostid_seq(), since they + * assume the 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. + */ + 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 ? + 0 : (__u32)lmm_oi_id(&lum->lmm_oi); + ver = (__u32)(lmm_oi_id(&lum->lmm_oi) >> 32); + } + if (yaml) llapi_printf(LLAPI_MSG_NORMAL, DFID_NOBRACE"\n", (unsigned long long)seq, oid, ver); @@ -3211,10 +3331,56 @@ void lmv_dump_user_lmm(struct lmv_user_md *lum, char *pool_name, llapi_printf(LLAPI_MSG_NORMAL, ",bad_type"); if (flags & LMV_HASH_FLAG_LOST_LMV) llapi_printf(LLAPI_MSG_NORMAL, ",lost_lmv"); + if (flags & LMV_HASH_FLAG_FIXED) + llapi_printf(LLAPI_MSG_NORMAL, ",fixed"); + if (flags & ~LMV_HASH_FLAG_KNOWN) + llapi_printf(LLAPI_MSG_NORMAL, ",unknown_%04x", + flags & ~LMV_HASH_FLAG_KNOWN); - separator = "\n"; + if (verbose & VERBOSE_HASH_TYPE && !yaml) + separator = " "; + else + separator = "\n"; + } + + if ((verbose & VERBOSE_INHERIT) && lum->lum_magic == LMV_USER_MAGIC) { + llapi_printf(LLAPI_MSG_NORMAL, "%s", separator); + if (verbose & ~VERBOSE_INHERIT) + llapi_printf(LLAPI_MSG_NORMAL, "lmv_max_inherit: "); + if (lum->lum_max_inherit == LMV_INHERIT_UNLIMITED) + llapi_printf(LLAPI_MSG_NORMAL, "-1"); + else if (lum->lum_max_inherit == LMV_INHERIT_NONE) + llapi_printf(LLAPI_MSG_NORMAL, "0"); + else + llapi_printf(LLAPI_MSG_NORMAL, "%hhu", + lum->lum_max_inherit); + if (verbose & VERBOSE_INHERIT && !yaml) + separator = " "; + else + separator = "\n"; + } + + if ((verbose & VERBOSE_INHERIT_RR) && + lum->lum_magic == LMV_USER_MAGIC && + lum->lum_stripe_offset == LMV_OFFSET_DEFAULT) { + llapi_printf(LLAPI_MSG_NORMAL, "%s", separator); + if (verbose & ~VERBOSE_INHERIT_RR) + llapi_printf(LLAPI_MSG_NORMAL, "lmv_max_inherit_rr: "); + if (lum->lum_max_inherit_rr == LMV_INHERIT_RR_UNLIMITED) + llapi_printf(LLAPI_MSG_NORMAL, "-1"); + else if (lum->lum_max_inherit_rr == LMV_INHERIT_RR_NONE) + llapi_printf(LLAPI_MSG_NORMAL, "0"); + else + llapi_printf(LLAPI_MSG_NORMAL, "%hhu", + lum->lum_max_inherit_rr); + if (verbose & VERBOSE_INHERIT_RR && !yaml) + separator = " "; + else + separator = "\n"; } + separator = "\n"; + if (verbose & VERBOSE_OBJID && lum->lum_magic != LMV_USER_MAGIC) { llapi_printf(LLAPI_MSG_NORMAL, "%s", separator); if (lum->lum_stripe_count > 0) @@ -3504,7 +3670,7 @@ static inline void lov_v1v3_pool_name(struct lov_user_md *v1, char *pool_name) { if (v1->lmm_magic == LOV_USER_MAGIC_V3) - snprintf(pool_name, LOV_MAXPOOLNAME, "%s", + snprintf(pool_name, LOV_MAXPOOLNAME + 1, "%s", ((struct lov_user_md_v3 *)v1)->lmm_pool_name); else pool_name[0] = '\0'; @@ -4005,7 +4171,7 @@ static void llapi_lov_dump_user_lmm(struct find_param *param, char *path, } } -int llapi_file_get_stripe(const char *path, struct lov_user_md *lum) +static int llapi_file_get_stripe1(const char *path, struct lov_user_md *lum) { const char *fname; char *dname; @@ -4047,6 +4213,31 @@ out_free: return rc; } +int llapi_file_get_stripe(const char *path, struct lov_user_md *lum) +{ + char *canon_path = NULL; + int rc, rc2; + + rc = llapi_file_get_stripe1(path, lum); + if (!(rc == -ENOTTY || rc == -ENODATA)) + goto out; + + /* Handle failure due to symlinks by dereferencing path manually. */ + canon_path = canonicalize_file_name(path); + if (canon_path == NULL) + goto out; /* Keep original rc. */ + + rc2 = llapi_file_get_stripe1(canon_path, lum); + if (rc2 < 0) + goto out; /* Keep original rc. */ + + rc = 0; +out: + free(canon_path); + + return rc; +} + int llapi_file_lookup(int dirfd, const char *name) { struct obd_ioctl_data data = { 0 }; @@ -4491,7 +4682,7 @@ static int find_check_foreign(struct find_param *param) struct lmv_foreign_md *lfm; lfm = (void *)param->fp_lmv_md; - if (lfm->lfm_magic != LMV_MAGIC_FOREIGN) { + if (lmv_is_foreign(lfm->lfm_magic)) { if (param->fp_foreign_type == LU_FOREIGN_TYPE_UNKNOWN) return param->fp_exclude_foreign ? 1 : -1; return -1; @@ -4697,6 +4888,35 @@ static int fget_projid(int fd, int *projid) return 0; } +/* + * Check that the file's permissions in *st matches the one in find_param + */ +static int check_file_permissions(const struct find_param *param, + mode_t mode) +{ + int decision = 0; + + mode &= 07777; + + switch (param->fp_perm_sign) { + case LFS_FIND_PERM_EXACT: + decision = (mode == param->fp_perm); + break; + case LFS_FIND_PERM_ALL: + decision = ((mode & param->fp_perm) == param->fp_perm); + break; + case LFS_FIND_PERM_ANY: + decision = ((mode & param->fp_perm) != 0); + break; + } + + if ((param->fp_exclude_perm && decision) + || (!param->fp_exclude_perm && !decision)) + return -1; + else + return 1; +} + static int cb_find_init(char *path, int p, int *dp, void *data, struct dirent64 *de) { @@ -4726,16 +4946,21 @@ static int cb_find_init(char *path, int p, int *dp, } /* See if we can check the file type from the dirent. */ - if (param->fp_type != 0 && de != NULL && de->d_type != DT_UNKNOWN) { - checked_type = 1; + if (de != NULL && de->d_type != DT_UNKNOWN) { + if (param->fp_type != 0) { + checked_type = 1; - if (DTTOIF(de->d_type) == param->fp_type) { - if (param->fp_exclude_type) - goto decided; - } else { - if (!param->fp_exclude_type) - goto decided; + if (DTTOIF(de->d_type) == param->fp_type) { + if (param->fp_exclude_type) + goto decided; + } else { + if (!param->fp_exclude_type) + goto decided; + } } + if ((param->fp_check_mdt_count || param->fp_hash_type || + param->fp_check_hash_flag) && de->d_type != DT_DIR) + goto decided; } ret = 0; @@ -4751,30 +4976,73 @@ static int cb_find_init(char *path, int p, int *dp, param->fp_check_size || param->fp_check_blocks || find_check_lmm_info(param) || param->fp_check_mdt_count || param->fp_hash_type || - param->fp_check_hash_flag) + param->fp_check_hash_flag || param->fp_perm_sign) decision = 0; if (param->fp_type != 0 && checked_type == 0) decision = 0; if (decision == 0) { - if (d != -1 && (param->fp_check_mdt_count || - param->fp_hash_type || param->fp_check_foreign || - param->fp_check_hash_flag)) { + if (d != -1 && + (param->fp_check_mdt_count || param->fp_hash_type || + param->fp_check_hash_flag || param->fp_check_foreign)) { param->fp_get_lmv = 1; ret = cb_get_dirstripe(path, &d, param); 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; + if (errno == ENODATA) { + ret = 0; + if (param->fp_check_mdt_count || + param->fp_hash_type || + param->fp_check_hash_flag) { + param->fp_lmv_md->lum_stripe_count = 0; + param->fp_lmv_md->lum_hash_type = 0; + } + if (param->fp_check_foreign) { + if (param->fp_exclude_foreign) + goto print; + goto decided; + } + } else { + return ret; } - return ret; + } + + if (param->fp_check_mdt_count) { + if (lmv_is_foreign(param->fp_lmv_md->lum_magic)) + goto decided; + + decision = find_value_cmp(param->fp_lmv_md->lum_stripe_count, + param->fp_mdt_count, + param->fp_mdt_count_sign, + param->fp_exclude_mdt_count, 1, 0); + if (decision == -1) + goto decided; + } + + if (param->fp_hash_type) { + __u32 found; + __u32 type = param->fp_lmv_md->lum_hash_type & + LMV_HASH_TYPE_MASK; + + if (lmv_is_foreign(param->fp_lmv_md->lum_magic)) + goto decided; + + found = (1 << type) & param->fp_hash_type; + if ((found && param->fp_exclude_hash_type) || + (!found && !param->fp_exclude_hash_type)) + goto decided; + } + + if (param->fp_check_hash_flag) { + __u32 flags = param->fp_lmv_md->lum_hash_type & + ~LMV_HASH_TYPE_MASK; + + if (lmv_is_foreign(param->fp_lmv_md->lum_magic)) + goto decided; + + if (!(flags & param->fp_hash_inflags) || + (flags & param->fp_hash_exflags)) + goto decided; } } @@ -4839,7 +5107,18 @@ static int cb_find_init(char *path, int p, int *dp, } } + /* Check the file permissions from the stat info */ + if (param->fp_perm_sign) { + decision = check_file_permissions(param, lmd->lmd_stx.stx_mode); + if (decision == -1) + goto decided; + } + if (param->fp_type && !checked_type) { + if ((param->fp_check_mdt_count || param->fp_check_hash_flag || + param->fp_hash_type) && !S_ISDIR(lmd->lmd_stx.stx_mode)) + goto decided; + if ((lmd->lmd_stx.stx_mode & S_IFMT) == param->fp_type) { if (param->fp_exclude_type) goto decided; @@ -4903,61 +5182,12 @@ static int cb_find_init(char *path, int p, int *dp, goto decided; } - 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, - param->fp_mdt_count_sign, - param->fp_exclude_mdt_count, 1, 0); - if (decision == -1) - goto decided; - } - if (param->fp_check_layout) { decision = find_check_layout(param); if (decision == -1) goto decided; } - if (param->fp_hash_type) { - __u32 found; - __u32 type = param->fp_lmv_md->lum_hash_type & - LMV_HASH_TYPE_MASK; - - if (param->fp_lmv_md->lum_magic == LMV_MAGIC_FOREIGN) { - decision = -1; - goto decided; - } - - found = (1 << type) & param->fp_hash_type; - if ((found && param->fp_exclude_hash_type) || - (!found && !param->fp_exclude_hash_type)) { - decision = -1; - goto decided; - } - } - - if (param->fp_check_hash_flag) { - __u32 flags = param->fp_lmv_md->lum_hash_type & - ~LMV_HASH_TYPE_MASK; - - if (param->fp_lmv_md->lum_magic == LMV_MAGIC_FOREIGN) { - decision = -1; - goto decided; - } - - if (!(flags & param->fp_hash_inflags) || - (flags & param->fp_hash_exflags)) { - decision = -1; - goto decided; - } - } - /* If an OBD UUID is specified but none matches, skip this file. */ if ((param->fp_obd_uuid && param->fp_obd_index == OBD_NOT_FOUND) || (param->fp_mdt_uuid && param->fp_mdt_index == OBD_NOT_FOUND)) @@ -5184,12 +5414,9 @@ obd_matches: goto decided; } -foreign: - llapi_printf(LLAPI_MSG_NORMAL, "%s", path); - if (param->fp_zero_end) - llapi_printf(LLAPI_MSG_NORMAL, "%c", '\0'); - else - llapi_printf(LLAPI_MSG_NORMAL, "\n"); +print: + llapi_printf(LLAPI_MSG_NORMAL, "%s%c", path, + param->fp_zero_end ? '\0' : '\n'); decided: ret = 0; @@ -5247,6 +5474,9 @@ static int cb_migrate_mdt_init(char *path, int p, int *dp, data.ioc_inlbuf2 = (char *)lmu; data.ioc_inllen2 = lmv_user_md_size(lmu->lum_stripe_count, lmu->lum_magic); + /* reach bottom? */ + if (param->fp_depth == param->fp_max_depth) + data.ioc_type = MDS_MIGRATE_NSONLY; ret = llapi_ioctl_pack(&data, &rawbuf, sizeof(raw)); if (ret != 0) { llapi_error(LLAPI_MSG_ERROR, ret, @@ -5288,6 +5518,11 @@ migrate: } out: + /* Do not get down anymore? */ + if (param->fp_depth == param->fp_max_depth) + ret = 1; + param->fp_depth++; + if (dp != NULL) { /* * If the directory is being migration, we need @@ -5821,39 +6056,6 @@ int llapi_get_connect_flags(const char *mnt, __u64 *flags) } /** - * Get a 64-bit value representing the version of file data pointed by fd. - * - * Each write or truncate, flushed on OST, will change this value. You can use - * this value to verify if file data was modified. This only checks the file - * data, not metadata. - * - * \param flags 0: no flush pages, usually used it the process has already - * taken locks; - * LL_DV_RD_FLUSH: OSTs will take LCK_PR to flush dirty pages - * from clients; - * LL_DV_WR_FLUSH: OSTs will take LCK_PW to flush all caching - * pages from clients. - * - * \retval 0 on success. - * \retval -errno on error. - */ -int llapi_get_data_version(int fd, __u64 *data_version, __u64 flags) -{ - int rc; - struct ioc_data_version idv; - - idv.idv_flags = (__u32)flags; - - rc = ioctl(fd, LL_IOC_DATA_VERSION, &idv); - if (rc) - rc = -errno; - else - *data_version = idv.idv_version; - - return rc; -} - -/** * Flush cached pages from all clients. * * \param fd File descriptor @@ -5867,301 +6069,3 @@ int llapi_file_flush(int fd) return llapi_get_data_version(fd, &dv, LL_DV_WR_FLUSH); } -/* - * Fetch layout version from OST objects. Layout version on OST objects are - * only set when the file is a mirrored file AND after the file has been - * written at least once. - * - * It actually fetches the least layout version from the objects. - */ -int llapi_get_ost_layout_version(int fd, __u32 *layout_version) -{ - int rc; - struct ioc_data_version idv = { 0 }; - - rc = ioctl(fd, LL_IOC_DATA_VERSION, &idv); - if (rc) - rc = -errno; - else - *layout_version = idv.idv_layout_version; - - return rc; -} - -/* - * Create a file without any name and open it for read/write - * - * - file is created as if it were a standard file in the given \a directory - * - file does not appear in \a directory and mtime does not change because - * the filename is handled specially by the Lustre MDS. - * - file is destroyed at final close - * - * \param[in] directory directory from which to inherit layout/MDT idx - * \param[in] mdt_idx MDT index on which the file is created, - * \a idx == -1 means no specific MDT is requested - * \param[in] mode standard open(2) mode - * \param[in] stripe_param stripe parameters. May be NULL. - * - * \retval a file descriptor on success. - * \retval -errno on error. - */ -int llapi_create_volatile_param(const char *directory, int mdt_idx, - int open_flags, mode_t mode, - const struct llapi_stripe_param *stripe_param) -{ - char file_path[PATH_MAX]; - int saved_errno = errno; - int fd; - unsigned int rnumber; - int rc; - - do { - rnumber = random(); - if (mdt_idx == -1) - rc = snprintf(file_path, sizeof(file_path), - "%s/" LUSTRE_VOLATILE_HDR "::%.4X", - directory, rnumber); - else - rc = snprintf(file_path, sizeof(file_path), - "%s/" LUSTRE_VOLATILE_HDR ":%.4X:%.4X", - directory, mdt_idx, rnumber); - - if (rc < 0 || rc >= sizeof(file_path)) - return -ENAMETOOLONG; - - /* - * Either open O_WRONLY or O_RDWR, creating RDONLY - * is non-sensical here - */ - if ((open_flags & O_ACCMODE) == O_RDONLY) - open_flags = O_RDWR | (open_flags & ~O_ACCMODE); - - open_flags |= O_CREAT | O_EXCL | O_NOFOLLOW; - - if (stripe_param != NULL) { - fd = llapi_file_open_param(file_path, open_flags, - mode, stripe_param); - if (fd < 0) - rc = fd; - } else { - fd = open(file_path, open_flags, mode); - if (fd < 0) - rc = -errno; - } - } while (fd < 0 && rc == -EEXIST); - - if (fd < 0) { - llapi_error(LLAPI_MSG_ERROR, rc, - "Cannot create volatile file '%s' in '%s'", - file_path + strlen(directory) + 1 + - LUSTRE_VOLATILE_HDR_LEN, - directory); - return rc; - } - - /* - * Unlink file in case this wasn't a Lustre filesystem and the magic - * volatile filename wasn't handled as intended. The effect is the - * same. If volatile open was supported then we expect unlink() to - * return -ENOENT. - */ - (void)unlink(file_path); - - /* - * Since we are returning successfully we restore errno (and - * mask out possible EEXIST from open() and ENOENT from unlink(). - */ - errno = saved_errno; - - return fd; -} - -/* - * Create a file without any name open it for read/write - * - * - file is created as if it were a standard file in the given \a directory - * - file does not appear in \a directory and mtime does not change because - * the filename is handled specially by the Lustre MDS. - * - file is removed at final close - * - file modes are rw------- since it doesn't make sense to have a read-only - * or write-only file that cannot be opened again. - * - if user wants another mode it must use fchmod() on the open file, no - * security problems arise because it cannot be opened by another process. - * - * \param[in] directory directory from which to inherit layout/MDT idx - * \param[in] idx MDT index on which the file is created, - * \a idx == -1 means no specific MDT is requested - * \param[in] open_flags standard open(2) flags - * - * \retval a file descriptor on success. - * \retval -errno on error. - */ -int llapi_create_volatile_idx(const char *directory, int mdt_idx, - int open_flags) -{ - return llapi_create_volatile_param(directory, mdt_idx, open_flags, - S_IRUSR | S_IWUSR, NULL); -} - -/** - * Swap the layouts between 2 file descriptors - * the 2 files must be open for writing - * first fd received the ioctl, second fd is passed as arg - * this is assymetric but avoid use of root path for ioctl - */ -int llapi_fswap_layouts_grouplock(int fd1, int fd2, __u64 dv1, __u64 dv2, - int gid, __u64 flags) -{ - struct lustre_swap_layouts lsl; - struct stat st1; - struct stat st2; - int rc; - - if (flags & (SWAP_LAYOUTS_KEEP_ATIME | SWAP_LAYOUTS_KEEP_MTIME)) { - rc = fstat(fd1, &st1); - if (rc < 0) - return -errno; - - rc = fstat(fd2, &st2); - if (rc < 0) - return -errno; - } - lsl.sl_fd = fd2; - lsl.sl_flags = flags; - lsl.sl_gid = gid; - lsl.sl_dv1 = dv1; - lsl.sl_dv2 = dv2; - rc = ioctl(fd1, LL_IOC_LOV_SWAP_LAYOUTS, &lsl); - if (rc < 0) - return -errno; - - if (flags & (SWAP_LAYOUTS_KEEP_ATIME | SWAP_LAYOUTS_KEEP_MTIME)) { - struct timeval tv1[2]; - struct timeval tv2[2]; - - memset(tv1, 0, sizeof(tv1)); - memset(tv2, 0, sizeof(tv2)); - - if (flags & SWAP_LAYOUTS_KEEP_ATIME) { - tv1[0].tv_sec = st1.st_atime; - tv2[0].tv_sec = st2.st_atime; - } else { - tv1[0].tv_sec = st2.st_atime; - tv2[0].tv_sec = st1.st_atime; - } - - if (flags & SWAP_LAYOUTS_KEEP_MTIME) { - tv1[1].tv_sec = st1.st_mtime; - tv2[1].tv_sec = st2.st_mtime; - } else { - tv1[1].tv_sec = st2.st_mtime; - tv2[1].tv_sec = st1.st_mtime; - } - - rc = futimes(fd1, tv1); - if (rc < 0) - return -errno; - - rc = futimes(fd2, tv2); - if (rc < 0) - return -errno; - } - - return 0; -} - -int llapi_fswap_layouts(int fd1, int fd2, __u64 dv1, __u64 dv2, __u64 flags) -{ - int rc; - int grp_id; - - do - grp_id = random(); - while (grp_id == 0); - - rc = llapi_fswap_layouts_grouplock(fd1, fd2, dv1, dv2, grp_id, flags); - if (rc < 0) - return rc; - - return 0; -} - -/** - * Swap the layouts between 2 files - * the 2 files are open in write - */ -int llapi_swap_layouts(const char *path1, const char *path2, - __u64 dv1, __u64 dv2, __u64 flags) -{ - int fd1, fd2, rc; - - fd1 = open(path1, O_WRONLY | O_LOV_DELAY_CREATE); - if (fd1 < 0) { - rc = -errno; - llapi_error(LLAPI_MSG_ERROR, rc, - "error: cannot open '%s' for write", path1); - goto out; - } - - fd2 = open(path2, O_WRONLY | O_LOV_DELAY_CREATE); - if (fd2 < 0) { - rc = -errno; - llapi_error(LLAPI_MSG_ERROR, rc, - "error: cannot open '%s' for write", path2); - goto out_close; - } - - rc = llapi_fswap_layouts(fd1, fd2, dv1, dv2, flags); - if (rc < 0) - llapi_error(LLAPI_MSG_ERROR, rc, - "error: cannot swap layout between '%s' and '%s'", - path1, path2); - - close(fd2); -out_close: - close(fd1); -out: - return rc; -} - -/** - * Take group lock. - * - * \param fd File to lock. - * \param gid Group Identifier. - * - * \retval 0 on success. - * \retval -errno on failure. - */ -int llapi_group_lock(int fd, int gid) -{ - int rc; - - rc = ioctl(fd, LL_IOC_GROUP_LOCK, gid); - if (rc < 0) { - rc = -errno; - llapi_error(LLAPI_MSG_ERROR, rc, "cannot get group lock"); - } - return rc; -} - -/** - * Put group lock. - * - * \param fd File to unlock. - * \param gid Group Identifier. - * - * \retval 0 on success. - * \retval -errno on failure. - */ -int llapi_group_unlock(int fd, int gid) -{ - int rc; - - rc = ioctl(fd, LL_IOC_GROUP_UNLOCK, gid); - if (rc < 0) { - rc = -errno; - llapi_error(LLAPI_MSG_ERROR, rc, "cannot put group lock"); - } - return rc; -}