]> git.proxmox.com Git - mirror_zfs.git/commitdiff
Ignore pool ashift property during vdev attachment
authorAmeer Hamza <ahamza@ixsystems.com>
Thu, 20 Jul 2023 16:57:16 +0000 (21:57 +0500)
committerGitHub <noreply@github.com>
Thu, 20 Jul 2023 16:57:16 +0000 (09:57 -0700)
Ashift can be set for a vdev only during its creation, and the
top-level vdev does not change when a vdev is attached or replaced.
The ashift property should not be used during attachment, as it
does not allow attaching/replacing a vdev if the pool's ashift
property is increased after the existing vdev was created. Instead,
we should be able to attach the vdev if the attached vdev can
satisfy the ashift requirement with its parent.

Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Reviewed-by: Alexander Motin <mav@FreeBSD.org>
Signed-off-by: Ameer Hamza <ahamza@ixsystems.com>
Closes #15061

include/sys/vdev_impl.h
module/zfs/vdev.c
tests/zfs-tests/tests/functional/cli_root/zpool_attach/attach-o_ashift.ksh
tests/zfs-tests/tests/functional/cli_root/zpool_replace/replace-o_ashift.ksh
tests/zfs-tests/tests/functional/cli_root/zpool_replace/replace_prop_ashift.ksh

index 2b22b973ba49e2ad4c3c518e1023b34d14823d26..5f4e82ad86576b95ce466b1d7572ef762e024564 100644 (file)
@@ -420,6 +420,7 @@ struct vdev {
        boolean_t       vdev_copy_uberblocks;  /* post expand copy uberblocks */
        boolean_t       vdev_resilver_deferred;  /* resilver deferred */
        boolean_t       vdev_kobj_flag; /* kobj event record */
+       boolean_t       vdev_attaching; /* vdev attach ashift handling */
        vdev_queue_t    vdev_queue;     /* I/O deadline schedule queue  */
        spa_aux_vdev_t  *vdev_aux;      /* for l2cache and spares vdevs */
        zio_t           *vdev_probe_zio; /* root of current probe       */
index 30551feb63227f9cda6543ee03524ac590e12ff2..1199bf5d32ca043aa054144ee24945984ef13f4d 100644 (file)
@@ -889,9 +889,15 @@ vdev_alloc(spa_t *spa, vdev_t **vdp, nvlist_t *nv, vdev_t *parent, uint_t id,
            &vd->vdev_not_present);
 
        /*
-        * Get the alignment requirement.
+        * Get the alignment requirement. Ignore pool ashift for vdev
+        * attach case.
         */
-       (void) nvlist_lookup_uint64(nv, ZPOOL_CONFIG_ASHIFT, &vd->vdev_ashift);
+       if (alloctype != VDEV_ALLOC_ATTACH) {
+               (void) nvlist_lookup_uint64(nv, ZPOOL_CONFIG_ASHIFT,
+                   &vd->vdev_ashift);
+       } else {
+               vd->vdev_attaching = B_TRUE;
+       }
 
        /*
         * Retrieve the vdev creation time.
@@ -2144,9 +2150,9 @@ vdev_open(vdev_t *vd)
                                return (SET_ERROR(EDOM));
                        }
 
-                       if (vd->vdev_top == vd) {
+                       if (vd->vdev_top == vd && vd->vdev_attaching == B_FALSE)
                                vdev_ashift_optimize(vd);
-                       }
+                       vd->vdev_attaching = B_FALSE;
                }
                if (vd->vdev_ashift != 0 && (vd->vdev_ashift < ASHIFT_MIN ||
                    vd->vdev_ashift > ASHIFT_MAX)) {
index 6ccec6abd66f276cdafe216d0f12511756fd7eb5..574cb7654d10048c45a7fc8e36b18803ee008170 100755 (executable)
@@ -35,7 +35,7 @@
 #
 # STRATEGY:
 #      1. Create various pools with different ashift values.
-#      2. Verify 'attach -o ashift=<n>' works only with allowed values.
+#      2. Verify 'attach' works.
 #
 
 verify_runnable "global"
@@ -66,26 +66,14 @@ log_must set_tunable32 VDEV_FILE_PHYSICAL_ASHIFT 16
 typeset ashifts=("9" "10" "11" "12" "13" "14" "15" "16")
 for ashift in ${ashifts[@]}
 do
-       for cmdval in ${ashifts[@]}
-       do
-               log_must zpool create -o ashift=$ashift $TESTPOOL1 $disk1
-               log_must verify_ashift $disk1 $ashift
-
-               # ashift_of(attached_disk) <= ashift_of(existing_vdev)
-               if [[ $cmdval -le $ashift ]]
-               then
-                       log_must zpool attach -o ashift=$cmdval $TESTPOOL1 \
-                           $disk1 $disk2
-                       log_must verify_ashift $disk2 $ashift
-               else
-                       log_mustnot zpool attach -o ashift=$cmdval $TESTPOOL1 \
-                           $disk1 $disk2
-               fi
-               # clean things for the next run
-               log_must zpool destroy $TESTPOOL1
-               log_must zpool labelclear $disk1
-               log_must zpool labelclear $disk2
-       done
+       log_must zpool create -o ashift=$ashift $TESTPOOL1 $disk1
+       log_must verify_ashift $disk1 $ashift
+       log_must zpool attach $TESTPOOL1 $disk1 $disk2
+       log_must verify_ashift $disk2 $ashift
+       # clean things for the next run
+       log_must zpool destroy $TESTPOOL1
+       log_must zpool labelclear $disk1
+       log_must zpool labelclear $disk2
 done
 
 typeset badvals=("off" "on" "1" "8" "17" "1b" "ff" "-")
index 37ed0062e61cf185711cee097ffa6a075c5a17f5..9595e51241b3e14c4ccc38c878344e75c80e68ec 100755 (executable)
@@ -35,7 +35,7 @@
 #
 # STRATEGY:
 #      1. Create various pools with different ashift values.
-#      2. Verify 'replace -o ashift=<n>' works only with allowed values.
+#      2. Verify 'replace' works.
 #
 
 verify_runnable "global"
@@ -66,26 +66,16 @@ log_must set_tunable32 VDEV_FILE_PHYSICAL_ASHIFT 16
 typeset ashifts=("9" "10" "11" "12" "13" "14" "15" "16")
 for ashift in ${ashifts[@]}
 do
-       for cmdval in ${ashifts[@]}
-       do
-               log_must zpool create -o ashift=$ashift $TESTPOOL1 $disk1
-               log_must verify_ashift $disk1 $ashift
-               # ashift_of(replacing_disk) <= ashift_of(existing_vdev)
-               if [[ $cmdval -le $ashift ]]
-               then
-                       log_must zpool replace -o ashift=$cmdval $TESTPOOL1 \
-                           $disk1 $disk2
-                       log_must verify_ashift $disk2 $ashift
-                       wait_replacing $TESTPOOL1
-               else
-                       log_mustnot zpool replace -o ashift=$cmdval $TESTPOOL1 \
-                           $disk1 $disk2
-               fi
-               # clean things for the next run
-               log_must zpool destroy $TESTPOOL1
-               log_must zpool labelclear $disk1
-               log_must zpool labelclear $disk2
-       done
+       log_must zpool create -o ashift=$ashift $TESTPOOL1 $disk1
+       log_must verify_ashift $disk1 $ashift
+       # ashift_of(replacing_disk) <= ashift_of(existing_vdev)
+       log_must zpool replace $TESTPOOL1 $disk1 $disk2
+       log_must verify_ashift $disk2 $ashift
+       wait_replacing $TESTPOOL1
+       # clean things for the next run
+       log_must zpool destroy $TESTPOOL1
+       log_must zpool labelclear $disk1
+       log_must zpool labelclear $disk2
 done
 
 typeset badvals=("off" "on" "1" "8" "17" "1b" "ff" "-")
index ffdaf91a28415f89062b77d5d3e388128bd3f562..b4ac18e5ea2540eed8c73b3eb409730ead51139d 100755 (executable)
 #
 # STRATEGY:
 #      1. Create a pool with default values.
-#      2. Verify 'zpool replace' uses the ashift pool property value when
-#         replacing an existing device.
-#      3. Verify the default ashift value can still be overridden by manually
-#         specifying '-o ashift=<n>' from the command line.
+#      2. Override the pool ashift property.
+#      3. Verify 'zpool replace' works.
 #
 
 verify_runnable "global"
@@ -72,21 +70,9 @@ do
        do
                log_must zpool create -o ashift=$ashift $TESTPOOL1 $disk1
                log_must zpool set ashift=$pprop $TESTPOOL1
-               # ashift_of(replacing_disk) <= ashift_of(existing_vdev)
-               if [[ $pprop -le $ashift ]]
-               then
-                       log_must zpool replace $TESTPOOL1 $disk1 $disk2
-                       wait_replacing $TESTPOOL1
-                       log_must verify_ashift $disk2 $ashift
-               else
-                       # cannot replace if pool prop ashift > vdev ashift
-                       log_mustnot zpool replace $TESTPOOL1 $disk1 $disk2
-                       # verify we can override the pool prop value manually
-                       log_must zpool replace -o ashift=$ashift $TESTPOOL1 \
-                           $disk1 $disk2
-                       wait_replacing $TESTPOOL1
-                       log_must verify_ashift $disk2 $ashift
-               fi
+               log_must zpool replace $TESTPOOL1 $disk1 $disk2
+               wait_replacing $TESTPOOL1
+               log_must verify_ashift $disk2 $ashift
                # clean things for the next run
                log_must zpool destroy $TESTPOOL1
                log_must zpool labelclear $disk1