From 83e38bba6237f838c9a5d7d36b258cf6dd28bd13 Mon Sep 17 00:00:00 2001 From: Andreas Dilger Date: Mon, 25 Jan 2021 18:14:10 -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. Signed-off-by: Andreas Dilger Signed-off-by: Jian Yu Change-Id: I47fe7729ffd447c1c1cc098e5117e456263ebbe5 Reviewed-on: https://review.whamcloud.com/41239 Tested-by: jenkins Tested-by: Maloo Reviewed-by: John L. Hammond Reviewed-by: Oleg Drokin --- 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 3bbac99..b9a144a 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 e011f7a..de18c92 100644 --- a/lustre/lod/lod_lov.c +++ b/lustre/lod/lod_lov.c @@ -1186,7 +1186,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) @@ -1914,7 +1933,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 876f8b4..9165fe2 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 c68a626..938a24c 100644 --- a/lustre/utils/lfs.c +++ b/lustre/utils/lfs.c @@ -198,36 +198,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 \ @@ -3481,9 +3481,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); @@ -3696,7 +3700,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); @@ -4667,6 +4675,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, @@ -5073,6 +5084,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); @@ -5415,6 +5429,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