Skip to content

Commit

Permalink
6393 zfs receive a full send as a clone
Browse files Browse the repository at this point in the history
Reviewed by: Matthew Ahrens <[email protected]>
Reviewed by: Prakash Surya <[email protected]>
Reviewed by: Richard Elling <[email protected]>
Approved by: Dan McDonald <[email protected]>
  • Loading branch information
pcd1193182 authored and ahrens committed Nov 16, 2015
1 parent 3d729ae commit 68ecb2e
Show file tree
Hide file tree
Showing 8 changed files with 304 additions and 63 deletions.
9 changes: 6 additions & 3 deletions usr/src/man/man1m/zfs.1m
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
.\"
.\" Copyright (c) 2009 Sun Microsystems, Inc. All Rights Reserved.
.\" Copyright 2011 Joshua M. Clulow <[email protected]>
.\" Copyright (c) 2011, 2014 by Delphix. All rights reserved.
.\" Copyright (c) 2011, 2015 by Delphix. All rights reserved.
.\" Copyright (c) 2013 by Saso Kiselkov. All rights reserved.
.\" Copyright (c) 2014, Joyent, Inc. All rights reserved.
.\" Copyright (c) 2014 by Adam Stevko. All rights reserved.
Expand Down Expand Up @@ -2775,8 +2775,11 @@ Do not actually receive the stream. This can be useful in conjunction with the
option to verify the name the receive operation would use.
.It Fl o Sy origin Ns = Ns Ar snapshot
Forces the stream to be received as a clone of the given snapshot.
This is only valid if the stream is an incremental stream whose source
is the same as the provided origin.
If the stream is a full send stream, this will create the filesystem
described by the stream as a clone of the specified snapshot. Which
snapshot was specified will not affect the success or failure of the
receive, as long as the snapshot does exist. If the stream is an
incremental send stream, all the normal verification will be performed.
.It Fl u
File system that is associated with the received stream is not mounted.
.It Fl v
Expand Down
5 changes: 4 additions & 1 deletion usr/src/pkg/manifests/system-test-zfstest.mf
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
#

#
# Copyright (c) 2012, 2014 by Delphix. All rights reserved.
# Copyright (c) 2012, 2015 by Delphix. All rights reserved.
# Copyright 2014, OmniTI Computer Consulting, Inc. All rights reserved.
# Copyright 2015, Nexenta Systems Inc. All rights reserved.
#
Expand Down Expand Up @@ -662,6 +662,9 @@ file \
file \
path=opt/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_009_neg \
mode=0555
file \
path=opt/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_010_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 \
Expand Down
3 changes: 2 additions & 1 deletion usr/src/test/zfs-tests/runfiles/delphix.run
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,8 @@ tests = ['zfs_written_property_001_pos']
[/opt/zfs-tests/tests/functional/cli_root/zfs_receive]
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_007_neg', 'zfs_receive_008_pos', 'zfs_receive_009_neg',
'zfs_receive_010_pos']

[/opt/zfs-tests/tests/functional/cli_root/zfs_rename]
tests = ['zfs_rename_001_pos', 'zfs_rename_002_pos', 'zfs_rename_003_pos',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
#

#
# Copyright (c) 2012 by Delphix. All rights reserved.
# Copyright (c) 2012, 2015 by Delphix. All rights reserved.
#

include $(SRC)/Makefile.master
Expand All @@ -28,7 +28,8 @@ PROGS = cleanup \
zfs_receive_006_pos \
zfs_receive_007_neg \
zfs_receive_008_pos \
zfs_receive_009_neg
zfs_receive_009_neg \
zfs_receive_010_pos

CMDS = $(PROGS:%=$(TESTDIR)/%)
$(CMDS) := FILEMODE = 0555
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
#!/bin/ksh -p
#
# CDDL HEADER START
#
# The contents of this file are subject to the terms of the
# Common Development and Distribution License (the "License").
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
# or http://www.opensolaris.org/os/licensing.
# See the License for the specific language governing permissions
# and limitations under the License.
#
# When distributing Covered Code, include this CDDL HEADER in each
# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
# If applicable, add the following below this CDDL HEADER, with the
# fields enclosed by brackets "[]" replaced with your own identifying
# information: Portions Copyright [yyyy] [name of copyright owner]
#
# CDDL HEADER END
#

#
# Copyright (c) 2015 by Delphix. All rights reserved.
#

. $STF_SUITE/include/libtest.shlib

#
# DESCRIPTION:
# Test that receiving a full send as a clone works correctly.
#
# STRATEGY:
# 1. Create pool and filesystems.
# 2. Send filesystem, receive as clone of itself.
# 3. Verify that nop-write saves space.
# 4. Send filesystem, receive as clone of other filesystem.
# 5. Verify that contents are correct.
# 6. Repeat steps 4 and 5 with filesystems swapped.
#

verify_runnable "both"

fs=$TESTPOOL/$TESTFS/base/fs
fs2=$TESTPOOL/$TESTFS/base/fs2
rfs=$TESTPOOL/$TESTFS/base/rfs

function make_object
{
local objnum=$1
local mntpnt=$2
local type=$3
if [[ $type == "file" ]]; then
$DD if=/dev/urandom of=${mntpnt}/f$objnum bs=512 count=16
elif [[ $type == "hole1" ]]; then
$DD if=/dev/urandom of=${mntpnt}/fh$objnum bs=512 count=5 stride=4
elif [[ $type == "hole2" ]]; then
$DD if=/dev/urandom of=${mntpnt}/fh$objnum bs=512 count=4 stride=5
elif [[ $type == "directory" ]]; then
$MKDIR ${mntpnt}/d$objnum
elif [[ $type == "missing" ]]; then
$TOUCH ${mntpnt}/h$objnum
fi
}

function create_pair
{
local objnum=$1
local mntpnt1=$2
local mntpnt2=$3
local type1=$4
local type2=$5
make_object $objnum $mntpnt1 $type1
make_object $objnum $mntpnt2 $type2
}

function cleanup
{
$ZFS destroy -Rf $TESTPOOL/$TESTFS/base
rm /tmp/zr010p*
}

log_assert "zfs receive of full send as clone should work"
log_onexit cleanup
log_must $ZFS create -o checksum=sha256 -o compression=gzip -o recordsize=512 \
$TESTPOOL/$TESTFS/base

log_must $ZFS create $fs
log_must $ZFS create $fs2
mntpnt=$(get_prop mountpoint $fs)
mntpnt2=$(get_prop mountpoint $fs2)

#
# Now, we create the two filesystems. By creating objects with
# different types and the same object number in each filesystem, we
# create a situation where, when you receive the full send of each as
# a clone of the other, we will test to ensure that the code correctly
# handles receiving all object types onto all other object types.
#

# Receive a file onto a file (and vice versa).
create_pair 8 $mntpnt $mntpnt2 "file" "file"

# Receive a file onto a file with holes (and vice versa).
create_pair 9 $mntpnt $mntpnt2 "file" "hole1"

# Receive a file onto a directory (and vice versa).
create_pair 10 $mntpnt $mntpnt2 "file" "directory"

# Receive a file onto a missing object (and vice versa).
create_pair 11 $mntpnt $mntpnt2 "file" "missing"

# Receive a file with holes onto a file with holes (and vice versa).
create_pair 12 $mntpnt $mntpnt2 "hole1" "hole2"

# Receive a file with holes onto a directory (and vice versa).
create_pair 13 $mntpnt $mntpnt2 "hole1" "directory"

# Receive a file with holes onto a missing object (and vice versa).
create_pair 14 $mntpnt $mntpnt2 "hole1" "missing"

# Receive a directory onto a directory (and vice versa).
create_pair 15 $mntpnt $mntpnt2 "directory" "directory"

# Receive a directory onto a missing object (and vice versa).
create_pair 16 $mntpnt $mntpnt2 "directory" "missing"

# Receive a missing object onto a missing object (and vice versa).
create_pair 17 $mntpnt $mntpnt2 "missing" "missing"

# Receive a file with a different record size onto a file (and vice versa).
log_must $ZFS set recordsize=128k $fs
$DD if=/dev/urandom of=$mntpnt/f18 bs=128k count=64
$TOUCH $mntpnt2/f18

# Remove objects that are intended to be missing.
$RM $mntpnt/h17
$RM $mntpnt2/h*

log_must $ZFS snapshot $fs@s1
log_must $ZFS snapshot $fs2@s1

log_must $ZFS send $fs@s1 > /tmp/zr010p
log_must $ZFS send $fs2@s1 > /tmp/zr010p2


#
# Test that, when we receive a full send as a clone of itself,
# nop-write saves us all the space used by data blocks.
#
cat /tmp/zr010p | log_must $ZFS receive -o origin=$fs@s1 $rfs
size=$(get_prop used $rfs)
size2=$(get_prop used $fs)
if [[ $size -ge $(($size2 / 10)) ]] then
log_fail "nop-write failure; expected usage less than "\
"$(($size2 / 10)), but is using $size"
fi
log_must $ZFS destroy -fr $rfs

# Correctness testing: receive each full send as a clone of the other fiesystem.
cat /tmp/zr010p | log_must $ZFS receive -o origin=$fs2@s1 $rfs
mntpnt_old=$(get_prop mountpoint $fs)
mntpnt_new=$(get_prop mountpoint $rfs)
log_must $DIFF -r $mntpnt_old $mntpnt_new
log_must $ZFS destroy -r $rfs

cat /tmp/zr010p2 | log_must $ZFS receive -o origin=$fs@s1 $rfs
mntpnt_old=$(get_prop mountpoint $fs2)
mntpnt_new=$(get_prop mountpoint $rfs)
log_must $DIFF -r $mntpnt_old $mntpnt_new

log_pass "zfs receive of full send as clone works"
Loading

0 comments on commit 68ecb2e

Please sign in to comment.