OpenZFS 8600 - ZFS channel programs - snapshot

Authored by: Chris Williamson <chris.williamson@delphix.com>
Reviewed by: Matthew Ahrens <mahrens@delphix.com>
Reviewed by: John Kennedy <john.kennedy@delphix.com>
Reviewed by: Brad Lewis <brad.lewis@delphix.com>
Approved by: Robert Mustacchi <rm@joyent.com>
Ported-by: Don Brady <don.brady@delphix.com>

ZFS channel programs should be able to create snapshots.
In addition to the base snapshot functionality, this entails extra
logic to handle edge cases which were formerly not possible, such as
creating then destroying a snapshot in the same transaction sync.

OpenZFS-issue: https://www.illumos.org/issues/8600
OpenZFS-commit: https://github.com/openzfs/openzfs/commit/68089b8b
This commit is contained in:
Chris Williamson
2018-02-08 09:24:39 -07:00
committed by Brian Behlendorf
parent af07368986
commit 234c91c508
22 changed files with 500 additions and 33 deletions
+6 -3
View File
@@ -67,8 +67,9 @@ tests = ['tst.args_to_lua', 'tst.divide_by_zero', 'tst.exists',
'tst.integer_illegal', 'tst.integer_overflow', 'tst.language_functions_neg',
'tst.language_functions_pos', 'tst.large_prog', 'tst.memory_limit',
'tst.nested_neg', 'tst.nested_pos', 'tst.nvlist_to_lua',
'tst.recursive_neg', 'tst.recursive_pos', 'tst.return_nvlist_neg',
'tst.return_nvlist_pos', 'tst.return_recursive_table', 'tst.timeout']
'tst.recursive_neg', 'tst.recursive_pos', 'tst.return_large',
'tst.return_nvlist_neg', 'tst.return_nvlist_pos',
'tst.return_recursive_table', 'tst.timeout']
tags = ['functional', 'channel_program', 'lua_core']
[tests/functional/channel_program/synctask_core]
@@ -78,7 +79,9 @@ tests = ['tst.destroy_fs', 'tst.destroy_snap', 'tst.get_count_and_limit',
'tst.get_userquota', 'tst.get_written', 'tst.list_children',
'tst.list_clones', 'tst.list_snapshots', 'tst.list_system_props',
'tst.parse_args_neg', 'tst.promote_conflict', 'tst.promote_multiple',
'tst.promote_simple', 'tst.rollback_mult', 'tst.rollback_one']
'tst.promote_simple', 'tst.rollback_mult', 'tst.rollback_one',
'tst.snapshot_destroy', 'tst.snapshot_neg', 'tst.snapshot_recursive',
'tst.snapshot_simple']
tags = ['functional', 'channel_program', 'synctask_core']
[tests/functional/chattr]
@@ -26,6 +26,8 @@ dist_pkgdata_SCRIPTS = \
tst.recursive_neg.ksh \
tst.recursive_pos.ksh \
tst.recursive.zcp \
tst.return_large.ksh \
tst.return_large.zcp \
tst.return_nvlist_neg.ksh \
tst.return_nvlist_pos.ksh \
tst.return_recursive_table.ksh \
@@ -0,0 +1,54 @@
#!/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) 2016, 2017 by Delphix. All rights reserved.
#
. $STF_SUITE/tests/functional/channel_program/channel_common.kshlib
#
# DESCRIPTION: Returning very large (up to the memory limit) lists should
# function correctly.
#
verify_runnable "global"
fs=$TESTPOOL/$TESTFS/testchild
function cleanup
{
datasetexists $fs && log_must zfs destroy -R $fs
}
log_onexit cleanup
log_must zfs create $fs
#
# Actually checking in the ~500kb expected result of this program would be
# awful, so we just make sure it was as long as we expected.
#
output_lines=$(log_must zfs program $TESTPOOL \
$ZCP_ROOT/lua_core/tst.return_large.zcp | wc -l)
[[ $output_lines -lt 5000 ]] &&
log_fail "Expected return of full list but only got $output_lines lines"
#
# Make sure we fail if the return is over the memory limit
#
log_mustnot_program $TESTPOOL -m 10000 \
$ZCP_ROOT/lua_core/tst.return_large.zcp
log_pass "Large return values work properly"
@@ -0,0 +1,24 @@
--
-- 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) 2016, 2017 by Delphix. All rights reserved.
--
basestring = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" ..
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
ret = {}
for i=1,5000 do
table.insert(ret, basestring)
end
return ret
@@ -29,4 +29,12 @@ dist_pkgdata_SCRIPTS = \
tst.promote_multiple.ksh \
tst.promote_simple.ksh \
tst.rollback_mult.ksh \
tst.rollback_one.ksh
tst.rollback_one.ksh \
tst.snapshot_destroy.ksh \
tst.snapshot_destroy.zcp \
tst.snapshot_neg.ksh \
tst.snapshot_neg.zcp \
tst.snapshot_recursive.ksh \
tst.snapshot_recursive.zcp \
tst.snapshot_simple.ksh \
tst.snapshot_simple.zcp
@@ -0,0 +1,39 @@
#!/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) 2016, 2017 by Delphix. All rights reserved.
#
. $STF_SUITE/tests/functional/channel_program/channel_common.kshlib
#
# DESCRIPTION: Creating and destroying snapshots in the same txg should work.
#
verify_runnable "global"
fs=$TESTPOOL/$TESTFS/testchild
function cleanup
{
datasetexists $fs && log_must zfs destroy -R $fs
}
log_onexit cleanup
log_must zfs create $fs
log_must_program $TESTPOOL \
$ZCP_ROOT/synctask_core/tst.snapshot_destroy.zcp $fs
log_pass "Creating/destroying snapshots in one channel program works"
@@ -0,0 +1,24 @@
--
-- 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) 2016, 2017 by Delphix. All rights reserved.
--
args = ...
argv = args["argv"]
assert(zfs.sync.snapshot(argv[1] .. "@snap1") == 0)
assert(zfs.sync.destroy(argv[1] .. "@snap1") == 0)
for s in zfs.list.snapshots(argv[1]) do
assert(false)
end
@@ -0,0 +1,44 @@
#!/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) 2016, 2017 by Delphix. All rights reserved.
#
. $STF_SUITE/tests/functional/channel_program/channel_common.kshlib
#
# DESCRIPTION: Check various invalid snapshot error cases
#
verify_runnable "global"
fs1=$TESTPOOL/$TESTFS/testchild1
fs2=$TESTPOOL/$TESTFS/testchild2
function cleanup
{
for fs in $fs1 $fs2; do
datasetexists $fs && log_must zfs destroy -R $fs
done
}
log_onexit cleanup
log_must zfs create $fs1
log_must zfs create $fs2
log_must zfs snapshot $fs1@snap1
log_must_program $TESTPOOL $ZCP_ROOT/synctask_core/tst.snapshot_neg.zcp $fs1 $fs2
log_pass "zfs.sync.snapshot returns correct errors on invalid input"
@@ -0,0 +1,35 @@
--
-- 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) 2016, 2017 by Delphix. All rights reserved.
--
args = ...
argv = args["argv"]
fs1 = argv[1]
fs2 = argv[2]
longstring = "a"
for i=1,9 do
longstring = longstring .. longstring
end
-- invalid snapshot names
assert(zfs.sync.snapshot("ceci_nest_pas_une_dataset") == EINVAL);
assert(zfs.sync.snapshot(fs1) == EINVAL)
assert(zfs.sync.snapshot(fs1 .. "@" .. longstring) == ENAMETOOLONG)
assert(zfs.sync.snapshot(fs2 .. "@snap1") == 0)
-- only one snapshot of a filesystem is allowed per TXG.
assert(zfs.sync.snapshot(fs2 .. "@snap2") == EAGAIN)
-- snapshot already exists
assert(zfs.sync.snapshot(fs1 .. "@snap1") == EEXIST)
@@ -0,0 +1,61 @@
#!/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) 2016, 2017 by Delphix. All rights reserved.
#
. $STF_SUITE/tests/functional/channel_program/channel_common.kshlib
#
# DESCRIPTION: Construct a set of nested filesystems, then recursively snapshot
# all of them.
#
verify_runnable "global"
rootfs=$TESTPOOL/$TESTFS/root
snapname=snap
function cleanup
{
datasetexists $rootfs && log_must zfs destroy -R $rootfs
}
log_onexit cleanup
filesystems="$rootfs \
$rootfs/child1 \
$rootfs/child1/subchild1 \
$rootfs/child1/subchild2 \
$rootfs/child1/subchild3 \
$rootfs/child2 \
$rootfs/child2/subchild4 \
$rootfs/child2/subchild5"
for fs in $filesystems; do
log_must zfs create $fs
done
log_must_program $TESTPOOL \
$ZCP_ROOT/synctask_core/tst.snapshot_recursive.zcp $rootfs $snapname
#
# Make sure all of the snapshots we expect were created.
#
for fs in $filesystems; do
log_must snapexists $fs@$snapname
done
log_pass "Recursively snapshotting multiple filesystems works."
@@ -0,0 +1,28 @@
--
-- 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) 2016, 2017 by Delphix. All rights reserved.
--
args = ...
argv = args["argv"]
fs = argv[1]
snap = argv[2]
function snapshot_recursive(root)
assert(zfs.sync.snapshot(root .. "@" .. snap) == 0)
for child in zfs.list.children(root) do
snapshot_recursive(child)
end
end
snapshot_recursive(fs)
@@ -0,0 +1,40 @@
#!/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) 2016, 2017 by Delphix. All rights reserved.
#
. $STF_SUITE/tests/functional/channel_program/channel_common.kshlib
#
# DESCRIPTION: Make sure basic snapshot functionality works in channel programs
#
verify_runnable "global"
fs=$TESTPOOL/$TESTFS/testchild
snapname=testsnap
function cleanup
{
datasetexists $fs && log_must zfs destroy -R $fs
}
log_onexit cleanup
log_must zfs create $fs
log_must_program $TESTPOOL \
$ZCP_ROOT/synctask_core/tst.snapshot_simple.zcp $fs $snapname
log_pass "Simple snapshotting works"
@@ -0,0 +1,26 @@
--
-- 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) 2016, 2017 by Delphix. All rights reserved.
--
-- This program should be invoked as "zfs program <pool> <prog> <fs> <snap>"
args = ...
argv = args["argv"]
assert(zfs.sync.snapshot(argv[1] .. "@" .. argv[2]) == 0)
snaps = {}
for s in zfs.list.snapshots(argv[1]) do
table.insert(snaps, s)
end
assert(#snaps == 1)
assert(snaps[1] == (argv[1] .. "@" .. argv[2]))