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_rename_snapshot(lua_State
*, boolean_t
, nvlist_t
*);
306 static const zcp_synctask_info_t zcp_synctask_rename_snapshot_info
= {
307 .name
= "rename_snapshot",
308 .func
= zcp_synctask_rename_snapshot
,
310 {.za_name
= "filesystem | volume", .za_lua_type
= LUA_TSTRING
},
311 {.za_name
= "oldsnapname", .za_lua_type
= LUA_TSTRING
},
312 {.za_name
= "newsnapname", .za_lua_type
= LUA_TSTRING
},
315 .space_check
= ZFS_SPACE_CHECK_RESERVED
,
320 zcp_synctask_rename_snapshot(lua_State
*state
, boolean_t sync
,
321 nvlist_t
*err_details
)
325 const char *fsname
= lua_tostring(state
, 1);
326 const char *oldsnapname
= lua_tostring(state
, 2);
327 const char *newsnapname
= lua_tostring(state
, 3);
329 struct dsl_dataset_rename_snapshot_arg ddrsa
= { 0 };
330 ddrsa
.ddrsa_fsname
= fsname
;
331 ddrsa
.ddrsa_oldsnapname
= oldsnapname
;
332 ddrsa
.ddrsa_newsnapname
= newsnapname
;
333 ddrsa
.ddrsa_recursive
= B_FALSE
;
335 err
= zcp_sync_task(state
, dsl_dataset_rename_snapshot_check
,
336 dsl_dataset_rename_snapshot_sync
, &ddrsa
, sync
, NULL
);
341 static int zcp_synctask_inherit_prop(lua_State
*, boolean_t
,
342 nvlist_t
*err_details
);
343 static const zcp_synctask_info_t zcp_synctask_inherit_prop_info
= {
345 .func
= zcp_synctask_inherit_prop
,
346 .space_check
= ZFS_SPACE_CHECK_RESERVED
,
347 .blocks_modified
= 2, /* 2 * numprops */
349 { .za_name
= "dataset", .za_lua_type
= LUA_TSTRING
},
350 { .za_name
= "property", .za_lua_type
= LUA_TSTRING
},
359 zcp_synctask_inherit_prop_check(void *arg
, dmu_tx_t
*tx
)
361 zcp_inherit_prop_arg_t
*args
= arg
;
362 zfs_prop_t prop
= zfs_name_to_prop(args
->zipa_prop
);
364 if (prop
== ZPROP_USERPROP
) {
365 if (zfs_prop_user(args
->zipa_prop
))
371 if (zfs_prop_readonly(prop
))
374 if (!zfs_prop_inheritable(prop
))
377 return (dsl_props_set_check(&args
->zipa_dpsa
, tx
));
381 zcp_synctask_inherit_prop_sync(void *arg
, dmu_tx_t
*tx
)
383 zcp_inherit_prop_arg_t
*args
= arg
;
384 dsl_props_set_arg_t
*dpsa
= &args
->zipa_dpsa
;
386 dsl_props_set_sync(dpsa
, tx
);
390 zcp_synctask_inherit_prop(lua_State
*state
, boolean_t sync
,
391 nvlist_t
*err_details
)
395 zcp_inherit_prop_arg_t zipa
= { 0 };
396 dsl_props_set_arg_t
*dpsa
= &zipa
.zipa_dpsa
;
398 const char *dsname
= lua_tostring(state
, 1);
399 const char *prop
= lua_tostring(state
, 2);
401 zipa
.zipa_state
= state
;
402 zipa
.zipa_prop
= prop
;
403 dpsa
->dpsa_dsname
= dsname
;
404 dpsa
->dpsa_source
= ZPROP_SRC_INHERITED
;
405 dpsa
->dpsa_props
= fnvlist_alloc();
406 fnvlist_add_boolean(dpsa
->dpsa_props
, prop
);
408 zcp_cleanup_handler_t
*zch
= zcp_register_cleanup(state
,
409 zcp_synctask_cleanup
, dpsa
->dpsa_props
);
411 err
= zcp_sync_task(state
, zcp_synctask_inherit_prop_check
,
412 zcp_synctask_inherit_prop_sync
, &zipa
, sync
, dsname
);
414 zcp_deregister_cleanup(state
, zch
);
415 fnvlist_free(dpsa
->dpsa_props
);
420 static int zcp_synctask_bookmark(lua_State
*, boolean_t
, nvlist_t
*);
421 static const zcp_synctask_info_t zcp_synctask_bookmark_info
= {
423 .func
= zcp_synctask_bookmark
,
425 {.za_name
= "snapshot | bookmark", .za_lua_type
= LUA_TSTRING
},
426 {.za_name
= "bookmark", .za_lua_type
= LUA_TSTRING
},
432 .space_check
= ZFS_SPACE_CHECK_NORMAL
,
433 .blocks_modified
= 1,
437 zcp_synctask_bookmark(lua_State
*state
, boolean_t sync
, nvlist_t
*err_details
)
441 const char *source
= lua_tostring(state
, 1);
442 const char *new = lua_tostring(state
, 2);
444 nvlist_t
*bmarks
= fnvlist_alloc();
445 fnvlist_add_string(bmarks
, new, source
);
447 zcp_cleanup_handler_t
*zch
= zcp_register_cleanup(state
,
448 zcp_synctask_cleanup
, bmarks
);
450 dsl_bookmark_create_arg_t dbca
= {
451 .dbca_bmarks
= bmarks
,
454 err
= zcp_sync_task(state
, dsl_bookmark_create_check
,
455 dsl_bookmark_create_sync
, &dbca
, sync
, source
);
457 zcp_deregister_cleanup(state
, zch
);
458 fnvlist_free(bmarks
);
463 static int zcp_synctask_set_prop(lua_State
*, boolean_t
, nvlist_t
*err_details
);
464 static const zcp_synctask_info_t zcp_synctask_set_prop_info
= {
466 .func
= zcp_synctask_set_prop
,
467 .space_check
= ZFS_SPACE_CHECK_RESERVED
,
468 .blocks_modified
= 2,
470 { .za_name
= "dataset", .za_lua_type
= LUA_TSTRING
},
471 { .za_name
= "property", .za_lua_type
= LUA_TSTRING
},
472 { .za_name
= "value", .za_lua_type
= LUA_TSTRING
},
481 zcp_synctask_set_prop(lua_State
*state
, boolean_t sync
, nvlist_t
*err_details
)
485 zcp_set_prop_arg_t args
= { 0 };
487 const char *dsname
= lua_tostring(state
, 1);
488 const char *prop
= lua_tostring(state
, 2);
489 const char *val
= lua_tostring(state
, 3);
492 args
.dsname
= dsname
;
496 err
= zcp_sync_task(state
, zcp_set_prop_check
, zcp_set_prop_sync
,
497 &args
, sync
, dsname
);
503 zcp_synctask_wrapper(lua_State
*state
)
506 zcp_cleanup_handler_t
*zch
;
508 nvlist_t
*err_details
= fnvlist_alloc();
511 * Make sure err_details is properly freed, even if a fatal error is
512 * thrown during the synctask.
514 zch
= zcp_register_cleanup(state
, zcp_synctask_cleanup
, err_details
);
516 zcp_synctask_info_t
*info
= lua_touserdata(state
, lua_upvalueindex(1));
517 boolean_t sync
= lua_toboolean(state
, lua_upvalueindex(2));
519 zcp_run_info_t
*ri
= zcp_run_info(state
);
520 dsl_pool_t
*dp
= ri
->zri_pool
;
522 /* MOS space is triple-dittoed, so we multiply by 3. */
524 ((uint64_t)info
->blocks_modified
<< DST_AVG_BLKSHIFT
) * 3;
526 zcp_parse_args(state
, info
->name
, info
->pargs
, info
->kwargs
);
529 if (info
->space_check
!= ZFS_SPACE_CHECK_NONE
) {
530 uint64_t quota
= dsl_pool_unreserved_space(dp
,
532 uint64_t used
= dsl_dir_phys(dp
->dp_root_dir
)->dd_used_bytes
+
535 if (used
+ funcspace
> quota
) {
536 err
= SET_ERROR(ENOSPC
);
541 err
= info
->func(state
, sync
, err_details
);
545 ri
->zri_space_used
+= funcspace
;
548 lua_pushnumber(state
, (lua_Number
)err
);
549 if (fnvlist_num_pairs(err_details
) > 0) {
550 (void) zcp_nvlist_to_lua(state
, err_details
, NULL
, 0);
554 zcp_deregister_cleanup(state
, zch
);
555 fnvlist_free(err_details
);
561 zcp_load_synctask_lib(lua_State
*state
, boolean_t sync
)
563 const zcp_synctask_info_t
*zcp_synctask_funcs
[] = {
564 &zcp_synctask_destroy_info
,
565 &zcp_synctask_promote_info
,
566 &zcp_synctask_rollback_info
,
567 &zcp_synctask_snapshot_info
,
568 &zcp_synctask_rename_snapshot_info
,
569 &zcp_synctask_inherit_prop_info
,
570 &zcp_synctask_bookmark_info
,
571 &zcp_synctask_set_prop_info
,
577 for (int i
= 0; zcp_synctask_funcs
[i
] != NULL
; i
++) {
578 const zcp_synctask_info_t
*info
= zcp_synctask_funcs
[i
];
579 lua_pushlightuserdata(state
, (void *)(uintptr_t)info
);
580 lua_pushboolean(state
, sync
);
581 lua_pushcclosure(state
, &zcp_synctask_wrapper
, 2);
582 lua_setfield(state
, -2, info
->name
);