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.
18 * Copyright (c) 2019, 2020 by Christian Schwarz. All rights reserved.
19 * Copyright 2020 Joyent, Inc.
22 #include <sys/lua/lua.h>
23 #include <sys/lua/lauxlib.h>
26 #include <sys/zcp_set.h>
27 #include <sys/dsl_dir.h>
28 #include <sys/dsl_pool.h>
29 #include <sys/dsl_prop.h>
30 #include <sys/dsl_synctask.h>
31 #include <sys/dsl_dataset.h>
32 #include <sys/dsl_bookmark.h>
33 #include <sys/dsl_destroy.h>
34 #include <sys/dmu_objset.h>
35 #include <sys/zfs_znode.h>
36 #include <sys/zfeature.h>
37 #include <sys/metaslab.h>
39 #define DST_AVG_BLKSHIFT 14
41 typedef struct zcp_inherit_prop_arg
{
42 lua_State
*zipa_state
;
43 const char *zipa_prop
;
44 dsl_props_set_arg_t zipa_dpsa
;
45 } zcp_inherit_prop_arg_t
;
47 typedef int (zcp_synctask_func_t
)(lua_State
*, boolean_t
, nvlist_t
*);
48 typedef struct zcp_synctask_info
{
50 zcp_synctask_func_t
*func
;
51 const zcp_arg_t pargs
[4];
52 const zcp_arg_t kwargs
[2];
53 zfs_space_check_t space_check
;
55 } zcp_synctask_info_t
;
58 zcp_synctask_cleanup(void *arg
)
64 * Generic synctask interface for channel program syncfuncs.
66 * To perform some action in syncing context, we'd generally call
67 * dsl_sync_task(), but since the Lua script is already running inside a
68 * synctask we need to leave out some actions (such as acquiring the config
69 * rwlock and performing space checks).
71 * If 'sync' is false, executes a dry run and returns the error code.
73 * If we are not running in syncing context and we are not doing a dry run
74 * (meaning we are running a zfs.sync function in open-context) then we
77 * This function also handles common fatal error cases for channel program
78 * library functions. If a fatal error occurs, err_dsname will be the dataset
79 * name reported in error messages, if supplied.
82 zcp_sync_task(lua_State
*state
, dsl_checkfunc_t
*checkfunc
,
83 dsl_syncfunc_t
*syncfunc
, void *arg
, boolean_t sync
, const char *err_dsname
)
86 zcp_run_info_t
*ri
= zcp_run_info(state
);
88 err
= checkfunc(arg
, ri
->zri_tx
);
93 return (luaL_error(state
, "running functions from the zfs.sync "
94 "submodule requires passing sync=TRUE to "
95 "lzc_channel_program() (i.e. do not specify the \"-n\" "
96 "command line argument)"));
100 syncfunc(arg
, ri
->zri_tx
);
101 } else if (err
== EIO
) {
102 if (err_dsname
!= NULL
) {
103 return (luaL_error(state
,
104 "I/O error while accessing dataset '%s'",
107 return (luaL_error(state
,
108 "I/O error while accessing dataset."));
116 static int zcp_synctask_destroy(lua_State
*, boolean_t
, nvlist_t
*);
117 static const zcp_synctask_info_t zcp_synctask_destroy_info
= {
119 .func
= zcp_synctask_destroy
,
121 {.za_name
= "filesystem | snapshot", .za_lua_type
= LUA_TSTRING
},
125 {.za_name
= "defer", .za_lua_type
= LUA_TBOOLEAN
},
128 .space_check
= ZFS_SPACE_CHECK_DESTROY
,
133 zcp_synctask_destroy(lua_State
*state
, boolean_t sync
, nvlist_t
*err_details
)
137 const char *dsname
= lua_tostring(state
, 1);
139 boolean_t issnap
= (strchr(dsname
, '@') != NULL
);
141 if (!issnap
&& !lua_isnil(state
, 2)) {
142 return (luaL_error(state
,
143 "'deferred' kwarg only supported for snapshots: %s",
148 dsl_destroy_snapshot_arg_t ddsa
= { 0 };
149 ddsa
.ddsa_name
= dsname
;
150 if (!lua_isnil(state
, 2)) {
151 ddsa
.ddsa_defer
= lua_toboolean(state
, 2);
153 ddsa
.ddsa_defer
= B_FALSE
;
156 err
= zcp_sync_task(state
, dsl_destroy_snapshot_check
,
157 dsl_destroy_snapshot_sync
, &ddsa
, sync
, dsname
);
159 dsl_destroy_head_arg_t ddha
= { 0 };
160 ddha
.ddha_name
= dsname
;
162 err
= zcp_sync_task(state
, dsl_destroy_head_check
,
163 dsl_destroy_head_sync
, &ddha
, sync
, dsname
);
169 static int zcp_synctask_promote(lua_State
*, boolean_t
, nvlist_t
*);
170 static const zcp_synctask_info_t zcp_synctask_promote_info
= {
172 .func
= zcp_synctask_promote
,
174 {.za_name
= "clone", .za_lua_type
= LUA_TSTRING
},
180 .space_check
= ZFS_SPACE_CHECK_RESERVED
,
185 zcp_synctask_promote(lua_State
*state
, boolean_t sync
, nvlist_t
*err_details
)
188 dsl_dataset_promote_arg_t ddpa
= { 0 };
189 const char *dsname
= lua_tostring(state
, 1);
190 zcp_run_info_t
*ri
= zcp_run_info(state
);
192 ddpa
.ddpa_clonename
= dsname
;
193 ddpa
.err_ds
= err_details
;
194 ddpa
.cr
= ri
->zri_cred
;
195 ddpa
.proc
= ri
->zri_proc
;
198 * If there was a snapshot name conflict, then err_ds will be filled
199 * with a list of conflicting snapshot names.
201 err
= zcp_sync_task(state
, dsl_dataset_promote_check
,
202 dsl_dataset_promote_sync
, &ddpa
, sync
, dsname
);
207 static int zcp_synctask_rollback(lua_State
*, boolean_t
, nvlist_t
*err_details
);
208 static const zcp_synctask_info_t zcp_synctask_rollback_info
= {
210 .func
= zcp_synctask_rollback
,
211 .space_check
= ZFS_SPACE_CHECK_RESERVED
,
212 .blocks_modified
= 1,
214 {.za_name
= "filesystem", .za_lua_type
= LUA_TSTRING
},
223 zcp_synctask_rollback(lua_State
*state
, boolean_t sync
, nvlist_t
*err_details
)
226 const char *dsname
= lua_tostring(state
, 1);
227 dsl_dataset_rollback_arg_t ddra
= { 0 };
229 ddra
.ddra_fsname
= dsname
;
230 ddra
.ddra_result
= err_details
;
232 err
= zcp_sync_task(state
, dsl_dataset_rollback_check
,
233 dsl_dataset_rollback_sync
, &ddra
, sync
, dsname
);
238 static int zcp_synctask_snapshot(lua_State
*, boolean_t
, nvlist_t
*);
239 static const zcp_synctask_info_t zcp_synctask_snapshot_info
= {
241 .func
= zcp_synctask_snapshot
,
243 {.za_name
= "filesystem@snapname | volume@snapname",
244 .za_lua_type
= LUA_TSTRING
},
250 .space_check
= ZFS_SPACE_CHECK_NORMAL
,
255 zcp_synctask_snapshot(lua_State
*state
, boolean_t sync
, nvlist_t
*err_details
)
259 dsl_dataset_snapshot_arg_t ddsa
= { 0 };
260 const char *dsname
= lua_tostring(state
, 1);
261 zcp_run_info_t
*ri
= zcp_run_info(state
);
264 * On old pools, the ZIL must not be active when a snapshot is created,
265 * but we can't suspend the ZIL because we're already in syncing
268 if (spa_version(ri
->zri_pool
->dp_spa
) < SPA_VERSION_FAST_SNAP
) {
269 return (SET_ERROR(ENOTSUP
));
273 * We only allow for a single snapshot rather than a list, so the
274 * error list output is unnecessary.
276 ddsa
.ddsa_errors
= NULL
;
277 ddsa
.ddsa_props
= NULL
;
278 ddsa
.ddsa_cr
= ri
->zri_cred
;
279 ddsa
.ddsa_proc
= ri
->zri_proc
;
280 ddsa
.ddsa_snaps
= fnvlist_alloc();
281 fnvlist_add_boolean(ddsa
.ddsa_snaps
, dsname
);
283 zcp_cleanup_handler_t
*zch
= zcp_register_cleanup(state
,
284 zcp_synctask_cleanup
, ddsa
.ddsa_snaps
);
286 err
= zcp_sync_task(state
, dsl_dataset_snapshot_check
,
287 dsl_dataset_snapshot_sync
, &ddsa
, sync
, dsname
);
291 * We may need to create a new device minor node for this
292 * dataset (if it is a zvol and the "snapdev" property is set).
293 * Save it in the nvlist so that it can be processed in open
296 fnvlist_add_boolean(ri
->zri_new_zvols
, dsname
);
299 zcp_deregister_cleanup(state
, zch
);
300 fnvlist_free(ddsa
.ddsa_snaps
);
305 static int zcp_synctask_inherit_prop(lua_State
*, boolean_t
,
306 nvlist_t
*err_details
);
307 static const zcp_synctask_info_t zcp_synctask_inherit_prop_info
= {
309 .func
= zcp_synctask_inherit_prop
,
310 .space_check
= ZFS_SPACE_CHECK_RESERVED
,
311 .blocks_modified
= 2, /* 2 * numprops */
313 { .za_name
= "dataset", .za_lua_type
= LUA_TSTRING
},
314 { .za_name
= "property", .za_lua_type
= LUA_TSTRING
},
323 zcp_synctask_inherit_prop_check(void *arg
, dmu_tx_t
*tx
)
325 zcp_inherit_prop_arg_t
*args
= arg
;
326 zfs_prop_t prop
= zfs_name_to_prop(args
->zipa_prop
);
328 if (prop
== ZPROP_INVAL
) {
329 if (zfs_prop_user(args
->zipa_prop
))
335 if (zfs_prop_readonly(prop
))
338 if (!zfs_prop_inheritable(prop
))
341 return (dsl_props_set_check(&args
->zipa_dpsa
, tx
));
345 zcp_synctask_inherit_prop_sync(void *arg
, dmu_tx_t
*tx
)
347 zcp_inherit_prop_arg_t
*args
= arg
;
348 dsl_props_set_arg_t
*dpsa
= &args
->zipa_dpsa
;
350 dsl_props_set_sync(dpsa
, tx
);
354 zcp_synctask_inherit_prop(lua_State
*state
, boolean_t sync
,
355 nvlist_t
*err_details
)
359 zcp_inherit_prop_arg_t zipa
= { 0 };
360 dsl_props_set_arg_t
*dpsa
= &zipa
.zipa_dpsa
;
362 const char *dsname
= lua_tostring(state
, 1);
363 const char *prop
= lua_tostring(state
, 2);
365 zipa
.zipa_state
= state
;
366 zipa
.zipa_prop
= prop
;
367 dpsa
->dpsa_dsname
= dsname
;
368 dpsa
->dpsa_source
= ZPROP_SRC_INHERITED
;
369 dpsa
->dpsa_props
= fnvlist_alloc();
370 fnvlist_add_boolean(dpsa
->dpsa_props
, prop
);
372 zcp_cleanup_handler_t
*zch
= zcp_register_cleanup(state
,
373 zcp_synctask_cleanup
, dpsa
->dpsa_props
);
375 err
= zcp_sync_task(state
, zcp_synctask_inherit_prop_check
,
376 zcp_synctask_inherit_prop_sync
, &zipa
, sync
, dsname
);
378 zcp_deregister_cleanup(state
, zch
);
379 fnvlist_free(dpsa
->dpsa_props
);
384 static int zcp_synctask_bookmark(lua_State
*, boolean_t
, nvlist_t
*);
385 static const zcp_synctask_info_t zcp_synctask_bookmark_info
= {
387 .func
= zcp_synctask_bookmark
,
389 {.za_name
= "snapshot | bookmark", .za_lua_type
= LUA_TSTRING
},
390 {.za_name
= "bookmark", .za_lua_type
= LUA_TSTRING
},
396 .space_check
= ZFS_SPACE_CHECK_NORMAL
,
397 .blocks_modified
= 1,
401 zcp_synctask_bookmark(lua_State
*state
, boolean_t sync
, nvlist_t
*err_details
)
405 const char *source
= lua_tostring(state
, 1);
406 const char *new = lua_tostring(state
, 2);
408 nvlist_t
*bmarks
= fnvlist_alloc();
409 fnvlist_add_string(bmarks
, new, source
);
411 zcp_cleanup_handler_t
*zch
= zcp_register_cleanup(state
,
412 zcp_synctask_cleanup
, bmarks
);
414 dsl_bookmark_create_arg_t dbca
= {
415 .dbca_bmarks
= bmarks
,
418 err
= zcp_sync_task(state
, dsl_bookmark_create_check
,
419 dsl_bookmark_create_sync
, &dbca
, sync
, source
);
421 zcp_deregister_cleanup(state
, zch
);
422 fnvlist_free(bmarks
);
427 static int zcp_synctask_set_prop(lua_State
*, boolean_t
, nvlist_t
*err_details
);
428 static const zcp_synctask_info_t zcp_synctask_set_prop_info
= {
430 .func
= zcp_synctask_set_prop
,
431 .space_check
= ZFS_SPACE_CHECK_RESERVED
,
432 .blocks_modified
= 2,
434 { .za_name
= "dataset", .za_lua_type
= LUA_TSTRING
},
435 { .za_name
= "property", .za_lua_type
= LUA_TSTRING
},
436 { .za_name
= "value", .za_lua_type
= LUA_TSTRING
},
445 zcp_synctask_set_prop(lua_State
*state
, boolean_t sync
, nvlist_t
*err_details
)
449 zcp_set_prop_arg_t args
= { 0 };
451 const char *dsname
= lua_tostring(state
, 1);
452 const char *prop
= lua_tostring(state
, 2);
453 const char *val
= lua_tostring(state
, 3);
456 args
.dsname
= dsname
;
460 err
= zcp_sync_task(state
, zcp_set_prop_check
, zcp_set_prop_sync
,
461 &args
, sync
, dsname
);
467 zcp_synctask_wrapper(lua_State
*state
)
470 zcp_cleanup_handler_t
*zch
;
472 nvlist_t
*err_details
= fnvlist_alloc();
475 * Make sure err_details is properly freed, even if a fatal error is
476 * thrown during the synctask.
478 zch
= zcp_register_cleanup(state
, zcp_synctask_cleanup
, err_details
);
480 zcp_synctask_info_t
*info
= lua_touserdata(state
, lua_upvalueindex(1));
481 boolean_t sync
= lua_toboolean(state
, lua_upvalueindex(2));
483 zcp_run_info_t
*ri
= zcp_run_info(state
);
484 dsl_pool_t
*dp
= ri
->zri_pool
;
486 /* MOS space is triple-dittoed, so we multiply by 3. */
488 ((uint64_t)info
->blocks_modified
<< DST_AVG_BLKSHIFT
) * 3;
490 zcp_parse_args(state
, info
->name
, info
->pargs
, info
->kwargs
);
493 if (info
->space_check
!= ZFS_SPACE_CHECK_NONE
) {
494 uint64_t quota
= dsl_pool_unreserved_space(dp
,
496 uint64_t used
= dsl_dir_phys(dp
->dp_root_dir
)->dd_used_bytes
+
499 if (used
+ funcspace
> quota
) {
500 err
= SET_ERROR(ENOSPC
);
505 err
= info
->func(state
, sync
, err_details
);
509 ri
->zri_space_used
+= funcspace
;
512 lua_pushnumber(state
, (lua_Number
)err
);
513 if (fnvlist_num_pairs(err_details
) > 0) {
514 (void) zcp_nvlist_to_lua(state
, err_details
, NULL
, 0);
518 zcp_deregister_cleanup(state
, zch
);
519 fnvlist_free(err_details
);
525 zcp_load_synctask_lib(lua_State
*state
, boolean_t sync
)
527 const zcp_synctask_info_t
*zcp_synctask_funcs
[] = {
528 &zcp_synctask_destroy_info
,
529 &zcp_synctask_promote_info
,
530 &zcp_synctask_rollback_info
,
531 &zcp_synctask_snapshot_info
,
532 &zcp_synctask_inherit_prop_info
,
533 &zcp_synctask_bookmark_info
,
534 &zcp_synctask_set_prop_info
,
540 for (int i
= 0; zcp_synctask_funcs
[i
] != NULL
; i
++) {
541 const zcp_synctask_info_t
*info
= zcp_synctask_funcs
[i
];
542 lua_pushlightuserdata(state
, (void *)(uintptr_t)info
);
543 lua_pushboolean(state
, sync
);
544 lua_pushcclosure(state
, &zcp_synctask_wrapper
, 2);
545 lua_setfield(state
, -2, info
->name
);