]> granicus.if.org Git - zfs/commitdiff
zpool split can create a corrupted pool
authorRoman Strashkin <Ramzec@users.noreply.github.com>
Thu, 13 Sep 2018 01:14:42 +0000 (04:14 +0300)
committerBrian Behlendorf <behlendorf1@llnl.gov>
Thu, 13 Sep 2018 01:14:42 +0000 (18:14 -0700)
Added vdev_resilver_needed() check to verify VDEVs are fully
synced, so that after split the new pool will not be corrupted.

Reviewed by: Pavel Zakharov <pavel.zakharov@delphix.com>
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Reviewed-by: loli10K <ezomori.nozomu@gmail.com>
Signed-off-by: Roman Strashkin <roman.strashkin@nexenta.com>
Closes #7865
Closes #7881

module/zfs/spa.c
tests/runfiles/linux.run
tests/zfs-tests/tests/functional/cli_root/zpool_split/Makefile.am
tests/zfs-tests/tests/functional/cli_root/zpool_split/zpool_split_resilver.ksh [new file with mode: 0755]

index c503b06bc930c1b8ae78efcd5e0a8f71c9f44f94..7bf9cde5b302f42c96794c5ae0f222120a1c962b 100644 (file)
@@ -22,8 +22,7 @@
 /*
  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
  * Copyright (c) 2011, 2017 by Delphix. All rights reserved.
- * Copyright (c) 2015, Nexenta Systems, Inc.  All rights reserved.
- * Copyright (c) 2013, 2014, Nexenta Systems, Inc.  All rights reserved.
+ * Copyright (c) 2018, Nexenta Systems, Inc.  All rights reserved.
  * Copyright (c) 2014 Spectra Logic Corporation, All rights reserved.
  * Copyright 2013 Saso Kiselkov. All rights reserved.
  * Copyright (c) 2014 Integros [integros.com]
@@ -6485,7 +6484,8 @@ spa_vdev_split_mirror(spa_t *spa, char *newname, nvlist_t *config,
                        break;
                }
 
-               if (vdev_dtl_required(vml[c])) {
+               if (vdev_dtl_required(vml[c]) ||
+                   vdev_resilver_needed(vml[c], NULL, NULL)) {
                        error = SET_ERROR(EBUSY);
                        break;
                }
index 0090fe30db447bf873f54b206debb51a033e563b..4b41c3f743cae17b034a25ccc10d73517cf676d0 100644 (file)
@@ -432,7 +432,8 @@ tags = ['functional', 'cli_root', 'zpool_set']
 
 [tests/functional/cli_root/zpool_split]
 tests = ['zpool_split_cliargs', 'zpool_split_devices',
-    'zpool_split_encryption', 'zpool_split_props', 'zpool_split_vdevs']
+    'zpool_split_encryption', 'zpool_split_props', 'zpool_split_vdevs',
+    'zpool_split_resilver']
 tags = ['functional', 'cli_root', 'zpool_split']
 
 [tests/functional/cli_root/zpool_status]
index 863d1a059d22338beef46f4302a01b175884712d..b2a7fec10f2185dc7eb351874d367eb048ebe170 100644 (file)
@@ -9,4 +9,5 @@ dist_pkgdata_SCRIPTS = \
        zpool_split_devices.ksh \
        zpool_split_encryption.ksh \
        zpool_split_props.ksh \
-       zpool_split_vdevs.ksh
+       zpool_split_vdevs.ksh \
+       zpool_split_resilver.ksh
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_split/zpool_split_resilver.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_split/zpool_split_resilver.ksh
new file mode 100755 (executable)
index 0000000..4fa1d92
--- /dev/null
@@ -0,0 +1,109 @@
+#!/bin/ksh -p
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source.  A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2018, Nexenta Systems, Inc.  All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# 'zpool split' should fail if resilver in progress for a disk
+#
+# STRATEGY:
+# The first scenario:
+# 1. Create a mirror pool
+# 2. Offline the first VDEV
+# 3. Put some data
+# 4. Online the first VDEV
+# 5. Verify 'zpool split' must fail
+#
+# The second scenario:
+# 1. Create a mirror pool
+# 2. Offline the second VDEV
+# 3. Put some data
+# 4. Online the second VDEV
+# 5. Verify 'zpool split' must fail
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+       log_must zinject -c all
+       destroy_pool $TESTPOOL
+       destroy_pool $TESTPOOL2
+       rm -f $DEVICE1 $DEVICE2
+}
+
+function setup_mirror
+{
+       truncate -s $DEVSIZE $DEVICE1
+       truncate -s $DEVSIZE $DEVICE2
+       log_must zpool create -f $TESTPOOL mirror $DEVICE1 $DEVICE2
+}
+
+function zpool_split #disk_to_be_offline/online
+{
+       typeset disk=$1
+
+       setup_mirror
+
+       # offline a disk, so it will not be fully sync before split
+       log_must zpool offline $TESTPOOL $disk
+
+       # Create 2G of additional data
+       mntpnt=$(get_prop mountpoint $TESTPOOL)
+       log_must file_write -b 2097152 -c 1024 -o create -d 0 -f $mntpnt/biggerfile
+       log_must sync
+
+       # slow-down resilvering, so it will not finish too early
+       log_must set_tunable64 zfs_scan_vdev_limit $ZFS_SCAN_VDEV_LIMIT_SLOW
+       log_must zinject -d $DEVICE1 -D 50:1 $TESTPOOL
+       log_must zinject -d $DEVICE2 -D 50:1 $TESTPOOL
+
+       log_must zpool online $TESTPOOL $disk
+
+       typeset i=0
+       while ! is_pool_resilvering $TESTPOOL; do
+               if (( i > 10 )); then
+                       log_fail "resilvering is not started"
+               fi
+               ((i += 1))
+               sleep 1
+       done
+
+       log_mustnot zpool split $TESTPOOL $TESTPOOL2
+
+       log_must set_tunable64 zfs_scan_vdev_limit $ZFS_SCAN_VDEV_LIMIT_DEFAULT
+}
+
+log_assert "Verify 'zpool split' will fail if resilver in progress for a disk"
+log_onexit cleanup
+
+DEVSIZE='3g'
+DEVICE1="$TEST_BASE_DIR/device-1"
+DEVICE2="$TEST_BASE_DIR/device-2"
+
+ZFS_SCAN_VDEV_LIMIT_SLOW=$((128*1024))
+ZFS_SCAN_VDEV_LIMIT_DEFAULT=$(get_tunable zfs_scan_vdev_limit)
+
+log_note "Verify ZFS prevents main pool curruption during 'split'"
+zpool_split $DEVICE1
+
+cleanup
+
+log_note "Verify ZFS prevents new pool curruption during 'split'"
+zpool_split $DEVICE2
+
+log_pass "'zpool split' failed as expected"