From 81481104fdc8f52b3a36fc659f41a3b696a5bbf3 Mon Sep 17 00:00:00 2001 From: Emoly Liu Date: Wed, 4 Dec 2024 04:24:19 +0800 Subject: [PATCH] LU-13720 lfs: resync file if needed before mirror_split() If "lfs mirror delete" is called on a file to delete the only non-stale mirror of the file, it makes sense from a usability point of view to automatically resync the stale mirror(s) and then remove the mirror requested by the user, rather than returning an error to the user. Also, sanity-flr.sh test_44a/b and test_211 are modified to verify this patch. Man pages lfs-mirror-delete.1 and lfs-mirror-split.1 are updated to reflect this change. Test-Parameters: testlist=sanity-flr env=ONLY="44,211" Signed-off-by: Emoly Liu Change-Id: Ice5ef893910e744d235dcb07f1049dfeede65858 Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/55978 Tested-by: jenkins Tested-by: Maloo Reviewed-by: Andreas Dilger Reviewed-by: Zhenyu Xu Reviewed-by: Oleg Drokin --- lustre/doc/lfs-mirror-delete.1 | 3 --- lustre/doc/lfs-mirror-split.1 | 4 +-- lustre/tests/sanity-flr.sh | 36 ++++++++------------------- lustre/tests/sanity.sh | 30 ----------------------- lustre/utils/lfs.c | 55 ++++++++++++++++++++++++------------------ 5 files changed, 43 insertions(+), 85 deletions(-) diff --git a/lustre/doc/lfs-mirror-delete.1 b/lustre/doc/lfs-mirror-delete.1 index b03043a..62d64a6 100644 --- a/lustre/doc/lfs-mirror-delete.1 +++ b/lustre/doc/lfs-mirror-delete.1 @@ -16,9 +16,6 @@ converted to a regular non-mirrored file. .br If the original \fImirrored_file\fR is not a mirrored file, then the command will return an error. -.br -If the specified mirror is the last non-stale mirror, then the command will -return an error. .SH OPTIONS .TP .BR \-\-mirror\-id\fR\ <\fImirror_id\fR> diff --git a/lustre/doc/lfs-mirror-split.1 b/lustre/doc/lfs-mirror-split.1 index eaeb196..4fc1e84 100644 --- a/lustre/doc/lfs-mirror-split.1 +++ b/lustre/doc/lfs-mirror-split.1 @@ -14,9 +14,7 @@ This command splits a mirror with mirror ID <\fImirror_id\fR> or containing a component with <\fIcomp_id\fR> or containing a component on <\fIpool\fR> out of a mirrored file specified by the path name \fImirrored_file\fR. By default, the layout of the split mirror will be stored into a new file named -<\fImirrored_file\fR>.mirror~<\fImirror_id\fR>. If \fB\-\-destroy\fR|\fB\-d\fR -option is specified, and the split mirror is not the last non-stale mirror, -then it will be destroyed. +<\fImirrored_file\fR>.mirror~<\fImirror_id\fR>. If \fB\-f\fR <\fInew_file\fR> option is specified, then the layout of the split mirror will be stored into the named file. .br diff --git a/lustre/tests/sanity-flr.sh b/lustre/tests/sanity-flr.sh index cd37816..aa0f815 100644 --- a/lustre/tests/sanity-flr.sh +++ b/lustre/tests/sanity-flr.sh @@ -2213,18 +2213,8 @@ test_44a() { # write data in [0, 3M) dd if=/dev/urandom of=$tf bs=1M count=3 conv=notrunc || error "writing $tf failed" - verify_flr_state $tf "wp" - # disallow destroying the last non-stale mirror - ! $LFS mirror delete --mirror-id 1 $tf > /dev/null 2>&1 || - error "destroying mirror 1 should fail" - - # synchronize all mirrors of the file - $LFS mirror resync $tf || error "mirror resync $tf failed" - - verify_flr_state $tf "ro" - # split mirror 1 $LFS mirror split --mirror-id 1 -f $tf1 $tf || error "split to $tf1 failed" @@ -2248,14 +2238,9 @@ test_44a() { $LFS setstripe --comp-set -I 0x30008 --comp-flags=stale $tf || error "setting stale flag on component 0x30008 failed" - # disallow destroying the last non-stale mirror - ! $LFS mirror split --mirror-id 4 -d $tf > /dev/null 2>&1 || - error "destroying mirror 4 should fail" - - $LFS mirror resync $tf || error "resynchronizing $tf failed" - - $LFS mirror split --mirror-id 3 -d $tf || - error "destroying mirror 3 failed" + # allow destroying the last non-stale mirror + $LFS mirror split --mirror-id 4 -d $tf > /dev/null 2>&1 || + error "destroying mirror 4 failed" verify_mirror_count $tf 1 # verify splitted file contains the same content as the orig file does @@ -2301,16 +2286,17 @@ test_44b() { $LFS getstripe $tf - # split the updated mirror, should fail - echo "split mirror_id ${mirror_ids[$i]} id ${ids[$i]}, should fail" - $LFS mirror split --mirror-id=${mirror_ids[$i]} $tf &> /dev/null && - error "split --mirror-id=${mirror_ids[$i]} $tf should fail" + # split the updated mirror + echo "split mirror_id ${mirror_ids[$i]} id ${ids[$i]}" + $LFS mirror split --mirror-id=${mirror_ids[$i]} $tf &> /dev/null || + error "split --mirror-id=${mirror_ids[$i]} $tf should succeed" i=$(( 1 - i )) # split the stale mirror + $LFS getstripe $tf echo "split mirror_id ${mirror_ids[$i]} id ${ids[$i]}" - $LFS mirror split --mirror-id=${mirror_ids[$i]} -d $tf || - error "mirror split --mirror-id=${mirror_ids[$i]} $tf failed" + $LFS mirror split --mirror-id=${mirror_ids[$i]} -d $tf && + error "Should fail due to only one mirror now" echo "make sure there's no stale comp in the file" # make sure there's no stale comp in the file @@ -4593,8 +4579,6 @@ test_211() { ls -la $tf md5_1=$(md5sum $tf) || error "error getting first md5sum of '$tf'" - $LFS mirror resync $tf || error "error resync-ing '$tf'" - $LFS mirror delete --mirror-id=1 $tf || error "error deleting mirror 1 of '$tf'" echo "size after mirror delete" diff --git a/lustre/tests/sanity.sh b/lustre/tests/sanity.sh index 0696b91..bd239ee 100755 --- a/lustre/tests/sanity.sh +++ b/lustre/tests/sanity.sh @@ -22300,36 +22300,6 @@ test_210() { } run_test 210 "lfs getstripe does not break leases" -function test_211() { - local PID - local id - local rc - - stack_trap "rm -f $DIR/$tfile" EXIT - dd if=/dev/zero of=$DIR/$tfile bs=$PAGE_SIZE count=10 oflag=direct || - error "can't create file" - $LFS mirror extend -N $DIR/$tfile || - error "can't create a replica" - dd if=/dev/zero of=$DIR/$tfile bs=$PAGE_SIZE count=1 oflag=direct - $LFS getstripe $DIR/$tfile - stale=$($LFS getstripe $DIR/$tfile | grep stale | wc -l) - (( $stale != 1 )) && error "expected 1 stale, found $stale" - - $MULTIOP $DIR/$tfile OeW_E+eUc & - PID=$! - sleep 0.3 - - id=$($LFS getstripe $DIR/$tfile | - awk '/lcme_mirror_id:/{id=$2}/lcme_flags.*init$/{print id}') - $LFS mirror split -d --mirror-id $id $DIR/$tfile && - error "removed last in-sync replica?" - - kill -USR1 $PID - wait $PID - (( $? == 0 )) || error "failed split broke the lease" -} -run_test 211 "failed mirror split doesn't break write lease" - test_212() { size=`date +%s` size=$((size % 8192 + 1)) diff --git a/lustre/utils/lfs.c b/lustre/utils/lfs.c index c365572..5294ace 100755 --- a/lustre/utils/lfs.c +++ b/lustre/utils/lfs.c @@ -2444,14 +2444,6 @@ static int mirror_split(const char *fname, __u32 id, const char *pool, } } - if (last_non_stale_mirror(mirror_id, layout)) { - rc = -EUCLEAN; - fprintf(stderr, - "%s: cannot destroy the last non-stale mirror of file '%s'\n", - progname, fname); - goto free_layout; - } - if (!victim_file && mflags & MF_DESTROY) /* Allow mirror split even without the key on encrypted files, * and in this case of a 'split -d', open file with O_DIRECT @@ -2513,14 +2505,6 @@ again: unsigned int rnumber; int open_flags; - if (last_non_stale_mirror(mirror_id, layout)) { - rc = -EUCLEAN; - fprintf(stderr, - "%s: cannot destroy the last non-stale mirror of file '%s'\n", - progname, fname); - goto close_fd; - } - if (purge) { /* don't use volatile file for mirror destroy */ fdv = fd; @@ -4762,10 +4746,35 @@ create_mirror: progname, fname); goto usage_error; } - result = mirror_split(fname, comp_id, lsa.lsa_pool_name, - mirror_flags, - has_m_file ? mirror_list->m_file : - NULL); + + /* If the mirror is the only non-stale mirror, + * do resync before mirror_split(). + */ + result = 0; + if (!layout) + layout = layout_get_by_name_or_fid(template ?: + fname, fname, 0, O_RDONLY); + if (last_non_stale_mirror(mirror_id, layout)) { + struct ll_ioc_lease *ioc = NULL; + + ioc = calloc(1, sizeof(*ioc) + + sizeof(__u32) * IOC_IDS_MAX); + if (ioc) { + result = lfs_mirror_resync_file(fname, + ioc, NULL, 0, + stats_interval_sec, + bandwidth_bytes_sec); + if (result) + fprintf(stderr, + "Cannot resync file\n"); + free(ioc); + } + } + if (!result) + result = mirror_split(fname, comp_id, + lsa.lsa_pool_name, mirror_flags, + has_m_file ? + mirror_list->m_file : NULL); } else if (layout) { result = lfs_component_create(fname, O_CREAT | O_WRONLY, mode, layout); @@ -12407,7 +12416,7 @@ static inline int lfs_mirror_resync(int argc, char **argv) } /* set the lease on the file */ - ioc = calloc(sizeof(*ioc) + sizeof(__u32) * 4096, 1); + ioc = calloc(1, sizeof(*ioc) + sizeof(__u32) * IOC_IDS_MAX); if (!ioc) { fprintf(stderr, "%s: cannot alloc id array for ioc: %s.\n", argv[0], strerror(errno)); @@ -12423,7 +12432,7 @@ static inline int lfs_mirror_resync(int argc, char **argv) /* ignore previous file's error, continue with next file */ /* reset ioc */ - memset(ioc, 0, sizeof(*ioc) + sizeof(__u32) * 4096); + memset(ioc, 0, sizeof(*ioc) + sizeof(__u32) * IOC_IDS_MAX); } free(ioc); @@ -13195,7 +13204,7 @@ static inline int lfs_mirror_copy(int argc, char **argv) } } - ioc = calloc(sizeof(*ioc) + sizeof(__u32) * 4096, 1); + ioc = calloc(1, sizeof(*ioc) + sizeof(__u32) * IOC_IDS_MAX); if (!ioc) { fprintf(stderr, "%s %s: cannot alloc comp id array for ioc: %s\n", -- 1.8.3.1