aboutsummaryrefslogtreecommitdiffstats
path: root/module/zfs
diff options
context:
space:
mode:
authorChris Williamson <[email protected]>2018-02-08 09:24:39 -0700
committerBrian Behlendorf <[email protected]>2018-02-08 15:29:24 -0800
commit234c91c50848fa74bd72efff4e555331a25d9fe1 (patch)
treee93accbb8799995afbc2d3d3714577b1f925471c /module/zfs
parentaf0736898669eabe31e47405023c80b9a58e5e6c (diff)
OpenZFS 8600 - ZFS channel programs - snapshot
Authored by: Chris Williamson <[email protected]> Reviewed by: Matthew Ahrens <[email protected]> Reviewed by: John Kennedy <[email protected]> Reviewed by: Brad Lewis <[email protected]> Approved by: Robert Mustacchi <[email protected]> Ported-by: Don Brady <[email protected]> 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
Diffstat (limited to 'module/zfs')
-rw-r--r--module/zfs/dsl_dataset.c11
-rw-r--r--module/zfs/zcp.c9
-rw-r--r--module/zfs/zcp_global.c7
-rw-r--r--module/zfs/zcp_synctask.c71
-rw-r--r--module/zfs/zfs_ioctl.c2
5 files changed, 77 insertions, 23 deletions
diff --git a/module/zfs/dsl_dataset.c b/module/zfs/dsl_dataset.c
index a35ba1f7e..0bfc4cd7a 100644
--- a/module/zfs/dsl_dataset.c
+++ b/module/zfs/dsl_dataset.c
@@ -1140,13 +1140,6 @@ dsl_dataset_snapshot_reserve_space(dsl_dataset_t *ds, dmu_tx_t *tx)
return (0);
}
-typedef struct dsl_dataset_snapshot_arg {
- nvlist_t *ddsa_snaps;
- nvlist_t *ddsa_props;
- nvlist_t *ddsa_errors;
- cred_t *ddsa_cr;
-} dsl_dataset_snapshot_arg_t;
-
int
dsl_dataset_snapshot_check_impl(dsl_dataset_t *ds, const char *snapname,
dmu_tx_t *tx, boolean_t recv, uint64_t cnt, cred_t *cr)
@@ -1206,7 +1199,7 @@ dsl_dataset_snapshot_check_impl(dsl_dataset_t *ds, const char *snapname,
return (0);
}
-static int
+int
dsl_dataset_snapshot_check(void *arg, dmu_tx_t *tx)
{
dsl_dataset_snapshot_arg_t *ddsa = arg;
@@ -1486,7 +1479,7 @@ dsl_dataset_snapshot_sync_impl(dsl_dataset_t *ds, const char *snapname,
spa_history_log_internal_ds(ds->ds_prev, "snapshot", tx, "");
}
-static void
+void
dsl_dataset_snapshot_sync(void *arg, dmu_tx_t *tx)
{
dsl_dataset_snapshot_arg_t *ddsa = arg;
diff --git a/module/zfs/zcp.c b/module/zfs/zcp.c
index 83560309b..1a39330d3 100644
--- a/module/zfs/zcp.c
+++ b/module/zfs/zcp.c
@@ -14,7 +14,7 @@
*/
/*
- * Copyright (c) 2016 by Delphix. All rights reserved.
+ * Copyright (c) 2016, 2017 by Delphix. All rights reserved.
*/
/*
@@ -106,10 +106,15 @@
#define KM_NORMALPRI 0
#endif
+#define ZCP_NVLIST_MAX_DEPTH 20
+
uint64_t zfs_lua_check_instrlimit_interval = 100;
uint64_t zfs_lua_max_instrlimit = ZCP_MAX_INSTRLIMIT;
uint64_t zfs_lua_max_memlimit = ZCP_MAX_MEMLIMIT;
+/*
+ * Forward declarations for mutually recursive functions
+ */
static int zcp_nvpair_value_to_lua(lua_State *, nvpair_t *, char *, int);
static int zcp_lua_to_nvlist_impl(lua_State *, int, nvlist_t *, const char *,
int);
@@ -217,8 +222,6 @@ zcp_cleanup(lua_State *state)
}
}
-#define ZCP_NVLIST_MAX_DEPTH 20
-
/*
* Convert the lua table at the given index on the Lua stack to an nvlist
* and return it.
diff --git a/module/zfs/zcp_global.c b/module/zfs/zcp_global.c
index b6c3c3a4f..8e166e073 100644
--- a/module/zfs/zcp_global.c
+++ b/module/zfs/zcp_global.c
@@ -14,7 +14,7 @@
*/
/*
- * Copyright (c) 2016 by Delphix. All rights reserved.
+ * Copyright (c) 2016, 2017 by Delphix. All rights reserved.
*/
#include <sys/zcp_global.h>
@@ -62,7 +62,12 @@ static const zcp_errno_global_t errno_globals[] = {
{"EPIPE", EPIPE},
{"EDOM", EDOM},
{"ERANGE", ERANGE},
+ {"EDEADLK", EDEADLK},
+ {"ENOLCK", ENOLCK},
+ {"ECANCELED", ECANCELED},
+ {"ENOTSUP", ENOTSUP},
{"EDQUOT", EDQUOT},
+ {"ENAMETOOLONG", ENAMETOOLONG},
{0, 0}
};
diff --git a/module/zfs/zcp_synctask.c b/module/zfs/zcp_synctask.c
index 93797e9f3..ad9bffacb 100644
--- a/module/zfs/zcp_synctask.c
+++ b/module/zfs/zcp_synctask.c
@@ -39,10 +39,10 @@ typedef int (zcp_synctask_func_t)(lua_State *, boolean_t, nvlist_t *);
typedef struct zcp_synctask_info {
const char *name;
zcp_synctask_func_t *func;
- zfs_space_check_t space_check;
- int blocks_modified;
const zcp_arg_t pargs[4];
const zcp_arg_t kwargs[2];
+ zfs_space_check_t space_check;
+ int blocks_modified;
} zcp_synctask_info_t;
/*
@@ -91,8 +91,6 @@ static int zcp_synctask_destroy(lua_State *, boolean_t, nvlist_t *);
static zcp_synctask_info_t zcp_synctask_destroy_info = {
.name = "destroy",
.func = zcp_synctask_destroy,
- .space_check = ZFS_SPACE_CHECK_NONE,
- .blocks_modified = 0,
.pargs = {
{.za_name = "filesystem | snapshot", .za_lua_type = LUA_TSTRING},
{NULL, 0}
@@ -100,7 +98,9 @@ static zcp_synctask_info_t zcp_synctask_destroy_info = {
.kwargs = {
{.za_name = "defer", .za_lua_type = LUA_TBOOLEAN},
{NULL, 0}
- }
+ },
+ .space_check = ZFS_SPACE_CHECK_NONE,
+ .blocks_modified = 0
};
/* ARGSUSED */
@@ -140,19 +140,19 @@ zcp_synctask_destroy(lua_State *state, boolean_t sync, nvlist_t *err_details)
return (err);
}
-static int zcp_synctask_promote(lua_State *, boolean_t, nvlist_t *err_details);
+static int zcp_synctask_promote(lua_State *, boolean_t, nvlist_t *);
static zcp_synctask_info_t zcp_synctask_promote_info = {
.name = "promote",
.func = zcp_synctask_promote,
- .space_check = ZFS_SPACE_CHECK_RESERVED,
- .blocks_modified = 3,
.pargs = {
{.za_name = "clone", .za_lua_type = LUA_TSTRING},
{NULL, 0}
},
.kwargs = {
{NULL, 0}
- }
+ },
+ .space_check = ZFS_SPACE_CHECK_RESERVED,
+ .blocks_modified = 3
};
static int
@@ -208,6 +208,58 @@ zcp_synctask_rollback(lua_State *state, boolean_t sync, nvlist_t *err_details)
return (err);
}
+static int zcp_synctask_snapshot(lua_State *, boolean_t, nvlist_t *);
+static zcp_synctask_info_t zcp_synctask_snapshot_info = {
+ .name = "snapshot",
+ .func = zcp_synctask_snapshot,
+ .pargs = {
+ {.za_name = "filesystem@snapname | volume@snapname",
+ .za_lua_type = LUA_TSTRING},
+ {NULL, 0}
+ },
+ .kwargs = {
+ {NULL, 0}
+ },
+ .space_check = ZFS_SPACE_CHECK_NORMAL,
+ .blocks_modified = 3
+};
+
+/* ARGSUSED */
+static int
+zcp_synctask_snapshot(lua_State *state, boolean_t sync, nvlist_t *err_details)
+{
+ int err;
+ dsl_dataset_snapshot_arg_t ddsa = { 0 };
+ const char *dsname = lua_tostring(state, 1);
+ zcp_run_info_t *ri = zcp_run_info(state);
+
+ /*
+ * We only allow for a single snapshot rather than a list, so the
+ * error list output is unnecessary.
+ */
+ ddsa.ddsa_errors = NULL;
+ ddsa.ddsa_props = NULL;
+ ddsa.ddsa_cr = ri->zri_cred;
+ ddsa.ddsa_snaps = fnvlist_alloc();
+ fnvlist_add_boolean(ddsa.ddsa_snaps, dsname);
+
+ /*
+ * On old pools, the ZIL must not be active when a snapshot is created,
+ * but we can't suspend the ZIL because we're already in syncing
+ * context.
+ */
+ if (spa_version(ri->zri_pool->dp_spa) < SPA_VERSION_FAST_SNAP) {
+ return (ENOTSUP);
+ }
+
+ err = zcp_sync_task(state, dsl_dataset_snapshot_check,
+ dsl_dataset_snapshot_sync, &ddsa, sync, dsname);
+
+ fnvlist_free(ddsa.ddsa_snaps);
+
+ return (err);
+}
+
void
zcp_synctask_wrapper_cleanup(void *arg)
{
@@ -279,6 +331,7 @@ zcp_load_synctask_lib(lua_State *state, boolean_t sync)
&zcp_synctask_destroy_info,
&zcp_synctask_promote_info,
&zcp_synctask_rollback_info,
+ &zcp_synctask_snapshot_info,
NULL
};
diff --git a/module/zfs/zfs_ioctl.c b/module/zfs/zfs_ioctl.c
index a8f37fe84..8b0cbb40b 100644
--- a/module/zfs/zfs_ioctl.c
+++ b/module/zfs/zfs_ioctl.c
@@ -3695,7 +3695,7 @@ zfs_ioc_channel_program(const char *poolname, nvlist_t *innvl,
if (instrlimit == 0 || instrlimit > zfs_lua_max_instrlimit)
return (EINVAL);
- if (memlimit == 0 || memlimit > ZCP_MAX_MEMLIMIT)
+ if (memlimit == 0 || memlimit > zfs_lua_max_memlimit)
return (EINVAL);
return (zcp_eval(poolname, program, instrlimit, memlimit,