From e768624788b7b8797c97ca27f2e6f9f63124dba0 Mon Sep 17 00:00:00 2001 From: Vitaly Fertman Date: Sat, 22 Jun 2019 01:45:49 +0300 Subject: [PATCH] LU-10070 utils: setstripe component-add support for SEL the math of the SEL component sizes calculation does not work for the component end when some components already exist. Signed-off-by: Vitaly Fertman Change-Id: I793ea7e5a5ac8f4639f694f83af7d413bd2b982c Reviewed-on: https://review.whamcloud.com/35314 Tested-by: jenkins Tested-by: Maloo Reviewed-by: Alexey Lyashkov Reviewed-by: Patrick Farrell Reviewed-by: Oleg Drokin --- lustre/tests/sanity-pfl.sh | 68 ++++++++++++++ lustre/utils/lfs.c | 215 ++++++++++++++++++++++++++++++++------------- 2 files changed, 222 insertions(+), 61 deletions(-) diff --git a/lustre/tests/sanity-pfl.sh b/lustre/tests/sanity-pfl.sh index 714d6cb..6a0665d 100644 --- a/lustre/tests/sanity-pfl.sh +++ b/lustre/tests/sanity-pfl.sh @@ -1255,6 +1255,74 @@ test_19f() { } run_test 19f "Rejection of invalid layouts" +test_19g() { + [ $OSTCOUNT -lt 2 ] && skip "needs >= 2 OSTs" && return + [ $(lustre_version_code $SINGLEMDS) -lt $(version_code $SEL_VER) ] && + skip "skipped for lustre < $SEL_VER" + + local file1=$DIR/${tfile}-1 + local file2=$DIR/${tfile}-2 + + test_mkdir -p $DIR/$tdir + multiop $file1 oO_RDWR:O_CREAT:O_LOV_DELAY_CREATE:c || + error "create failed $file1" + multiop $file2 oO_RDWR:O_CREAT:O_LOV_DELAY_CREATE:c || + error "create failed $file2" + + $LFS setstripe --component-add -E 1G -c 1 $file1 || + error "comp-add [0,1G] failed $file1" + $LFS setstripe --component-add -E 10G -z 128M $file1 || + error "comp-add [1G,1G],SEL[1G,10G] failed $file1" + $LFS setstripe --component-add -E -1 $file1 || + error "comp-add [10G,-1] failed $file1" + + $LFS setstripe --component-add -E 1G -z 128M -c 1 $file2 || + error "comp-add [0,128M],SEL[128M,1G] failed $file1" + $LFS setstripe --component-add -E 10G $file2 || + error "comp-add [1G,10G] failed $file1" + $LFS setstripe --component-add -E -1 -z 128M -c 1 $file2 || + error "comp-add [10G,10G],SEL[10G,-1] failed $file1" + + $LFS getstripe $file1 + flg_opts="--comp-flags init" + found=$($LFS find --comp-start 0 -E 1G $flg_opts $file1 | wc -l) + [ $found -eq 1 ] || error "First component not found $file1" + + flg_opts="--comp-flags ^init" + found=$($LFS find --comp-start 1G -E 1G $flg_opts $file1 | wc -l) + [ $found -eq 1 ] || error "Second component not found $file1" + + flg_opts="--comp-flags ^init,extension" + found=$($LFS find --comp-start 1G -E 10G $flg_opts $file1 | wc -l) + [ $found -eq 1 ] || error "Third component not found $file1" + + flg_opts="--comp-flags ^init" + found=$($LFS find --comp-start 10G -E EOF $flg_opts $file1 | wc -l) + [ $found -eq 1 ] || error "Fourth component not found $file1" + + $LFS getstripe $file2 + flg_opts="--comp-flags init" + found=$($LFS find --comp-start 0 -E 128M $flg_opts $file2 | wc -l) + [ $found -eq 1 ] || error "First component not found $file2" + + flg_opts="--comp-flags extension" + found=$($LFS find --comp-start 128M -E 1G $flg_opts $file2 | wc -l) + [ $found -eq 1 ] || error "Second component not found $file2" + + flg_opts="--comp-flags ^init" + found=$($LFS find --comp-start 1G -E 10G $flg_opts $file2 | wc -l) + [ $found -eq 1 ] || error "Third component not found $file2" + + flg_opts="--comp-flags ^init" + found=$($LFS find --comp-start 10G -E 10G $flg_opts $file2 | wc -l) + [ $found -eq 1 ] || error "Fourth component not found $file2" + + flg_opts="--comp-flags ^init,extension" + found=$($LFS find --comp-start 10G -E EOF $flg_opts $file2 | wc -l) + [ $found -eq 1 ] || error "Fifth component not found $file2" +} +run_test 19g "component-add behaviour" + # Test out of space behavior test_20a() { [ $OSTCOUNT -lt 2 ] && skip "needs >= 2 OSTs" && return diff --git a/lustre/utils/lfs.c b/lustre/utils/lfs.c index 8babfb4..6927d84 100644 --- a/lustre/utils/lfs.c +++ b/lustre/utils/lfs.c @@ -2183,14 +2183,9 @@ new_comp: if (set_extent) { uint64_t comp_end = lsa->lsa_comp_end; - /* Extension space handling: - * If this is the first component, length is extension_size. - * If not, it is zero length, so it can be removed if there is - * insufficient space to extend it. - */ - if (lsa->lsa_extension_comp && lsa->lsa_first_comp) - comp_end = prev_end + lsa->lsa_extension_size; - else if (lsa->lsa_extension_comp) + /* The extendable component is 0-length, so it can be removed + * if there is insufficient space to extend it. */ + if (lsa->lsa_extension_comp) comp_end = prev_end; rc = llapi_layout_comp_extent_set(layout, prev_end, @@ -2487,50 +2482,133 @@ err: return rc; } -/* 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) +/** + * Get the extension size from the next (SEL) component and extend the + * current component on it. The start of the next component is to be + * adjusted as well. + * + * \param[in] layout the current layout + * \param[in] start the start of the current component + * \param[in,out] end the end of the current component + * \param[in] offset the offset to adjust the end position to instead of + * extension size + * + * \retval 0 - extended successfully + * \retval < 0 - error + */ +static int layout_extend_comp(struct llapi_layout *layout, + uint64_t start, uint64_t *end, + uint64_t offset) { - struct llapi_layout *head; - uint64_t start, end, stripe_size, prev_end = 0; + uint64_t size, next_start, next_end; int rc; - if (layout == NULL) { - fprintf(stderr, - "%s setstripe: layout must be specified\n", - progname); - return -EINVAL; + rc = llapi_layout_comp_use(layout, LLAPI_LAYOUT_COMP_USE_NEXT); + if (rc < 0) { + fprintf(stderr, "%s setstripe: cannot move component cursor: " + "%s\n", progname, strerror(errno)); + return rc; } - errno = 0; - head = llapi_layout_get_by_path(fname, 0); - if (head == NULL) { - fprintf(stderr, - "%s setstripe: cannot read layout from '%s': %s\n", - progname, fname, strerror(errno)); - return -EINVAL; - } else if (errno == ENODATA) { - /* file without LOVEA, this component-add will be turned - * into a component-create. */ - llapi_layout_free(head); - return -ENODATA; - } else if (!llapi_layout_is_composite(head)) { - fprintf(stderr, "%s setstripe: '%s' not a composite file\n", - progname, fname); - llapi_layout_free(head); - return -EINVAL; + /* Even if the @size will not be used below, this will fail if + * this is not a SEL component - a good confirmation we are + * working on right components. */ + rc = llapi_layout_extension_size_get(layout, &size); + if (rc < 0) { + fprintf(stderr, "%s setstripe: cannot get component ext size: " + "%s\n", progname, strerror(errno)); + return rc; } - rc = llapi_layout_comp_extent_get(head, &start, &prev_end); + rc = llapi_layout_comp_extent_get(layout, &next_start, &next_end); if (rc) { - fprintf(stderr, "%s setstripe: cannot get prev extent: %s\n", + fprintf(stderr, "%s setstripe: cannot get extent: %s\n", progname, strerror(errno)); - llapi_layout_free(head); return rc; } - llapi_layout_free(head); + next_start += offset ?: size; + rc = llapi_layout_comp_extent_set(layout, next_start, next_end); + if (rc) { + fprintf(stderr, "%s setstripe: cannot set extent: %s\n", + progname, strerror(errno)); + return rc; + } + + rc = llapi_layout_comp_use(layout, LLAPI_LAYOUT_COMP_USE_PREV); + if (rc < 0) { + fprintf(stderr, "%s setstripe: cannot move component cursor: " + "%s\n", progname, strerror(errno)); + return rc; + } + + *end += offset ?: size; + rc = llapi_layout_comp_extent_set(layout, start, *end); + if (rc) { + fprintf(stderr, "%s setstripe: cannot set extent: %s\n", + progname, 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. + * + * In the create mode, we need to check if the first component is an extendable + * SEL component and extend its length to the extension size (first component + * of the PFL file is initialised at the create time, cannot be 0-lenght. + */ +static int layout_adjust_first_extent(char *fname, struct llapi_layout *layout, + bool comp_add) +{ + struct llapi_layout *head; + uint64_t start = 0, prev_end = 0; + uint64_t end; + int rc, ret = 0; + + if (layout == NULL) + return 0; + + errno = 0; + while (comp_add) { + head = llapi_layout_get_by_path(fname, 0); + if (head == NULL) { + fprintf(stderr, + "%s setstripe: cannot read layout from '%s': " + "%s\n", progname, fname, strerror(errno)); + return -EINVAL; + } else if (errno == ENODATA) { + /* file without LOVEA, this component-add will be turned + * into a component-create. */ + llapi_layout_free(head); + ret = -ENODATA; + + /* the new layout will be added to an empty one, it + * still needs to be adjusted below */ + comp_add = 0; + break; + } else if (!llapi_layout_is_composite(head)) { + fprintf(stderr, "%s setstripe: '%s' not a composite " + "file\n", progname, fname); + llapi_layout_free(head); + return -EINVAL; + } + + rc = llapi_layout_comp_extent_get(head, &start, &prev_end); + if (rc) { + fprintf(stderr, "%s setstripe: cannot get prev " + "extent: %s\n", progname, strerror(errno)); + llapi_layout_free(head); + return rc; + } + + llapi_layout_free(head); + break; + } /* Make sure we use the first component of the layout to be added. */ rc = llapi_layout_comp_use(layout, LLAPI_LAYOUT_COMP_USE_FIRST); @@ -2548,37 +2626,46 @@ static int adjust_first_extent(char *fname, struct llapi_layout *layout) return rc; } - if (start > prev_end || end <= prev_end) { - fprintf(stderr, - "%s setstripe: first extent [%lu, %lu) not adjacent with extent end %lu\n", - progname, start, end, prev_end); - return -EINVAL; - } - - rc = llapi_layout_stripe_size_get(layout, &stripe_size); - if (rc) { - fprintf(stderr, "%s setstripe: cannot get stripe size: %s\n", - progname, strerror(errno)); - return rc; + if (start == 0 && end == 0) { + rc = layout_extend_comp(layout, start, &end, + comp_add ? prev_end : 0); + if (rc) + return rc; } - if (stripe_size != LLAPI_LAYOUT_DEFAULT && - (prev_end & (stripe_size - 1))) { - fprintf(stderr, - "%s setstripe: stripe size %lu not aligned with %lu\n", - progname, stripe_size, prev_end); + if (start > prev_end || end < prev_end) { + fprintf(stderr, "%s setstripe: first extent [%lu, %lu) not " + "adjacent with extent end %lu\n", + progname, start, end, prev_end); return -EINVAL; } rc = llapi_layout_comp_extent_set(layout, prev_end, end); if (rc) { - fprintf(stderr, - "%s setstripe: cannot set component extent [%lu, %lu): %s\n", + fprintf(stderr, "%s setstripe: cannot set component extent " + "[%lu, %lu): %s\n", progname, prev_end, end, strerror(errno)); return rc; } - return 0; + return ret; +} + +static int mirror_adjust_first_extents(struct mirror_args *list) +{ + int rc = 0; + + if (list == NULL) + return 0; + + while (list != NULL) { + rc = layout_adjust_first_extent(NULL, list->m_layout, false); + if (rc) + break; + list = list->m_next; + } + + return rc; } static inline bool arg_is_eof(char *arg) @@ -3367,8 +3454,14 @@ static int lfs_setstripe_internal(int argc, char **argv, progname, argv[0]); goto usage_error; } + } - result = adjust_first_extent(fname, layout); + if (layout != NULL || mirror_list != NULL) { + if (mirror_list) + result = mirror_adjust_first_extents(mirror_list); + else + result = layout_adjust_first_extent(fname, layout, + comp_add); if (result == -ENODATA) comp_add = 0; else if (result != 0) { -- 1.8.3.1