From fce9af0b7fc883834ea4ae8cb6d2045a0672cc61 Mon Sep 17 00:00:00 2001 From: Thomas Bertschinger Date: Fri, 17 Mar 2023 16:24:13 -0400 Subject: [PATCH] LU-16503 utils: add --hex-idx option for lfs getstripe The --hex-idx option for lfs getstripe and getdirstripe makes them output OST and MDT indexes in hex. In addition, this commit modifies the YAML parser to treat input like "0x[0-9a-f]+" as a number so that lfs setstripe --yaml can accept output produced by lfs getstripe --yaml --hex-idx. Signed-off-by: Thomas Bertschinger Change-Id: I98eaa9741db787bcf4516648e58e92c7520d8640 Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/50340 Tested-by: jenkins Tested-by: Maloo Reviewed-by: Andreas Dilger Reviewed-by: Olaf Faaland Reviewed-by: Oleg Drokin --- lnet/utils/lnetconfig/cyaml.c | 17 ++++++++++++++ lustre/doc/lfs-getdirstripe.1 | 3 +++ lustre/doc/lfs-getstripe.1 | 4 ++++ lustre/include/lustre/lustreapi.h | 3 ++- lustre/tests/sanity.sh | 26 +++++++++++++++++++++ lustre/utils/lfs.c | 32 ++++++++++++++++++-------- lustre/utils/liblustreapi.c | 48 ++++++++++++++++++++++++++------------- 7 files changed, 106 insertions(+), 27 deletions(-) diff --git a/lnet/utils/lnetconfig/cyaml.c b/lnet/utils/lnetconfig/cyaml.c index 032bb5a..f11a4f8 100644 --- a/lnet/utils/lnetconfig/cyaml.c +++ b/lnet/utils/lnetconfig/cyaml.c @@ -348,6 +348,23 @@ static bool parse_number(struct cYAML *item, const char *input) int subscale = 0, signsubscale = 1; const char *num = input; + if (!strncmp(input, "0x", 2)) { + int64_t hex; /* hex input is always an integer */ + char *invalid = NULL; + + errno = 0; + hex = strtoll(input, &invalid, 16); + if (errno) + return false; + if (*invalid) + return false; + + item->cy_valuedouble = (double) hex; + item->cy_valueint = hex; + item->cy_type = CYAML_TYPE_NUMBER; + return true; + } + if (*num == '-') { sign = -1; num++; diff --git a/lustre/doc/lfs-getdirstripe.1 b/lustre/doc/lfs-getdirstripe.1 index b3d50aa..ad86f6e 100644 --- a/lustre/doc/lfs-getdirstripe.1 +++ b/lustre/doc/lfs-getdirstripe.1 @@ -23,6 +23,9 @@ Print usage message. .BR \-H ", " \-\-mdt-hash Only show the hash function being used for this directory. .TP +.BR --hex-idx +Print MDT indexes in hexademical rather than decimal. +.TP .BR \-i ", " \-m ", " \-\-mdt-index Only show the master MDT index of the directory. .TP diff --git a/lustre/doc/lfs-getstripe.1 b/lustre/doc/lfs-getstripe.1 index 3a9c461..b6b5a52 100644 --- a/lustre/doc/lfs-getstripe.1 +++ b/lustre/doc/lfs-getstripe.1 @@ -13,6 +13,7 @@ lfs-getstripe \- Lustre client command to print layout parameters of a file [\fB--fid\fR|\fB-F\fR] [\fB--generation\fR|\fB-g\fR] [\fB--help\fR|\fB-h\fR] +[\fB--hex-idx\fR] [\fB--layout\fR|\fB-L\fR] [\fB--mdt\fR|\fB--mdt-index\fR|\fB-m\fR] [\fB--ost\fR|\fB-O\fR <\fIuuid\fR>] @@ -160,6 +161,9 @@ Print only the layout generation number. .BR --help | -h Print usage message. .TP +.BR --hex-idx +Print OST and MDT indexes in hexademical rather than decimal. +.TP .BR --layout Show only the file layout, which is one of: .RS 1.2i diff --git a/lustre/include/lustre/lustreapi.h b/lustre/include/lustre/lustreapi.h index e72d2b2..93ccb4c 100644 --- a/lustre/include/lustre/lustreapi.h +++ b/lustre/include/lustre/lustreapi.h @@ -398,7 +398,8 @@ struct find_param { unsigned long fp_got_uuids:1, fp_obds_printed:1, - fp_no_follow:1; + fp_no_follow:1, + fp_hex_idx:1; unsigned int fp_depth; unsigned int fp_hash_type; unsigned int fp_time_margin; /* time margin in seconds */ diff --git a/lustre/tests/sanity.sh b/lustre/tests/sanity.sh index 96ec5be..3772861 100755 --- a/lustre/tests/sanity.sh +++ b/lustre/tests/sanity.sh @@ -8699,6 +8699,32 @@ test_56eb() { } run_test 56eb "check lfs getstripe on symlink" +test_56ec() { + [[ $OSTCOUNT -lt 2 ]] && skip_env "needs >= 2 OSTs" + local dir=$DIR/$tdir + local srcfile=$dir/srcfile + local srcyaml=$dir/srcyaml + local destfile=$dir/destfile + + test_mkdir -p $dir + + $LFS setstripe -i 1 $srcfile + $LFS getstripe --hex-idx --yaml $srcfile > $srcyaml + # if the setstripe yaml parsing fails for any reason, the command can + # randomly assign the correct OST index, leading to an erroneous + # success. but the chance of false success is low enough that a + # regression should still be quickly caught. + $LFS setstripe --yaml=$srcyaml $destfile + + local srcindex=$($LFS getstripe -i $srcfile) + local destindex=$($LFS getstripe -i $destfile) + + if [[ ! $srcindex -eq $destindex ]]; then + error "setstripe did not set OST index correctly" + fi +} +run_test 56ec "check lfs getstripe,setstripe --hex --yaml" + test_57a() { [ $PARALLEL == "yes" ] && skip "skip parallel run" # note test will not do anything if MDS is not local diff --git a/lustre/utils/lfs.c b/lustre/utils/lfs.c index dbfbfbb..e8f013a 100644 --- a/lustre/utils/lfs.c +++ b/lustre/utils/lfs.c @@ -370,7 +370,8 @@ command_t cmdlist[] = { " [--pool|-p] [--stripe-size|-S] [--directory|-d]\n" " [--mdt-index|-m] [--recursive|-r] [--raw|-R]\n" " [--layout|-L] [--generation|-g] [--yaml|-y]\n" - " [--help|-h] [--component-id|-I[=COMP_ID]]\n" + " [--help|-h] [--hex-idx]\n" + " [--component-id|-I[=COMP_ID]]\n" " [--component-flags[=COMP_FLAGS]]\n" " [--component-count]\n" " [--extension-size|--ext-size|-z]\n" @@ -389,8 +390,8 @@ command_t cmdlist[] = { "To list the layout pattern info for a given directory\n" "or recursively for all directories in a directory tree.\n" "usage: getdirstripe [--mdt-count|-c] [--mdt-index|-m|-i]\n" - " [--help|-h] [--mdt-hash|-H] [--obd|-O UUID]\n" - " [--recursive|-r] [--yaml|-y]\n" + " [--help|-h] [--hex-idx] [--mdt-hash|-H]\n" + " [--obd|-O UUID] [--recursive|-r] [--yaml|-y]\n" " [--verbose|-v] [--default|-D]\n" " [--max-inherit|-X]\n" " [--max-inherit-rr] ..."}, @@ -3522,6 +3523,7 @@ enum { LFS_FIND_PERM, LFS_PRINTF_OPT, LFS_NO_FOLLOW_OPT, + LFS_HEX_IDX_OPT, LFS_STATS_OPT, LFS_STATS_INTERVAL_OPT }; @@ -5983,12 +5985,6 @@ static int lfs_getstripe_internal(int argc, char **argv, .name = "comp-start", .has_arg = optional_argument }, { .val = LFS_COMP_START_OPT, .name = "component-start", .has_arg = optional_argument }, - { .val = LFS_MIRROR_INDEX_OPT, - .name = "mirror-index", .has_arg = required_argument }, - { .val = LFS_MIRROR_ID_OPT, - .name = "mirror-id", .has_arg = required_argument }, - { .val = LFS_NO_FOLLOW_OPT, - .name = "no-follow", .has_arg = no_argument }, { .val = 'c', .name = "stripe-count", .has_arg = no_argument }, { .val = 'c', .name = "stripe_count", .has_arg = no_argument }, /* find { .val = 'C', .name = "ctime", .has_arg = required_argument }*/ @@ -6000,6 +5996,8 @@ static int lfs_getstripe_internal(int argc, char **argv, { .val = 'g', .name = "generation", .has_arg = no_argument }, /* find { .val = 'G', .name = "group", .has_arg = required_argument }*/ { .val = 'h', .name = "help", .has_arg = no_argument }, + { .val = LFS_HEX_IDX_OPT, + .name = "hex-idx", .has_arg = no_argument }, /* dirstripe { .val = 'H', .name = "mdt-hash", .has_arg = required_argument }*/ { .val = 'i', .name = "stripe-index", .has_arg = no_argument }, { .val = 'i', .name = "stripe_index", .has_arg = no_argument }, @@ -6013,6 +6011,12 @@ static int lfs_getstripe_internal(int argc, char **argv, /* find { .val = 'M', .name = "mtime", .has_arg = required_argument }*/ /* find { .val = 'n', .name = "name", .has_arg = required_argument }*/ { .val = 'N', .name = "mirror-count", .has_arg = no_argument }, + { .val = LFS_MIRROR_INDEX_OPT, + .name = "mirror-index", .has_arg = required_argument }, + { .val = LFS_MIRROR_ID_OPT, + .name = "mirror-id", .has_arg = required_argument }, + { .val = LFS_NO_FOLLOW_OPT, + .name = "no-follow", .has_arg = no_argument }, { .val = 'O', .name = "obd", .has_arg = required_argument }, { .val = 'O', .name = "ost", .has_arg = required_argument }, { .val = 'p', .name = "pool", .has_arg = no_argument }, @@ -6187,6 +6191,9 @@ static int lfs_getstripe_internal(int argc, char **argv, case LFS_NO_FOLLOW_OPT: param->fp_no_follow = true; break; + case LFS_HEX_IDX_OPT: + param->fp_hex_idx = true; + break; case 'd': param->fp_max_depth = 0; break; @@ -6427,6 +6434,8 @@ static int lfs_getdirstripe(int argc, char **argv) { .val = 'D', .name = "default", .has_arg = no_argument }, { .val = 'h', .name = "help", .has_arg = no_argument }, { .val = 'H', .name = "mdt-hash", .has_arg = no_argument }, + { .val = LFS_HEX_IDX_OPT, + .name = "hex-idx", .has_arg = no_argument }, { .val = 'i', .name = "mdt-index", .has_arg = no_argument }, { .val = 'm', .name = "mdt-index", .has_arg = no_argument }, { .val = 'O', .name = "obd", .has_arg = required_argument }, @@ -6434,9 +6443,9 @@ static int lfs_getdirstripe(int argc, char **argv) { .val = 'T', .name = "mdt-count", .has_arg = no_argument }, { .val = 'v', .name = "verbose", .has_arg = no_argument }, { .val = 'X', .name = "max-inherit", .has_arg = no_argument }, - { .val = 'y', .name = "yaml", .has_arg = no_argument }, { .val = LFS_INHERIT_RR_OPT, .name = "max-inherit-rr", .has_arg = no_argument }, + { .val = 'y', .name = "yaml", .has_arg = no_argument }, { .name = NULL } }; int c, rc = 0; @@ -6461,6 +6470,9 @@ static int lfs_getdirstripe(int argc, char **argv) case 'H': param.fp_verbose |= VERBOSE_HASH_TYPE; break; + case LFS_HEX_IDX_OPT: + param.fp_hex_idx = 1; + break; case 'i': fallthrough; case 'm': diff --git a/lustre/utils/liblustreapi.c b/lustre/utils/liblustreapi.c index c3831d7..f32a8ef 100644 --- a/lustre/utils/liblustreapi.c +++ b/lustre/utils/liblustreapi.c @@ -2662,6 +2662,7 @@ enum lov_dump_flags { LDF_SKIP_OBJS = 0x0008, LDF_YAML = 0x0010, LDF_EXTENSION = 0x0020, + LDF_HEX_IDX = 0x0040, }; static void lov_dump_user_lmm_header(struct lov_user_md *lum, char *path, @@ -2679,6 +2680,7 @@ static void lov_dump_user_lmm_header(struct lov_user_md *lum, char *path, char *prefix = is_dir ? "" : "lmm_"; char *separator = ""; char *space = indent ? " " : ""; + char *fmt_idx = flags & LDF_HEX_IDX ? "%#x" : "%d"; int rc; if (is_dir && lmm_oi_seq(&lum->lmm_oi) == FID_SEQ_LOV_DEFAULT) { @@ -2858,14 +2860,16 @@ static void lov_dump_user_lmm_header(struct lov_user_md *lum, char *path, llapi_printf(LLAPI_MSG_NORMAL, "%s%sstripe_offset: ", space, prefix); if (is_dir || skip_objs) - llapi_printf(LLAPI_MSG_NORMAL, "%d", - lum->lmm_stripe_offset == - (typeof(lum->lmm_stripe_offset))(-1) ? -1 : - lum->lmm_stripe_offset); + if (lum->lmm_stripe_offset == + (typeof(lum->lmm_stripe_offset))(-1)) + llapi_printf(LLAPI_MSG_NORMAL, "-1"); + else + llapi_printf(LLAPI_MSG_NORMAL, fmt_idx, + lum->lmm_stripe_offset); else if (lov_pattern(lum->lmm_pattern) == LOV_PATTERN_MDT) llapi_printf(LLAPI_MSG_NORMAL, "0"); else - llapi_printf(LLAPI_MSG_NORMAL, "%u", + llapi_printf(LLAPI_MSG_NORMAL, fmt_idx, objects[0].l_ost_idx); if (!yaml && is_dir) separator = " "; @@ -2900,6 +2904,7 @@ void lov_dump_user_lmm_v1v3(struct lov_user_md *lum, char *pool_name, bool indent = flags & LDF_INDENT; bool skip_objs = flags & LDF_SKIP_OBJS; bool yaml = flags & LDF_YAML; + bool hex = flags & LDF_HEX_IDX; bool obdstripe = obdindex == OBD_NOT_FOUND; int i; @@ -2942,10 +2947,11 @@ void lov_dump_user_lmm_v1v3(struct lov_user_md *lum, char *pool_name, if (yaml) { struct lu_fid fid = { 0 }; - ostid_to_fid(&fid, &objects[i].l_ost_oi, idx); llapi_printf(LLAPI_MSG_NORMAL, - "%sl_ost_idx: %d\n", space, idx); + hex ? "%sl_ost_idx: %#x\n" + : "%sl_ost_idx: %d\n", + space, idx); llapi_printf(LLAPI_MSG_NORMAL, "%8sl_fid: "DFID_NOBRACE"\n", " ", PFID(&fid)); @@ -2953,14 +2959,16 @@ void lov_dump_user_lmm_v1v3(struct lov_user_md *lum, char *pool_name, 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", + llapi_printf(LLAPI_MSG_NORMAL, hex ? + "%s%3d: { l_ost_idx: %#5x, l_fid: "DFID" }\n" : + "%s%3d: { l_ost_idx: %3d, l_fid: "DFID" }\n", space, i, idx, PFID(&fid)); } else { - char fmt[48]; + char fmt[48] = { 0 }; sprintf(fmt, "%s%s%s\n", - "\t%6u\t%14llu\t%#13llx\t", + hex ? "\t%#6x\t%14llu\t%#13llx\t" + : "\t%6u\t%14llu\t%#13llx\t", (fid_seq_is_rsvd(gr) || fid_seq_is_mdt0(gr)) ? "%14llu" : "%#14llx", "%s"); @@ -2982,6 +2990,7 @@ void lmv_dump_user_lmm(struct lmv_user_md *lum, char *pool_name, char *prefix = lum->lum_magic == LMV_USER_MAGIC ? "(Default)" : ""; char *separator = ""; bool yaml = flags & LDF_YAML; + bool hex = flags & LDF_HEX_IDX; bool obdstripe = false; int i; @@ -3035,7 +3044,7 @@ void lmv_dump_user_lmm(struct lmv_user_md *lum, char *pool_name, llapi_printf(LLAPI_MSG_NORMAL, "%s", separator); if (verbose & ~VERBOSE_STRIPE_OFFSET) llapi_printf(LLAPI_MSG_NORMAL, "lmv_stripe_offset: "); - llapi_printf(LLAPI_MSG_NORMAL, "%d", + llapi_printf(LLAPI_MSG_NORMAL, hex ? "%#x" : "%d", (int)lum->lum_stripe_offset); if (verbose & VERBOSE_HASH_TYPE && !yaml) separator = " "; @@ -3116,13 +3125,16 @@ void lmv_dump_user_lmm(struct lmv_user_md *lum, char *pool_name, if (lum->lum_stripe_count > 0) llapi_printf(LLAPI_MSG_NORMAL, "mdtidx\t\t FID[seq:oid:ver]\n"); + + char fmt[48] = { 0 }; + sprintf(fmt, "%s%s", hex ? "%#6x" : "%6u", + "\t\t "DFID"\t\t%s\n"); for (i = 0; i < lum->lum_stripe_count; i++) { int idx = objects[i].lum_mds; struct lu_fid *fid = &objects[i].lum_fid; if ((obdindex == OBD_NOT_FOUND) || (obdindex == idx)) - llapi_printf(LLAPI_MSG_NORMAL, - "%6u\t\t "DFID"\t\t%s\n", + llapi_printf(LLAPI_MSG_NORMAL, fmt, idx, PFID(fid), obdindex == idx ? " *" : ""); } @@ -3862,6 +3874,8 @@ static void llapi_lov_dump_user_lmm(struct find_param *param, char *path, flags |= LDF_IS_RAW; if (param->fp_yaml) flags |= LDF_YAML; + if (param->fp_hex_idx) + flags |= LDF_HEX_IDX; switch (magic) { case LOV_USER_MAGIC_V1: @@ -6035,6 +6049,7 @@ static int cb_get_mdt_index(char *path, int p, int *dp, void *data, int d = dp == NULL ? -1 : *dp; int ret; int mdtidx; + bool hex = param->fp_hex_idx; if (p == -1 && d == -1) return -EINVAL; @@ -6077,9 +6092,10 @@ static int cb_get_mdt_index(char *path, int p, int *dp, void *data, } if (param->fp_quiet || !(param->fp_verbose & VERBOSE_DETAIL)) - llapi_printf(LLAPI_MSG_NORMAL, "%d\n", mdtidx); + llapi_printf(LLAPI_MSG_NORMAL, hex ? "%#x\n" : "%d\n", mdtidx); else - llapi_printf(LLAPI_MSG_NORMAL, "%s\nmdt_index:\t%d\n", + llapi_printf(LLAPI_MSG_NORMAL, hex ? "%s\nmdt_index:\t%#x\n" + : "%s\nmdt_index:\t%d\n", path, mdtidx); out: -- 1.8.3.1