Fix issues with truncated files in raw sends

This patch fixes a few issues with raw receives involving
truncated files:

* dnode_reallocate() now calls dnode_set_blksz() instead of
  dnode_setdblksz(). This ensures that any remaining dbufs with
  blkid 0 are resized along with their containing dnode upon
  reallocation.

* One of the calls to dmu_free_long_range() in receive_object()
  needs to check that the object it is about to free some contents
  or hasn't been completely removed already by a previous call to
  dmu_free_long_object() in the same function.

* The same call to dmu_free_long_range() in the previous point
  needs to ensure it uses the object's current block size and
  not the new block size. This ensures the blocks of the object
  that are supposed to be freed are completely removed and not
  simply partially zeroed out.

This patch also adds handling for DRR_OBJECT_RANGE records to
dprintf_drr() for debugging purposes.

Reviewed-by: Matt Ahrens <mahrens@delphix.com>
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Tom Caputi <tcaputi@datto.com>
Closes #7378 
Closes #8528
This commit is contained in:
Tom Caputi
2019-03-27 14:30:48 -04:00
committed by Brian Behlendorf
parent 85a150ce1e
commit 5dbf8b4edd
7 changed files with 157 additions and 50 deletions
@@ -22,6 +22,7 @@ dist_pkgdata_SCRIPTS = \
rsend_022_pos.ksh \
rsend_024_pos.ksh \
send_encrypted_files.ksh \
send_encrypted_truncated_files.ksh \
send_encrypted_heirarchy.ksh \
send_encrypted_props.ksh \
send-cD.ksh \
@@ -22,7 +22,8 @@
#
# DESCRIPTION:
#
# Verify that a raw zfs send and receive can deal with several different
# types of file layouts.
#
# STRATEGY:
# 1. Create a new encrypted filesystem
@@ -30,18 +31,14 @@
# 3. Add a small 512 byte file to the filesystem
# 4. Add a larger 32M file to the filesystem
# 5. Add a large sparse file to the filesystem
# 6. Add a 3 files that are to be truncated later
# 7. Add 1000 empty files to the filesystem
# 8. Add a file with a large xattr value
# 9. Use xattrtest to create files with random xattrs (with and without xattrs=on)
# 10. Take a snapshot of the filesystem
# 11. Truncate one of the files from 32M to 128k
# 12. Truncate one of the files from 512k to 384k
# 13. Truncate one of the files from 512k to 0 to 384k
# 14. Remove the 1000 empty files to the filesystem
# 15. Take another snapshot of the filesystem
# 16. Send and receive both snapshots
# 17. Mount the filesystem and check the contents
# 6. Add 1000 empty files to the filesystem
# 7. Add a file with a large xattr value
# 8. Use xattrtest to create files with random xattrs (with and without xattrs=on)
# 9. Take a snapshot of the filesystem
# 10. Remove the 1000 empty files to the filesystem
# 11. Take another snapshot of the filesystem
# 12. Send and receive both snapshots
# 13. Mount the filesystem and check the contents
#
verify_runnable "both"
@@ -74,15 +71,12 @@ log_must eval "echo 'password' > $keyfile"
log_must zfs create -o encryption=on -o keyformat=passphrase \
-o keylocation=file://$keyfile $TESTPOOL/$TESTFS2
# Create files with vaired layouts on disk
# Create files with varied layouts on disk
log_must touch /$TESTPOOL/$TESTFS2/empty
log_must mkfile 512 /$TESTPOOL/$TESTFS2/small
log_must mkfile 32M /$TESTPOOL/$TESTFS2/full
log_must dd if=/dev/urandom of=/$TESTPOOL/$TESTFS2/sparse \
bs=512 count=1 seek=1048576 >/dev/null 2>&1
log_must mkfile 32M /$TESTPOOL/$TESTFS2/truncated
log_must mkfile 524288 /$TESTPOOL/$TESTFS2/truncated2
log_must mkfile 524288 /$TESTPOOL/$TESTFS2/truncated3
log_must mkdir -p /$TESTPOOL/$TESTFS2/dir
for i in {1..1000}; do
@@ -101,23 +95,10 @@ log_must zfs set compression=on xattr=sa $TESTPOOL/$TESTFS2
log_must touch /$TESTPOOL/$TESTFS2/attrs
log_must eval "python -c 'print \"a\" * 4096' | \
attr -s bigval /$TESTPOOL/$TESTFS2/attrs"
log_must zfs set compression=off xattr=on $TESTPOOL/$TESTFS2
log_must zfs snapshot $TESTPOOL/$TESTFS2@snap1
#
# Truncate files created in the first snapshot. The first tests
# truncating a large file to a single block. The second tests
# truncating one block off the end of a file without changing
# the required nlevels to hold it. The last tests handling
# of a maxblkid that is dropped and then raised again.
#
log_must truncate -s 131072 /$TESTPOOL/$TESTFS2/truncated
log_must truncate -s 393216 /$TESTPOOL/$TESTFS2/truncated2
log_must truncate -s 0 /$TESTPOOL/$TESTFS2/truncated3
log_must zpool sync $TESTPOOL
log_must dd if=/dev/urandom of=/$TESTPOOL/$TESTFS2/truncated3 \
bs=128k count=3 iflag=fullblock
# Remove the empty files created in the first snapshot
for i in {1..1000}; do
log_must rm /$TESTPOOL/$TESTFS2/dir/file-$i
@@ -0,0 +1,114 @@
#!/bin/ksh -p
#
# CDDL HEADER START
#
# 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.
#
# CDDL HEADER END
#
#
# Copyright (c) 2018 by Datto Inc. All rights reserved.
#
. $STF_SUITE/tests/functional/rsend/rsend.kshlib
#
# DESCRIPTION:
#
#
# STRATEGY:
# 1. Create a new encrypted filesystem
# 2. Add a 4 files that are to be truncated later
# 3. Take a snapshot of the filesystem
# 4. Truncate one of the files from 32M to 128k
# 5. Truncate one of the files from 512k to 384k
# 6. Truncate one of the files from 512k to 0 to 384k via reallocation
# 7. Truncate one of the files from 1k to 0 to 512b via reallocation
# 8. Take another snapshot of the filesystem
# 9. Send and receive both snapshots
# 10. Mount the filesystem and check the contents
#
verify_runnable "both"
function cleanup
{
datasetexists $TESTPOOL/$TESTFS2 && \
log_must zfs destroy -r $TESTPOOL/$TESTFS2
datasetexists $TESTPOOL/recv && \
log_must zfs destroy -r $TESTPOOL/recv
[[ -f $keyfile ]] && log_must rm $keyfile
[[ -f $sendfile ]] && log_must rm $sendfile
}
log_onexit cleanup
function recursive_cksum
{
find $1 -type f -exec sha256sum {} \; | \
sort -k 2 | awk '{ print $1 }' | sha256sum
}
log_assert "Verify 'zfs send -w' works with many different file layouts"
typeset keyfile=/$TESTPOOL/pkey
typeset sendfile=/$TESTPOOL/sendfile
typeset sendfile2=/$TESTPOOL/sendfile2
# Create an encrypted dataset
log_must eval "echo 'password' > $keyfile"
log_must zfs create -o encryption=on -o keyformat=passphrase \
-o keylocation=file://$keyfile $TESTPOOL/$TESTFS2
# Create files with varied layouts on disk
log_must mkfile 32M /$TESTPOOL/$TESTFS2/truncated
log_must mkfile 524288 /$TESTPOOL/$TESTFS2/truncated2
log_must mkfile 524288 /$TESTPOOL/$TESTFS2/truncated3
log_must mkfile 1024 /$TESTPOOL/$TESTFS2/truncated4
log_must zfs snapshot $TESTPOOL/$TESTFS2@snap1
#
# Truncate files created in the first snapshot. The first tests
# truncating a large file to a single block. The second tests
# truncating one block off the end of a file without changing
# the required nlevels to hold it. The third tests handling
# of a maxblkid that is dropped and then raised again. The
# fourth tests an object that is truncated from a single block
# to a smaller single block.
#
log_must truncate -s 131072 /$TESTPOOL/$TESTFS2/truncated
log_must truncate -s 393216 /$TESTPOOL/$TESTFS2/truncated2
log_must rm -f /$TESTPOOL/$TESTFS2/truncated3
log_must rm -f /$TESTPOOL/$TESTFS2/truncated4
log_must zpool sync $TESTPOOL
log_must zfs umount $TESTPOOL/$TESTFS2
log_must zfs mount $TESTPOOL/$TESTFS2
log_must dd if=/dev/urandom of=/$TESTPOOL/$TESTFS2/truncated3 \
bs=128k count=3 iflag=fullblock
log_must dd if=/dev/urandom of=/$TESTPOOL/$TESTFS2/truncated4 \
bs=512 count=1 iflag=fullblock
log_must zfs snapshot $TESTPOOL/$TESTFS2@snap2
expected_cksum=$(recursive_cksum /$TESTPOOL/$TESTFS2)
log_must eval "zfs send -wp $TESTPOOL/$TESTFS2@snap1 > $sendfile"
log_must eval "zfs send -wp -i @snap1 $TESTPOOL/$TESTFS2@snap2 > $sendfile2"
log_must eval "zfs recv -F $TESTPOOL/recv < $sendfile"
log_must eval "zfs recv -F $TESTPOOL/recv < $sendfile2"
log_must zfs load-key $TESTPOOL/recv
log_must zfs mount -a
actual_cksum=$(recursive_cksum /$TESTPOOL/recv)
[[ "$expected_cksum" != "$actual_cksum" ]] && \
log_fail "Recursive checksums differ ($expected_cksum != $actual_cksum)"
log_pass "Verified 'zfs send -w' works with many different file layouts"