4 * This file and its contents are supplied under the terms of the
5 * Common Development and Distribution License ("CDDL"), version 1.0.
6 * You may only use this file in accordance with the terms of version
9 * A full copy of the text of the CDDL should have accompanied this
10 * source. A copy of the CDDL is also available via the Internet at
11 * http://www.illumos.org/license/CDDL.
17 * Copyright (c) 2016, 2017 by Delphix. All rights reserved.
24 #include <sys/dsl_dir.h>
25 #include <sys/dsl_pool.h>
26 #include <sys/dsl_prop.h>
27 #include <sys/dsl_synctask.h>
28 #include <sys/dsl_dataset.h>
29 #include <sys/dsl_bookmark.h>
30 #include <sys/dsl_destroy.h>
31 #include <sys/dmu_objset.h>
32 #include <sys/zfs_znode.h>
33 #include <sys/zfeature.h>
34 #include <sys/metaslab.h>
36 #define DST_AVG_BLKSHIFT 14
38 typedef int (zcp_synctask_func_t
)(lua_State
*, boolean_t
, nvlist_t
*);
39 typedef struct zcp_synctask_info
{
41 zcp_synctask_func_t
*func
;
42 const zcp_arg_t pargs
[4];
43 const zcp_arg_t kwargs
[2];
44 zfs_space_check_t space_check
;
46 } zcp_synctask_info_t
;
49 * Generic synctask interface for channel program syncfuncs.
51 * To perform some action in syncing context, we'd generally call
52 * dsl_sync_task(), but since the Lua script is already running inside a
53 * synctask we need to leave out some actions (such as acquiring the config
54 * rwlock and performing space checks).
56 * If 'sync' is false, executes a dry run and returns the error code.
58 * If we are not running in syncing context and we are not doing a dry run
59 * (meaning we are running a zfs.sync function in open-context) then we
62 * This function also handles common fatal error cases for channel program
63 * library functions. If a fatal error occurs, err_dsname will be the dataset
64 * name reported in error messages, if supplied.
67 zcp_sync_task(lua_State
*state
, dsl_checkfunc_t
*checkfunc
,
68 dsl_syncfunc_t
*syncfunc
, void *arg
, boolean_t sync
, const char *err_dsname
)
71 zcp_run_info_t
*ri
= zcp_run_info(state
);
73 err
= checkfunc(arg
, ri
->zri_tx
);
78 return (luaL_error(state
, "running functions from the zfs.sync "
79 "submodule requires passing sync=TRUE to "
80 "lzc_channel_program() (i.e. do not specify the \"-n\" "
81 "command line argument)"));
85 syncfunc(arg
, ri
->zri_tx
);
86 } else if (err
== EIO
) {
87 if (err_dsname
!= NULL
) {
88 return (luaL_error(state
,
89 "I/O error while accessing dataset '%s'",
92 return (luaL_error(state
,
93 "I/O error while accessing dataset."));
101 static int zcp_synctask_destroy(lua_State
*, boolean_t
, nvlist_t
*);
102 static zcp_synctask_info_t zcp_synctask_destroy_info
= {
104 .func
= zcp_synctask_destroy
,
106 {.za_name
= "filesystem | snapshot", .za_lua_type
= LUA_TSTRING
},
110 {.za_name
= "defer", .za_lua_type
= LUA_TBOOLEAN
},
113 .space_check
= ZFS_SPACE_CHECK_NONE
,
119 zcp_synctask_destroy(lua_State
*state
, boolean_t sync
, nvlist_t
*err_details
)
122 const char *dsname
= lua_tostring(state
, 1);
124 boolean_t issnap
= (strchr(dsname
, '@') != NULL
);
126 if (!issnap
&& !lua_isnil(state
, 2)) {
127 return (luaL_error(state
,
128 "'deferred' kwarg only supported for snapshots: %s",
133 dsl_destroy_snapshot_arg_t ddsa
= { 0 };
134 ddsa
.ddsa_name
= dsname
;
135 if (!lua_isnil(state
, 2)) {
136 ddsa
.ddsa_defer
= lua_toboolean(state
, 2);
138 ddsa
.ddsa_defer
= B_FALSE
;
141 err
= zcp_sync_task(state
, dsl_destroy_snapshot_check
,
142 dsl_destroy_snapshot_sync
, &ddsa
, sync
, dsname
);
144 dsl_destroy_head_arg_t ddha
= { 0 };
145 ddha
.ddha_name
= dsname
;
147 err
= zcp_sync_task(state
, dsl_destroy_head_check
,
148 dsl_destroy_head_sync
, &ddha
, sync
, dsname
);
154 static int zcp_synctask_promote(lua_State
*, boolean_t
, nvlist_t
*);
155 static zcp_synctask_info_t zcp_synctask_promote_info
= {
157 .func
= zcp_synctask_promote
,
159 {.za_name
= "clone", .za_lua_type
= LUA_TSTRING
},
165 .space_check
= ZFS_SPACE_CHECK_RESERVED
,
170 zcp_synctask_promote(lua_State
*state
, boolean_t sync
, nvlist_t
*err_details
)
173 dsl_dataset_promote_arg_t ddpa
= { 0 };
174 const char *dsname
= lua_tostring(state
, 1);
175 zcp_run_info_t
*ri
= zcp_run_info(state
);
177 ddpa
.ddpa_clonename
= dsname
;
178 ddpa
.err_ds
= err_details
;
179 ddpa
.cr
= ri
->zri_cred
;
182 * If there was a snapshot name conflict, then err_ds will be filled
183 * with a list of conflicting snapshot names.
185 err
= zcp_sync_task(state
, dsl_dataset_promote_check
,
186 dsl_dataset_promote_sync
, &ddpa
, sync
, dsname
);
191 static int zcp_synctask_rollback(lua_State
*, boolean_t
, nvlist_t
*err_details
);
192 static zcp_synctask_info_t zcp_synctask_rollback_info
= {
194 .func
= zcp_synctask_rollback
,
195 .space_check
= ZFS_SPACE_CHECK_RESERVED
,
196 .blocks_modified
= 1,
198 {.za_name
= "filesystem", .za_lua_type
= LUA_TSTRING
},
207 zcp_synctask_rollback(lua_State
*state
, boolean_t sync
, nvlist_t
*err_details
)
210 const char *dsname
= lua_tostring(state
, 1);
211 dsl_dataset_rollback_arg_t ddra
= { 0 };
213 ddra
.ddra_fsname
= dsname
;
214 ddra
.ddra_result
= err_details
;
216 err
= zcp_sync_task(state
, dsl_dataset_rollback_check
,
217 dsl_dataset_rollback_sync
, &ddra
, sync
, dsname
);
222 static int zcp_synctask_snapshot(lua_State
*, boolean_t
, nvlist_t
*);
223 static zcp_synctask_info_t zcp_synctask_snapshot_info
= {
225 .func
= zcp_synctask_snapshot
,
227 {.za_name
= "filesystem@snapname | volume@snapname",
228 .za_lua_type
= LUA_TSTRING
},
234 .space_check
= ZFS_SPACE_CHECK_NORMAL
,
240 zcp_synctask_snapshot(lua_State
*state
, boolean_t sync
, nvlist_t
*err_details
)
243 dsl_dataset_snapshot_arg_t ddsa
= { 0 };
244 const char *dsname
= lua_tostring(state
, 1);
245 zcp_run_info_t
*ri
= zcp_run_info(state
);
248 * On old pools, the ZIL must not be active when a snapshot is created,
249 * but we can't suspend the ZIL because we're already in syncing
252 if (spa_version(ri
->zri_pool
->dp_spa
) < SPA_VERSION_FAST_SNAP
) {
257 * We only allow for a single snapshot rather than a list, so the
258 * error list output is unnecessary.
260 ddsa
.ddsa_errors
= NULL
;
261 ddsa
.ddsa_props
= NULL
;
262 ddsa
.ddsa_cr
= ri
->zri_cred
;
263 ddsa
.ddsa_snaps
= fnvlist_alloc();
264 fnvlist_add_boolean(ddsa
.ddsa_snaps
, dsname
);
266 zcp_cleanup_handler_t
*zch
= zcp_register_cleanup(state
,
267 (zcp_cleanup_t
*)&fnvlist_free
, ddsa
.ddsa_snaps
);
269 err
= zcp_sync_task(state
, dsl_dataset_snapshot_check
,
270 dsl_dataset_snapshot_sync
, &ddsa
, sync
, dsname
);
272 zcp_deregister_cleanup(state
, zch
);
273 fnvlist_free(ddsa
.ddsa_snaps
);
279 zcp_synctask_wrapper(lua_State
*state
)
282 zcp_cleanup_handler_t
*zch
;
284 nvlist_t
*err_details
= fnvlist_alloc();
287 * Make sure err_details is properly freed, even if a fatal error is
288 * thrown during the synctask.
290 zch
= zcp_register_cleanup(state
,
291 (zcp_cleanup_t
*)&fnvlist_free
, err_details
);
293 zcp_synctask_info_t
*info
= lua_touserdata(state
, lua_upvalueindex(1));
294 boolean_t sync
= lua_toboolean(state
, lua_upvalueindex(2));
296 zcp_run_info_t
*ri
= zcp_run_info(state
);
297 dsl_pool_t
*dp
= ri
->zri_pool
;
299 /* MOS space is triple-dittoed, so we multiply by 3. */
300 uint64_t funcspace
= (info
->blocks_modified
<< DST_AVG_BLKSHIFT
) * 3;
302 zcp_parse_args(state
, info
->name
, info
->pargs
, info
->kwargs
);
305 if (info
->space_check
!= ZFS_SPACE_CHECK_NONE
&& funcspace
> 0) {
306 uint64_t quota
= dsl_pool_adjustedsize(dp
,
307 info
->space_check
== ZFS_SPACE_CHECK_RESERVED
) -
308 metaslab_class_get_deferred(spa_normal_class(dp
->dp_spa
));
309 uint64_t used
= dsl_dir_phys(dp
->dp_root_dir
)->dd_used_bytes
+
312 if (used
+ funcspace
> quota
) {
313 err
= SET_ERROR(ENOSPC
);
318 err
= info
->func(state
, sync
, err_details
);
322 ri
->zri_space_used
+= funcspace
;
325 lua_pushnumber(state
, (lua_Number
)err
);
326 if (fnvlist_num_pairs(err_details
) > 0) {
327 (void) zcp_nvlist_to_lua(state
, err_details
, NULL
, 0);
331 zcp_deregister_cleanup(state
, zch
);
332 fnvlist_free(err_details
);
338 zcp_load_synctask_lib(lua_State
*state
, boolean_t sync
)
341 zcp_synctask_info_t
*zcp_synctask_funcs
[] = {
342 &zcp_synctask_destroy_info
,
343 &zcp_synctask_promote_info
,
344 &zcp_synctask_rollback_info
,
345 &zcp_synctask_snapshot_info
,
351 for (i
= 0; zcp_synctask_funcs
[i
] != NULL
; i
++) {
352 zcp_synctask_info_t
*info
= zcp_synctask_funcs
[i
];
353 lua_pushlightuserdata(state
, info
);
354 lua_pushboolean(state
, sync
);
355 lua_pushcclosure(state
, &zcp_synctask_wrapper
, 2);
356 lua_setfield(state
, -2, info
->name
);