diff options
author | Chris Williamson <[email protected]> | 2018-02-08 09:24:39 -0700 |
---|---|---|
committer | Brian Behlendorf <[email protected]> | 2018-02-08 15:29:24 -0800 |
commit | 234c91c50848fa74bd72efff4e555331a25d9fe1 (patch) | |
tree | e93accbb8799995afbc2d3d3714577b1f925471c /module | |
parent | af0736898669eabe31e47405023c80b9a58e5e6c (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')
-rw-r--r-- | module/zfs/dsl_dataset.c | 11 | ||||
-rw-r--r-- | module/zfs/zcp.c | 9 | ||||
-rw-r--r-- | module/zfs/zcp_global.c | 7 | ||||
-rw-r--r-- | module/zfs/zcp_synctask.c | 71 | ||||
-rw-r--r-- | module/zfs/zfs_ioctl.c | 2 |
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, |