summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Williamson <chris.williamson@delphix.com>2016-08-30 11:58:30 -0700
committerMatthew Ahrens <mahrens@delphix.com>2016-09-01 10:49:56 -0700
commit2ad25b4055c18f39b3fb20bd5c8c61057e34f377 (patch)
treeeee31823d676666884f3dd815232440d633b8c8c
parent9cfb65faacc43d80fb0e3cc182d2dae107cdf60c (diff)
downloadillumos-joyent-2ad25b4055c18f39b3fb20bd5c8c61057e34f377.tar.gz
7247 zfs receive of deduplicated stream fails
Reviewed by: Matthew Ahrens <mahrens@delphix.com> Reviewed by: Dan Kimmel <dan.kimmel@delphix.com> Approved by: Robert Mustacchi <rm@joyent.com>
-rw-r--r--usr/src/pkg/manifests/system-test-zfstest.mf3
-rw-r--r--usr/src/test/zfs-tests/runfiles/delphix.run3
-rw-r--r--usr/src/test/zfs-tests/tests/functional/cli_root/zfs_receive/Makefile3
-rw-r--r--usr/src/test/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_013_pos.ksh73
-rw-r--r--usr/src/uts/common/fs/zfs/dmu_send.c44
5 files changed, 101 insertions, 25 deletions
diff --git a/usr/src/pkg/manifests/system-test-zfstest.mf b/usr/src/pkg/manifests/system-test-zfstest.mf
index 4ea9b22ac3..27c5874083 100644
--- a/usr/src/pkg/manifests/system-test-zfstest.mf
+++ b/usr/src/pkg/manifests/system-test-zfstest.mf
@@ -710,6 +710,9 @@ file \
file \
path=opt/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_012_pos \
mode=0555
+file \
+ path=opt/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_013_pos \
+ mode=0555
file path=opt/zfs-tests/tests/functional/cli_root/zfs_rename/cleanup mode=0555
file path=opt/zfs-tests/tests/functional/cli_root/zfs_rename/setup mode=0555
file path=opt/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename.cfg \
diff --git a/usr/src/test/zfs-tests/runfiles/delphix.run b/usr/src/test/zfs-tests/runfiles/delphix.run
index 1fdd593eae..f9e8868cb3 100644
--- a/usr/src/test/zfs-tests/runfiles/delphix.run
+++ b/usr/src/test/zfs-tests/runfiles/delphix.run
@@ -150,7 +150,8 @@ tests = ['zfs_written_property_001_pos']
tests = ['zfs_receive_001_pos', 'zfs_receive_002_pos', 'zfs_receive_003_pos',
'zfs_receive_005_neg', 'zfs_receive_006_pos',
'zfs_receive_007_neg', 'zfs_receive_008_pos', 'zfs_receive_009_neg',
- 'zfs_receive_010_pos', 'zfs_receive_011_pos', 'zfs_receive_012_pos']
+ 'zfs_receive_010_pos', 'zfs_receive_011_pos', 'zfs_receive_012_pos',
+ 'zfs_receive_013_pos']
[/opt/zfs-tests/tests/functional/cli_root/zfs_rename]
tests = ['zfs_rename_001_pos', 'zfs_rename_002_pos', 'zfs_rename_003_pos',
diff --git a/usr/src/test/zfs-tests/tests/functional/cli_root/zfs_receive/Makefile b/usr/src/test/zfs-tests/tests/functional/cli_root/zfs_receive/Makefile
index e5e0e8cfd4..516c0eb77d 100644
--- a/usr/src/test/zfs-tests/tests/functional/cli_root/zfs_receive/Makefile
+++ b/usr/src/test/zfs-tests/tests/functional/cli_root/zfs_receive/Makefile
@@ -32,7 +32,8 @@ PROGS = cleanup \
zfs_receive_009_neg \
zfs_receive_010_pos \
zfs_receive_011_pos \
- zfs_receive_012_pos
+ zfs_receive_012_pos \
+ zfs_receive_013_pos
CMDS = $(PROGS:%=$(TESTDIR)/%)
$(CMDS) := FILEMODE = 0555
diff --git a/usr/src/test/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_013_pos.ksh b/usr/src/test/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_013_pos.ksh
new file mode 100644
index 0000000000..145ff68702
--- /dev/null
+++ b/usr/src/test/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_013_pos.ksh
@@ -0,0 +1,73 @@
+#!/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) 2015 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/cli_root/cli_common.kshlib
+
+#
+# DESCRIPTION:
+# Verifying 'zfs receive' works correctly on deduplicated streams
+#
+# STRATEGY:
+# 1. Create some snapshots with duplicated data
+# 2. Send a deduplicated stream of the last snapshot
+# 3. Attempt to receive the deduplicated stream
+#
+
+src_fs=$TESTPOOL/drecvsrc
+temppool=recvtank
+dst_fs=$temppool/drecvdest
+streamfile=/var/tmp/drecvstream.$$
+tpoolfile=/temptank.$$
+
+function cleanup
+{
+ for fs in $src_fs $dst_fs; do
+ datasetexists $fs && log_must $ZFS destroy -rf $fs
+ done
+ zpool destroy $temppool
+ [[ -f $streamfile ]] && log_must $RM -f $streamfile
+ [[ -f $tpoolfile ]] && log_must $RM -f $tpoolfile
+}
+
+log_assert "Verifying 'zfs receive' works correctly on deduplicated streams"
+log_onexit cleanup
+
+truncate -s 100M $tpoolfile
+log_must zpool create $temppool $tpoolfile
+log_must $ZFS create $src_fs
+src_mnt=$(get_prop mountpoint $src_fs) || log_fail "get_prop mountpoint $src_fs"
+
+echo blah > $src_mnt/blah
+$ZFS snapshot $src_fs@base
+
+echo grumble > $src_mnt/grumble
+echo blah > $src_mnt/blah2
+$ZFS snapshot $src_fs@snap2
+
+echo grumble > $src_mnt/mumble
+echo blah > $src_mnt/blah3
+$ZFS snapshot $src_fs@snap3
+
+log_must eval "$ZFS send -D -R $src_fs@snap3 > $streamfile"
+log_must eval "$ZFS receive -v $dst_fs < $streamfile"
+
+cleanup
+
+log_pass "Verifying 'zfs receive' works correctly on deduplicated streams"
diff --git a/usr/src/uts/common/fs/zfs/dmu_send.c b/usr/src/uts/common/fs/zfs/dmu_send.c
index f442baf390..91b85a89ef 100644
--- a/usr/src/uts/common/fs/zfs/dmu_send.c
+++ b/usr/src/uts/common/fs/zfs/dmu_send.c
@@ -3047,6 +3047,9 @@ dmu_recv_end_sync(void *arg, dmu_tx_t *tx)
dsl_dataset_phys(origin_head)->ds_flags &=
~DS_FLAG_INCONSISTENT;
+ drc->drc_newsnapobj =
+ dsl_dataset_phys(origin_head)->ds_prev_snap_obj;
+
dsl_dataset_rele(origin_head, FTAG);
dsl_destroy_head_sync_impl(drc->drc_ds, tx);
@@ -3082,8 +3085,9 @@ dmu_recv_end_sync(void *arg, dmu_tx_t *tx)
(void) zap_remove(dp->dp_meta_objset, ds->ds_object,
DS_FIELD_RESUME_TONAME, tx);
}
+ drc->drc_newsnapobj =
+ dsl_dataset_phys(drc->drc_ds)->ds_prev_snap_obj;
}
- drc->drc_newsnapobj = dsl_dataset_phys(drc->drc_ds)->ds_prev_snap_obj;
/*
* Release the hold from dmu_recv_begin. This must be done before
* we return to open context, so that when we free the dataset's dnode,
@@ -3126,8 +3130,6 @@ static int dmu_recv_end_modified_blocks = 3;
static int
dmu_recv_existing_end(dmu_recv_cookie_t *drc)
{
- int error;
-
#ifdef _KERNEL
/*
* We will be destroying the ds; make sure its origin is unmounted if
@@ -3138,23 +3140,30 @@ dmu_recv_existing_end(dmu_recv_cookie_t *drc)
zfs_destroy_unmount_origin(name);
#endif
- error = dsl_sync_task(drc->drc_tofs,
+ return (dsl_sync_task(drc->drc_tofs,
dmu_recv_end_check, dmu_recv_end_sync, drc,
- dmu_recv_end_modified_blocks, ZFS_SPACE_CHECK_NORMAL);
-
- if (error != 0)
- dmu_recv_cleanup_ds(drc);
- return (error);
+ dmu_recv_end_modified_blocks, ZFS_SPACE_CHECK_NORMAL));
}
static int
dmu_recv_new_end(dmu_recv_cookie_t *drc)
{
+ return (dsl_sync_task(drc->drc_tofs,
+ dmu_recv_end_check, dmu_recv_end_sync, drc,
+ dmu_recv_end_modified_blocks, ZFS_SPACE_CHECK_NORMAL));
+}
+
+int
+dmu_recv_end(dmu_recv_cookie_t *drc, void *owner)
+{
int error;
- error = dsl_sync_task(drc->drc_tofs,
- dmu_recv_end_check, dmu_recv_end_sync, drc,
- dmu_recv_end_modified_blocks, ZFS_SPACE_CHECK_NORMAL);
+ drc->drc_owner = owner;
+
+ if (drc->drc_newfs)
+ error = dmu_recv_new_end(drc);
+ else
+ error = dmu_recv_existing_end(drc);
if (error != 0) {
dmu_recv_cleanup_ds(drc);
@@ -3166,17 +3175,6 @@ dmu_recv_new_end(dmu_recv_cookie_t *drc)
return (error);
}
-int
-dmu_recv_end(dmu_recv_cookie_t *drc, void *owner)
-{
- drc->drc_owner = owner;
-
- if (drc->drc_newfs)
- return (dmu_recv_new_end(drc));
- else
- return (dmu_recv_existing_end(drc));
-}
-
/*
* Return TRUE if this objset is currently being received into.
*/