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
+2 -9
View File
@@ -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;
+6 -3
View File
@@ -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.
+6 -1
View File
@@ -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}
};
+62 -9
View File
@@ -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
};
+1 -1
View File
@@ -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,