svn commit: r323530 - vendor-sys/illumos/dist/common/zfs vendor-sys/illumos/dist/uts/common vendor-sys/illumos/dist/uts/common/fs/zfs vendor-sys/illumos/dist/uts/common/fs/zfs/lua vendor-sys/illumo...
Andriy Gapon
avg at FreeBSD.org
Wed Sep 13 10:45:50 UTC 2017
Author: avg
Date: Wed Sep 13 10:45:49 2017
New Revision: 323530
URL: https://svnweb.freebsd.org/changeset/base/323530
Log:
7431 ZFS Channel Programs
illumos/illumos-gate at dfc115332c94a2f62058ac7f2bce7631fbd20b3d
https://github.com/illumos/illumos-gate/commit/dfc115332c94a2f62058ac7f2bce7631fbd20b3d
https://www.illumos.org/issues/7431
ZFS channel programs (ZCP) adds support for performing compound ZFS
administrative actions via Lua scripts in a sandboxed environment (with time
and memory limits).
This initial commit includes both base support for running ZCP scripts, and a
small initial library of API calls which support getting properties and
listing, destroying, and promoting datasets.
Testing: in addition to the included unit tests, channel programs have been in
use at Delphix for several months for batch destroying filesystems. The
dsl_destroy_snaps_nvl() call has also been replaced with
For reference, the new zfs-program manpage is included below.
ZFS-PROGRAM(1M) 1M ZFS-PROGRAM(1M)
NAME
zfs program – executes ZFS channel programs
SYNOPSIS
zfs program [-t timeout] [-m memory-limit] pool script
DESCRIPTION
The ZFS channel program interface allows ZFS administrative operations to
be run programmatically as a Lua script. The entire script is executed
atomically, with no other administrative operations taking effect
concurrently. A library of ZFS calls is made available to channel program
scripts. Channel programs may only be run with root privileges.
A modified version of the Lua 5.2 interpreter is used to run channel
program scripts. The Lua 5.2 manual can be found at:
http://www.lua.org/manual/5.2/
...
Reviewed by: Matthew Ahrens <mahrens at delphix.com>
Reviewed by: George Wilson <george.wilson at delphix.com>
Reviewed by: John Kennedy <john.kennedy at delphix.com>
Reviewed by: Dan Kimmel <dan.kimmel at delphix.com>
Approved by: Garrett D'Amore <garrett at damore.org>
Author: Chris Williamson <chris.williamson at delphix.com>
Added:
vendor-sys/illumos/dist/uts/common/fs/zfs/lua/
vendor-sys/illumos/dist/uts/common/fs/zfs/lua/README.zfs
vendor-sys/illumos/dist/uts/common/fs/zfs/lua/lapi.c (contents, props changed)
vendor-sys/illumos/dist/uts/common/fs/zfs/lua/lapi.h (contents, props changed)
vendor-sys/illumos/dist/uts/common/fs/zfs/lua/lauxlib.c (contents, props changed)
vendor-sys/illumos/dist/uts/common/fs/zfs/lua/lauxlib.h (contents, props changed)
vendor-sys/illumos/dist/uts/common/fs/zfs/lua/lbaselib.c (contents, props changed)
vendor-sys/illumos/dist/uts/common/fs/zfs/lua/lbitlib.c (contents, props changed)
vendor-sys/illumos/dist/uts/common/fs/zfs/lua/lcode.c (contents, props changed)
vendor-sys/illumos/dist/uts/common/fs/zfs/lua/lcode.h (contents, props changed)
vendor-sys/illumos/dist/uts/common/fs/zfs/lua/lcompat.c (contents, props changed)
vendor-sys/illumos/dist/uts/common/fs/zfs/lua/lcorolib.c (contents, props changed)
vendor-sys/illumos/dist/uts/common/fs/zfs/lua/lctype.c (contents, props changed)
vendor-sys/illumos/dist/uts/common/fs/zfs/lua/lctype.h (contents, props changed)
vendor-sys/illumos/dist/uts/common/fs/zfs/lua/ldebug.c (contents, props changed)
vendor-sys/illumos/dist/uts/common/fs/zfs/lua/ldebug.h (contents, props changed)
vendor-sys/illumos/dist/uts/common/fs/zfs/lua/ldo.c (contents, props changed)
vendor-sys/illumos/dist/uts/common/fs/zfs/lua/ldo.h (contents, props changed)
vendor-sys/illumos/dist/uts/common/fs/zfs/lua/ldump.c (contents, props changed)
vendor-sys/illumos/dist/uts/common/fs/zfs/lua/lfunc.c (contents, props changed)
vendor-sys/illumos/dist/uts/common/fs/zfs/lua/lfunc.h (contents, props changed)
vendor-sys/illumos/dist/uts/common/fs/zfs/lua/lgc.c (contents, props changed)
vendor-sys/illumos/dist/uts/common/fs/zfs/lua/lgc.h (contents, props changed)
vendor-sys/illumos/dist/uts/common/fs/zfs/lua/llex.c (contents, props changed)
vendor-sys/illumos/dist/uts/common/fs/zfs/lua/llex.h (contents, props changed)
vendor-sys/illumos/dist/uts/common/fs/zfs/lua/llimits.h (contents, props changed)
vendor-sys/illumos/dist/uts/common/fs/zfs/lua/lmem.c (contents, props changed)
vendor-sys/illumos/dist/uts/common/fs/zfs/lua/lmem.h (contents, props changed)
vendor-sys/illumos/dist/uts/common/fs/zfs/lua/lobject.c (contents, props changed)
vendor-sys/illumos/dist/uts/common/fs/zfs/lua/lobject.h (contents, props changed)
vendor-sys/illumos/dist/uts/common/fs/zfs/lua/lopcodes.c (contents, props changed)
vendor-sys/illumos/dist/uts/common/fs/zfs/lua/lopcodes.h (contents, props changed)
vendor-sys/illumos/dist/uts/common/fs/zfs/lua/lparser.c (contents, props changed)
vendor-sys/illumos/dist/uts/common/fs/zfs/lua/lparser.h (contents, props changed)
vendor-sys/illumos/dist/uts/common/fs/zfs/lua/lstate.c (contents, props changed)
vendor-sys/illumos/dist/uts/common/fs/zfs/lua/lstate.h (contents, props changed)
vendor-sys/illumos/dist/uts/common/fs/zfs/lua/lstring.c (contents, props changed)
vendor-sys/illumos/dist/uts/common/fs/zfs/lua/lstring.h (contents, props changed)
vendor-sys/illumos/dist/uts/common/fs/zfs/lua/lstrlib.c (contents, props changed)
vendor-sys/illumos/dist/uts/common/fs/zfs/lua/ltable.c (contents, props changed)
vendor-sys/illumos/dist/uts/common/fs/zfs/lua/ltable.h (contents, props changed)
vendor-sys/illumos/dist/uts/common/fs/zfs/lua/ltablib.c (contents, props changed)
vendor-sys/illumos/dist/uts/common/fs/zfs/lua/ltm.c (contents, props changed)
vendor-sys/illumos/dist/uts/common/fs/zfs/lua/ltm.h (contents, props changed)
vendor-sys/illumos/dist/uts/common/fs/zfs/lua/lua.h (contents, props changed)
vendor-sys/illumos/dist/uts/common/fs/zfs/lua/luaconf.h (contents, props changed)
vendor-sys/illumos/dist/uts/common/fs/zfs/lua/lualib.h (contents, props changed)
vendor-sys/illumos/dist/uts/common/fs/zfs/lua/lundump.c (contents, props changed)
vendor-sys/illumos/dist/uts/common/fs/zfs/lua/lundump.h (contents, props changed)
vendor-sys/illumos/dist/uts/common/fs/zfs/lua/lvm.c (contents, props changed)
vendor-sys/illumos/dist/uts/common/fs/zfs/lua/lvm.h (contents, props changed)
vendor-sys/illumos/dist/uts/common/fs/zfs/lua/lzio.c (contents, props changed)
vendor-sys/illumos/dist/uts/common/fs/zfs/lua/lzio.h (contents, props changed)
vendor-sys/illumos/dist/uts/common/fs/zfs/sys/zcp.h (contents, props changed)
vendor-sys/illumos/dist/uts/common/fs/zfs/sys/zcp_global.h (contents, props changed)
vendor-sys/illumos/dist/uts/common/fs/zfs/sys/zcp_iter.h (contents, props changed)
vendor-sys/illumos/dist/uts/common/fs/zfs/sys/zcp_prop.h (contents, props changed)
vendor-sys/illumos/dist/uts/common/fs/zfs/zcp.c (contents, props changed)
vendor-sys/illumos/dist/uts/common/fs/zfs/zcp_get.c (contents, props changed)
vendor-sys/illumos/dist/uts/common/fs/zfs/zcp_global.c (contents, props changed)
vendor-sys/illumos/dist/uts/common/fs/zfs/zcp_iter.c (contents, props changed)
vendor-sys/illumos/dist/uts/common/fs/zfs/zcp_synctask.c (contents, props changed)
Modified:
vendor-sys/illumos/dist/common/zfs/zfs_prop.c
vendor-sys/illumos/dist/uts/common/Makefile.files
vendor-sys/illumos/dist/uts/common/fs/zfs/dsl_dataset.c
vendor-sys/illumos/dist/uts/common/fs/zfs/dsl_destroy.c
vendor-sys/illumos/dist/uts/common/fs/zfs/dsl_dir.c
vendor-sys/illumos/dist/uts/common/fs/zfs/sys/dsl_dataset.h
vendor-sys/illumos/dist/uts/common/fs/zfs/sys/dsl_destroy.h
vendor-sys/illumos/dist/uts/common/fs/zfs/sys/dsl_dir.h
vendor-sys/illumos/dist/uts/common/fs/zfs/sys/zfs_ioctl.h
vendor-sys/illumos/dist/uts/common/fs/zfs/sys/zfs_vfsops.h
vendor-sys/illumos/dist/uts/common/fs/zfs/zfs_ioctl.c
vendor-sys/illumos/dist/uts/common/fs/zfs/zfs_vfsops.c
vendor-sys/illumos/dist/uts/common/sys/fs/zfs.h
Changes in other areas also in this revision:
Added:
vendor/illumos/dist/man/man1m/zfs-program.1m
Modified:
vendor/illumos/dist/cmd/zfs/zfs_main.c
vendor/illumos/dist/cmd/zpool/zpool_main.c
vendor/illumos/dist/lib/libzfs/common/libzfs_dataset.c
vendor/illumos/dist/lib/libzfs/common/libzfs_impl.h
vendor/illumos/dist/lib/libzfs/common/libzfs_util.c
vendor/illumos/dist/lib/libzfs_core/common/libzfs_core.c
vendor/illumos/dist/lib/libzfs_core/common/libzfs_core.h
vendor/illumos/dist/lib/libzpool/common/kernel.c
vendor/illumos/dist/lib/libzpool/common/sys/zfs_context.h
vendor/illumos/dist/man/man1m/zfs.1m
Modified: vendor-sys/illumos/dist/common/zfs/zfs_prop.c
==============================================================================
--- vendor-sys/illumos/dist/common/zfs/zfs_prop.c Wed Sep 13 10:41:47 2017 (r323529)
+++ vendor-sys/illumos/dist/common/zfs/zfs_prop.c Wed Sep 13 10:45:49 2017 (r323530)
@@ -20,7 +20,7 @@
*/
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2011, 2014 by Delphix. All rights reserved.
+ * Copyright (c) 2011, 2016 by Delphix. All rights reserved.
* Copyright (c) 2013 by Saso Kiselkov. All rights reserved.
* Copyright (c) 2013, Joyent, Inc. All rights reserved.
* Copyright (c) 2014 Integros [integros.com]
@@ -381,7 +381,8 @@ zfs_prop_init(void)
zprop_register_number(ZFS_PROP_WRITTEN, "written", 0, PROP_READONLY,
ZFS_TYPE_DATASET, "<size>", "WRITTEN");
zprop_register_number(ZFS_PROP_LOGICALUSED, "logicalused", 0,
- PROP_READONLY, ZFS_TYPE_DATASET, "<size>", "LUSED");
+ PROP_READONLY, ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, "<size>",
+ "LUSED");
zprop_register_number(ZFS_PROP_LOGICALREFERENCED, "logicalreferenced",
0, PROP_READONLY, ZFS_TYPE_DATASET, "<size>", "LREFER");
@@ -582,6 +583,15 @@ zfs_prop_readonly(zfs_prop_t prop)
{
return (zfs_prop_table[prop].pd_attr == PROP_READONLY ||
zfs_prop_table[prop].pd_attr == PROP_ONETIME);
+}
+
+/*
+ * Returns TRUE if the property is visible (not hidden).
+ */
+boolean_t
+zfs_prop_visible(zfs_prop_t prop)
+{
+ return (zfs_prop_table[prop].pd_visible);
}
/*
Modified: vendor-sys/illumos/dist/uts/common/Makefile.files
==============================================================================
--- vendor-sys/illumos/dist/uts/common/Makefile.files Wed Sep 13 10:41:47 2017 (r323529)
+++ vendor-sys/illumos/dist/uts/common/Makefile.files Wed Sep 13 10:45:49 2017 (r323530)
@@ -1308,6 +1308,35 @@ SMBFS_OBJS += smbfs_vfsops.o smbfs_vnops.o smbfs_node.
$(SMBFS_COMMON_OBJS)
+LUA_OBJS += \
+ ldo.o \
+ lvm.o \
+ lbitlib.o \
+ lopcodes.o \
+ lstring.o \
+ ltable.o \
+ ltm.o \
+ lcorolib.o \
+ lauxlib.o \
+ ldebug.o \
+ lstate.o \
+ lgc.o \
+ lmem.o \
+ lctype.o \
+ lfunc.o \
+ ldump.o \
+ lundump.o \
+ lstrlib.o \
+ ltablib.o \
+ lapi.o \
+ lobject.o \
+ lbaselib.o \
+ lcompat.o \
+ lzio.o \
+ lcode.o \
+ llex.o \
+ lparser.o
+
ZFS_COMMON_OBJS += \
abd.o \
arc.o \
@@ -1375,6 +1404,11 @@ ZFS_COMMON_OBJS += \
zap.o \
zap_leaf.o \
zap_micro.o \
+ zcp.o \
+ zcp_get.o \
+ zcp_global.o \
+ zcp_iter.o \
+ zcp_synctask.o \
zfs_byteswap.o \
zfs_debug.o \
zfs_fm.o \
@@ -1958,7 +1992,7 @@ IXGBE_OBJS = ixgbe_82598.o ixgbe_82599.o ixgbe_api.
# illumos-written ones.
I40E_OBJS = i40e_main.o i40e_osdep.o i40e_intr.o i40e_transceiver.o \
- i40e_stats.o i40e_gld.o
+ i40e_stats.o i40e_gld.o
# Intel-written ones.
I40E_INTC_OBJS = i40e_adminq.o i40e_common.o i40e_hmc.o i40e_lan_hmc.o \
i40e_nvm.o
Modified: vendor-sys/illumos/dist/uts/common/fs/zfs/dsl_dataset.c
==============================================================================
--- vendor-sys/illumos/dist/uts/common/fs/zfs/dsl_dataset.c Wed Sep 13 10:41:47 2017 (r323529)
+++ vendor-sys/illumos/dist/uts/common/fs/zfs/dsl_dataset.c Wed Sep 13 10:45:49 2017 (r323530)
@@ -1616,7 +1616,6 @@ dsl_dataset_snapshot_tmp(const char *fsname, const cha
return (error);
}
-
void
dsl_dataset_sync(dsl_dataset_t *ds, zio_t *zio, dmu_tx_t *tx)
{
@@ -1684,30 +1683,17 @@ dsl_dataset_sync_done(dsl_dataset_t *ds, dmu_tx_t *tx)
dmu_buf_rele(ds->ds_dbuf, ds);
}
-static void
-get_clones_stat(dsl_dataset_t *ds, nvlist_t *nv)
+int
+get_clones_stat_impl(dsl_dataset_t *ds, nvlist_t *val)
{
uint64_t count = 0;
objset_t *mos = ds->ds_dir->dd_pool->dp_meta_objset;
zap_cursor_t zc;
zap_attribute_t za;
- nvlist_t *propval = fnvlist_alloc();
- nvlist_t *val;
ASSERT(dsl_pool_config_held(ds->ds_dir->dd_pool));
/*
- * We use nvlist_alloc() instead of fnvlist_alloc() because the
- * latter would allocate the list with NV_UNIQUE_NAME flag.
- * As a result, every time a clone name is appended to the list
- * it would be (linearly) searched for for a duplicate name.
- * We already know that all clone names must be unique and we
- * want avoid the quadratic complexity of double-checking that
- * because we can have a large number of clones.
- */
- VERIFY0(nvlist_alloc(&val, 0, KM_SLEEP));
-
- /*
* There may be missing entries in ds_next_clones_obj
* due to a bug in a previous version of the code.
* Only trust it if it has the right number of entries.
@@ -1716,8 +1702,9 @@ get_clones_stat(dsl_dataset_t *ds, nvlist_t *nv)
VERIFY0(zap_count(mos, dsl_dataset_phys(ds)->ds_next_clones_obj,
&count));
}
- if (count != dsl_dataset_phys(ds)->ds_num_children - 1)
- goto fail;
+ if (count != dsl_dataset_phys(ds)->ds_num_children - 1) {
+ return (ENOENT);
+ }
for (zap_cursor_init(&zc, mos,
dsl_dataset_phys(ds)->ds_next_clones_obj);
zap_cursor_retrieve(&zc, &za) == 0;
@@ -1731,16 +1718,43 @@ get_clones_stat(dsl_dataset_t *ds, nvlist_t *nv)
dsl_dataset_rele(clone, FTAG);
}
zap_cursor_fini(&zc);
- fnvlist_add_nvlist(propval, ZPROP_VALUE, val);
- fnvlist_add_nvlist(nv, zfs_prop_to_name(ZFS_PROP_CLONES), propval);
-fail:
- nvlist_free(val);
- nvlist_free(propval);
+ return (0);
}
-static void
-get_receive_resume_stats(dsl_dataset_t *ds, nvlist_t *nv)
+void
+get_clones_stat(dsl_dataset_t *ds, nvlist_t *nv)
{
+ nvlist_t *propval = fnvlist_alloc();
+ nvlist_t *val;
+
+ /*
+ * We use nvlist_alloc() instead of fnvlist_alloc() because the
+ * latter would allocate the list with NV_UNIQUE_NAME flag.
+ * As a result, every time a clone name is appended to the list
+ * it would be (linearly) searched for for a duplicate name.
+ * We already know that all clone names must be unique and we
+ * want avoid the quadratic complexity of double-checking that
+ * because we can have a large number of clones.
+ */
+ VERIFY0(nvlist_alloc(&val, 0, KM_SLEEP));
+
+ if (get_clones_stat_impl(ds, val) == 0) {
+ fnvlist_add_nvlist(propval, ZPROP_VALUE, val);
+ fnvlist_add_nvlist(nv, zfs_prop_to_name(ZFS_PROP_CLONES),
+ propval);
+ } else {
+ nvlist_free(val);
+ nvlist_free(propval);
+ }
+}
+
+/*
+ * Returns a string that represents the receive resume stats token. It should
+ * be freed with strfree().
+ */
+char *
+get_receive_resume_stats_impl(dsl_dataset_t *ds)
+{
dsl_pool_t *dp = ds->ds_dir->dd_pool;
if (dsl_dataset_has_resume_receive_state(ds)) {
@@ -1807,84 +1821,359 @@ get_receive_resume_stats(dsl_dataset_t *ds, nvlist_t *
ZFS_SEND_RESUME_TOKEN_VERSION,
(longlong_t)cksum.zc_word[0],
(longlong_t)packed_size, str);
- dsl_prop_nvlist_add_string(nv,
- ZFS_PROP_RECEIVE_RESUME_TOKEN, propval);
kmem_free(packed, packed_size);
kmem_free(str, compressed_size * 2 + 1);
kmem_free(compressed, packed_size);
- strfree(propval);
+ return (propval);
}
+ return (strdup(""));
}
+/*
+ * Returns a string that represents the receive resume stats token of the
+ * dataset's child. It should be freed with strfree().
+ */
+char *
+get_child_receive_stats(dsl_dataset_t *ds)
+{
+ char recvname[ZFS_MAX_DATASET_NAME_LEN + 6];
+ dsl_dataset_t *recv_ds;
+ dsl_dataset_name(ds, recvname);
+ if (strlcat(recvname, "/", sizeof (recvname)) <
+ sizeof (recvname) &&
+ strlcat(recvname, recv_clone_name, sizeof (recvname)) <
+ sizeof (recvname) &&
+ dsl_dataset_hold(ds->ds_dir->dd_pool, recvname, FTAG,
+ &recv_ds) == 0) {
+ char *propval = get_receive_resume_stats_impl(recv_ds);
+ dsl_dataset_rele(recv_ds, FTAG);
+ return (propval);
+ }
+ return (strdup(""));
+}
+
+static void
+get_receive_resume_stats(dsl_dataset_t *ds, nvlist_t *nv)
+{
+ char *propval = get_receive_resume_stats_impl(ds);
+ if (strcmp(propval, "") != 0) {
+ dsl_prop_nvlist_add_string(nv,
+ ZFS_PROP_RECEIVE_RESUME_TOKEN, propval);
+ } else {
+ char *childval = get_child_receive_stats(ds);
+ if (strcmp(childval, "") != 0) {
+ dsl_prop_nvlist_add_string(nv,
+ ZFS_PROP_RECEIVE_RESUME_TOKEN, childval);
+ }
+ strfree(childval);
+ }
+ strfree(propval);
+}
+
+uint64_t
+dsl_get_refratio(dsl_dataset_t *ds)
+{
+ uint64_t ratio = dsl_dataset_phys(ds)->ds_compressed_bytes == 0 ? 100 :
+ (dsl_dataset_phys(ds)->ds_uncompressed_bytes * 100 /
+ dsl_dataset_phys(ds)->ds_compressed_bytes);
+ return (ratio);
+}
+
+uint64_t
+dsl_get_logicalreferenced(dsl_dataset_t *ds)
+{
+ return (dsl_dataset_phys(ds)->ds_uncompressed_bytes);
+}
+
+uint64_t
+dsl_get_compressratio(dsl_dataset_t *ds)
+{
+ if (ds->ds_is_snapshot) {
+ return (dsl_get_refratio(ds));
+ } else {
+ dsl_dir_t *dd = ds->ds_dir;
+ mutex_enter(&dd->dd_lock);
+ uint64_t val = dsl_dir_get_compressratio(dd);
+ mutex_exit(&dd->dd_lock);
+ return (val);
+ }
+}
+
+uint64_t
+dsl_get_used(dsl_dataset_t *ds)
+{
+ if (ds->ds_is_snapshot) {
+ return (dsl_dataset_phys(ds)->ds_unique_bytes);
+ } else {
+ dsl_dir_t *dd = ds->ds_dir;
+ mutex_enter(&dd->dd_lock);
+ uint64_t val = dsl_dir_get_used(dd);
+ mutex_exit(&dd->dd_lock);
+ return (val);
+ }
+}
+
+uint64_t
+dsl_get_creation(dsl_dataset_t *ds)
+{
+ return (dsl_dataset_phys(ds)->ds_creation_time);
+}
+
+uint64_t
+dsl_get_creationtxg(dsl_dataset_t *ds)
+{
+ return (dsl_dataset_phys(ds)->ds_creation_txg);
+}
+
+uint64_t
+dsl_get_refquota(dsl_dataset_t *ds)
+{
+ return (ds->ds_quota);
+}
+
+uint64_t
+dsl_get_refreservation(dsl_dataset_t *ds)
+{
+ return (ds->ds_reserved);
+}
+
+uint64_t
+dsl_get_guid(dsl_dataset_t *ds)
+{
+ return (dsl_dataset_phys(ds)->ds_guid);
+}
+
+uint64_t
+dsl_get_unique(dsl_dataset_t *ds)
+{
+ return (dsl_dataset_phys(ds)->ds_unique_bytes);
+}
+
+uint64_t
+dsl_get_objsetid(dsl_dataset_t *ds)
+{
+ return (ds->ds_object);
+}
+
+uint64_t
+dsl_get_userrefs(dsl_dataset_t *ds)
+{
+ return (ds->ds_userrefs);
+}
+
+uint64_t
+dsl_get_defer_destroy(dsl_dataset_t *ds)
+{
+ return (DS_IS_DEFER_DESTROY(ds) ? 1 : 0);
+}
+
+uint64_t
+dsl_get_referenced(dsl_dataset_t *ds)
+{
+ return (dsl_dataset_phys(ds)->ds_referenced_bytes);
+}
+
+uint64_t
+dsl_get_numclones(dsl_dataset_t *ds)
+{
+ ASSERT(ds->ds_is_snapshot);
+ return (dsl_dataset_phys(ds)->ds_num_children - 1);
+}
+
+uint64_t
+dsl_get_inconsistent(dsl_dataset_t *ds)
+{
+ return ((dsl_dataset_phys(ds)->ds_flags & DS_FLAG_INCONSISTENT) ?
+ 1 : 0);
+}
+
+uint64_t
+dsl_get_available(dsl_dataset_t *ds)
+{
+ uint64_t refdbytes = dsl_get_referenced(ds);
+ uint64_t availbytes = dsl_dir_space_available(ds->ds_dir,
+ NULL, 0, TRUE);
+ if (ds->ds_reserved > dsl_dataset_phys(ds)->ds_unique_bytes) {
+ availbytes +=
+ ds->ds_reserved - dsl_dataset_phys(ds)->ds_unique_bytes;
+ }
+ if (ds->ds_quota != 0) {
+ /*
+ * Adjust available bytes according to refquota
+ */
+ if (refdbytes < ds->ds_quota) {
+ availbytes = MIN(availbytes,
+ ds->ds_quota - refdbytes);
+ } else {
+ availbytes = 0;
+ }
+ }
+ return (availbytes);
+}
+
+int
+dsl_get_written(dsl_dataset_t *ds, uint64_t *written)
+{
+ dsl_pool_t *dp = ds->ds_dir->dd_pool;
+ dsl_dataset_t *prev;
+ int err = dsl_dataset_hold_obj(dp,
+ dsl_dataset_phys(ds)->ds_prev_snap_obj, FTAG, &prev);
+ if (err == 0) {
+ uint64_t comp, uncomp;
+ err = dsl_dataset_space_written(prev, ds, written,
+ &comp, &uncomp);
+ dsl_dataset_rele(prev, FTAG);
+ }
+ return (err);
+}
+
+/*
+ * 'snap' should be a buffer of size ZFS_MAX_DATASET_NAME_LEN.
+ */
+int
+dsl_get_prev_snap(dsl_dataset_t *ds, char *snap)
+{
+ dsl_pool_t *dp = ds->ds_dir->dd_pool;
+ if (ds->ds_prev != NULL && ds->ds_prev != dp->dp_origin_snap) {
+ dsl_dataset_name(ds->ds_prev, snap);
+ return (0);
+ } else {
+ return (ENOENT);
+ }
+}
+
+/*
+ * Returns the mountpoint property and source for the given dataset in the value
+ * and source buffers. The value buffer must be at least as large as MAXPATHLEN
+ * and the source buffer as least as large a ZFS_MAX_DATASET_NAME_LEN.
+ * Returns 0 on success and an error on failure.
+ */
+int
+dsl_get_mountpoint(dsl_dataset_t *ds, const char *dsname, char *value,
+ char *source)
+{
+ int error;
+ dsl_pool_t *dp = ds->ds_dir->dd_pool;
+
+ /* Retrieve the mountpoint value stored in the zap opbject */
+ error = dsl_prop_get_ds(ds, zfs_prop_to_name(ZFS_PROP_MOUNTPOINT), 1,
+ ZAP_MAXVALUELEN, value, source);
+ if (error != 0) {
+ return (error);
+ }
+
+ /* Process the dsname and source to find the full mountpoint string */
+ if (value[0] == '/') {
+ char *buf = kmem_alloc(ZAP_MAXVALUELEN, KM_SLEEP);
+ char *root = buf;
+ const char *relpath;
+
+ /*
+ * If we inherit the mountpoint, even from a dataset
+ * with a received value, the source will be the path of
+ * the dataset we inherit from. If source is
+ * ZPROP_SOURCE_VAL_RECVD, the received value is not
+ * inherited.
+ */
+ if (strcmp(source, ZPROP_SOURCE_VAL_RECVD) == 0) {
+ relpath = "";
+ } else {
+ ASSERT0(strncmp(dsname, source, strlen(source)));
+ relpath = dsname + strlen(source);
+ if (relpath[0] == '/')
+ relpath++;
+ }
+
+ spa_altroot(dp->dp_spa, root, ZAP_MAXVALUELEN);
+
+ /*
+ * Special case an alternate root of '/'. This will
+ * avoid having multiple leading slashes in the
+ * mountpoint path.
+ */
+ if (strcmp(root, "/") == 0)
+ root++;
+
+ /*
+ * If the mountpoint is '/' then skip over this
+ * if we are obtaining either an alternate root or
+ * an inherited mountpoint.
+ */
+ char *mnt = value;
+ if (value[1] == '\0' && (root[0] != '\0' ||
+ relpath[0] != '\0'))
+ mnt = value + 1;
+
+ if (relpath[0] == '\0') {
+ (void) snprintf(value, ZAP_MAXVALUELEN, "%s%s",
+ root, mnt);
+ } else {
+ (void) snprintf(value, ZAP_MAXVALUELEN, "%s%s%s%s",
+ root, mnt, relpath[0] == '@' ? "" : "/",
+ relpath);
+ }
+ kmem_free(buf, ZAP_MAXVALUELEN);
+ } else {
+ /* 'legacy' or 'none' */
+ (void) snprintf(value, ZAP_MAXVALUELEN, "%s", value);
+ }
+ return (0);
+}
+
void
dsl_dataset_stats(dsl_dataset_t *ds, nvlist_t *nv)
{
dsl_pool_t *dp = ds->ds_dir->dd_pool;
- uint64_t refd, avail, uobjs, aobjs, ratio;
ASSERT(dsl_pool_config_held(dp));
- ratio = dsl_dataset_phys(ds)->ds_compressed_bytes == 0 ? 100 :
- (dsl_dataset_phys(ds)->ds_uncompressed_bytes * 100 /
- dsl_dataset_phys(ds)->ds_compressed_bytes);
-
- dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_REFRATIO, ratio);
+ dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_REFRATIO,
+ dsl_get_refratio(ds));
dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_LOGICALREFERENCED,
- dsl_dataset_phys(ds)->ds_uncompressed_bytes);
+ dsl_get_logicalreferenced(ds));
+ dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_COMPRESSRATIO,
+ dsl_get_compressratio(ds));
+ dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_USED,
+ dsl_get_used(ds));
if (ds->ds_is_snapshot) {
- dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_COMPRESSRATIO, ratio);
- dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_USED,
- dsl_dataset_phys(ds)->ds_unique_bytes);
get_clones_stat(ds, nv);
} else {
- if (ds->ds_prev != NULL && ds->ds_prev != dp->dp_origin_snap) {
- char buf[ZFS_MAX_DATASET_NAME_LEN];
- dsl_dataset_name(ds->ds_prev, buf);
- dsl_prop_nvlist_add_string(nv, ZFS_PROP_PREV_SNAP, buf);
- }
-
+ char buf[ZFS_MAX_DATASET_NAME_LEN];
+ if (dsl_get_prev_snap(ds, buf) == 0)
+ dsl_prop_nvlist_add_string(nv, ZFS_PROP_PREV_SNAP,
+ buf);
dsl_dir_stats(ds->ds_dir, nv);
}
- dsl_dataset_space(ds, &refd, &avail, &uobjs, &aobjs);
- dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_AVAILABLE, avail);
- dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_REFERENCED, refd);
-
+ dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_AVAILABLE,
+ dsl_get_available(ds));
+ dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_REFERENCED,
+ dsl_get_referenced(ds));
dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_CREATION,
- dsl_dataset_phys(ds)->ds_creation_time);
+ dsl_get_creation(ds));
dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_CREATETXG,
- dsl_dataset_phys(ds)->ds_creation_txg);
+ dsl_get_creationtxg(ds));
dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_REFQUOTA,
- ds->ds_quota);
+ dsl_get_refquota(ds));
dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_REFRESERVATION,
- ds->ds_reserved);
+ dsl_get_refreservation(ds));
dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_GUID,
- dsl_dataset_phys(ds)->ds_guid);
+ dsl_get_guid(ds));
dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_UNIQUE,
- dsl_dataset_phys(ds)->ds_unique_bytes);
+ dsl_get_unique(ds));
dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_OBJSETID,
- ds->ds_object);
+ dsl_get_objsetid(ds));
dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_USERREFS,
- ds->ds_userrefs);
+ dsl_get_userrefs(ds));
dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_DEFER_DESTROY,
- DS_IS_DEFER_DESTROY(ds) ? 1 : 0);
+ dsl_get_defer_destroy(ds));
if (dsl_dataset_phys(ds)->ds_prev_snap_obj != 0) {
- uint64_t written, comp, uncomp;
- dsl_pool_t *dp = ds->ds_dir->dd_pool;
- dsl_dataset_t *prev;
-
- int err = dsl_dataset_hold_obj(dp,
- dsl_dataset_phys(ds)->ds_prev_snap_obj, FTAG, &prev);
- if (err == 0) {
- err = dsl_dataset_space_written(prev, ds, &written,
- &comp, &uncomp);
- dsl_dataset_rele(prev, FTAG);
- if (err == 0) {
- dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_WRITTEN,
- written);
- }
+ uint64_t written;
+ if (dsl_get_written(ds, &written) == 0) {
+ dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_WRITTEN,
+ written);
}
}
@@ -1921,27 +2210,19 @@ dsl_dataset_fast_stat(dsl_dataset_t *ds, dmu_objset_st
dsl_pool_t *dp = ds->ds_dir->dd_pool;
ASSERT(dsl_pool_config_held(dp));
- stat->dds_creation_txg = dsl_dataset_phys(ds)->ds_creation_txg;
- stat->dds_inconsistent =
- dsl_dataset_phys(ds)->ds_flags & DS_FLAG_INCONSISTENT;
- stat->dds_guid = dsl_dataset_phys(ds)->ds_guid;
+ stat->dds_creation_txg = dsl_get_creationtxg(ds);
+ stat->dds_inconsistent = dsl_get_inconsistent(ds);
+ stat->dds_guid = dsl_get_guid(ds);
stat->dds_origin[0] = '\0';
if (ds->ds_is_snapshot) {
stat->dds_is_snapshot = B_TRUE;
- stat->dds_num_clones =
- dsl_dataset_phys(ds)->ds_num_children - 1;
+ stat->dds_num_clones = dsl_get_numclones(ds);
} else {
stat->dds_is_snapshot = B_FALSE;
stat->dds_num_clones = 0;
if (dsl_dir_is_clone(ds->ds_dir)) {
- dsl_dataset_t *ods;
-
- VERIFY0(dsl_dataset_hold_obj(dp,
- dsl_dir_phys(ds->ds_dir)->dd_origin_obj,
- FTAG, &ods));
- dsl_dataset_name(ods, stat->dds_origin);
- dsl_dataset_rele(ods, FTAG);
+ dsl_dir_get_origin(ds->ds_dir, stat->dds_origin);
}
}
}
@@ -2348,22 +2629,12 @@ struct promotenode {
dsl_dataset_t *ds;
};
-typedef struct dsl_dataset_promote_arg {
- const char *ddpa_clonename;
- dsl_dataset_t *ddpa_clone;
- list_t shared_snaps, origin_snaps, clone_snaps;
- dsl_dataset_t *origin_origin; /* origin of the origin */
- uint64_t used, comp, uncomp, unique, cloneusedsnap, originusedsnap;
- char *err_ds;
- cred_t *cr;
-} dsl_dataset_promote_arg_t;
-
static int snaplist_space(list_t *l, uint64_t mintxg, uint64_t *spacep);
static int promote_hold(dsl_dataset_promote_arg_t *ddpa, dsl_pool_t *dp,
void *tag);
static void promote_rele(dsl_dataset_promote_arg_t *ddpa, void *tag);
-static int
+int
dsl_dataset_promote_check(void *arg, dmu_tx_t *tx)
{
dsl_dataset_promote_arg_t *ddpa = arg;
@@ -2375,14 +2646,19 @@ dsl_dataset_promote_check(void *arg, dmu_tx_t *tx)
uint64_t unused;
uint64_t ss_mv_cnt;
size_t max_snap_len;
+ boolean_t conflicting_snaps;
err = promote_hold(ddpa, dp, FTAG);
if (err != 0)
return (err);
hds = ddpa->ddpa_clone;
+ snap = list_head(&ddpa->shared_snaps);
+ origin_ds = snap->ds;
max_snap_len = MAXNAMELEN - strlen(ddpa->ddpa_clonename) - 1;
+ snap = list_head(&ddpa->origin_snaps);
+
if (dsl_dataset_phys(hds)->ds_flags & DS_FLAG_NOPROMOTE) {
promote_rele(ddpa, FTAG);
return (SET_ERROR(EXDEV));
@@ -2397,9 +2673,6 @@ dsl_dataset_promote_check(void *arg, dmu_tx_t *tx)
return (0);
}
- snap = list_head(&ddpa->shared_snaps);
- origin_ds = snap->ds;
-
/* compute origin's new unique space */
snap = list_tail(&ddpa->clone_snaps);
ASSERT3U(dsl_dataset_phys(snap->ds)->ds_prev_snap_obj, ==,
@@ -2423,6 +2696,7 @@ dsl_dataset_promote_check(void *arg, dmu_tx_t *tx)
* Note however, if we stop before we reach the ORIGIN we get:
* uN + kN + kN-1 + ... + kM - uM-1
*/
+ conflicting_snaps = B_FALSE;
ss_mv_cnt = 0;
ddpa->used = dsl_dataset_phys(origin_ds)->ds_referenced_bytes;
ddpa->comp = dsl_dataset_phys(origin_ds)->ds_compressed_bytes;
@@ -2451,12 +2725,12 @@ dsl_dataset_promote_check(void *arg, dmu_tx_t *tx)
}
err = dsl_dataset_snap_lookup(hds, ds->ds_snapname, &val);
if (err == 0) {
- (void) strcpy(ddpa->err_ds, snap->ds->ds_snapname);
- err = SET_ERROR(EEXIST);
+ fnvlist_add_boolean(ddpa->err_ds,
+ snap->ds->ds_snapname);
+ conflicting_snaps = B_TRUE;
+ } else if (err != ENOENT) {
goto out;
}
- if (err != ENOENT)
- goto out;
/* The very first snapshot does not have a deadlist */
if (dsl_dataset_phys(ds)->ds_prev_snap_obj == 0)
@@ -2470,6 +2744,15 @@ dsl_dataset_promote_check(void *arg, dmu_tx_t *tx)
}
/*
+ * In order to return the full list of conflicting snapshots, we check
+ * whether there was a conflict after traversing all of them.
+ */
+ if (conflicting_snaps) {
+ err = SET_ERROR(EEXIST);
+ goto out;
+ }
+
+ /*
* If we are a clone of a clone then we never reached ORIGIN,
* so we need to subtract out the clone origin's used space.
*/
@@ -2531,7 +2814,7 @@ out:
return (err);
}
-static void
+void
dsl_dataset_promote_sync(void *arg, dmu_tx_t *tx)
{
dsl_dataset_promote_arg_t *ddpa = arg;
@@ -2856,6 +3139,7 @@ dsl_dataset_promote(const char *name, char *conflsnap)
dsl_dataset_promote_arg_t ddpa = { 0 };
uint64_t numsnaps;
int error;
+ nvpair_t *snap_pair;
objset_t *os;
/*
@@ -2873,12 +3157,22 @@ dsl_dataset_promote(const char *name, char *conflsnap)
return (error);
ddpa.ddpa_clonename = name;
- ddpa.err_ds = conflsnap;
+ ddpa.err_ds = fnvlist_alloc();
ddpa.cr = CRED();
- return (dsl_sync_task(name, dsl_dataset_promote_check,
+ error = dsl_sync_task(name, dsl_dataset_promote_check,
dsl_dataset_promote_sync, &ddpa,
- 2 + numsnaps, ZFS_SPACE_CHECK_RESERVED));
+ 2 + numsnaps, ZFS_SPACE_CHECK_RESERVED);
+
+ /*
+ * Return the first conflicting snapshot found.
+ */
+ snap_pair = nvlist_next_nvpair(ddpa.err_ds, NULL);
+ if (snap_pair != NULL && conflsnap != NULL)
+ (void) strcpy(conflsnap, nvpair_name(snap_pair));
+
+ fnvlist_free(ddpa.err_ds);
+ return (error);
}
int
Modified: vendor-sys/illumos/dist/uts/common/fs/zfs/dsl_destroy.c
==============================================================================
--- vendor-sys/illumos/dist/uts/common/fs/zfs/dsl_destroy.c Wed Sep 13 10:41:47 2017 (r323529)
+++ vendor-sys/illumos/dist/uts/common/fs/zfs/dsl_destroy.c Wed Sep 13 10:45:49 2017 (r323530)
@@ -20,7 +20,7 @@
*/
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2012, 2015 by Delphix. All rights reserved.
+ * Copyright (c) 2012, 2016 by Delphix. All rights reserved.
* Copyright (c) 2013 Steven Hartland. All rights reserved.
* Copyright (c) 2013 by Joyent, Inc. All rights reserved.
* Copyright (c) 2014 Integros [integros.com]
@@ -30,6 +30,7 @@
#include <sys/dsl_userhold.h>
#include <sys/dsl_dataset.h>
#include <sys/dsl_synctask.h>
+#include <sys/dsl_destroy.h>
#include <sys/dmu_tx.h>
#include <sys/dsl_pool.h>
#include <sys/dsl_dir.h>
@@ -41,14 +42,8 @@
#include <sys/zfs_ioctl.h>
#include <sys/dsl_deleg.h>
#include <sys/dmu_impl.h>
+#include <sys/zcp.h>
-typedef struct dmu_snapshots_destroy_arg {
- nvlist_t *dsda_snaps;
- nvlist_t *dsda_successful_snaps;
- boolean_t dsda_defer;
- nvlist_t *dsda_errlist;
-} dmu_snapshots_destroy_arg_t;
-
int
dsl_destroy_snapshot_check_impl(dsl_dataset_t *ds, boolean_t defer)
{
@@ -85,51 +80,33 @@ dsl_destroy_snapshot_check_impl(dsl_dataset_t *ds, boo
return (0);
}
-static int
+int
dsl_destroy_snapshot_check(void *arg, dmu_tx_t *tx)
{
- dmu_snapshots_destroy_arg_t *dsda = arg;
+ dsl_destroy_snapshot_arg_t *ddsa = arg;
+ const char *dsname = ddsa->ddsa_name;
+ boolean_t defer = ddsa->ddsa_defer;
+
dsl_pool_t *dp = dmu_tx_pool(tx);
- nvpair_t *pair;
int error = 0;
+ dsl_dataset_t *ds;
- if (!dmu_tx_is_syncing(tx))
+ error = dsl_dataset_hold(dp, dsname, FTAG, &ds);
+
+ /*
+ * If the snapshot does not exist, silently ignore it, and
+ * dsl_destroy_snapshot_sync() will be a no-op
+ * (it's "already destroyed").
+ */
+ if (error == ENOENT)
return (0);
- for (pair = nvlist_next_nvpair(dsda->dsda_snaps, NULL);
- pair != NULL; pair = nvlist_next_nvpair(dsda->dsda_snaps, pair)) {
- dsl_dataset_t *ds;
-
- error = dsl_dataset_hold(dp, nvpair_name(pair),
- FTAG, &ds);
-
- /*
- * If the snapshot does not exist, silently ignore it
- * (it's "already destroyed").
- */
- if (error == ENOENT)
- continue;
-
- if (error == 0) {
- error = dsl_destroy_snapshot_check_impl(ds,
- dsda->dsda_defer);
- dsl_dataset_rele(ds, FTAG);
- }
-
- if (error == 0) {
- fnvlist_add_boolean(dsda->dsda_successful_snaps,
- nvpair_name(pair));
- } else {
- fnvlist_add_int32(dsda->dsda_errlist,
- nvpair_name(pair), error);
- }
+ if (error == 0) {
+ error = dsl_destroy_snapshot_check_impl(ds, defer);
+ dsl_dataset_rele(ds, FTAG);
}
- pair = nvlist_next_nvpair(dsda->dsda_errlist, NULL);
- if (pair != NULL)
- return (fnvpair_value_int32(pair));
-
- return (0);
+ return (error);
}
struct process_old_arg {
@@ -473,23 +450,22 @@ dsl_destroy_snapshot_sync_impl(dsl_dataset_t *ds, bool
dmu_object_free_zapified(mos, obj, tx);
}
-static void
+void
dsl_destroy_snapshot_sync(void *arg, dmu_tx_t *tx)
{
- dmu_snapshots_destroy_arg_t *dsda = arg;
+ dsl_destroy_snapshot_arg_t *ddsa = arg;
+ const char *dsname = ddsa->ddsa_name;
+ boolean_t defer = ddsa->ddsa_defer;
+
dsl_pool_t *dp = dmu_tx_pool(tx);
- nvpair_t *pair;
+ dsl_dataset_t *ds;
- for (pair = nvlist_next_nvpair(dsda->dsda_successful_snaps, NULL);
- pair != NULL;
- pair = nvlist_next_nvpair(dsda->dsda_successful_snaps, pair)) {
- dsl_dataset_t *ds;
-
- VERIFY0(dsl_dataset_hold(dp, nvpair_name(pair), FTAG, &ds));
-
- dsl_destroy_snapshot_sync_impl(ds, dsda->dsda_defer, tx);
- dsl_dataset_rele(ds, FTAG);
- }
+ int error = dsl_dataset_hold(dp, dsname, FTAG, &ds);
+ if (error == ENOENT)
+ return;
+ ASSERT0(error);
+ dsl_destroy_snapshot_sync_impl(ds, defer, tx);
+ dsl_dataset_rele(ds, FTAG);
}
/*
@@ -509,25 +485,85 @@ int
dsl_destroy_snapshots_nvl(nvlist_t *snaps, boolean_t defer,
nvlist_t *errlist)
{
- dmu_snapshots_destroy_arg_t dsda;
- int error;
- nvpair_t *pair;
-
- pair = nvlist_next_nvpair(snaps, NULL);
- if (pair == NULL)
+ if (nvlist_next_nvpair(snaps, NULL) == NULL)
return (0);
- dsda.dsda_snaps = snaps;
- dsda.dsda_successful_snaps = fnvlist_alloc();
- dsda.dsda_defer = defer;
- dsda.dsda_errlist = errlist;
+ nvlist_t *arg = fnvlist_alloc();
+ nvlist_t *snaps_normalized = fnvlist_alloc();
+ /*
+ * lzc_destroy_snaps() is documented to take an nvlist whose
+ * values "don't matter". We need to convert that nvlist to one
+ * that we know can be converted to LUA.
+ */
+ for (nvpair_t *pair = nvlist_next_nvpair(snaps, NULL);
+ pair != NULL; pair = nvlist_next_nvpair(snaps, pair)) {
+ fnvlist_add_boolean_value(snaps_normalized,
+ nvpair_name(pair), B_TRUE);
+ }
+ fnvlist_add_nvlist(arg, "snaps", snaps_normalized);
+ fnvlist_add_boolean_value(arg, "defer", defer);
- error = dsl_sync_task(nvpair_name(pair),
- dsl_destroy_snapshot_check, dsl_destroy_snapshot_sync,
- &dsda, 0, ZFS_SPACE_CHECK_NONE);
- fnvlist_free(dsda.dsda_successful_snaps);
+ nvlist_t *wrapper = fnvlist_alloc();
+ fnvlist_add_nvlist(wrapper, ZCP_ARG_ARGLIST, arg);
+ fnvlist_free(arg);
- return (error);
+ const char *program =
+ "arg = ...\n"
+ "snaps = arg['snaps']\n"
+ "defer = arg['defer']\n"
+ "errors = { }\n"
+ "has_errors = false\n"
+ "for snap, v in pairs(snaps) do\n"
+ " errno = zfs.check.destroy{snap, defer=defer}\n"
+ " zfs.debug('snap: ' .. snap .. ' errno: ' .. errno)\n"
+ " if errno == ENOENT then\n"
+ " snaps[snap] = nil\n"
+ " elseif errno ~= 0 then\n"
+ " errors[snap] = errno\n"
+ " has_errors = true\n"
+ " end\n"
+ "end\n"
+ "if has_errors then\n"
+ " return errors\n"
+ "end\n"
+ "for snap, v in pairs(snaps) do\n"
+ " errno = zfs.sync.destroy{snap, defer=defer}\n"
+ " assert(errno == 0)\n"
+ "end\n"
+ "return { }\n";
+
+ nvlist_t *result = fnvlist_alloc();
+ int error = zcp_eval(nvpair_name(nvlist_next_nvpair(snaps, NULL)),
+ program,
+ 0,
+ zfs_lua_max_memlimit,
+ fnvlist_lookup_nvpair(wrapper, ZCP_ARG_ARGLIST), result);
+ if (error != 0) {
+ char *errorstr = NULL;
+ (void) nvlist_lookup_string(result, ZCP_RET_ERROR, &errorstr);
+ if (errorstr != NULL) {
+ zfs_dbgmsg(errorstr);
+ }
+ return (error);
+ }
*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
More information about the svn-src-vendor
mailing list