Whamcloud - gitweb
LU-13720 lfs: resync file if needed before mirror_split() 78/55978/10
authorEmoly Liu <emoly@whamcloud.com>
Tue, 3 Dec 2024 20:24:19 +0000 (04:24 +0800)
committerOleg Drokin <green@whamcloud.com>
Thu, 2 Jan 2025 20:47:39 +0000 (20:47 +0000)
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 <emoly@whamcloud.com>
Change-Id: Ice5ef893910e744d235dcb07f1049dfeede65858
Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/55978
Tested-by: jenkins <devops@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
Reviewed-by: Zhenyu Xu <bobijam@hotmail.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
lustre/doc/lfs-mirror-delete.1
lustre/doc/lfs-mirror-split.1
lustre/tests/sanity-flr.sh
lustre/tests/sanity.sh
lustre/utils/lfs.c

index b03043a..62d64a6 100644 (file)
@@ -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>
index eaeb196..4fc1e84 100644 (file)
@@ -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
index cd37816..aa0f815 100644 (file)
@@ -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"
index 0696b91..bd239ee 100755 (executable)
@@ -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))
index c365572..5294ace 100755 (executable)
@@ -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",