diff options
-rw-r--r-- | module/zfs/zio.c | 18 | ||||
-rw-r--r-- | tests/zfs-tests/tests/functional/nopwrite/nopwrite.shlib | 8 | ||||
-rwxr-xr-x | tests/zfs-tests/tests/functional/removal/removal_nopwrite.ksh | 45 |
3 files changed, 55 insertions, 16 deletions
diff --git a/module/zfs/zio.c b/module/zfs/zio.c index 46904b800..2ae42e2df 100644 --- a/module/zfs/zio.c +++ b/module/zfs/zio.c @@ -20,7 +20,7 @@ */ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2011, 2020 by Delphix. All rights reserved. + * Copyright (c) 2011, 2022 by Delphix. All rights reserved. * Copyright (c) 2011 Nexenta Systems, Inc. All rights reserved. * Copyright (c) 2017, Intel Corporation. * Copyright (c) 2019, Klara Inc. @@ -2974,6 +2974,7 @@ zio_nop_write(zio_t *zio) blkptr_t *bp_orig = &zio->io_bp_orig; zio_prop_t *zp = &zio->io_prop; + ASSERT(BP_IS_HOLE(bp)); ASSERT(BP_GET_LEVEL(bp) == 0); ASSERT(!(zio->io_flags & ZIO_FLAG_IO_REWRITE)); ASSERT(zp->zp_nopwrite); @@ -3007,8 +3008,7 @@ zio_nop_write(zio_t *zio) ASSERT3U(BP_GET_PSIZE(bp), ==, BP_GET_PSIZE(bp_orig)); ASSERT3U(BP_GET_LSIZE(bp), ==, BP_GET_LSIZE(bp_orig)); ASSERT(zp->zp_compress != ZIO_COMPRESS_OFF); - ASSERT(memcmp(&bp->blk_prop, &bp_orig->blk_prop, - sizeof (uint64_t)) == 0); + ASSERT3U(bp->blk_prop, ==, bp_orig->blk_prop); /* * If we're overwriting a block that is currently on an @@ -3016,11 +3016,13 @@ zio_nop_write(zio_t *zio) * allow a new block to be allocated on a concrete vdev. */ spa_config_enter(zio->io_spa, SCL_VDEV, FTAG, RW_READER); - vdev_t *tvd = vdev_lookup_top(zio->io_spa, - DVA_GET_VDEV(&bp->blk_dva[0])); - if (tvd->vdev_ops == &vdev_indirect_ops) { - spa_config_exit(zio->io_spa, SCL_VDEV, FTAG); - return (zio); + for (int d = 0; d < BP_GET_NDVAS(bp_orig); d++) { + vdev_t *tvd = vdev_lookup_top(zio->io_spa, + DVA_GET_VDEV(&bp_orig->blk_dva[d])); + if (tvd->vdev_ops == &vdev_indirect_ops) { + spa_config_exit(zio->io_spa, SCL_VDEV, FTAG); + return (zio); + } } spa_config_exit(zio->io_spa, SCL_VDEV, FTAG); diff --git a/tests/zfs-tests/tests/functional/nopwrite/nopwrite.shlib b/tests/zfs-tests/tests/functional/nopwrite/nopwrite.shlib index 139b4b26e..a6d1eb2c7 100644 --- a/tests/zfs-tests/tests/functional/nopwrite/nopwrite.shlib +++ b/tests/zfs-tests/tests/functional/nopwrite/nopwrite.shlib @@ -57,12 +57,12 @@ function verify_nopwrite within_percent $origin_used $snap_refer $high || return 1 # - # The comparisons below should pass regardless of nopwrite. They're - # here for sanity. + # The comparisons below should be within 90% regardless of nopwrite. + # They're here for sanity. # typeset deadlist=$(zdb -Pddd $clone | awk '/Deadlist:/ {print $2}') - within_percent $deadlist $clone_written $high || return 1 - within_percent $snap_refer $snap_written $high || return 1 + within_percent $deadlist $clone_written 90 || return 1 + within_percent $snap_refer $snap_written 90 || return 1 return 0 } diff --git a/tests/zfs-tests/tests/functional/removal/removal_nopwrite.ksh b/tests/zfs-tests/tests/functional/removal/removal_nopwrite.ksh index cede81ad6..3533c41ca 100755 --- a/tests/zfs-tests/tests/functional/removal/removal_nopwrite.ksh +++ b/tests/zfs-tests/tests/functional/removal/removal_nopwrite.ksh @@ -15,7 +15,7 @@ # # -# Copyright (c) 2019 by Delphix. All rights reserved. +# Copyright (c) 2019, 2022 by Delphix. All rights reserved. # . $STF_SUITE/include/libtest.shlib @@ -24,19 +24,35 @@ default_setup_noexit "$DISKS" log_onexit default_cleanup_noexit -BLOCKSIZE=8192 + +# +# Randomly pick a device to remove +# +DISK_TOKENS=( $DISKS ) +DISK_INDEX_TO_REMOVE=$((RANDOM%${#DISK_TOKENS[@]})) +DISK_TO_REMOVE=${DISK_TOKENS[${DISK_INDEX_TO_REMOVE}]} origin="$TESTPOOL/$TESTFS" log_must zfs set compress=on $origin log_must zfs set checksum=skein $origin +log_must zfs set copies=1 $origin log_must zfs set recordsize=8k $origin dd if=/dev/urandom of=$TESTDIR/file_8k bs=1024k count=$MEGS oflag=sync \ conv=notrunc >/dev/null 2>&1 || log_fail "dd into $TESTDIR/file failed." +log_must zfs set copies=3 $origin +dd if=/dev/urandom of=$TESTDIR/file_8k_copies bs=1024k count=$MEGS oflag=sync \ + conv=notrunc >/dev/null 2>&1 || log_fail "dd into $TESTDIR/file failed." + +log_must zfs set copies=1 $origin log_must zfs set recordsize=128k $origin dd if=/dev/urandom of=$TESTDIR/file_128k bs=1024k count=$MEGS oflag=sync \ conv=notrunc >/dev/null 2>&1 || log_fail "dd into $TESTDIR/file failed." +log_must zfs set copies=3 $origin +dd if=/dev/urandom of=$TESTDIR/file_128k_copies bs=1024k \ + count=$MEGS oflag=sync conv=notrunc >/dev/null 2>&1 || \ + log_fail "dd into $TESTDIR/file failed." zfs snapshot $origin@a || log_fail "zfs snap failed" log_must zfs clone $origin@a $origin/clone @@ -44,22 +60,33 @@ log_must zfs clone $origin@a $origin/clone # # Verify that nopwrites work prior to removal # +log_must zfs set copies=1 $origin/clone log_must zfs set recordsize=8k $origin/clone dd if=/$TESTDIR/file_8k of=/$TESTDIR/clone/file_8k bs=1024k \ oflag=sync conv=notrunc >/dev/null 2>&1 || log_fail "dd failed." log_must verify_nopwrite $origin $origin@a $origin/clone +log_must zfs set copies=3 $origin/clone +dd if=/$TESTDIR/file_8k_copies of=/$TESTDIR/clone/file_8k_copies bs=1024k \ + oflag=sync conv=notrunc >/dev/null 2>&1 || log_fail "dd failed." +log_must verify_nopwrite $origin $origin@a $origin/clone +log_must zfs set copies=1 $origin/clone log_must zfs set recordsize=128k $origin/clone dd if=/$TESTDIR/file_128k of=/$TESTDIR/clone/file_128k bs=1024k \ oflag=sync conv=notrunc >/dev/null 2>&1 || log_fail "dd failed." log_must verify_nopwrite $origin $origin@a $origin/clone +log_must zfs set copies=3 $origin/clone +dd if=/$TESTDIR/file_128k_copies of=/$TESTDIR/clone/file_128k_copies bs=1024k \ + oflag=sync conv=notrunc >/dev/null 2>&1 || log_fail "dd failed." +log_must verify_nopwrite $origin $origin@a $origin/clone # # Remove a device before testing nopwrites again # -log_must zpool remove $TESTPOOL $REMOVEDISK +log_note "Removing: $DISK_TO_REMOVE" +log_must zpool remove $TESTPOOL $DISK_TO_REMOVE log_must wait_for_removal $TESTPOOL -log_mustnot vdevs_in_pool $TESTPOOL $REMOVEDISK +log_mustnot vdevs_in_pool $TESTPOOL $DISK_TO_REMOVE # # Normally, we expect nopwrites to avoid allocating new blocks, but @@ -71,17 +98,27 @@ log_mustnot vdevs_in_pool $TESTPOOL $REMOVEDISK # # Perform a direct zil nopwrite test # +log_must zfs set copies=1 $origin/clone log_must zfs set recordsize=8k $origin/clone dd if=/$TESTDIR/file_8k of=/$TESTDIR/clone/file_8k bs=1024k \ oflag=sync conv=notrunc >/dev/null 2>&1 || log_fail "dd failed." log_mustnot verify_nopwrite $origin $origin@a $origin/clone +log_must zfs set copies=3 $origin/clone +dd if=/$TESTDIR/file_8k_copies of=/$TESTDIR/clone/file_8k_copies bs=1024k \ + oflag=sync conv=notrunc >/dev/null 2>&1 || log_fail "dd failed." +log_mustnot verify_nopwrite $origin $origin@a $origin/clone # # Perform an indirect zil nopwrite test # +log_must zfs set copies=1 $origin/clone log_must zfs set recordsize=128k $origin/clone dd if=/$TESTDIR/file_128k of=/$TESTDIR/clone/file_128k bs=1024k \ oflag=sync conv=notrunc >/dev/null 2>&1 || log_fail "dd failed." log_mustnot verify_nopwrite $origin $origin@a $origin/clone +log_must zfs set copies=3 $origin/clone +dd if=/$TESTDIR/file_128k_copies of=/$TESTDIR/clone/file_128k_copies bs=1024k \ + oflag=sync conv=notrunc >/dev/null 2>&1 || log_fail "dd failed." +log_mustnot verify_nopwrite $origin $origin@a $origin/clone log_pass "Remove works with nopwrite." |