From d645373541fcf69fe1e49095c2637cd90ef26dab Mon Sep 17 00:00:00 2001 From: Andreas Dilger Date: Sun, 28 Feb 2021 15:51:14 -0800 Subject: [PATCH] LU-14180 utils: verify setstripe comp_end is valid Verify that the "lfs setstripe -E " value is valid. Otherwise, if "-S" is not specified at the same time, then an invalid file layout can be created and the file cannot be deleted normally, only via "lfs rmdif ". Allow values < 4096 (e.g. '64' or '128' which would all be invalid anyway) to be interpreted as KiB units. Update usage messages and man pages to match. Lustre-change: https://review.whamcloud.com/41239 Lustre-commit: 83e38bba6237f838c9a5d7d36b258cf6dd28bd13 Signed-off-by: Andreas Dilger Signed-off-by: Jian Yu Change-Id: I47fe7729ffd447c1c1cc098e5117e456263ebbe5 Reviewed-on: https://review.whamcloud.com/41790 Tested-by: jenkins Tested-by: Maloo --- lustre/doc/lfs-setstripe.1 | 7 ++-- lustre/lod/lod_lov.c | 24 +++++++++++++- lustre/lod/lod_object.c | 7 +++- lustre/tests/sanity-pfl.sh | 55 ++++++++++++++++++++++++++++++++ lustre/utils/lfs.c | 79 ++++++++++++++++++++++++++++------------------ 5 files changed, 137 insertions(+), 35 deletions(-) diff --git a/lustre/doc/lfs-setstripe.1 b/lustre/doc/lfs-setstripe.1 index 97f74e5..b69ce56 100644 --- a/lustre/doc/lfs-setstripe.1 +++ b/lustre/doc/lfs-setstripe.1 @@ -163,7 +163,7 @@ means the file should use the filesystem-wide default stripe_size .BR G ibibytes. The .I stripe_size -must be a multiple of 64KiB in size. +must be a multiple of 64KiB. Values below 4096 are assumed to be in KiB units. .TP .B -i\fR, \fB--stripe-index \fR<\fIstart_ost_index\fR> The OST index (starting at 0) on which to start striping for this file. A @@ -297,7 +297,10 @@ or means the following options extend to the end of the file. The first component starts at offset 0, and each subsequent component starts at the end of the previous component, so they must be specified in increasing -file offset order. +file offset order, and must be a multiple of 64KiB to align with the +minimum +.I stripe_size +value. Values below 4096 are assumed to be in KiB units. .PP .RS The first component specified will inherit default parameters from the diff --git a/lustre/lod/lod_lov.c b/lustre/lod/lod_lov.c index 76f41f1..19f852b 100644 --- a/lustre/lod/lod_lov.c +++ b/lustre/lod/lod_lov.c @@ -1183,7 +1183,26 @@ int lod_parse_striping(const struct lu_env *env, struct lod_object *lo, ext = &comp_v1->lcm_entries[i].lcme_extent; lod_comp->llc_extent.e_start = le64_to_cpu(ext->e_start); + if (lod_comp->llc_extent.e_start & + (LOV_MIN_STRIPE_SIZE - 1)) { + CDEBUG(D_LAYOUT, + "extent start %llu is not a multiple of min size %u\n", + lod_comp->llc_extent.e_start, + LOV_MIN_STRIPE_SIZE); + GOTO(out, rc = -EINVAL); + } + lod_comp->llc_extent.e_end = le64_to_cpu(ext->e_end); + if (lod_comp->llc_extent.e_end != LUSTRE_EOF && + lod_comp->llc_extent.e_end & + (LOV_MIN_STRIPE_SIZE - 1)) { + CDEBUG(D_LAYOUT, + "extent end %llu is not a multiple of min size %u\n", + lod_comp->llc_extent.e_end, + LOV_MIN_STRIPE_SIZE); + GOTO(out, rc = -EINVAL); + } + lod_comp->llc_flags = le32_to_cpu(comp_v1->lcm_entries[i].lcme_flags); if (lod_comp->llc_flags & LCME_FL_NOSYNC) @@ -1911,7 +1930,10 @@ recheck: for_each_comp_entry_v1(comp_v1, ent) { ext = &ent->lcme_extent; - if (le64_to_cpu(ext->e_start) > le64_to_cpu(ext->e_end)) { + if (le64_to_cpu(ext->e_start) > le64_to_cpu(ext->e_end) || + le64_to_cpu(ext->e_start) & (LOV_MIN_STRIPE_SIZE - 1) || + (le64_to_cpu(ext->e_end) != LUSTRE_EOF && + le64_to_cpu(ext->e_end) & (LOV_MIN_STRIPE_SIZE - 1))) { CDEBUG(D_LAYOUT, "invalid extent "DEXT"\n", le64_to_cpu(ext->e_start), le64_to_cpu(ext->e_end)); diff --git a/lustre/lod/lod_object.c b/lustre/lod/lod_object.c index 7851961..751eb6b 100644 --- a/lustre/lod/lod_object.c +++ b/lustre/lod/lod_object.c @@ -1136,6 +1136,12 @@ void lod_adjust_stripe_size(struct lod_layout_component *comp, else comp->llc_stripe_size = comp_end & ~(comp_end - 1); } else { + if (comp_end != LUSTRE_EOF && + comp_end & (LOV_MIN_STRIPE_SIZE - 1)) { + CWARN("Component end %llu is not a multiple of min size %u\n", + comp_end, LOV_MIN_STRIPE_SIZE); + comp_end = round_up(comp_end, LOV_MIN_STRIPE_SIZE); + } /* check stripe size is multiplier of comp_end */ if (comp_end != LUSTRE_EOF && comp_end % comp->llc_stripe_size) { @@ -1144,7 +1150,6 @@ void lod_adjust_stripe_size(struct lod_layout_component *comp, */ CWARN("Component end %llu is not aligned by the stripe size %u\n", comp_end, comp->llc_stripe_size); - dump_stack(); comp->llc_stripe_size = comp_end & ~(comp_end - 1); } } diff --git a/lustre/tests/sanity-pfl.sh b/lustre/tests/sanity-pfl.sh index 664acc2..601846d 100644 --- a/lustre/tests/sanity-pfl.sh +++ b/lustre/tests/sanity-pfl.sh @@ -128,6 +128,61 @@ test_0c() { } run_test 0c "Verify SEL comp stripe count limits" +test_0d() { + local td=$DIR/$tdir + local tf=$td/$tfile + local comp_end + local stripe_size + + # Create parent directory + test_mkdir $td + + # Component end must be a multiple of stripe size + # and a multiple of 64KiB to align with the minimum + # stripe size value. + # Values below 4096 are assumed to be in KiB units. + $LFS setstripe -E 127 $tf-1 > /dev/null 2>&1 && + error "creating $tf-1 with '-E 127' should fail" + + $LFS setstripe -E 128 -S 512 $tf-1 > /dev/null 2>&1 && + error "creating $tf-1 with '-E 128 -S 512' should fail" + + $LFS setstripe -E 128 $tf-1 || + error "creating $tf-1 failed" + + yes | dd bs=1K count=129 iflag=fullblock of=$tf-1 && + error "writing to $tf-1 should fail" + + yes | dd bs=1K count=128 iflag=fullblock of=$tf-1 || + error "writing to $tf-1 failed" + + comp_end=$($LFS getstripe -I1 -E $tf-1) + stripe_size=$($LFS getstripe -I1 -S $tf-1) + + [[ $comp_end == $((128 * 1024)) ]] || + error "incorrect component end '$comp_end' for $tf-1" + + [[ $stripe_size == $((128 * 1024)) ]] || + error "incorrect stripe size '$stripe_size' for $tf-1" + + rm $tf-1 || error "removing $tf-1 failed" + + # The stripe size must be a multiple of 64KiB. + # Values below 4096 are assumed to be in KiB units. + $LFS setstripe -E -1 -S 2047 $tf-2 > /dev/null 2>&1 && + error "creating $tf-2 with '-S 2047' should fail" + + $LFS setstripe -E -1 -S 2048 $tf-2 || + error "creating $tf-2 failed" + + stripe_size=$($LFS getstripe -I1 -S $tf-2) + [[ $stripe_size == $((2048 * 1024)) ]] || + error "incorrect stripe size '$stripe_size' for $tf-2" + + rm $tf-2 || error "removing $tf-2 failed" +} +run_test 0d "Verify comp end and stripe size" + test_1a() { local comp_file=$DIR/$tdir/$tfile local rw_len=$((3 * 1024 * 1024)) # 3M diff --git a/lustre/utils/lfs.c b/lustre/utils/lfs.c index c11a824..0dde872 100644 --- a/lustre/utils/lfs.c +++ b/lustre/utils/lfs.c @@ -197,36 +197,36 @@ static inline int lfs_mirror_delete(int argc, char **argv) " [--copy=]\n" #define SSM_HELP_COMMON \ - "\tstripe_count: Number of OSTs to stripe over (0=fs default, -1 all)\n" \ - "\t Using -C instead of -c allows overstriping, which\n" \ - "\t will place more than one stripe per OST if\n" \ - "\t stripe_count is greater than the number of OSTs\n" \ + "\tstripe_count: Number of OSTs to stripe on (0=fs default, -1 all)\n" \ + "\t Using -C instead of -c allows overstriping, which\n" \ + "\t will place more than one stripe per OST if\n" \ + "\t stripe_count is greater than the number of OSTs.\n" \ "\tstart_ost_idx: OST index of first stripe (-1=default round robin)\n"\ - "\tstripe_size: Number of bytes on each OST (0=fs default)\n" \ - "\t Can be specified with K, M or G (for KB, MB, GB\n" \ - "\t respectively)\n" \ - "\textension_size:\n" \ + "\tstripe_size: Number of bytes on each OST (0=fs default)\n" \ + "\t Optional K, M, or G suffix (for KB, MB, GB\n" \ + "\t respectively). Must be a multiple of 64KiB.\n" \ + "\textension_size:\n" \ "\t Number of bytes the previous component is extended\n" \ - "\t each time. Can be specified with K, M, G (for KB,\n" \ - "\t MB, GB respectively)\n" \ - "\tpool_name: Name of OST pool to use (default none)\n" \ - "\tlayout: stripe pattern type: raid0, mdt (default raid0)\n"\ + "\t each time. Optional K, M, or G suffix (for KB,\n" \ + "\t MB, GB respectively)\n" \ + "\tpool_name: Name of OST pool to use (default none)\n" \ + "\tlayout: stripe pattern type: raid0, mdt (default raid0)\n" \ "\tost_indices: List of OST indices, can be repeated multiple times\n"\ - "\t Indices be specified in a format of:\n" \ - "\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.\n" \ - "\tcomp_end: Extent end of component, start after previous end.\n"\ - "\t Can be specified with K, M or G (for KB, MB, GB\n" \ - "\t respectively, -1 for EOF). Must be a multiple of\n"\ - "\t stripe_size.\n" \ - "\tyaml_template_file:\n" \ - "\t YAML layout template file, can't be used with -c,\n" \ - "\t -i, -S, -p, -o, or -E arguments.\n" \ - "\tlustre_src: Lustre file/dir whose layout info is used to set\n" \ - "\t another lustre file or directory, can't used with\n" \ + "\t Indices be specified in a format of:\n" \ + "\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.\n" \ + "\tcomp_end: Extent end of component, start after previous end.\n" \ + "\t Optional K, M, or G suffix (for KiB, MiB, GiB), or\n" \ + "\t -1 or 'eof' for max file size). Must be a multiple\n" \ + "\t of stripe_size and a multiple of 64KiB.\n" \ + "\tyaml_template_file:\n" \ + "\t YAML layout template file, can't be used with -c,\n" \ + "\t -i, -S, -p, -o, or -E arguments.\n" \ + "\tlustre_src: Lustre file/dir whose layout info is used to set\n" \ + "\t another lustre file or directory, can't used with\n" \ "\t -c, -i, -S, -p, -o, or -E arguments.\n" #define MIRROR_CREATE_HELP \ @@ -3508,9 +3508,13 @@ static int lfs_setstripe_internal(int argc, char **argv, lsa.lsa_comp_end = LUSTRE_EOF; } else { result = llapi_parse_size(optarg, - &lsa.lsa_comp_end, - &size_units, 0); - if (result) { + &lsa.lsa_comp_end, + &size_units, 0); + /* assume units of KB if too small */ + if (lsa.lsa_comp_end < 4096) + lsa.lsa_comp_end *= 1024; + if (result || + lsa.lsa_comp_end & (LOV_MIN_STRIPE_SIZE - 1)) { fprintf(stderr, "%s %s: invalid component end '%s'\n", progname, argv[0], optarg); @@ -3723,7 +3727,11 @@ static int lfs_setstripe_internal(int argc, char **argv, case 'S': result = llapi_parse_size(optarg, &lsa.lsa_stripe_size, &size_units, 0); - if (result) { + /* assume units of KB if too small to be valid */ + if (lsa.lsa_stripe_size < 4096) + lsa.lsa_stripe_size *= 1024; + if (result || + lsa.lsa_stripe_size & (LOV_MIN_STRIPE_SIZE - 1)) { fprintf(stderr, "%s %s: invalid stripe size '%s'\n", progname, argv[0], optarg); @@ -4694,6 +4702,9 @@ static int lfs_find(int argc, char **argv) rc = llapi_parse_size(optarg, ¶m.fp_comp_end, ¶m.fp_comp_end_units, 0); + /* assume units of KB if too small */ + if (param.fp_comp_end < 4096) + param.fp_comp_end *= 1024; } if (rc) { fprintf(stderr, @@ -5100,6 +5111,9 @@ err_free: ret = llapi_parse_size(optarg, ¶m.fp_stripe_size, ¶m.fp_stripe_size_units, 0); + /* assume units of KB if too small to be valid */ + if (param.fp_stripe_size < 4096) + param.fp_stripe_size *= 1024; if (ret) { fprintf(stderr, "error: bad stripe_size '%s'\n", optarg); @@ -5442,6 +5456,9 @@ static int lfs_getstripe_internal(int argc, char **argv, rc = llapi_parse_size(tmp, ¶m->fp_comp_end, ¶m->fp_comp_end_units, 0); + /* assume units of KB if too small */ + if (param->fp_comp_end < 4096) + param->fp_comp_end *= 1024; } if (rc != 0) { fprintf(stderr, -- 1.8.3.1