From 000cce6b6fad4a8b0eecef6e1251f6aca1719c55 Mon Sep 17 00:00:00 2001 From: Brad Lewis Date: Fri, 6 Jan 2017 16:14:08 -0700 Subject: [PATCH] 8592 ZFS channel programs - rollback Reviewed by: Chris Williamson Reviewed by: Matthew Ahrens Approved by: Robert Mustacchi --- usr/src/man/man1m/zfs-program.1m | 14 ++++- usr/src/pkg/manifests/system-test-zfstest.mf | 10 +++- .../synctask_core/tst.rollback_mult.ksh | 61 ++++++++++++++++++++++ .../synctask_core/tst.rollback_one.ksh | 51 ++++++++++++++++++ usr/src/uts/common/fs/zfs/dsl_dataset.c | 13 ++--- usr/src/uts/common/fs/zfs/sys/dsl_dataset.h | 12 ++++- usr/src/uts/common/fs/zfs/zcp_synctask.c | 34 +++++++++++- 7 files changed, 180 insertions(+), 15 deletions(-) create mode 100644 usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/tst.rollback_mult.ksh create mode 100644 usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/tst.rollback_one.ksh diff --git a/usr/src/man/man1m/zfs-program.1m b/usr/src/man/man1m/zfs-program.1m index d8acd4972a..2564df4d47 100644 --- a/usr/src/man/man1m/zfs-program.1m +++ b/usr/src/man/man1m/zfs-program.1m @@ -8,7 +8,7 @@ .\" http://www.illumos.org/license/CDDL. .\" .\" -.\" Copyright (c) 2016 by Delphix. All Rights Reserved. +.\" Copyright (c) 2016, 2017 by Delphix. All rights reserved. .\" .Dd January 21, 2016 .Dt ZFS-PROGRAM 1M @@ -361,6 +361,17 @@ dataset (string) .Bd -ragged -compact -offset "xxxx" Clone to be promoted. .Ed +.It Em zfs.sync.rollback(filesystem) +Rollback to the previous snapshot for a dataset. +Returns 0 on successful rollback, or a nonzero error code otherwise. +Rollbacks can be performed on filesystems or zvols, but not on snapshots +or mounted datasets. +EBUSY is returned in the case where the filesystem is mounted. +.Pp +filesystem (string) +.Bd -ragged -compact -offset "xxxx" +Filesystem to rollback. +.Ed .El .It Sy zfs.check submodule For each function in the zfs.sync submodule, there is a corresponding zfs.check @@ -380,6 +391,7 @@ The available zfs.check functions are: .Bl -tag -width "xx" .It Em zfs.check.destroy(dataset, [defer=true|false]) .It Em zfs.check.promote(dataset) +.It Em zfs.check.rollback(filesystem) .El .It Sy zfs.list submodule The zfs.list submodule provides functions for iterating over datasets and diff --git a/usr/src/pkg/manifests/system-test-zfstest.mf b/usr/src/pkg/manifests/system-test-zfstest.mf index f1b43d56bc..64b01a4e27 100644 --- a/usr/src/pkg/manifests/system-test-zfstest.mf +++ b/usr/src/pkg/manifests/system-test-zfstest.mf @@ -10,9 +10,9 @@ # # -# Copyright (c) 2012, 2016 by Delphix. All rights reserved. +# Copyright (c) 2012, 2017 by Delphix. All rights reserved. +# Copyright 2015, 2016 Nexenta Systems, Inc. All rights reserved. # Copyright 2016, OmniTI Computer Consulting, Inc. All rights reserved. -# Copyright 2016 Nexenta Systems, Inc. # set name=pkg.fmri value=pkg:/system/test/zfstest@$(PKGVERS) @@ -555,6 +555,12 @@ file \ file \ path=opt/zfs-tests/tests/functional/channel_program/synctask_core/tst.promote_simple \ mode=0555 +file \ + path=opt/zfs-tests/tests/functional/channel_program/synctask_core/tst.rollback_mult \ + mode=0555 +file \ + path=opt/zfs-tests/tests/functional/channel_program/synctask_core/tst.rollback_one \ + mode=0555 $(i386_ONLY)file path=opt/zfs-tests/tests/functional/checksum/edonr_test.amd64 \ mode=0555 $(i386_ONLY)file path=opt/zfs-tests/tests/functional/checksum/edonr_test.i386 \ diff --git a/usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/tst.rollback_mult.ksh b/usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/tst.rollback_mult.ksh new file mode 100644 index 0000000000..778abc09dd --- /dev/null +++ b/usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/tst.rollback_mult.ksh @@ -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 + +verify_runnable "global" +snap1=$TESTPOOL/$TESTFS@$TESTSNAP1 +snap2=$TESTPOOL/$TESTFS@$TESTSNAP2 +fs=$TESTPOOL/$TESTFS +file=$TESTDIR/$TESTFILE0 + +function cleanup +{ + datasetexists $snap1 && log_must zfs destroy $snap1 && \ + log_must rm $file +} + +log_onexit cleanup + +log_must mkfile 128b $file +create_snapshot $TESTPOOL/$TESTFS $TESTSNAP1 +log_must rm $file +create_snapshot $TESTPOOL/$TESTFS $TESTSNAP2 + +log_must snapexists $snap1 +log_must snapexists $snap2 +log_must zfs unmount $fs + +log_must_program $TESTPOOL - $fs $snap2 <<-EOF + arg = ... + fs = arg["argv"][1] + snap = arg["argv"][2] + err = zfs.sync.rollback(fs) + if err == 0 then + err = zfs.sync.destroy(snap) + end + if err == 0 then + err = zfs.sync.rollback(fs) + end + msg = "rolling back " .. fs .. " err=" .. err + return msg +EOF + +log_must zfs mount $fs +log_must [ -f $file ] +log_mustnot snapexists $snap2 + +log_pass "Rolling back snapshot with channel program works." diff --git a/usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/tst.rollback_one.ksh b/usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/tst.rollback_one.ksh new file mode 100644 index 0000000000..2a8e83913b --- /dev/null +++ b/usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/tst.rollback_one.ksh @@ -0,0 +1,51 @@ +#!/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 + +verify_runnable "global" +snap=$TESTPOOL/$TESTFS@$TESTSNAP +fs=$TESTPOOL/$TESTFS +file=$TESTDIR/$TESTFILE0 + +function cleanup +{ + datasetexists $snap && log_must zfs destroy $snap && \ + log_must rm $file + +} + +log_onexit cleanup + +log_must mkfile 128b $file +create_snapshot $TESTPOOL/$TESTFS $TESTSNAP +log_must rm $file + +log_must snapexists $snap +log_must zfs unmount $fs + +log_must_program $TESTPOOL - $fs <<-EOF + arg = ... + fs = arg["argv"][1] + err = zfs.sync.rollback(fs) + msg = "rolling back " .. fs .. " err=" .. err + return msg +EOF + +log_must zfs mount $fs +log_must [ -f $file ] + +log_pass "Rolling back snapshot with channel program works." diff --git a/usr/src/uts/common/fs/zfs/dsl_dataset.c b/usr/src/uts/common/fs/zfs/dsl_dataset.c index 5706965ffe..ab7aa0c146 100644 --- a/usr/src/uts/common/fs/zfs/dsl_dataset.c +++ b/usr/src/uts/common/fs/zfs/dsl_dataset.c @@ -21,7 +21,7 @@ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2011, 2016 by Delphix. All rights reserved. + * Copyright (c) 2011, 2017 by Delphix. All rights reserved. * Copyright (c) 2014, Joyent, Inc. All rights reserved. * Copyright (c) 2014 RackTop Systems. * Copyright (c) 2014 Spectra Logic Corporation, All rights reserved. @@ -2452,14 +2452,7 @@ dsl_dataset_handoff_check(dsl_dataset_t *ds, void *owner, dmu_tx_t *tx) return (0); } -typedef struct dsl_dataset_rollback_arg { - const char *ddra_fsname; - const char *ddra_tosnap; - void *ddra_owner; - nvlist_t *ddra_result; -} dsl_dataset_rollback_arg_t; - -static int +int dsl_dataset_rollback_check(void *arg, dmu_tx_t *tx) { dsl_dataset_rollback_arg_t *ddra = arg; @@ -2567,7 +2560,7 @@ dsl_dataset_rollback_check(void *arg, dmu_tx_t *tx) return (0); } -static void +void dsl_dataset_rollback_sync(void *arg, dmu_tx_t *tx) { dsl_dataset_rollback_arg_t *ddra = arg; diff --git a/usr/src/uts/common/fs/zfs/sys/dsl_dataset.h b/usr/src/uts/common/fs/zfs/sys/dsl_dataset.h index 214d5919ff..d9c62996bc 100644 --- a/usr/src/uts/common/fs/zfs/sys/dsl_dataset.h +++ b/usr/src/uts/common/fs/zfs/sys/dsl_dataset.h @@ -20,7 +20,7 @@ */ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2011, 2015 by Delphix. All rights reserved. + * Copyright (c) 2011, 2017 by Delphix. All rights reserved. * Copyright (c) 2013, Joyent, Inc. All rights reserved. * Copyright (c) 2013 Steven Hartland. All rights reserved. * Copyright (c) 2014 Spectra Logic Corporation, All rights reserved. @@ -237,6 +237,13 @@ typedef struct dsl_dataset_promote_arg { cred_t *cr; } dsl_dataset_promote_arg_t; +typedef struct dsl_dataset_rollback_arg { + const char *ddra_fsname; + const char *ddra_tosnap; + void *ddra_owner; + nvlist_t *ddra_result; +} dsl_dataset_rollback_arg_t; + /* * The max length of a temporary tag prefix is the number of hex digits * required to express UINT64_MAX plus one for the hyphen. @@ -375,6 +382,9 @@ void dsl_dataset_set_refreservation_sync_impl(dsl_dataset_t *ds, void dsl_dataset_zapify(dsl_dataset_t *ds, dmu_tx_t *tx); boolean_t dsl_dataset_is_zapified(dsl_dataset_t *ds); boolean_t dsl_dataset_has_resume_receive_state(dsl_dataset_t *ds); + +int dsl_dataset_rollback_check(void *arg, dmu_tx_t *tx); +void dsl_dataset_rollback_sync(void *arg, dmu_tx_t *tx); int dsl_dataset_rollback(const char *fsname, const char *tosnap, void *owner, nvlist_t *result); diff --git a/usr/src/uts/common/fs/zfs/zcp_synctask.c b/usr/src/uts/common/fs/zfs/zcp_synctask.c index 2238281416..a24d2cff21 100644 --- a/usr/src/uts/common/fs/zfs/zcp_synctask.c +++ b/usr/src/uts/common/fs/zfs/zcp_synctask.c @@ -14,7 +14,7 @@ */ /* - * Copyright (c) 2016 by Delphix. All rights reserved. + * Copyright (c) 2016, 2017 by Delphix. All rights reserved. */ #include "lua.h" @@ -177,6 +177,37 @@ zcp_synctask_promote(lua_State *state, boolean_t sync, nvlist_t *err_details) return (err); } +static int zcp_synctask_rollback(lua_State *, boolean_t, nvlist_t *err_details); +static zcp_synctask_info_t zcp_synctask_rollback_info = { + .name = "rollback", + .func = zcp_synctask_rollback, + .space_check = ZFS_SPACE_CHECK_RESERVED, + .blocks_modified = 1, + .pargs = { + {.za_name = "filesystem", .za_lua_type = LUA_TSTRING}, + {NULL, NULL} + }, + .kwargs = { + {NULL, NULL} + } +}; + +static int +zcp_synctask_rollback(lua_State *state, boolean_t sync, nvlist_t *err_details) +{ + int err; + const char *dsname = lua_tostring(state, 1); + dsl_dataset_rollback_arg_t ddra = { 0 }; + + ddra.ddra_fsname = dsname; + ddra.ddra_result = err_details; + + err = zcp_sync_task(state, dsl_dataset_rollback_check, + dsl_dataset_rollback_sync, &ddra, sync, dsname); + + return (err); +} + void zcp_synctask_wrapper_cleanup(void *arg) { @@ -247,6 +278,7 @@ zcp_load_synctask_lib(lua_State *state, boolean_t sync) zcp_synctask_info_t *zcp_synctask_funcs[] = { &zcp_synctask_destroy_info, &zcp_synctask_promote_info, + &zcp_synctask_rollback_info, NULL }; -- 2.11.4.GIT