From 5a76aee24476e7c063d8b48ff70cbf322734c167 Mon Sep 17 00:00:00 2001 From: Niu Yawei Date: Thu, 6 Apr 2017 07:59:49 +0800 Subject: [PATCH] LU-8998 lfs: user space tools for PFL * 'lfs getstripe' to support composite file: --component-count: Display component count only; --component-id|-I [comp_id]: When 'comp_id' is provided, display components matching the provided 'copm_id', otherwise, display component ID only; --component-flags [flags]: When the 'flags' is provided, dispaly components contains the provided 'flags', otherwise, display component flags only; --component-start [[+-]start]: When '[+-]start' is provided, display components which have 'at most' or 'at least' or exactly same extent start, otherwise, display component extent start only; --component-end|-E [[+-]end]: When '[+-]end' is provided, display components which have 'at most' or 'at least' or exactly sme extent end, otherwise, display component extent end only; * 'lfs find' to support composite file: --component-count <[+-]count>: Find composite files according to component count; --component-flags : Find composite files according to component flags; --component-start <[+-]start>: Find composite files according to component extent start; --component-end|-E <[+-]end>: Find composite files according to component extent end; * 'lfs setstripe' to support composite file: --component-del [-I | --component-flags ] filename Delete specified component(s) from existing composite file; --component-add -E [stripe options] -E [stripe options] ...: Add component(s) to an existing composite file; -E [stripe options] -E [stripe options] ...: Create composite file with specifed layout components; * 'lfs migrate' to support migrate composite files: - composite layout-> plain layout; - plain layout -> composite layout; - composite layout -> composite layout; Reviewed-on: https://review.whamcloud.com/24867 Signed-off-by: Niu Yawei Change-Id: Ib0d3eeb7927cf83a173099c474df6539d1264370 Reviewed-by: Andreas Dilger Reviewed-by: Jinshan Xiong --- lustre/include/lustre/lustre_idl.h | 87 +++- lustre/include/lustre/lustre_ostid.h | 54 ++ lustre/include/lustre/lustreapi.h | 32 +- lustre/include/lustre_fid.h | 56 -- lustre/utils/lfs.c | 958 +++++++++++++++++++++++++++++------ lustre/utils/liblustreapi.c | 905 ++++++++++++++++++++++++++------- 6 files changed, 1669 insertions(+), 423 deletions(-) diff --git a/lustre/include/lustre/lustre_idl.h b/lustre/include/lustre/lustre_idl.h index c31a3c4..aa961de 100644 --- a/lustre/include/lustre/lustre_idl.h +++ b/lustre/include/lustre/lustre_idl.h @@ -236,12 +236,93 @@ enum { }; /** + * Different FID Format + * http://arch.lustre.org/index.php?title=Interoperability_fids_zfs#NEW.0 + * + * FID: + * File IDentifier generated by client from range allocated by the seq service. + * First 0x400 sequences [2^33, 2^33 + 0x400] are reserved for system use. Note + * that on ldiskfs MDTs that IGIF FIDs can use inode numbers starting at 12, + * but this is in the IGIF SEQ rangeand does not conflict with assigned FIDs. + * + * IGIF: + * Inode and Generation In FID, a surrogate FID used to globally identify an + * existing object on OLD formatted MDT file system. This would only be used on + * MDT0 in a DNE filesystem, because there are not expected to be any OLD + * formatted DNE filesystems. Belongs to a sequence in [12, 2^32 - 1] range, + * where sequence number is inode number, and inode generation is used as OID. + * NOTE: This assumes no more than 2^32-1 inodes exist in the MDT filesystem, + * which is the maximum possible for an ldiskfs backend. NOTE: This assumes + * that the reserved ext3/ext4/ldiskfs inode numbers [0-11] are never visible + * to clients, which has always been true. + * + * IDIF: + * Object ID in FID, a surrogate FID used to globally identify an existing + * object on OLD formatted OST file system. Belongs to a sequence in + * [2^32, 2^33 - 1]. Sequence number is calculated as: + * 1 << 32 | (ost_index << 16) | ((objid >> 32) & 0xffff) + * that is, SEQ consists of 16-bit OST index, and higher 16 bits of object ID. + * The generation of unique SEQ values per OST allows the IDIF FIDs to be + * identified in the FLD correctly. The OID field is calculated as: + * objid & 0xffffffff + * that is, it consists of lower 32 bits of object ID. NOTE This assumes that + * no more than 2^48-1 objects have ever been created on an OST, and that no + * more than 65535 OSTs are in use. Both are very reasonable assumptions (can + * uniquely map all objects on an OST that created 1M objects per second for 9 + * years, or combinations thereof). + * + * OST_MDT0: + * Surrogate FID used to identify an existing object on OLD formatted OST + * filesystem. Belongs to the reserved sequence 0, and is used internally prior + * to the introduction of FID-on-OST, at which point IDIF will be used to + * identify objects as residing on a specific OST. + * + * LLOG: + * For Lustre Log objects the object sequence 1 is used. This is compatible with + * both OLD and NEW.1 namespaces, as this SEQ number is in the ext3/ldiskfs + * reserved inode range and does not conflict with IGIF sequence numbers. + * + * ECHO: + * For testing OST IO performance the object sequence 2 is used. This is + * compatible with both OLD and NEW.1 namespaces, as this SEQ number is in the + * ext3/ldiskfs reserved inode range and does not conflict with IGIF sequence + * numbers. + * + * OST_MDT1 .. OST_MAX: + * For testing with multiple MDTs the object sequence 3 through 9 is used, + * allowing direct mapping of MDTs 1 through 7 respectively, for a total of 8 + * MDTs including OST_MDT0. This matches the legacy CMD project "group" + * mappings. However, this SEQ range is only for testing prior to any production + * DNE release, as the objects in this range conflict across all OSTs, as the + * OST index is not part of the FID. + * + * + * For compatibility with existing OLD OST network protocol structures, the FID + * must map onto the o_id and o_gr in a manner that ensures existing objects are + * identified consistently for IO, as well as onto the lock namespace to ensure + * both IDIFs map onto the same objects for IO as well as resources in the DLM. + * + * DLM OLD OBIF/IDIF: + * resource[] = {o_id, o_seq, 0, 0}; // o_seq == 0 for production releases + * + * DLM NEW.1 FID (this is the same for both the MDT and OST): + * resource[] = {SEQ, OID, VER, HASH}; + * + * Note that for mapping IDIF values to DLM resource names the o_id may be + * larger than the 2^33 reserved sequence numbers for IDIF, so it is possible + * for the o_id numbers to overlap FID SEQ numbers in the resource. However, in + * all production releases the OLD o_seq field is always zero, and all valid FID + * OID values are non-zero, so the lock resources will not collide. + * + * For objects within the IDIF range, group extraction (non-CMD) will be: + * o_id = (fid->f_seq & 0x7fff) << 16 | fid->f_oid; + * o_seq = 0; // formerly group number + */ + +/** * Note that reserved SEQ numbers below 12 will conflict with ldiskfs * inodes in the IGIF namespace, so these reserved SEQ numbers can be * used for other purposes and not risk collisions with existing inodes. - * - * Different FID Format - * http://arch.lustre.org/index.php?title=Interoperability_fids_zfs#NEW.0 */ enum fid_seq { FID_SEQ_OST_MDT0 = 0, diff --git a/lustre/include/lustre/lustre_ostid.h b/lustre/include/lustre/lustre_ostid.h index aebb33e..4e1122d 100644 --- a/lustre/include/lustre/lustre_ostid.h +++ b/lustre/include/lustre/lustre_ostid.h @@ -239,4 +239,58 @@ static inline void fid_to_lmm_oi(const struct lu_fid *fid, oi->oi.oi_seq = fid_seq(fid); } +/** + * Unpack an OST object id/seq (group) into a FID. This is needed for + * converting all obdo, lmm, lsm, etc. 64-bit id/seq pairs into proper + * FIDs. Note that if an id/seq is already in FID/IDIF format it will + * be passed through unchanged. Only legacy OST objects in "group 0" + * will be mapped into the IDIF namespace so that they can fit into the + * struct lu_fid fields without loss. + */ +static inline int ostid_to_fid(struct lu_fid *fid, const struct ost_id *ostid, + __u32 ost_idx) +{ + __u64 seq = ostid_seq(ostid); + + if (ost_idx > 0xffff) { + CERROR("bad ost_idx, "DOSTID" ost_idx:%u\n", POSTID(ostid), + ost_idx); + return -EBADF; + } + + if (fid_seq_is_mdt0(seq)) { + __u64 oid = ostid_id(ostid); + + /* This is a "legacy" (old 1.x/2.early) OST object in "group 0" + * that we map into the IDIF namespace. It allows up to 2^48 + * objects per OST, as this is the object namespace that has + * been in production for years. This can handle create rates + * of 1M objects/s/OST for 9 years, or combinations thereof. + */ + if (oid >= IDIF_MAX_OID) { + CERROR("bad MDT0 id(1), "DOSTID" ost_idx:%u\n", + POSTID(ostid), ost_idx); + return -EBADF; + } + fid->f_seq = fid_idif_seq(oid, ost_idx); + /* truncate to 32 bits by assignment */ + fid->f_oid = oid; + /* in theory, not currently used */ + fid->f_ver = oid >> 48; + } else if (!fid_seq_is_default(seq)) { + /* This is either an IDIF object, which identifies objects + * across all OSTs, or a regular FID. The IDIF namespace + * maps legacy OST objects into the FID namespace. In both + * cases, we just pass the FID through, no conversion needed. + */ + if (ostid->oi_fid.f_ver) { + CERROR("bad MDT0 id(2), "DOSTID" ost_idx:%u\n", + POSTID(ostid), ost_idx); + return -EBADF; + } + *fid = ostid->oi_fid; + } + + return 0; +} #endif diff --git a/lustre/include/lustre/lustreapi.h b/lustre/include/lustre/lustreapi.h index 62eb67d..ba6c25d 100644 --- a/lustre/include/lustre/lustreapi.h +++ b/lustre/include/lustre/lustreapi.h @@ -146,7 +146,10 @@ extern int llapi_file_lookup(int dirfd, const char *name); #define VERBOSE_DEFAULT (VERBOSE_COUNT | VERBOSE_SIZE | \ VERBOSE_OFFSET | VERBOSE_POOL | \ VERBOSE_OBJID | VERBOSE_GENERATION | \ - VERBOSE_LAYOUT | VERBOSE_HASH_TYPE) + VERBOSE_LAYOUT | VERBOSE_HASH_TYPE | \ + VERBOSE_COMP_COUNT | VERBOSE_COMP_FLAGS | \ + VERBOSE_COMP_START | VERBOSE_COMP_END | \ + VERBOSE_COMP_ID) struct find_param { unsigned int fp_max_depth; @@ -165,11 +168,14 @@ struct find_param { /* these need to be signed values */ int fp_size_sign:2, fp_stripe_size_sign:2, - fp_stripe_count_sign:2; + fp_stripe_count_sign:2, + fp_comp_start_sign:2, + fp_comp_end_sign:2, + fp_comp_count_sign:2; unsigned long long fp_size; unsigned long long fp_size_units; - unsigned long fp_zero_end:1, + unsigned long long fp_zero_end:1, fp_recursive:1, fp_exclude_pattern:1, fp_exclude_type:1, @@ -195,7 +201,17 @@ struct find_param { fp_check_layout:1, fp_exclude_layout:1, fp_get_default_lmv:1, /* Get default LMV */ - fp_migrate:1; + fp_migrate:1, + fp_check_comp_count:1, + fp_exclude_comp_count:1, + fp_check_comp_flags:1, + fp_exclude_comp_flags:1, + fp_check_comp_start:1, + fp_exclude_comp_start:1, + fp_check_comp_end:1, + fp_exclude_comp_end:1, + fp_check_comp_id:1, + fp_exclude_comp_id:1; int fp_verbose; int fp_quiet; @@ -229,6 +245,14 @@ struct find_param { unsigned long long fp_stripe_count; __u32 fp_layout; + __u32 fp_comp_count; + __u32 fp_comp_flags; + __u32 fp_comp_id; + unsigned long long fp_comp_start; + unsigned long long fp_comp_start_units; + unsigned long long fp_comp_end; + unsigned long long fp_comp_end_units; + /* In-process parameters. */ unsigned long fp_got_uuids:1, fp_obds_printed:1; diff --git a/lustre/include/lustre_fid.h b/lustre/include/lustre_fid.h index 9021834..f85449a 100644 --- a/lustre/include/lustre_fid.h +++ b/lustre/include/lustre_fid.h @@ -661,62 +661,6 @@ static inline void ost_fid_build_resid(const struct lu_fid *fid, } } -/** - * Unpack an OST object id/seq (group) into a FID. This is needed for - * converting all obdo, lmm, lsm, etc. 64-bit id/seq pairs into proper - * FIDs. Note that if an id/seq is already in FID/IDIF format it will - * be passed through unchanged. Only legacy OST objects in "group 0" - * will be mapped into the IDIF namespace so that they can fit into the - * struct lu_fid fields without loss. For reference see: - * http://arch.lustre.org/index.php?title=Interoperability_fids_zfs - */ -static inline int ostid_to_fid(struct lu_fid *fid, const struct ost_id *ostid, - u32 ost_idx) -{ - u64 seq = ostid_seq(ostid); - - if (ost_idx > 0xffff) { - CERROR("bad ost_idx, "DOSTID" ost_idx:%u\n", POSTID(ostid), - ost_idx); - return -EBADF; - } - - if (fid_seq_is_mdt0(seq)) { - u64 oid = ostid_id(ostid); - - /* This is a "legacy" (old 1.x/2.early) OST object in "group 0" - * that we map into the IDIF namespace. It allows up to 2^48 - * objects per OST, as this is the object namespace that has - * been in production for years. This can handle create rates - * of 1M objects/s/OST for 9 years, or combinations thereof. - */ - if (oid >= IDIF_MAX_OID) { - CERROR("bad MDT0 id(1), "DOSTID" ost_idx:%u\n", - POSTID(ostid), ost_idx); - return -EBADF; - } - fid->f_seq = fid_idif_seq(oid, ost_idx); - /* truncate to 32 bits by assignment */ - fid->f_oid = oid; - /* in theory, not currently used */ - fid->f_ver = oid >> 48; - } else if (likely(!fid_seq_is_default(seq))) { - /* This is either an IDIF object, which identifies objects - * across all OSTs, or a regular FID. The IDIF namespace - * maps legacy OST objects into the FID namespace. In both - * cases, we just pass the FID through, no conversion needed. - */ - if (ostid->oi_fid.f_ver) { - CERROR("bad MDT0 id(2), "DOSTID" ost_idx:%u\n", - POSTID(ostid), ost_idx); - return -EBADF; - } - *fid = ostid->oi_fid; - } - - return 0; -} - static inline void ost_fid_from_resid(struct lu_fid *fid, const struct ldlm_res_id *name, int ost_idx) diff --git a/lustre/utils/lfs.c b/lustre/utils/lfs.c index b6665a1..f522852 100644 --- a/lustre/utils/lfs.c +++ b/lustre/utils/lfs.c @@ -120,7 +120,8 @@ static int lfs_list_commands(int argc, char **argv); " [--stripe-index|-i ]\n" \ " [--stripe-size|-S ]\n" \ " [--pool|-p ]\n" \ - " [--ost|-o ]\n" + " [--ost|-o ]\n" \ + " [--component-end|-E ]\n" #define SSM_HELP_COMMON \ "\tstripe_size: Number of bytes on each OST (0 filesystem default)\n" \ @@ -134,13 +135,17 @@ static int lfs_list_commands(int argc, char **argv); "\t -o ,-,\n" \ "\t Or:\n" \ "\t -o -o - -o \n" \ - "\t If --pool is set with --ost, then the OSTs\n" \ - "\t must be the members of the pool." + "\t If --pool is set with --ost, then the OSTs\n" \ + "\t must be the members of the pool." \ + "\tcomp_end: Extent end of the component\n" \ + "\t Can be specified with k, m or g (in KB, MB and GB\n" \ + "\t respectively, -1 for EOF), it must be aligned with\n"\ + "\t the stripe_size\n" #define SETSTRIPE_USAGE \ SSM_CMD_COMMON("setstripe") \ " \n" \ - SSM_HELP_COMMON + SSM_HELP_COMMON \ #define MIGRATE_USAGE \ SSM_CMD_COMMON("migrate ") \ @@ -173,9 +178,24 @@ command_t cmdlist[] = { {"setstripe", lfs_setstripe, 0, "Create a new file with a specific striping pattern or\n" "set the default striping pattern on an existing directory or\n" - "delete the default striping pattern from an existing directory\n" - "usage: setstripe -d (to delete default striping)\n"\ + "delete the default striping pattern from an existing directory or\n" + "add layout component(s) to an existing composite file or\n" + "delete specified component(s) from an existing composite file\n\n" + "To delete default striping from an existing directory:\n" + "usage: setstripe -d \n" + " or\n" + "To delete component(s) from an existing composite file:\n" + "usage: setstripe --component-del [--component-id|-I ]\n" + " [--component-flags|-F ]\n" + " \n" + "\tcomp_id: Unique component ID\n" + "\tcomp_flags: 'init' indicating all instantiated components\n" + "\t-I and -F can't be specified at the same time\n" + " or\n" + "To add component(s) to an existing composite file:\n" + SSM_CMD_COMMON("setstripe --component-add") " or\n" + "To create a file with specified striping/composite layout:\n" SETSTRIPE_USAGE}, {"getstripe", lfs_getstripe, 0, "To list the striping info for a given file or files in a\n" @@ -185,6 +205,11 @@ command_t cmdlist[] = { " [--pool|-p] [--stripe-size|-S] [--directory|-d]\n" " [--mdt|-m] [--recursive|-r] [--raw|-R]\n" " [--layout|-L] [--fid|-F] [--generation|-g]\n" + " [--component-id|-I [comp_id]]\n" + " [--component-flags [comp_flags]]\n" + " [--component-count [comp_count]]\n" + " [--component-start [comp_start]]\n" + " [--component-end|-E [comp_end]]\n" " ..."}, {"setdirstripe", lfs_setdirstripe, 0, "To create a striped directory on a specified MDT. This can only\n" @@ -225,6 +250,10 @@ command_t cmdlist[] = { " [[!] --gid|-g|--group|-G |]\n" " [[!] --uid|-u|--user|-U |] [[!] --pool ]\n" " [[!] --layout|-L released,raid0]\n" + " [[!] --component-count [+-]]\n" + " [[!] --component-start [+-]N[kMGTPE]]\n" + " [[!] --component-end|-E [+-]N[kMGTPE]]\n" + " [[!] --component-flags ]\n" "\t !: used before an option indicates 'NOT' requested attribute\n" "\t -: used before a value indicates 'AT MOST' requested value\n" "\t +: used before a value indicates 'AT LEAST' requested value\n"}, @@ -622,8 +651,82 @@ static int migrate_nonblock(int fd, int fdv, const struct stat *st, return 0; } +static int lfs_component_set(char *fname, int comp_id, __u32 flags) +{ + return -ENOTSUP; +} + +static int lfs_component_del(char *fname, __u32 comp_id, __u32 flags) +{ + int rc = 0; + + if (flags != 0 && comp_id != 0) + return -EINVAL; + + /* LCME_FL_INIT is the only supported flag in PFL */ + if (flags != 0) { + if (flags & ~LCME_KNOWN_FLAGS) { + fprintf(stderr, "Invalid component flags %#x\n", flags); + return -EINVAL; + } + comp_id = LCME_ID_NONE | flags; + } else if (comp_id > LCME_ID_MAX) { + fprintf(stderr, "Invalid component id %u\n", comp_id); + return -EINVAL; + } + + rc = llapi_layout_file_comp_del(fname, comp_id); + if (rc) + fprintf(stderr, "Delete component %#x from %s failed. %s\n", + comp_id, fname, strerror(errno)); + return rc; +} + +static int lfs_component_add(char *fname, struct llapi_layout *layout) +{ + int rc; + + if (layout == NULL) + return -EINVAL; + + rc = llapi_layout_file_comp_add(fname, layout); + if (rc) + fprintf(stderr, "Add layout component(s) to %s failed. %s\n", + fname, strerror(errno)); + return rc; +} + +static int lfs_component_create(char *fname, int open_flags, mode_t open_mode, + struct llapi_layout *layout) +{ + struct stat st; + int fd; + + if (layout == NULL) + return -EINVAL; + + fd = lstat(fname, &st); + if (fd == 0 && S_ISDIR(st.st_mode)) { + open_flags = O_DIRECTORY | O_RDONLY; + fd = llapi_layout_file_open(fname, open_flags, open_mode, + layout); + } else { + fd = llapi_layout_file_create(fname, open_flags, open_mode, + layout); + } + + if (fd < 0) + fprintf(stderr, "%s %s failed. %s\n", + S_ISDIR(st.st_mode) ? + "Set default composite layout to " : + "Create composite file", + fname, strerror(errno)); + return fd; +} + static int lfs_migrate(char *name, __u64 migration_flags, - struct llapi_stripe_param *param) + struct llapi_stripe_param *param, + struct llapi_layout *layout) { int fd = -1; int fdv = -1; @@ -638,7 +741,7 @@ static int lfs_migrate(char *name, __u64 migration_flags, int rc; struct lov_user_md *lum = NULL; int lum_size; - int buf_size; + int buf_size = 1024 * 1024 * 4; bool have_lease_rdlck = false; struct stat st; struct stat stv; @@ -656,10 +759,12 @@ static int lfs_migrate(char *name, __u64 migration_flags, * (eg: no stripe) * in case of a real error, a later call will fail with better * error management */ - if (rc < 0) - buf_size = 1024 * 1024; - else - buf_size = lum->lmm_stripe_size; + if (rc == 0) { + if ((lum->lmm_magic == LOV_USER_MAGIC_V1 || + lum->lmm_magic == LOV_USER_MAGIC_V3) && + lum->lmm_stripe_size != 0) + buf_size = lum->lmm_stripe_size; + } /* open file, direct io */ /* even if the file is only read, WR mode is nedeed to allow @@ -715,6 +820,9 @@ static int lfs_migrate(char *name, __u64 migration_flags, } do { + int open_flags = O_WRONLY | O_CREAT | O_EXCL | O_NOFOLLOW; + mode_t open_mode = S_IRUSR | S_IWUSR; + random_value = random(); rc = snprintf(volatile_file, sizeof(volatile_file), "%s/%s:%.4X:%.4X", parent, LUSTRE_VOLATILE_HDR, @@ -725,9 +833,14 @@ static int lfs_migrate(char *name, __u64 migration_flags, } /* create, open a volatile file, use caching (ie no directio) */ - fdv = llapi_file_open_param(volatile_file, - O_WRONLY | O_CREAT | O_EXCL | O_NOFOLLOW, - S_IRUSR | S_IWUSR, param); + if (param != NULL) + fdv = llapi_file_open_param(volatile_file, open_flags, + open_mode, param); + else if (layout != NULL) + fdv = lfs_component_create(volatile_file, open_flags, + open_mode, layout); + else + fdv = -EINVAL; } while (fdv == -EEXIST); if (fdv < 0) { @@ -886,9 +999,277 @@ static int parse_targets(__u32 *osts, int size, int offset, char *arg) return rc < 0 ? rc : nr; } +static int verify_pool_name(char *prog_name, char *pool_name) +{ + char *ptr; + int rc; + + if (pool_name == NULL) + return 0; + + ptr = strchr(pool_name, '.'); + if (ptr == NULL) { + ptr = pool_name; + } else { + if (ptr == pool_name) { + fprintf(stderr, "error: %s: fsname is empty " + "in pool name '%s'\n", + prog_name, pool_name); + return -EINVAL; + } + ++ptr; + } + + rc = lustre_is_poolname_valid(ptr, 1, LOV_MAXPOOLNAME); + if (rc == -1) { + fprintf(stderr, "error: %s: poolname '%s' is empty\n", + prog_name, pool_name); + return -EINVAL; + } else if (rc == -2) { + fprintf(stderr, "error: %s: pool name '%s' is too long " + "(max is %d characters)\n", + prog_name, pool_name, LOV_MAXPOOLNAME); + return -EINVAL; + } else if (rc > 0) { + fprintf(stderr, "error: %s: char '%c' not allowed in " + "pool name '%s'\n", + prog_name, rc, pool_name); + return -EINVAL; + } + return rc; +} + +struct lfs_setstripe_args { + __u64 lsa_comp_end; + unsigned long long lsa_stripe_size; + int lsa_stripe_count; + int lsa_stripe_off; + __u32 lsa_comp_flags; + int lsa_nr_osts; + __u32 *lsa_osts; + char *lsa_pool_name; +}; + +static inline void setstripe_args_init(struct lfs_setstripe_args *lsa) +{ + memset(lsa, 0, sizeof(*lsa)); + lsa->lsa_stripe_off = -1; +} + +static inline bool setstripe_args_specified(struct lfs_setstripe_args *lsa) +{ + return (lsa->lsa_stripe_size != 0 || lsa->lsa_stripe_count != 0 || + lsa->lsa_stripe_off != -1 || lsa->lsa_pool_name != NULL || + lsa->lsa_comp_end != 0); +} + +static int comp_args_to_layout(struct llapi_layout **composite, + struct lfs_setstripe_args *lsa) +{ + struct llapi_layout *layout = *composite; + uint64_t prev_end = 0; + int i = 0, rc; + + if (layout == NULL) { + layout = llapi_layout_alloc(); + if (layout == NULL) { + fprintf(stderr, "Alloc llapi_layout failed. %s\n", + strerror(errno)); + return -ENOMEM; + } + *composite = layout; + } else { + uint64_t start; + + /* Get current component extent, current component + * must be the tail component. */ + rc = llapi_layout_comp_extent_get(layout, &start, &prev_end); + if (rc) { + fprintf(stderr, "Get comp extent failed. %s\n", + strerror(errno)); + return rc; + } + + rc = llapi_layout_comp_add(layout); + if (rc) { + fprintf(stderr, "Add component failed. %s\n", + strerror(errno)); + return rc; + } + } + + rc = llapi_layout_comp_extent_set(layout, prev_end, lsa->lsa_comp_end); + if (rc) { + fprintf(stderr, "Set extent [%lu, %llu) failed. %s\n", + prev_end, lsa->lsa_comp_end, strerror(errno)); + return rc; + } + + if (lsa->lsa_stripe_size != 0) { + rc = llapi_layout_stripe_size_set(layout, + lsa->lsa_stripe_size); + if (rc) { + fprintf(stderr, "Set stripe size %llu failed. %s\n", + lsa->lsa_stripe_size, strerror(errno)); + return rc; + } + } + + if (lsa->lsa_stripe_count != 0) { + rc = llapi_layout_stripe_count_set(layout, + lsa->lsa_stripe_count == -1 ? + LLAPI_LAYOUT_WIDE : + lsa->lsa_stripe_count); + if (rc) { + fprintf(stderr, "Set stripe count %d failed. %s\n", + lsa->lsa_stripe_count, strerror(errno)); + return rc; + } + } + + if (lsa->lsa_pool_name != NULL) { + rc = llapi_layout_pool_name_set(layout, lsa->lsa_pool_name); + if (rc) { + fprintf(stderr, "Set pool name: %s failed. %s\n", + lsa->lsa_pool_name, strerror(errno)); + return rc; + } + } + + if (lsa->lsa_nr_osts > 0) { + if (lsa->lsa_stripe_count > 0 && + lsa->lsa_nr_osts != lsa->lsa_stripe_count) { + fprintf(stderr, "stripe_count(%d) != nr_osts(%d)\n", + lsa->lsa_stripe_count, lsa->lsa_nr_osts); + return -EINVAL; + } + for (i = 0; i < lsa->lsa_nr_osts; i++) { + rc = llapi_layout_ost_index_set(layout, i, + lsa->lsa_osts[i]); + if (rc) + break; + } + } else if (lsa->lsa_stripe_off != -1) { + rc = llapi_layout_ost_index_set(layout, 0, lsa->lsa_stripe_off); + } + if (rc) { + fprintf(stderr, "Set ost index %d failed. %s\n", + i, strerror(errno)); + return rc; + } + + return 0; +} + +/* In 'lfs setstripe --component-add' mode, we need to fetch the extent + * end of the last component in the existing file, and adjust the + * first extent start of the components to be added accordingly. */ +static int adjust_first_extent(char *fname, struct llapi_layout *layout) +{ + struct llapi_layout *head; + uint64_t start, end, stripe_size, prev_end = 0; + int rc; + + if (layout == NULL) + return -EINVAL; + + head = llapi_layout_get_by_path(fname, 0); + if (head == NULL) { + fprintf(stderr, "Read layout from %s failed. %s\n", + fname, strerror(errno)); + return -EINVAL; + } + + /* Current component of 'head' should be tail of component list. */ + rc = llapi_layout_comp_extent_get(head, &start, &prev_end); + if (rc) { + fprintf(stderr, "Get prev extent failed. %s\n", + strerror(errno)); + llapi_layout_free(head); + return rc; + } + + llapi_layout_free(head); + + /* Make sure we use the first component of the layout to be added. */ + rc = llapi_layout_comp_move(layout, LLAPI_LAYOUT_COMP_POS_FIRST); + if (rc < 0) { + fprintf(stderr, "Move component cursor failed. %s\n", + strerror(errno)); + return rc; + } + + rc = llapi_layout_comp_extent_get(layout, &start, &end); + if (rc) { + fprintf(stderr, "Get extent failed. %s\n", strerror(errno)); + return rc; + } + + if (start > prev_end || end <= prev_end) { + fprintf(stderr, "First extent to be set [%lu, %lu) isn't " + "adjacent with the existing file extent end: %lu\n", + start, end, prev_end); + return -EINVAL; + } + + rc = llapi_layout_stripe_size_get(layout, &stripe_size); + if (rc) { + fprintf(stderr, "Get stripe size failed. %s\n", + strerror(errno)); + return rc; + } + + if (stripe_size != LLAPI_LAYOUT_DEFAULT && + (prev_end & (stripe_size - 1))) { + fprintf(stderr, "Stripe size %lu not aligned with %lu\n", + stripe_size, prev_end); + return -EINVAL; + } + + rc = llapi_layout_comp_extent_set(layout, prev_end, end); + if (rc) { + fprintf(stderr, "Set component extent [%lu, %lu) failed. %s\n", + prev_end, end, strerror(errno)); + return rc; + } + + return 0; +} + +static int comp_name2flags(__u32 *flags, char *name) +{ + char *ptr; + + if (name == NULL) + return -EINVAL; + + *flags = 0; + for (ptr = name; ; ptr = NULL) { + char *flg = strtok(ptr, ","); + if (flg == NULL) + break; + if (strcmp(flg, "init") == 0) + *flags |= LCME_FL_INIT; + else + return -EINVAL; + } + return (*flags == 0) ? -EINVAL : 0; +} + +enum { + LFS_POOL_OPT = 3, + LFS_COMP_COUNT_OPT, + LFS_COMP_START_OPT, + LFS_COMP_FLAGS_OPT, + LFS_COMP_DEL_OPT, + LFS_COMP_SET_OPT, + LFS_COMP_ADD_OPT +}; + /* functions */ static int lfs_setstripe(int argc, char **argv) { + struct lfs_setstripe_args lsa; struct llapi_stripe_param *param = NULL; struct find_param migrate_mdt_param = { .fp_max_depth = -1, @@ -897,26 +1278,27 @@ static int lfs_setstripe(int argc, char **argv) char *fname; int result; int result2 = 0; - unsigned long long st_size; - int st_offset, st_count; char *end; int c; int delete = 0; - char *stripe_size_arg = NULL; - char *stripe_off_arg = NULL; - char *stripe_count_arg = NULL; - char *pool_name_arg = NULL; char *mdt_idx_arg = NULL; unsigned long long size_units = 1; bool migrate_mode = false; bool migration_block = false; __u64 migration_flags = 0; __u32 osts[LOV_MAX_STRIPE_COUNT] = { 0 }; - int nr_osts = 0; + int comp_del = 0, comp_set = 0; + int comp_add = 0; + __u32 comp_id = 0; + struct llapi_layout *layout = NULL; struct option long_opts[] = { /* --block is only valid in migrate mode */ {"block", no_argument, 0, 'b'}, + {"component-add", no_argument, 0, LFS_COMP_ADD_OPT}, + {"component-del", no_argument, 0, LFS_COMP_DEL_OPT}, + {"component-flags", required_argument, 0, LFS_COMP_FLAGS_OPT}, + {"component-set", no_argument, 0, LFS_COMP_SET_OPT}, #if LUSTRE_VERSION_CODE < OBD_OCD_VERSION(2, 9, 59, 0) /* This formerly implied "stripe-count", but was explicitly * made "stripe-count" for consistency with other options, @@ -926,6 +1308,7 @@ static int lfs_setstripe(int argc, char **argv) {"stripe-count", required_argument, 0, 'c'}, {"stripe_count", required_argument, 0, 'c'}, {"delete", no_argument, 0, 'd'}, + {"component-end", required_argument, 0, 'E'}, #if LUSTRE_VERSION_CODE < OBD_OCD_VERSION(2, 9, 59, 0) /* This formerly implied "stripe-index", but was explicitly * made "stripe-index" for consistency with other options, @@ -934,6 +1317,7 @@ static int lfs_setstripe(int argc, char **argv) #endif {"stripe-index", required_argument, 0, 'i'}, {"stripe_index", required_argument, 0, 'i'}, + {"component-id", required_argument, 0, 'I'}, {"mdt", required_argument, 0, 'm'}, {"mdt-index", required_argument, 0, 'm'}, {"mdt_index", required_argument, 0, 'm'}, @@ -958,24 +1342,39 @@ static int lfs_setstripe(int argc, char **argv) {0, 0, 0, 0} }; - st_size = 0; - st_offset = -1; - st_count = 0; + setstripe_args_init(&lsa); if (strcmp(argv[0], "migrate") == 0) migrate_mode = true; - while ((c = getopt_long(argc, argv, "bc:di:m:no:p:s:S:v", + while ((c = getopt_long(argc, argv, "bc:dE:i:I:m:no:p:s:S:v", long_opts, NULL)) >= 0) { switch (c) { case 0: /* Long options. */ break; + case LFS_COMP_ADD_OPT: + comp_add = 1; + break; + case LFS_COMP_DEL_OPT: + comp_del = 1; + break; + case LFS_COMP_FLAGS_OPT: + result = comp_name2flags(&lsa.lsa_comp_flags, optarg); + if (result != 0) { + fprintf(stderr, "error: %s: bad comp flags " + "'%s'\n", argv[0], optarg); + goto error; + } + break; + case LFS_COMP_SET_OPT: + comp_set = 1; + break; case 'b': if (!migrate_mode) { fprintf(stderr, "--block is valid only for" " migrate mode\n"); - return CMD_HELP; + goto error; } migration_block = true; break; @@ -985,39 +1384,66 @@ static int lfs_setstripe(int argc, char **argv) fprintf(stderr, "warning: '--count' deprecated" ", use '--stripe-count' instead\n"); #endif - stripe_count_arg = optarg; + lsa.lsa_stripe_count = strtoul(optarg, &end, 0); + if (*end != '\0') { + fprintf(stderr, "error: %s: bad stripe count " + "'%s'\n", argv[0], optarg); + goto error; + } break; case 'd': /* delete the default striping pattern */ delete = 1; break; - case 'o': - nr_osts = parse_targets(osts, - sizeof(osts) / sizeof(__u32), - nr_osts, optarg); - if (nr_osts < 0) { - fprintf(stderr, - "error: %s: bad OST indices '%s'\n", - argv[0], optarg); - return CMD_HELP; + case 'E': + if (lsa.lsa_comp_end != 0) { + result = comp_args_to_layout(&layout, &lsa); + if (result) + goto error; + + setstripe_args_init(&lsa); } - if (st_offset == -1) /* first in the command line */ - st_offset = osts[0]; + if (!strncmp(optarg, "-1", strlen("-1")) || + !strncmp(optarg, "EOF", strlen("EOF")) || + !strncmp(optarg, "eof", strlen("eof"))) { + lsa.lsa_comp_end = LUSTRE_EOF; + } else { + result = llapi_parse_size(optarg, + &lsa.lsa_comp_end, + &size_units, 0); + if (result) { + fprintf(stderr, "error: %s: " + "bad component end '%s'\n", + argv[0], optarg); + goto error; + } + } break; case 'i': -#if LUSTRE_VERSION_CODE >= OBD_OCD_VERSION(2, 6, 53, 0) if (strcmp(argv[optind - 1], "--index") == 0) fprintf(stderr, "warning: '--index' deprecated" ", use '--stripe-index' instead\n"); -#endif - stripe_off_arg = optarg; + lsa.lsa_stripe_off = strtol(optarg, &end, 0); + if (*end != '\0') { + fprintf(stderr, "error: %s: bad stripe offset " + "'%s'\n", argv[0], optarg); + goto error; + } + break; + case 'I': + comp_id = strtoul(optarg, &end, 0); + if (*end != '\0' || comp_id == 0) { + fprintf(stderr, "error: %s: bad comp ID " + "'%s'\n", argv[0], optarg); + goto error; + } break; case 'm': if (!migrate_mode) { fprintf(stderr, "--mdt-index is valid only for" " migrate mode\n"); - return CMD_HELP; + goto error; } mdt_idx_arg = optarg; break; @@ -1025,10 +1451,31 @@ static int lfs_setstripe(int argc, char **argv) if (!migrate_mode) { fprintf(stderr, "--non-block is valid only for" " migrate mode\n"); - return CMD_HELP; + goto error; } migration_flags |= MIGRATION_NONBLOCK; break; + case 'o': + lsa.lsa_nr_osts = parse_targets(osts, + sizeof(osts) / sizeof(__u32), + lsa.lsa_nr_osts, optarg); + if (lsa.lsa_nr_osts < 0) { + fprintf(stderr, + "error: %s: bad OST indices '%s'\n", + argv[0], optarg); + goto error; + } + + lsa.lsa_osts = osts; + if (lsa.lsa_stripe_off == -1) + lsa.lsa_stripe_off = osts[0]; + break; + case 'p': + result = verify_pool_name(argv[0], optarg); + if (result) + goto error; + lsa.lsa_pool_name = optarg; + break; #if LUSTRE_VERSION_CODE < OBD_OCD_VERSION(2, 9, 59, 0) case 's': #if LUSTRE_VERSION_CODE >= OBD_OCD_VERSION(2, 6, 53, 0) @@ -1037,119 +1484,109 @@ static int lfs_setstripe(int argc, char **argv) #endif #endif /* LUSTRE_VERSION_CODE < OBD_OCD_VERSION(2, 9, 59, 0) */ case 'S': - stripe_size_arg = optarg; - break; - case 'p': - pool_name_arg = optarg; + result = llapi_parse_size(optarg, &lsa.lsa_stripe_size, + &size_units, 0); + if (result) { + fprintf(stderr, "error: %s: bad stripe size " + "'%s'\n", argv[0], optarg); + goto error; + } break; case 'v': if (!migrate_mode) { fprintf(stderr, "--verbose is valid only for" " migrate mode\n"); - return CMD_HELP; + goto error; } migrate_mdt_param.fp_verbose = VERBOSE_DETAIL; break; default: - return CMD_HELP; + goto error; } } fname = argv[optind]; - if (delete && - (stripe_size_arg != NULL || stripe_off_arg != NULL || - stripe_count_arg != NULL || pool_name_arg != NULL)) { - fprintf(stderr, "error: %s: cannot specify -d with " - "-s, -c, -o, or -p options\n", - argv[0]); - return CMD_HELP; + if (lsa.lsa_comp_end != 0) { + result = comp_args_to_layout(&layout, &lsa); + if (result) + goto error; } if (optind == argc) { fprintf(stderr, "error: %s: missing filename|dirname\n", argv[0]); - return CMD_HELP; + goto error; } - if (mdt_idx_arg != NULL && optind > 3) { - fprintf(stderr, "error: %s: cannot specify -m with other " - "options\n", argv[0]); - return CMD_HELP; + /* Only LCME_FL_INIT flags is used in PFL, and it shouldn't be + * altered by user space tool, so we don't need to support the + * --component-set for this moment. */ + if (comp_set != 0) { + fprintf(stderr, "error: %s: --component-set isn't supported.\n", + argv[0]); + goto error; } - if ((migration_flags & MIGRATION_NONBLOCK) && migration_block) { - fprintf(stderr, - "error: %s: cannot specify --non-block and --block\n", + if ((delete + comp_set + comp_del + comp_add) > 1) { + fprintf(stderr, "error: %s: can't specify --component-set, " + "--component-del, --component-add or -d together\n", argv[0]); - return CMD_HELP; + goto error; } - if (pool_name_arg != NULL) { - char *ptr; - int rc; + if (delete && (setstripe_args_specified(&lsa) || comp_id != 0 || + lsa.lsa_comp_flags != 0 || layout != NULL)) { + fprintf(stderr, "error: %s: can't specify -d with " + "-s, -c, -o, -p, -I, -F or -E options\n", + argv[0]); + goto error; + } - ptr = strchr(pool_name_arg, '.'); - if (ptr == NULL) { - ptr = pool_name_arg; - } else { - if ((ptr - pool_name_arg) == 0) { - fprintf(stderr, "error: %s: fsname is empty " - "in pool name '%s'\n", - argv[0], pool_name_arg); - return CMD_HELP; - } + if ((comp_set || comp_del) && + (setstripe_args_specified(&lsa) || layout != NULL)) { + fprintf(stderr, "error: %s: can't specify --component-del or " + "--component-set with -s, -c, -o, -p or -E options.\n", + argv[0]); + goto error; + } - ++ptr; - } + if (comp_del && comp_id != 0 && lsa.lsa_comp_flags != 0) { + fprintf(stderr, "error: %s: can't specify both -I and -F for " + "--component-del option.\n", argv[0]); + goto error; + } - rc = lustre_is_poolname_valid(ptr, 1, LOV_MAXPOOLNAME); - if (rc == -1) { - fprintf(stderr, "error: %s: poolname '%s' is " - "empty\n", - argv[0], pool_name_arg); - return CMD_HELP; - } else if (rc == -2) { - fprintf(stderr, "error: %s: pool name '%s' is too long " - "(max is %d characters)\n", - argv[0], pool_name_arg, LOV_MAXPOOLNAME); - return CMD_HELP; - } else if (rc > 0) { - fprintf(stderr, "error: %s: char '%c' not allowed in " - "pool name '%s'\n", - argv[0], rc, pool_name_arg); - return CMD_HELP; + if (comp_add) { + if (layout == NULL) { + fprintf(stderr, "error: %s: -E option must be present" + "in --component-add mode.\n", argv[0]); + goto error; } + result = adjust_first_extent(fname, layout); + if (result != 0) + goto error; } - /* get the stripe size */ - if (stripe_size_arg != NULL) { - result = llapi_parse_size(stripe_size_arg, &st_size, - &size_units, 0); - if (result) { - fprintf(stderr, "error: %s: bad stripe size '%s'\n", - argv[0], stripe_size_arg); - return CMD_HELP; - } + if (mdt_idx_arg != NULL && optind > 3) { + fprintf(stderr, "error: %s: cannot specify -m with other " + "options\n", argv[0]); + goto error; + } + + if ((migration_flags & MIGRATION_NONBLOCK) && migration_block) { + fprintf(stderr, + "error: %s: cannot specify --non-block and --block\n", + argv[0]); + goto error; + } + + /* support --component-id option for migrate later. */ + if (migrate_mode && comp_id != 0) { + fprintf(stderr, "error: %s: -I isn't supported yet.\n", + argv[0]); + goto error; } - /* get the stripe offset */ - if (stripe_off_arg != NULL) { - st_offset = strtol(stripe_off_arg, &end, 0); - if (*end != '\0') { - fprintf(stderr, "error: %s: bad stripe offset '%s'\n", - argv[0], stripe_off_arg); - return CMD_HELP; - } - } - /* get the stripe count */ - if (stripe_count_arg != NULL) { - st_count = strtoul(stripe_count_arg, &end, 0); - if (*end != '\0') { - fprintf(stderr, "error: %s: bad stripe count '%s'\n", - argv[0], stripe_count_arg); - return CMD_HELP; - } - } if (mdt_idx_arg != NULL) { /* initialize migrate mdt parameters */ @@ -1157,41 +1594,72 @@ static int lfs_setstripe(int argc, char **argv) if (*end != '\0') { fprintf(stderr, "error: %s: bad MDT index '%s'\n", argv[0], mdt_idx_arg); - return CMD_HELP; + goto error; } migrate_mdt_param.fp_migrate = 1; - } else { + } else if (layout == NULL) { /* initialize stripe parameters */ - param = calloc(1, offsetof(typeof(*param), lsp_osts[nr_osts])); + param = calloc(1, offsetof(typeof(*param), + lsp_osts[lsa.lsa_nr_osts])); if (param == NULL) { - fprintf(stderr, "error: %s: run out of memory\n", - argv[0]); - return CMD_HELP; + fprintf(stderr, "error: %s: %s\n", argv[0], + strerror(ENOMEM)); + goto error; } - param->lsp_stripe_size = st_size; - param->lsp_stripe_offset = st_offset; - param->lsp_stripe_count = st_count; + param->lsp_stripe_size = lsa.lsa_stripe_size; + param->lsp_stripe_offset = lsa.lsa_stripe_off; + param->lsp_stripe_count = lsa.lsa_stripe_count; param->lsp_stripe_pattern = 0; - param->lsp_pool = pool_name_arg; + param->lsp_pool = lsa.lsa_pool_name; param->lsp_is_specific = false; - if (nr_osts > 0) { - if (st_count > 0 && nr_osts != st_count) { + if (lsa.lsa_nr_osts > 0) { + if (lsa.lsa_stripe_count > 0 && + lsa.lsa_nr_osts != lsa.lsa_stripe_count) { fprintf(stderr, "error: %s: stripe count '%d' " "doesn't match the number of OSTs: %d\n" - , argv[0], st_count, nr_osts); + , argv[0], lsa.lsa_stripe_count, + lsa.lsa_nr_osts); free(param); - return CMD_HELP; + goto error; } param->lsp_is_specific = true; - param->lsp_stripe_count = nr_osts; - memcpy(param->lsp_osts, osts, sizeof(*osts) * nr_osts); + param->lsp_stripe_count = lsa.lsa_nr_osts; + memcpy(param->lsp_osts, osts, + sizeof(*osts) * lsa.lsa_nr_osts); } } for (fname = argv[optind]; fname != NULL; fname = argv[++optind]) { - if (!migrate_mode) { + char *op; + if (mdt_idx_arg != NULL) { + result = llapi_migrate_mdt(fname, &migrate_mdt_param); + op = "migrate mdt objects of"; + } else if (migrate_mode) { + result = lfs_migrate(fname, migration_flags, param, + layout); + op = "migrate ost objects of"; + } else if (comp_set != 0) { + result = lfs_component_set(fname, comp_id, + lsa.lsa_comp_flags); + op = "modify component flags of"; + } else if (comp_del != 0) { + result = lfs_component_del(fname, comp_id, + lsa.lsa_comp_flags); + op = "delete component of"; + } else if (comp_add != 0) { + result = lfs_component_add(fname, layout); + op = "add component to"; + } else if (layout != NULL) { + result = lfs_component_create(fname, O_CREAT | O_WRONLY, + 0644, layout); + if (result >= 0) { + close(result); + result = 0; + } + op = "create composite"; + } else { result = llapi_file_open_param(fname, O_CREAT | O_WRONLY, 0644, param); @@ -1199,26 +1667,26 @@ static int lfs_setstripe(int argc, char **argv) close(result); result = 0; } - } else if (mdt_idx_arg != NULL) { - result = llapi_migrate_mdt(fname, &migrate_mdt_param); - } else { - result = lfs_migrate(fname, migration_flags, param); + op = "create striped"; } if (result) { /* Save the first error encountered. */ if (result2 == 0) result2 = result; fprintf(stderr, "error: %s: %s file '%s' failed: %s\n", - argv[0], migrate_mode ? "migrate" : "create", - fname, - pool_name_arg != NULL && result == EINVAL ? + argv[0], op, fname, + lsa.lsa_pool_name != NULL && result == EINVAL ? "OST not in pool?" : strerror(errno)); continue; } } free(param); + llapi_layout_free(layout); return result2; +error: + llapi_layout_free(layout); + return CMD_HELP; } static int lfs_poollist(int argc, char **argv) @@ -1330,7 +1798,6 @@ static int name2layout(__u32 *layout, char *name) return 0; } -#define FIND_POOL_OPT 3 static int lfs_find(int argc, char **argv) { int c, rc; @@ -1341,15 +1808,20 @@ static int lfs_find(int argc, char **argv) .fp_quiet = 1, }; struct option long_opts[] = { - {"atime", required_argument, 0, 'A'}, - {"stripe-count", required_argument, 0, 'c'}, - {"stripe_count", required_argument, 0, 'c'}, - {"ctime", required_argument, 0, 'C'}, - {"maxdepth", required_argument, 0, 'D'}, - {"gid", required_argument, 0, 'g'}, - {"group", required_argument, 0, 'G'}, - {"stripe-index", required_argument, 0, 'i'}, - {"stripe_index", required_argument, 0, 'i'}, + {"atime", required_argument, 0, 'A'}, + {"component-count", required_argument, 0, LFS_COMP_COUNT_OPT}, + {"component-flags", required_argument, 0, LFS_COMP_FLAGS_OPT}, + {"component-start", required_argument, 0, LFS_COMP_START_OPT}, + {"stripe-count", required_argument, 0, 'c'}, + {"stripe_count", required_argument, 0, 'c'}, + {"ctime", required_argument, 0, 'C'}, + {"maxdepth", required_argument, 0, 'D'}, + {"component-end", required_argument, 0, 'E'}, + {"gid", required_argument, 0, 'g'}, + {"group", required_argument, 0, 'G'}, + {"stripe-index", required_argument, 0, 'i'}, + {"stripe_index", required_argument, 0, 'i'}, + /*{"component-id", required_argument, 0, 'I'},*/ {"layout", required_argument, 0, 'L'}, {"mdt", required_argument, 0, 'm'}, {"mdt-index", required_argument, 0, 'm'}, @@ -1360,7 +1832,7 @@ static int lfs_find(int argc, char **argv) {"obd", required_argument, 0, 'O'}, {"ost", required_argument, 0, 'O'}, /* no short option for pool, p/P already used */ - {"pool", required_argument, 0, FIND_POOL_OPT}, + {"pool", required_argument, 0, LFS_POOL_OPT}, {"print0", no_argument, 0, 'p'}, {"print", no_argument, 0, 'P'}, {"size", required_argument, 0, 's'}, @@ -1383,8 +1855,8 @@ static int lfs_find(int argc, char **argv) /* when getopt_long_only() hits '!' it returns 1, puts "!" in optarg */ while ((c = getopt_long_only(argc, argv, - "-A:c:C:D:g:G:i:L:m:M:n:O:Ppqrs:S:t:u:U:v", - long_opts, NULL)) >= 0) { + "-A:c:C:D:E:g:G:i:L:m:M:n:O:Ppqrs:S:t:u:U:v", + long_opts, NULL)) >= 0) { xtime = NULL; xsign = NULL; if (neg_opt) @@ -1445,6 +1917,53 @@ static int lfs_find(int argc, char **argv) if (rc) *xsign = rc; break; + case LFS_COMP_COUNT_OPT: + if (optarg[0] == '+') { + param.fp_comp_count_sign = -1; + optarg++; + } else if (optarg[0] == '-') { + param.fp_comp_count_sign = 1; + optarg++; + } + + param.fp_comp_count = strtoul(optarg, &endptr, 0); + if (*endptr != '\0') { + fprintf(stderr, "error: bad component count " + "'%s'\n", optarg); + goto err; + } + param.fp_check_comp_count = 1; + param.fp_exclude_comp_count = !!neg_opt; + break; + case LFS_COMP_FLAGS_OPT: + rc = comp_name2flags(¶m.fp_comp_flags, optarg); + if (rc) { + fprintf(stderr, "error: bad component flags " + "'%s'\n", optarg); + goto err; + } + param.fp_check_comp_flags = 1; + param.fp_exclude_comp_flags = !!neg_opt; + break; + case LFS_COMP_START_OPT: + if (optarg[0] == '+') { + param.fp_comp_start_sign = -1; + optarg++; + } else if (optarg[0] == '-') { + param.fp_comp_start_sign = 1; + optarg++; + } + + rc = llapi_parse_size(optarg, ¶m.fp_comp_start, + ¶m.fp_comp_start_units, 0); + if (rc) { + fprintf(stderr, "error: bad component start " + "'%s'\n", optarg); + goto err; + } + param.fp_check_comp_start = 1; + param.fp_exclude_comp_start = !!neg_opt; + break; case 'c': if (optarg[0] == '+') { param.fp_stripe_count_sign = -1; @@ -1467,6 +1986,25 @@ static int lfs_find(int argc, char **argv) case 'D': param.fp_max_depth = strtol(optarg, 0, 0); break; + case 'E': + if (optarg[0] == '+') { + param.fp_comp_end_sign = -1; + optarg++; + } else if (optarg[0] == '-') { + param.fp_comp_end_sign = 1; + optarg++; + } + + rc = llapi_parse_size(optarg, ¶m.fp_comp_end, + ¶m.fp_comp_end_units, 0); + if (rc) { + fprintf(stderr, "error: bad component end " + "'%s'\n", optarg); + goto err; + } + param.fp_check_comp_end = 1; + param.fp_exclude_comp_end = !!neg_opt; + break; case 'g': case 'G': rc = name2id(¶m.fp_gid, optarg, GROUP); @@ -1504,7 +2042,7 @@ static int lfs_find(int argc, char **argv) param.fp_exclude_uid = !!neg_opt; param.fp_check_uid = 1; break; - case FIND_POOL_OPT: + case LFS_POOL_OPT: if (strlen(optarg) > LOV_MAXPOOLNAME) { fprintf(stderr, "Pool name %s is too long" @@ -1714,6 +2252,9 @@ static int lfs_getstripe_internal(int argc, char **argv, struct find_param *param) { struct option long_opts[] = { + {"component-count", no_argument, 0, LFS_COMP_COUNT_OPT}, + {"component-flags", required_argument, 0, LFS_COMP_FLAGS_OPT}, + {"component-start", required_argument, 0, LFS_COMP_START_OPT}, #if LUSTRE_VERSION_CODE < OBD_OCD_VERSION(2, 9, 59, 0) /* This formerly implied "stripe-count", but was explicitly * made "stripe-count" for consistency with other options, @@ -1724,6 +2265,7 @@ static int lfs_getstripe_internal(int argc, char **argv, {"stripe_count", no_argument, 0, 'c'}, {"directory", no_argument, 0, 'd'}, {"default", no_argument, 0, 'D'}, + {"component-end", required_argument, 0, 'E'}, {"fid", no_argument, 0, 'F'}, {"generation", no_argument, 0, 'g'}, #if LUSTRE_VERSION_CODE < OBD_OCD_VERSION(2, 9, 59, 0) @@ -1734,6 +2276,7 @@ static int lfs_getstripe_internal(int argc, char **argv, #endif {"stripe-index", no_argument, 0, 'i'}, {"stripe_index", no_argument, 0, 'i'}, + {"component-id", required_argument, 0, 'I'}, {"layout", no_argument, 0, 'L'}, {"mdt", no_argument, 0, 'm'}, {"mdt-index", no_argument, 0, 'm'}, @@ -1766,8 +2309,9 @@ static int lfs_getstripe_internal(int argc, char **argv, {0, 0, 0, 0} }; int c, rc; + char *end, *tmp; - while ((c = getopt_long(argc, argv, "cdDFghiLmMoO:pqrRsSv", + while ((c = getopt_long(argc, argv, "cdDE:FghiI:LmMoO:pqrRsSv", long_opts, NULL)) != -1) { switch (c) { case 'O': @@ -1782,12 +2326,83 @@ static int lfs_getstripe_internal(int argc, char **argv, case 'q': param->fp_quiet++; break; + case LFS_COMP_COUNT_OPT: + param->fp_verbose |= VERBOSE_COMP_COUNT; + param->fp_max_depth = 0; + break; + case LFS_COMP_FLAGS_OPT: + if (optarg != NULL) { + rc = comp_name2flags(¶m->fp_comp_flags, + optarg); + if (rc != 0) { + param->fp_verbose |= + VERBOSE_COMP_FLAGS; + param->fp_max_depth = 0; + optind--; + } else { + param->fp_check_comp_flags = 1; + } + } else { + param->fp_verbose |= VERBOSE_COMP_FLAGS; + param->fp_max_depth = 0; + } + break; + case LFS_COMP_START_OPT: + if (optarg != NULL) { + tmp = optarg; + if (tmp[0] == '+') { + param->fp_comp_start_sign = 1; + tmp++; + } else if (tmp[0] == '-') { + param->fp_comp_start_sign = -1; + tmp++; + } + rc = llapi_parse_size(tmp, + ¶m->fp_comp_start, + ¶m->fp_comp_start_units, 0); + if (rc != 0) { + param->fp_verbose |= VERBOSE_COMP_START; + param->fp_max_depth = 0; + optind--; + } else { + param->fp_check_comp_start = 1; + } + } else { + param->fp_verbose |= VERBOSE_COMP_START; + param->fp_max_depth = 0; + } + break; case 'd': param->fp_max_depth = 0; break; case 'D': param->fp_get_default_lmv = 1; break; + case 'E': + if (optarg != NULL) { + tmp = optarg; + if (tmp[0] == '+') { + param->fp_comp_end_sign = 1; + tmp++; + } else if (tmp[0] == '-') { + param->fp_comp_end_sign = -1; + tmp++; + } + rc = llapi_parse_size(tmp, + ¶m->fp_comp_end, + ¶m->fp_comp_end_units, 0); + if (rc != 0) { + param->fp_verbose |= VERBOSE_COMP_END; + param->fp_max_depth = 0; + optind--; + } else { + param->fp_check_comp_end = 1; + } + } else { + param->fp_verbose |= VERBOSE_COMP_END; + param->fp_max_depth = 0; + } + break; case 'F': if (!(param->fp_verbose & VERBOSE_DETAIL)) { param->fp_verbose |= VERBOSE_DFID; @@ -1840,6 +2455,21 @@ static int lfs_getstripe_internal(int argc, char **argv, param->fp_max_depth = 0; } break; + case 'I': + if (optarg != NULL) { + param->fp_comp_id = strtoul(optarg, &end, 0); + if (*end != '\0') { + param->fp_verbose |= VERBOSE_COMP_ID; + param->fp_max_depth = 0; + optind--; + } else { + param->fp_check_comp_id = 1; + } + } else { + param->fp_max_depth = 0; + param->fp_verbose |= VERBOSE_COMP_ID; + } + break; case 'p': if (!(param->fp_verbose & VERBOSE_DETAIL)) { param->fp_verbose |= VERBOSE_POOL; @@ -1883,6 +2513,8 @@ static int lfs_getstripe_internal(int argc, char **argv, if (param->fp_recursive) param->fp_max_depth = -1; + else if (param->fp_verbose & VERBOSE_DETAIL) + param->fp_max_depth = 1; if (!param->fp_verbose) param->fp_verbose = VERBOSE_DEFAULT; diff --git a/lustre/utils/liblustreapi.c b/lustre/utils/liblustreapi.c index e936b95..abcf0df 100644 --- a/lustre/utils/liblustreapi.c +++ b/lustre/utils/liblustreapi.c @@ -2101,35 +2101,48 @@ int sattr_cache_get_defaults(const char *const fsname, return 0; } +enum lov_dump_flags { + LDF_IS_DIR = 0x0001, + LDF_IS_RAW = 0x0002, + LDF_INDENT = 0x0004, +}; + static void lov_dump_user_lmm_header(struct lov_user_md *lum, char *path, struct lov_user_ost_data_v1 *objects, - int is_dir, int verbose, int depth, - int raw, char *pool_name) + int verbose, int depth, char *pool_name, + enum lov_dump_flags flags) { + bool is_dir = flags & LDF_IS_DIR; + bool is_raw = flags & LDF_IS_RAW; + bool indent = flags & LDF_INDENT; char *prefix = is_dir ? "" : "lmm_"; char *separator = ""; + char *space = indent ? " " : ""; int rc; if (is_dir && lmm_oi_seq(&lum->lmm_oi) == FID_SEQ_LOV_DEFAULT) { lmm_oi_set_seq(&lum->lmm_oi, 0); - if (verbose & VERBOSE_DETAIL) - llapi_printf(LLAPI_MSG_NORMAL, "(Default) "); + if (!indent && (verbose & VERBOSE_DETAIL)) + llapi_printf(LLAPI_MSG_NORMAL, "%s(Default) ", space); } - if (depth && path && ((verbose != VERBOSE_OBJID) || !is_dir)) + if (!indent && depth && path && ((verbose != VERBOSE_OBJID) || !is_dir)) llapi_printf(LLAPI_MSG_NORMAL, "%s\n", path); if ((verbose & VERBOSE_DETAIL) && !is_dir) { - llapi_printf(LLAPI_MSG_NORMAL, "lmm_magic: 0x%08X\n", - lum->lmm_magic); - llapi_printf(LLAPI_MSG_NORMAL, "lmm_seq: %#jx\n", + llapi_printf(LLAPI_MSG_NORMAL, "%s%smagic: 0x%08X\n", + space, prefix, lum->lmm_magic); + llapi_printf(LLAPI_MSG_NORMAL, "%s%sseq: %#jx\n", + space, prefix, (uintmax_t)lmm_oi_seq(&lum->lmm_oi)); - llapi_printf(LLAPI_MSG_NORMAL, "lmm_object_id: %#jx\n", + llapi_printf(LLAPI_MSG_NORMAL, "%s%sobject_id: %#jx\n", + space, prefix, (uintmax_t)lmm_oi_id(&lum->lmm_oi)); } if ((verbose & (VERBOSE_DETAIL | VERBOSE_DFID)) && !is_dir) { if (verbose & ~VERBOSE_DFID) - llapi_printf(LLAPI_MSG_NORMAL, "lmm_fid: "); + 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 @@ -2158,10 +2171,10 @@ static void lov_dump_user_lmm_header(struct lov_user_md *lum, char *path, if (verbose & VERBOSE_COUNT) { if (verbose & ~VERBOSE_COUNT) - llapi_printf(LLAPI_MSG_NORMAL, "%sstripe_count: ", - prefix); + llapi_printf(LLAPI_MSG_NORMAL, "%s%sstripe_count: ", + space, prefix); if (is_dir) { - if (!raw && lum->lmm_stripe_count == 0) { + if (!is_raw && lum->lmm_stripe_count == 0) { unsigned int scount; rc = sattr_cache_get_defaults(NULL, path, &scount, NULL, @@ -2189,9 +2202,9 @@ static void lov_dump_user_lmm_header(struct lov_user_md *lum, char *path, if (verbose & VERBOSE_SIZE) { llapi_printf(LLAPI_MSG_NORMAL, "%s", separator); if (verbose & ~VERBOSE_SIZE) - llapi_printf(LLAPI_MSG_NORMAL, "%sstripe_size: ", - prefix); - if (is_dir && !raw && lum->lmm_stripe_size == 0) { + 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); @@ -2211,8 +2224,8 @@ static void lov_dump_user_lmm_header(struct lov_user_md *lum, char *path, if ((verbose & VERBOSE_LAYOUT) && !is_dir) { llapi_printf(LLAPI_MSG_NORMAL, "%s", separator); if (verbose & ~VERBOSE_LAYOUT) - llapi_printf(LLAPI_MSG_NORMAL, "%spattern: ", - prefix); + llapi_printf(LLAPI_MSG_NORMAL, "%s%spattern: ", + space, prefix); llapi_printf(LLAPI_MSG_NORMAL, "%.x", lum->lmm_pattern); separator = "\n"; } @@ -2220,8 +2233,8 @@ static void lov_dump_user_lmm_header(struct lov_user_md *lum, char *path, if ((verbose & VERBOSE_GENERATION) && !is_dir) { llapi_printf(LLAPI_MSG_NORMAL, "%s", separator); if (verbose & ~VERBOSE_GENERATION) - llapi_printf(LLAPI_MSG_NORMAL, "%slayout_gen: ", - prefix); + llapi_printf(LLAPI_MSG_NORMAL, "%s%slayout_gen: ", + space, prefix); llapi_printf(LLAPI_MSG_NORMAL, "%u", (int)lum->lmm_layout_gen); separator = "\n"; @@ -2230,8 +2243,8 @@ static void lov_dump_user_lmm_header(struct lov_user_md *lum, char *path, if (verbose & VERBOSE_OFFSET) { llapi_printf(LLAPI_MSG_NORMAL, "%s", separator); if (verbose & ~VERBOSE_OFFSET) - llapi_printf(LLAPI_MSG_NORMAL, "%sstripe_offset: ", - prefix); + llapi_printf(LLAPI_MSG_NORMAL, "%s%sstripe_offset: ", + space, prefix); if (is_dir) llapi_printf(LLAPI_MSG_NORMAL, "%d", lum->lmm_stripe_offset == @@ -2243,49 +2256,70 @@ static void lov_dump_user_lmm_header(struct lov_user_md *lum, char *path, separator = is_dir ? " " : "\n"; } - if ((verbose & VERBOSE_POOL) && (pool_name != NULL)) { + if ((verbose & VERBOSE_POOL) && pool_name && (pool_name[0] != '\0')) { llapi_printf(LLAPI_MSG_NORMAL, "%s", separator); if (verbose & ~VERBOSE_POOL) - llapi_printf(LLAPI_MSG_NORMAL, "%spool: ", - prefix); + llapi_printf(LLAPI_MSG_NORMAL, "%s%spool: ", + space, prefix); llapi_printf(LLAPI_MSG_NORMAL, "%s", pool_name); + separator = is_dir ? " " : "\n"; } - if (!is_dir || (is_dir && (verbose != VERBOSE_OBJID))) + if (strlen(separator) != 0) llapi_printf(LLAPI_MSG_NORMAL, "\n"); } void lov_dump_user_lmm_v1v3(struct lov_user_md *lum, char *pool_name, - struct lov_user_ost_data_v1 *objects, - char *path, int is_dir, int obdindex, - int depth, int header, int raw) + struct lov_user_ost_data_v1 *objects, + char *path, int obdindex, int depth, + int header, enum lov_dump_flags flags) { - int i, obdstripe = (obdindex != OBD_NOT_FOUND) ? 0 : 1; + bool is_dir = flags & LDF_IS_DIR; + bool indent = flags & LDF_INDENT; + int i, obdstripe = (obdindex != OBD_NOT_FOUND) ? 0 : 1; - if (!obdstripe) { - for (i = 0; !is_dir && i < lum->lmm_stripe_count; i++) { - if (obdindex == objects[i].l_ost_idx) { - obdstripe = 1; - break; - } - } - } + if (!obdstripe) { + for (i = 0; !is_dir && i < lum->lmm_stripe_count; i++) { + if (obdindex == objects[i].l_ost_idx) { + obdstripe = 1; + break; + } + } + } - if (obdstripe == 1) - lov_dump_user_lmm_header(lum, path, objects, is_dir, header, - depth, raw, pool_name); + if (obdstripe == 0) + return; - if (!is_dir && (header & VERBOSE_OBJID) && + lov_dump_user_lmm_header(lum, path, objects, header, depth, pool_name, + flags); + + if (!is_dir && (header & VERBOSE_OBJID) && !(lum->lmm_pattern & LOV_PATTERN_F_RELEASED)) { - if (obdstripe == 1) - llapi_printf(LLAPI_MSG_NORMAL, - "\tobdidx\t\t objid\t\t objid\t\t group\n"); - - for (i = 0; i < lum->lmm_stripe_count; i++) { - int idx = objects[i].l_ost_idx; - long long oid = ostid_id(&objects[i].l_ost_oi); - long long gr = ostid_seq(&objects[i].l_ost_oi); - if ((obdindex == OBD_NOT_FOUND) || (obdindex == idx)) { + char *space = " - "; + + if (indent) + llapi_printf(LLAPI_MSG_NORMAL, + "%6slmm_objects:\n", " "); + else + llapi_printf(LLAPI_MSG_NORMAL, + "\tobdidx\t\t objid\t\t objid\t\t group\n"); + + for (i = 0; i < lum->lmm_stripe_count; i++) { + int idx = objects[i].l_ost_idx; + long long oid = ostid_id(&objects[i].l_ost_oi); + long long gr = ostid_seq(&objects[i].l_ost_oi); + + if (obdindex != OBD_NOT_FOUND && obdindex != idx) + continue; + + if (indent) { + struct lu_fid fid = { 0 }; + + ostid_to_fid(&fid, &objects[i].l_ost_oi, idx); + llapi_printf(LLAPI_MSG_NORMAL, + "%s%d: { l_ost_idx: %d, l_fid: "DFID" }\n", + space, i, idx, PFID(&fid)); + } else { char fmt[48]; sprintf(fmt, "%s%s%s\n", "\t%6u\t%14llu\t%#13llx\t", @@ -2296,10 +2330,9 @@ void lov_dump_user_lmm_v1v3(struct lov_user_md *lum, char *pool_name, oid, gr, obdindex == idx ? " *" : ""); } - - } - llapi_printf(LLAPI_MSG_NORMAL, "\n"); - } + } + llapi_printf(LLAPI_MSG_NORMAL, "\n"); + } } void lmv_dump_user_lmm(struct lmv_user_md *lum, char *pool_name, @@ -2414,7 +2447,321 @@ void lmv_dump_user_lmm(struct lmv_user_md *lum, char *pool_name, llapi_printf(LLAPI_MSG_NORMAL, "\n"); } -void llapi_lov_dump_user_lmm(struct find_param *param, char *path, int is_dir) +static void lov_dump_comp_v1_header(struct find_param *param, char *path, + enum lov_dump_flags flags) +{ + struct lov_comp_md_v1 *comp_v1 = (void *)¶m->fp_lmd->lmd_lmm; + int depth = param->fp_max_depth; + int verbose = param->fp_verbose; + + if (depth && path && ((verbose != VERBOSE_OBJID) || + !(flags & LDF_IS_DIR))) + llapi_printf(LLAPI_MSG_NORMAL, "%s\n", path); + + if (verbose & VERBOSE_DETAIL) { + llapi_printf(LLAPI_MSG_NORMAL, "composite_header:\n"); + llapi_printf(LLAPI_MSG_NORMAL, "%2slcm_magic: 0x%08X\n", + " ", comp_v1->lcm_magic); + llapi_printf(LLAPI_MSG_NORMAL, "%2slcm_size: %u\n", + " ", comp_v1->lcm_size); + llapi_printf(LLAPI_MSG_NORMAL, "%2slcm_flags: %u\n", + " ", comp_v1->lcm_flags); + } + + if (verbose & VERBOSE_GENERATION) { + if (verbose & ~VERBOSE_GENERATION) + llapi_printf(LLAPI_MSG_NORMAL, "%2slcm_layout_gen: ", + " "); + llapi_printf(LLAPI_MSG_NORMAL, "%u\n", comp_v1->lcm_layout_gen); + } + + if (verbose & VERBOSE_COMP_COUNT) { + if (verbose & ~VERBOSE_COMP_COUNT) + llapi_printf(LLAPI_MSG_NORMAL, "%2slcm_entry_count: ", + " "); + llapi_printf(LLAPI_MSG_NORMAL, "%u\n", + comp_v1->lcm_entry_count); + } + + if (verbose & VERBOSE_DETAIL) + llapi_printf(LLAPI_MSG_NORMAL, "components:\n"); +} + +static void lov_dump_comp_v1_entry(struct find_param *param, + enum lov_dump_flags flags, int index) +{ + struct lov_comp_md_v1 *comp_v1 = (void *)¶m->fp_lmd->lmd_lmm; + struct lov_comp_md_entry_v1 *entry; + char *separator = ""; + int verbose = param->fp_verbose; + + entry = &comp_v1->lcm_entries[index]; + + if (verbose & VERBOSE_COMP_ID) { + if (verbose & VERBOSE_DETAIL) + llapi_printf(LLAPI_MSG_NORMAL, + "%slcme_id: ", " - "); + else if (verbose & ~VERBOSE_COMP_ID) + llapi_printf(LLAPI_MSG_NORMAL, + "%4slcme_id: ", " "); + if (!(flags & LDF_IS_DIR)) + llapi_printf(LLAPI_MSG_NORMAL, "%u", entry->lcme_id); + else + llapi_printf(LLAPI_MSG_NORMAL, "N/A"); + separator = "\n"; + } + + if (verbose & VERBOSE_COMP_FLAGS) { + llapi_printf(LLAPI_MSG_NORMAL, "%s", separator); + if (verbose & ~VERBOSE_COMP_FLAGS) + llapi_printf(LLAPI_MSG_NORMAL, + "%4slcme_flags: ", " "); + llapi_printf(LLAPI_MSG_NORMAL, "%#x", entry->lcme_flags); + separator = "\n"; + } + + if (verbose & VERBOSE_COMP_START) { + llapi_printf(LLAPI_MSG_NORMAL, "%s", separator); + if (verbose & ~VERBOSE_COMP_START) + llapi_printf(LLAPI_MSG_NORMAL, + "%4slcme_extent.e_start: ", " "); + llapi_printf(LLAPI_MSG_NORMAL, "%llu", + entry->lcme_extent.e_start); + separator = "\n"; + } + + if (verbose & VERBOSE_COMP_END) { + llapi_printf(LLAPI_MSG_NORMAL, "%s", separator); + if (verbose & ~VERBOSE_COMP_END) + llapi_printf(LLAPI_MSG_NORMAL, + "%4slcme_extent.e_end: ", " "); + if (entry->lcme_extent.e_end == LUSTRE_EOF) + llapi_printf(LLAPI_MSG_NORMAL, "%s", "EOF"); + else + llapi_printf(LLAPI_MSG_NORMAL, "%llu", + entry->lcme_extent.e_end); + separator = "\n"; + } + + if (verbose & VERBOSE_DETAIL) { + llapi_printf(LLAPI_MSG_NORMAL, "%s", separator); + llapi_printf(LLAPI_MSG_NORMAL, "%4slcme_offset: %u\n", + " ", entry->lcme_offset); + llapi_printf(LLAPI_MSG_NORMAL, "%4slcme_size: %u\n", + " ", entry->lcme_size); + llapi_printf(LLAPI_MSG_NORMAL, "%4ssub_layout:\n", " "); + } else { + llapi_printf(LLAPI_MSG_NORMAL, "%s", separator); + } +} + +/* 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. + * The table below gives the answers for the specified parameters (value and + * sign), 1st column is the answer for the MDS value, the 2nd is for the OST: + * -------------------------------------- + * 1 | file > limit; sign > 0 | -1 / -1 | + * 2 | file = limit; sign > 0 | -1 / -1 | + * 3 | file < limit; sign > 0 | ? / 1 | + * 4 | file > limit; sign = 0 | -1 / -1 | + * 5 | file = limit; sign = 0 | ? / 1 | <- (see the Note below) + * 6 | file < limit; sign = 0 | ? / -1 | + * 7 | file > limit; sign < 0 | 1 / 1 | + * 8 | file = limit; sign < 0 | ? / -1 | + * 9 | file < limit; sign < 0 | ? / -1 | + * -------------------------------------- + * Note: 5th actually means that the value is within the interval + * (limit - margin, limit]. */ +static int find_value_cmp(unsigned long long file, unsigned long long limit, + int sign, int negopt, unsigned long long margin, + int mds) +{ + int ret = -1; + + if (sign > 0) { + /* Drop the fraction of margin (of days). */ + if (file + margin <= limit) + ret = mds ? 0 : 1; + } else if (sign == 0) { + if (file <= limit && file + margin > limit) + ret = mds ? 0 : 1; + else if (file + margin <= limit) + ret = mds ? 0 : -1; + } else if (sign < 0) { + if (file > limit) + ret = 1; + else if (mds) + ret = 0; + } + + return negopt ? ~ret + 1 : ret; +} + +static inline struct lov_user_md * +lov_comp_entry(struct lov_comp_md_v1 *comp_v1, int ent_idx) +{ + return (struct lov_user_md *)((char *)comp_v1 + + comp_v1->lcm_entries[ent_idx].lcme_offset); +} + +static inline struct lov_user_ost_data_v1 * +lov_v1v3_objects(struct lov_user_md *v1) +{ + if (v1->lmm_magic == LOV_USER_MAGIC_V3) + return ((struct lov_user_md_v3 *)v1)->lmm_objects; + else + return v1->lmm_objects; +} + +static inline void +lov_v1v3_pool_name(struct lov_user_md *v1, char *pool_name) +{ + if (v1->lmm_magic == LOV_USER_MAGIC_V3) + strlcpy(pool_name, ((struct lov_user_md_v3 *)v1)->lmm_pool_name, + LOV_MAXPOOLNAME); + else + pool_name[0] = '\0'; +} + +/** + * An example of "getstripe -v" for a two components PFL file: + * + * composite_header: + * lcm_magic: 0x0BD60BD0 + * lcm_size: 264 + * lcm_flags: 0 + * lcm_layout_gen: 2 + * lcm_entry_count: 2 + * components: + * - lcme_id: 1 + * lcme_flags: 0x10 + * lcme_extent.e_start: 0 + * lcme_extent.e_end: 1048576 + * lcme_offset: 128 + * lcme_size: 56 + * sub_layout: + * lmm_magic: 0x0BD10BD0 + * lmm_seq: 0x200000401 + * lmm_object_id: 0x1 + * lmm_fid: [0x200000401:0x1:0x0] + * lmm_stripe_count: 1 + * lmm_stripe_size: 1048576 + * lmm_pattern: 1 + * lmm_layout_gen: 0 + * lmm_stripe_offset: 0 + * lmm_objects: + * - 0: { l_ost_idx: 0, l_fid: [0x100000000:0x2:0x0] } + * + * - lcme_id: 2 + * lcme_flags: 0x10 + * lcme_extent.e_start: 1048576 + * lcme_extent.e_end: EOF + * lcme_offset: 184 + * lcme_size: 80 + * sub_layout: + * lmm_magic: 0x0BD10BD0 + * lmm_seq: 0x200000401 + * lmm_object_id: 0x1 + * lmm_fid: [0x200000401:0x1:0x0] + * lmm_stripe_count: 2 + * lmm_stripe_size: 1048576 + * lmm_pattern: 1 + * lmm_layout_gen: 0 + * lmm_stripe_offset: 1 + * lmm_objects: + * - 0: { l_ost_idx: 1, l_fid: [0x100010000:0x2:0x0] } + * - 1: { l_ost_idx: 0, l_fid: [0x100000000:0x3:0x0] } + */ +static void lov_dump_comp_v1(struct find_param *param, char *path, + enum lov_dump_flags flags) +{ + struct lov_comp_md_entry_v1 *entry; + struct lov_user_ost_data_v1 *objects; + struct lov_comp_md_v1 *comp_v1 = (void *)¶m->fp_lmd->lmd_lmm; + struct lov_user_md_v1 *v1; + char pool_name[LOV_MAXPOOLNAME + 1]; + int obdindex = param->fp_obd_index; + int i, j, match, obdstripe = 0; + + if (obdindex != OBD_NOT_FOUND) { + for (i = 0; !(flags & LDF_IS_DIR) && + i < comp_v1->lcm_entry_count; i++) { + if (!(comp_v1->lcm_entries[i].lcme_flags & + LCME_FL_INIT)) + continue; + + v1 = lov_comp_entry(comp_v1, i); + objects = lov_v1v3_objects(v1); + + for (j = 0; j < v1->lmm_stripe_count; j++) { + if (obdindex == objects[j].l_ost_idx) { + obdstripe = 1; + break; + } + } + } + } else { + obdstripe = 1; + } + + if (obdstripe == 0) + return; + + lov_dump_comp_v1_header(param, path, flags); + + flags |= LDF_INDENT; + + for (i = 0; i < comp_v1->lcm_entry_count; i++) { + entry = &comp_v1->lcm_entries[i]; + + if (param->fp_check_comp_flags && + !(param->fp_comp_flags & entry->lcme_flags)) + continue; + + if (param->fp_check_comp_id && + param->fp_comp_id != entry->lcme_id) + continue; + + if (param->fp_check_comp_start) { + match = find_value_cmp(entry->lcme_extent.e_start, + param->fp_comp_start, + param->fp_comp_start_sign, + 0, + param->fp_comp_start_units, 0); + if (match == -1) + continue; + } + + if (param->fp_check_comp_end) { + unsigned long long margin; + + margin = entry->lcme_extent.e_end == LUSTRE_EOF ? + 0 : param->fp_comp_end_units; + + match = find_value_cmp(entry->lcme_extent.e_end, + param->fp_comp_end, + param->fp_comp_end_sign, + 0, margin, 0); + if (match == -1) + continue; + } + + lov_dump_comp_v1_entry(param, flags, i); + + v1 = lov_comp_entry(comp_v1, i); + objects = lov_v1v3_objects(v1); + lov_v1v3_pool_name(v1, pool_name); + + lov_dump_user_lmm_v1v3(v1, pool_name, objects, path, obdindex, + param->fp_max_depth, param->fp_verbose, + flags); + } +} + +static void llapi_lov_dump_user_lmm(struct find_param *param, char *path, + enum lov_dump_flags flags) { __u32 magic; @@ -2423,27 +2770,29 @@ void llapi_lov_dump_user_lmm(struct find_param *param, char *path, int is_dir) else magic = *(__u32 *)¶m->fp_lmd->lmd_lmm; /* lum->lmm_magic */ + if (param->fp_raw) + flags |= LDF_IS_RAW; + switch (magic) { - case LOV_USER_MAGIC_V1: + case LOV_USER_MAGIC_V1: lov_dump_user_lmm_v1v3(¶m->fp_lmd->lmd_lmm, NULL, param->fp_lmd->lmd_lmm.lmm_objects, - path, is_dir, - param->fp_obd_index, param->fp_max_depth, - param->fp_verbose, param->fp_raw); - break; - case LOV_USER_MAGIC_V3: { - char pool_name[LOV_MAXPOOLNAME + 1]; - struct lov_user_ost_data_v1 *objects; + path, param->fp_obd_index, + param->fp_max_depth, param->fp_verbose, + flags); + break; + case LOV_USER_MAGIC_V3: { + char pool_name[LOV_MAXPOOLNAME + 1]; + struct lov_user_ost_data_v1 *objects; struct lov_user_md_v3 *lmmv3 = (void *)¶m->fp_lmd->lmd_lmm; strlcpy(pool_name, lmmv3->lmm_pool_name, sizeof(pool_name)); objects = lmmv3->lmm_objects; - lov_dump_user_lmm_v1v3(¶m->fp_lmd->lmd_lmm, - pool_name[0] == '\0' ? NULL : pool_name, - objects, path, is_dir, - param->fp_obd_index, param->fp_max_depth, - param->fp_verbose, param->fp_raw); - break; + lov_dump_user_lmm_v1v3(¶m->fp_lmd->lmd_lmm, pool_name, + objects, path, param->fp_obd_index, + param->fp_max_depth, param->fp_verbose, + flags); + break; } case LMV_MAGIC_V1: case LMV_USER_MAGIC: { @@ -2452,12 +2801,13 @@ void llapi_lov_dump_user_lmm(struct find_param *param, char *path, int is_dir) lum = (struct lmv_user_md *)param->fp_lmv_md; strlcpy(pool_name, lum->lum_pool_name, sizeof(pool_name)); - lmv_dump_user_lmm(lum, - pool_name[0] == '\0' ? NULL : pool_name, - path, param->fp_obd_index, + lmv_dump_user_lmm(lum, pool_name, path, param->fp_obd_index, param->fp_max_depth, param->fp_verbose); break; } + case LOV_USER_MAGIC_COMP_V1: + lov_dump_comp_v1(param, path, flags); + break; default: llapi_printf(LLAPI_MSG_NORMAL, "unknown lmm_magic: %#x " "(expecting one of %#x %#x %#x %#x)\n", @@ -2539,50 +2889,6 @@ int llapi_file_lookup(int dirfd, const char *name) return rc; } -/* 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. - * The table below gives the answers for the specified parameters (value and - * sign), 1st column is the answer for the MDS value, the 2nd is for the OST: - * -------------------------------------- - * 1 | file > limit; sign > 0 | -1 / -1 | - * 2 | file = limit; sign > 0 | -1 / -1 | - * 3 | file < limit; sign > 0 | ? / 1 | - * 4 | file > limit; sign = 0 | -1 / -1 | - * 5 | file = limit; sign = 0 | ? / 1 | <- (see the Note below) - * 6 | file < limit; sign = 0 | ? / -1 | - * 7 | file > limit; sign < 0 | 1 / 1 | - * 8 | file = limit; sign < 0 | ? / -1 | - * 9 | file < limit; sign < 0 | ? / -1 | - * -------------------------------------- - * Note: 5th actually means that the value is within the interval - * (limit - margin, limit]. */ -static int find_value_cmp(unsigned long long file, unsigned long long limit, - int sign, int negopt, unsigned long long margin, - int mds) -{ - int ret = -1; - - if (sign > 0) { - /* Drop the fraction of margin (of days). */ - if (file + margin <= limit) - ret = mds ? 0 : 1; - } else if (sign == 0) { - if (file <= limit && file + margin > limit) - ret = mds ? 0 : 1; - else if (file + margin <= limit) - ret = mds ? 0 : -1; - } else if (sign < 0) { - if (file > limit) - ret = 1; - else if (mds) - ret = 0; - } - - return negopt ? ~ret + 1 : ret; -} - /* 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 @@ -2641,9 +2947,11 @@ static int find_time_check(lstat_t *st, struct find_param *param, int mds) */ 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_ost_data_v1 *lmm_objects; - int i, j; + int i, j, k, count = 1; if (param->fp_obd_uuid && param->fp_obd_index == OBD_NOT_FOUND) return 0; @@ -2653,37 +2961,27 @@ static int check_obd_match(struct find_param *param) /* Only those files should be accepted, which have a * stripe on the specified OST. */ - if (!param->fp_lmd->lmd_lmm.lmm_stripe_count) - 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; + } - if (param->fp_lmd->lmd_lmm.lmm_magic == - LOV_USER_MAGIC_V3) { - struct lov_user_md_v3 *lmmv3 = (void *)¶m->fp_lmd->lmd_lmm; + for (i = 0; i < count; i++) { + if (comp_v1) + v1 = lov_comp_entry(comp_v1, i); - lmm_objects = lmmv3->lmm_objects; - } else if (param->fp_lmd->lmd_lmm.lmm_magic == LOV_USER_MAGIC_V1) { - lmm_objects = param->fp_lmd->lmd_lmm.lmm_objects; - } else { - llapi_err_noerrno(LLAPI_MSG_ERROR, "%s:Unknown magic: 0x%08X\n", - __func__, param->fp_lmd->lmd_lmm.lmm_magic); - return -EINVAL; - } + objects = lov_v1v3_objects(v1); - for (i = 0; i < param->fp_lmd->lmd_lmm.lmm_stripe_count; i++) { - for (j = 0; j < param->fp_num_obds; j++) { - if (param->fp_obd_indexes[j] == - lmm_objects[i].l_ost_idx) { - if (param->fp_exclude_obd) - return 0; - return 1; + for (j = 0; j < v1->lmm_stripe_count; j++) { + for (k = 0; k < param->fp_num_obds; k++) { + if (param->fp_obd_indexes[k] == + objects[j].l_ost_idx) + return !param->fp_exclude_obd; } } } - if (param->fp_exclude_obd) - return 1; - - return 0; + return param->fp_exclude_obd; } static int check_mdt_match(struct find_param *param) @@ -2734,22 +3032,257 @@ static int print_failed_tgt(struct find_param *param, char *path, int type) return ret; } +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; + int ret, i, count = 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) + 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 */ + if (ret != -1) + break; + } + + return ret; +} + +static __u32 find_get_stripe_count(struct find_param *param) +{ + struct lov_comp_md_v1 *comp_v1 = NULL; + struct lov_user_md_v1 *v1 = ¶m->fp_lmd->lmd_lmm; + int i, count = 1; + __u32 stripe_count = 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) + v1 = lov_comp_entry(comp_v1, i); + stripe_count += v1->lmm_stripe_count; + } + + return stripe_count; +} + +#define LOV_PATTERN_INVALID 0xFFFFFFFF + +static int find_check_layout(struct find_param *param) +{ + struct lov_comp_md_v1 *comp_v1 = NULL; + struct lov_user_md_v1 *v1 = ¶m->fp_lmd->lmd_lmm; + int i, count = 1; + bool found = false, valid = false; + + 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) + v1 = lov_comp_entry(comp_v1, i); + + if (v1->lmm_pattern == LOV_PATTERN_INVALID) + continue; + + valid = true; + if (v1->lmm_pattern & param->fp_layout) { + found = true; + break; + } + } + + if (!valid) + return -1; + + if ((found && !param->fp_exclude_layout) || + (!found && param->fp_exclude_layout)) + return 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; + int i, count = 1; + bool found = false; + + if (v1->lmm_magic == LOV_USER_MAGIC_COMP_V1) { + comp_v1 = (struct lov_comp_md_v1 *)v1; + count = comp_v1->lcm_entry_count; + /* empty requested pool is taken as no pool search */ + if (count == 0 && param->fp_poolname[0] == '\0') + found = true; + } + + for (i = 0; i < count; i++) { + if (comp_v1 != NULL) + v1 = lov_comp_entry(comp_v1, i); + + if (((v1->lmm_magic == LOV_USER_MAGIC_V1) && + (param->fp_poolname[0] == '\0')) || + ((v1->lmm_magic == LOV_USER_MAGIC_V3) && + (strncmp(v3->lmm_pool_name, + param->fp_poolname, LOV_MAXPOOLNAME) == 0)) || + ((v1->lmm_magic == LOV_USER_MAGIC_V3) && + (strcmp(param->fp_poolname, "*") == 0))) { + found = true; + break; + } + } + + if ((found && !param->fp_exclude_pool) || + (!found && param->fp_exclude_pool)) + return 1; + + return -1; +} + +static int find_check_comp_options(struct find_param *param) +{ + struct lov_comp_md_v1 *comp_v1; + struct lov_user_md_v1 *v1 = ¶m->fp_lmd->lmd_lmm; + struct lov_comp_md_entry_v1 *entry; + int i, ret; + + if (v1->lmm_magic != LOV_USER_MAGIC_COMP_V1) { + if ((param->fp_check_comp_count && + !param->fp_exclude_comp_count) || + (param->fp_check_comp_flags && + !param->fp_exclude_comp_flags) || + (param->fp_check_comp_start && + !param->fp_exclude_comp_start) || + (param->fp_check_comp_end && + !param->fp_exclude_comp_end)) + return -1; + else + return 1; + } + + comp_v1 = (struct lov_comp_md_v1 *)v1; + + if (param->fp_check_comp_count) { + ret = find_value_cmp(comp_v1->lcm_entry_count, + param->fp_comp_count, + param->fp_comp_count_sign, + param->fp_exclude_comp_count, 1, 0); + if (ret == -1) + return ret; + } + + if (comp_v1->lcm_entry_count == 0) { + if ((param->fp_check_comp_flags && + !param->fp_exclude_comp_flags) || + (param->fp_check_comp_start && + !param->fp_exclude_comp_start) || + (param->fp_check_comp_end && + !param->fp_exclude_comp_end)) + return -1; + } + + if (param->fp_check_comp_flags) { + for (i = 0; i < comp_v1->lcm_entry_count; i++) { + entry = &comp_v1->lcm_entries[i]; + + if (((entry->lcme_flags & param->fp_comp_flags) && + param->fp_exclude_comp_flags) || + (!(entry->lcme_flags & param->fp_comp_flags) && + !param->fp_exclude_comp_flags)) + ret = -1; + else + ret = 1; + /* If any flags matches */ + if (ret != -1) + break; + } + if (ret == -1) + return ret; + } + + if (param->fp_check_comp_start) { + for (i = 0; i < comp_v1->lcm_entry_count; i++) { + entry = &comp_v1->lcm_entries[i]; + + ret = find_value_cmp(entry->lcme_extent.e_start, + param->fp_comp_start, + param->fp_comp_start_sign, + param->fp_exclude_comp_start, + param->fp_comp_start_units, 0); + /* If any extent start matches */ + if (ret != -1) + break; + } + if (ret == -1) + return ret; + } + + if (param->fp_check_comp_end) { + for (i = 0; i < comp_v1->lcm_entry_count; i++) { + unsigned long long margin; + entry = &comp_v1->lcm_entries[i]; + + margin = entry->lcme_extent.e_end == LUSTRE_EOF ? + 0 : param->fp_comp_end_units; + + ret = find_value_cmp(entry->lcme_extent.e_end, + param->fp_comp_end, + param->fp_comp_end_sign, + param->fp_exclude_comp_end, margin, + 0); + /* If any extent end matches */ + if (ret != -1) + break; + } + if (ret == -1) + return ret; + } + + return 1; +} + +static bool find_check_lmm_info(struct find_param *param) +{ + return param->fp_check_pool || param->fp_check_stripe_count || + 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; +} + 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 find_param *param = (struct find_param *)data; DIR *dir = dirp == NULL ? NULL : *dirp; - int decision = 1; /* 1 is accepted; -1 is rejected. */ + 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; + int lustre_fs = 1; + int checked_type = 0; + int ret = 0; + __u32 stripe_count = 0; if (parent == NULL && dir == NULL) return -EINVAL; - param->fp_lmd->lmd_lmm.lmm_stripe_count = 0; - /* If a regular expression is presented, make the initial decision */ if (param->fp_pattern != NULL) { char *fname = strrchr(path, '/'); @@ -2780,9 +3313,7 @@ static int cb_find_init(char *path, DIR *parent, DIR **dirp, if (param->fp_obd_uuid || param->fp_mdt_uuid || param->fp_check_uid || param->fp_check_gid || param->fp_atime || param->fp_mtime || param->fp_ctime || - param->fp_check_pool || param->fp_check_size || - param->fp_check_stripe_count || param->fp_check_stripe_size || - param->fp_check_layout) + param->fp_check_size || find_check_lmm_info(param)) decision = 0; if (param->fp_type != 0 && checked_type == 0) @@ -2792,8 +3323,7 @@ static int cb_find_init(char *path, DIR *parent, DIR **dirp, ret = get_lmd_info(path, parent, dir, param->fp_lmd, param->fp_lum_size); if (ret == 0 && param->fp_lmd->lmd_lmm.lmm_magic == 0 && - (param->fp_check_pool || param->fp_check_stripe_count || - param->fp_check_stripe_size || param->fp_check_layout)) { + find_check_lmm_info(param)) { struct lov_user_md *lmm = ¶m->fp_lmd->lmd_lmm; /* We need to "fake" the "use the default" values @@ -2842,6 +3372,8 @@ static int cb_find_init(char *path, DIR *parent, DIR **dirp, goto decided; return ret; + } else { + stripe_count = find_get_stripe_count(param); } } @@ -2882,36 +3414,23 @@ static int cb_find_init(char *path, DIR *parent, DIR **dirp, } if (param->fp_check_stripe_size) { - decision = find_value_cmp( - param->fp_lmd->lmd_lmm.lmm_stripe_size, - param->fp_stripe_size, - param->fp_stripe_size_sign, - param->fp_exclude_stripe_size, - param->fp_stripe_size_units, 0); + decision = find_check_stripe_size(param); if (decision == -1) goto decided; } if (param->fp_check_stripe_count) { - decision = find_value_cmp( - param->fp_lmd->lmd_lmm.lmm_stripe_count, - param->fp_stripe_count, - param->fp_stripe_count_sign, - param->fp_exclude_stripe_count, 1, 0); + decision = find_value_cmp(stripe_count, param->fp_stripe_count, + param->fp_stripe_count_sign, + param->fp_exclude_stripe_count, 1, 0); if (decision == -1) goto decided; - } + } if (param->fp_check_layout) { - __u32 found; - - found = (param->fp_lmd->lmd_lmm.lmm_pattern & param->fp_layout); - if ((param->fp_lmd->lmd_lmm.lmm_pattern == 0xFFFFFFFF) || - (found && param->fp_exclude_layout) || - (!found && !param->fp_exclude_layout)) { - decision = -1; + decision = find_check_layout(param); + if (decision == -1) goto decided; - } } /* If an OBD UUID is specified but none matches, skip this file. */ @@ -2964,22 +3483,16 @@ obd_matches: } if (param->fp_check_pool) { - struct lov_user_md_v3 *lmmv3 = (void *)¶m->fp_lmd->lmd_lmm; + decision = find_check_pool(param); + if (decision == -1) + goto decided; + } - /* empty requested pool is taken as no pool search => V1 */ - if (((param->fp_lmd->lmd_lmm.lmm_magic == LOV_USER_MAGIC_V1) && - (param->fp_poolname[0] == '\0')) || - ((param->fp_lmd->lmd_lmm.lmm_magic == LOV_USER_MAGIC_V3) && - (strncmp(lmmv3->lmm_pool_name, - param->fp_poolname, LOV_MAXPOOLNAME) == 0)) || - ((param->fp_lmd->lmd_lmm.lmm_magic == LOV_USER_MAGIC_V3) && - (strcmp(param->fp_poolname, "*") == 0))) { - if (param->fp_exclude_pool) - goto decided; - } else { - if (!param->fp_exclude_pool) - goto decided; - } + if (param->fp_check_comp_count || param->fp_check_comp_flags || + param->fp_check_comp_start || param->fp_check_comp_end) { + decision = find_check_comp_options(param); + if (decision == -1) + goto decided; } /* Check the time on mds. */ @@ -2987,9 +3500,8 @@ obd_matches: if (param->fp_atime || param->fp_mtime || param->fp_ctime) { int for_mds; - for_mds = lustre_fs ? (S_ISREG(st->st_mode) && - param->fp_lmd->lmd_lmm.lmm_stripe_count) - : 0; + 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; @@ -2999,9 +3511,8 @@ obd_matches: The regular stat is almost of the same speed as some new 'glimpse-size-ioctl'. */ - if (param->fp_check_size && S_ISREG(st->st_mode) && - param->fp_lmd->lmd_lmm.lmm_stripe_count) - decision = 0; + if (param->fp_check_size && S_ISREG(st->st_mode) && stripe_count) + decision = 0; if (param->fp_check_size && S_ISDIR(st->st_mode)) decision = 0; @@ -3365,7 +3876,7 @@ err_out: dump: if (!(param->fp_verbose & VERBOSE_MDTINDEX)) - llapi_lov_dump_user_lmm(param, path, d ? 1 : 0); + llapi_lov_dump_user_lmm(param, path, d ? LDF_IS_DIR : 0); out: /* Do not get down anymore? */ -- 1.8.3.1