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 * This function also handles common fatal error cases for channel program
59 * library functions. If a fatal error occurs, err_dsname will be the dataset
60 * name reported in error messages, if supplied.
63 zcp_sync_task(lua_State
*state
, dsl_checkfunc_t
*checkfunc
,
64 dsl_syncfunc_t
*syncfunc
, void *arg
, boolean_t sync
, const char *err_dsname
)
67 zcp_run_info_t
*ri
= zcp_run_info(state
);
69 err
= checkfunc(arg
, ri
->zri_tx
);
74 syncfunc(arg
, ri
->zri_tx
);
75 } else if (err
== EIO
) {
76 if (err_dsname
!= NULL
) {
77 return (luaL_error(state
,
78 "I/O error while accessing dataset '%s'",
81 return (luaL_error(state
,
82 "I/O error while accessing dataset."));
90 static int zcp_synctask_destroy(lua_State
*, boolean_t
, nvlist_t
*);
91 static zcp_synctask_info_t zcp_synctask_destroy_info
= {
93 .func
= zcp_synctask_destroy
,
95 {.za_name
= "filesystem | snapshot", .za_lua_type
= LUA_TSTRING
},
99 {.za_name
= "defer", .za_lua_type
= LUA_TBOOLEAN
},
102 .space_check
= ZFS_SPACE_CHECK_NONE
,
108 zcp_synctask_destroy(lua_State
*state
, boolean_t sync
, nvlist_t
*err_details
)
111 const char *dsname
= lua_tostring(state
, 1);
113 boolean_t issnap
= (strchr(dsname
, '@') != NULL
);
115 if (!issnap
&& !lua_isnil(state
, 2)) {
116 return (luaL_error(state
,
117 "'deferred' kwarg only supported for snapshots: %s",
122 dsl_destroy_snapshot_arg_t ddsa
= { 0 };
123 ddsa
.ddsa_name
= dsname
;
124 if (!lua_isnil(state
, 2)) {
125 ddsa
.ddsa_defer
= lua_toboolean(state
, 2);
127 ddsa
.ddsa_defer
= B_FALSE
;
130 err
= zcp_sync_task(state
, dsl_destroy_snapshot_check
,
131 dsl_destroy_snapshot_sync
, &ddsa
, sync
, dsname
);
133 dsl_destroy_head_arg_t ddha
= { 0 };
134 ddha
.ddha_name
= dsname
;
136 err
= zcp_sync_task(state
, dsl_destroy_head_check
,
137 dsl_destroy_head_sync
, &ddha
, sync
, dsname
);
143 static int zcp_synctask_promote(lua_State
*, boolean_t
, nvlist_t
*);
144 static zcp_synctask_info_t zcp_synctask_promote_info
= {
146 .func
= zcp_synctask_promote
,
148 {.za_name
= "clone", .za_lua_type
= LUA_TSTRING
},
154 .space_check
= ZFS_SPACE_CHECK_RESERVED
,
159 zcp_synctask_promote(lua_State
*state
, boolean_t sync
, nvlist_t
*err_details
)
162 dsl_dataset_promote_arg_t ddpa
= { 0 };
163 const char *dsname
= lua_tostring(state
, 1);
164 zcp_run_info_t
*ri
= zcp_run_info(state
);
166 ddpa
.ddpa_clonename
= dsname
;
167 ddpa
.err_ds
= err_details
;
168 ddpa
.cr
= ri
->zri_cred
;
171 * If there was a snapshot name conflict, then err_ds will be filled
172 * with a list of conflicting snapshot names.
174 err
= zcp_sync_task(state
, dsl_dataset_promote_check
,
175 dsl_dataset_promote_sync
, &ddpa
, sync
, dsname
);
180 static int zcp_synctask_rollback(lua_State
*, boolean_t
, nvlist_t
*err_details
);
181 static zcp_synctask_info_t zcp_synctask_rollback_info
= {
183 .func
= zcp_synctask_rollback
,
184 .space_check
= ZFS_SPACE_CHECK_RESERVED
,
185 .blocks_modified
= 1,
187 {.za_name
= "filesystem", .za_lua_type
= LUA_TSTRING
},
196 zcp_synctask_rollback(lua_State
*state
, boolean_t sync
, nvlist_t
*err_details
)
199 const char *dsname
= lua_tostring(state
, 1);
200 dsl_dataset_rollback_arg_t ddra
= { 0 };
202 ddra
.ddra_fsname
= dsname
;
203 ddra
.ddra_result
= err_details
;
205 err
= zcp_sync_task(state
, dsl_dataset_rollback_check
,
206 dsl_dataset_rollback_sync
, &ddra
, sync
, dsname
);
211 static int zcp_synctask_snapshot(lua_State
*, boolean_t
, nvlist_t
*);
212 static zcp_synctask_info_t zcp_synctask_snapshot_info
= {
214 .func
= zcp_synctask_snapshot
,
216 {.za_name
= "filesystem@snapname | volume@snapname",
217 .za_lua_type
= LUA_TSTRING
},
223 .space_check
= ZFS_SPACE_CHECK_NORMAL
,
229 zcp_synctask_snapshot(lua_State
*state
, boolean_t sync
, nvlist_t
*err_details
)
232 dsl_dataset_snapshot_arg_t ddsa
= { 0 };
233 const char *dsname
= lua_tostring(state
, 1);
234 zcp_run_info_t
*ri
= zcp_run_info(state
);
237 * We only allow for a single snapshot rather than a list, so the
238 * error list output is unnecessary.
240 ddsa
.ddsa_errors
= NULL
;
241 ddsa
.ddsa_props
= NULL
;
242 ddsa
.ddsa_cr
= ri
->zri_cred
;
243 ddsa
.ddsa_snaps
= fnvlist_alloc();
244 fnvlist_add_boolean(ddsa
.ddsa_snaps
, dsname
);
247 * On old pools, the ZIL must not be active when a snapshot is created,
248 * but we can't suspend the ZIL because we're already in syncing
251 if (spa_version(ri
->zri_pool
->dp_spa
) < SPA_VERSION_FAST_SNAP
) {
255 err
= zcp_sync_task(state
, dsl_dataset_snapshot_check
,
256 dsl_dataset_snapshot_sync
, &ddsa
, sync
, dsname
);
258 fnvlist_free(ddsa
.ddsa_snaps
);
264 zcp_synctask_wrapper_cleanup(void *arg
)
270 zcp_synctask_wrapper(lua_State
*state
)
274 nvlist_t
*err_details
= fnvlist_alloc();
277 * Make sure err_details is properly freed, even if a fatal error is
278 * thrown during the synctask.
280 zcp_register_cleanup(state
, &zcp_synctask_wrapper_cleanup
, err_details
);
282 zcp_synctask_info_t
*info
= lua_touserdata(state
, lua_upvalueindex(1));
283 boolean_t sync
= lua_toboolean(state
, lua_upvalueindex(2));
285 zcp_run_info_t
*ri
= zcp_run_info(state
);
286 dsl_pool_t
*dp
= ri
->zri_pool
;
288 /* MOS space is triple-dittoed, so we multiply by 3. */
289 uint64_t funcspace
= (info
->blocks_modified
<< DST_AVG_BLKSHIFT
) * 3;
291 zcp_parse_args(state
, info
->name
, info
->pargs
, info
->kwargs
);
294 if (info
->space_check
!= ZFS_SPACE_CHECK_NONE
&& funcspace
> 0) {
295 uint64_t quota
= dsl_pool_adjustedsize(dp
,
296 info
->space_check
== ZFS_SPACE_CHECK_RESERVED
) -
297 metaslab_class_get_deferred(spa_normal_class(dp
->dp_spa
));
298 uint64_t used
= dsl_dir_phys(dp
->dp_root_dir
)->dd_used_bytes
+
301 if (used
+ funcspace
> quota
) {
302 err
= SET_ERROR(ENOSPC
);
307 err
= info
->func(state
, sync
, err_details
);
311 ri
->zri_space_used
+= funcspace
;
314 lua_pushnumber(state
, (lua_Number
)err
);
315 if (fnvlist_num_pairs(err_details
) > 0) {
316 (void) zcp_nvlist_to_lua(state
, err_details
, NULL
, 0);
320 zcp_clear_cleanup(state
);
321 fnvlist_free(err_details
);
327 zcp_load_synctask_lib(lua_State
*state
, boolean_t sync
)
330 zcp_synctask_info_t
*zcp_synctask_funcs
[] = {
331 &zcp_synctask_destroy_info
,
332 &zcp_synctask_promote_info
,
333 &zcp_synctask_rollback_info
,
334 &zcp_synctask_snapshot_info
,
340 for (i
= 0; zcp_synctask_funcs
[i
] != NULL
; i
++) {
341 zcp_synctask_info_t
*info
= zcp_synctask_funcs
[i
];
342 lua_pushlightuserdata(state
, info
);
343 lua_pushboolean(state
, sync
);
344 lua_pushcclosure(state
, &zcp_synctask_wrapper
, 2);
345 lua_setfield(state
, -2, info
->name
);