1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
23 * Copyright (c) 2012, 2016 by Delphix. All rights reserved.
24 * Copyright (c) 2013 Steven Hartland. All rights reserved.
25 * Copyright (c) 2013 by Joyent, Inc. All rights reserved.
26 * Copyright (c) 2014 Integros [integros.com]
27 * Copyright 2016 Nexenta Systems, Inc. All rights reserved.
28 */
29
30 #include <sys/autosnap.h>
31 #include <sys/zfs_context.h>
32 #include <sys/dsl_userhold.h>
33 #include <sys/dsl_dataset.h>
34 #include <sys/dsl_synctask.h>
35 #include <sys/dsl_destroy.h>
36 #include <sys/dmu_tx.h>
37 #include <sys/dsl_pool.h>
38 #include <sys/dsl_dir.h>
39 #include <sys/dmu_traverse.h>
40 #include <sys/dsl_scan.h>
41 #include <sys/dmu_objset.h>
42 #include <sys/zap.h>
43 #include <sys/zfeature.h>
44 #include <sys/zfs_ioctl.h>
45 #include <sys/dsl_deleg.h>
46 #include <sys/dmu_impl.h>
47 #include <sys/wbc.h>
48 #include <sys/zcp.h>
49
50 int
51 dsl_destroy_snapshot_check_impl(dsl_dataset_t *ds, boolean_t defer)
52 {
53 if (!ds->ds_is_snapshot)
54 return (SET_ERROR(EINVAL));
55
56 if (dsl_dataset_long_held(ds))
57 return (SET_ERROR(EBUSY));
58
59 /*
60 * Only allow deferred destroy on pools that support it.
61 * NOTE: deferred destroy is only supported on snapshots.
62 */
63 if (defer) {
64 if (spa_version(ds->ds_dir->dd_pool->dp_spa) <
65 SPA_VERSION_USERREFS)
66 return (SET_ERROR(ENOTSUP));
67 return (0);
68 }
69
70 /*
71 * If this snapshot has an elevated user reference count,
72 * we can't destroy it yet.
73 */
74 if (ds->ds_userrefs > 0)
75 return (SET_ERROR(EBUSY));
76
77 /*
78 * Can't delete a branch point.
79 */
80 if (dsl_dataset_phys(ds)->ds_num_children > 1)
81 return (SET_ERROR(EEXIST));
82
83 return (0);
84 }
85
86 int
87 dsl_destroy_snapshot_check(void *arg, dmu_tx_t *tx)
88 {
89 dsl_destroy_snapshot_arg_t *ddsa = arg;
90 const char *dsname = ddsa->ddsa_name;
91 boolean_t defer = ddsa->ddsa_defer;
92
93 dsl_pool_t *dp = dmu_tx_pool(tx);
94 int error = 0;
95 dsl_dataset_t *ds;
96
97 error = dsl_dataset_hold(dp, dsname, FTAG, &ds);
98
99 /*
100 * If the snapshot does not exist, silently ignore it, and
101 * dsl_destroy_snapshot_sync() will be a no-op
102 * (it's "already destroyed").
103 */
104 if (error == ENOENT)
105 return (0);
106
107 if (error == 0) {
108 error = dsl_destroy_snapshot_check_impl(ds, defer);
109 dsl_dataset_rele(ds, FTAG);
110 }
111
112 return (error);
113 }
114
115 struct process_old_arg {
116 dsl_dataset_t *ds;
117 dsl_dataset_t *ds_prev;
118 boolean_t after_branch_point;
119 zio_t *pio;
120 uint64_t used, comp, uncomp;
121 };
122
123 static int
124 process_old_cb(void *arg, const blkptr_t *bp, dmu_tx_t *tx)
125 {
126 struct process_old_arg *poa = arg;
127 dsl_pool_t *dp = poa->ds->ds_dir->dd_pool;
128
129 ASSERT(!BP_IS_HOLE(bp));
130
131 if (bp->blk_birth <= dsl_dataset_phys(poa->ds)->ds_prev_snap_txg) {
132 dsl_deadlist_insert(&poa->ds->ds_deadlist, bp, tx);
133 if (poa->ds_prev && !poa->after_branch_point &&
134 bp->blk_birth >
135 dsl_dataset_phys(poa->ds_prev)->ds_prev_snap_txg) {
136 dsl_dataset_phys(poa->ds_prev)->ds_unique_bytes +=
137 bp_get_dsize_sync(dp->dp_spa, bp);
138 }
139 } else {
140 poa->used += bp_get_dsize_sync(dp->dp_spa, bp);
141 poa->comp += BP_GET_PSIZE(bp);
142 poa->uncomp += BP_GET_UCSIZE(bp);
143 dsl_free_sync(poa->pio, dp, tx->tx_txg, bp);
144 }
145 return (0);
146 }
147
148 static void
149 process_old_deadlist(dsl_dataset_t *ds, dsl_dataset_t *ds_prev,
150 dsl_dataset_t *ds_next, boolean_t after_branch_point, dmu_tx_t *tx)
151 {
152 struct process_old_arg poa = { 0 };
153 dsl_pool_t *dp = ds->ds_dir->dd_pool;
154 objset_t *mos = dp->dp_meta_objset;
155 uint64_t deadlist_obj;
156
157 ASSERT(ds->ds_deadlist.dl_oldfmt);
158 ASSERT(ds_next->ds_deadlist.dl_oldfmt);
159
160 poa.ds = ds;
161 poa.ds_prev = ds_prev;
162 poa.after_branch_point = after_branch_point;
163 poa.pio = zio_root(dp->dp_spa, NULL, NULL, ZIO_FLAG_MUSTSUCCEED);
164 VERIFY0(bpobj_iterate(&ds_next->ds_deadlist.dl_bpobj,
165 process_old_cb, &poa, tx));
166 VERIFY0(zio_wait(poa.pio));
167 ASSERT3U(poa.used, ==, dsl_dataset_phys(ds)->ds_unique_bytes);
168
169 /* change snapused */
170 dsl_dir_diduse_space(ds->ds_dir, DD_USED_SNAP,
171 -poa.used, -poa.comp, -poa.uncomp, tx);
172
173 /* swap next's deadlist to our deadlist */
174 dsl_deadlist_close(&ds->ds_deadlist);
175 dsl_deadlist_close(&ds_next->ds_deadlist);
176 deadlist_obj = dsl_dataset_phys(ds)->ds_deadlist_obj;
177 dsl_dataset_phys(ds)->ds_deadlist_obj =
178 dsl_dataset_phys(ds_next)->ds_deadlist_obj;
179 dsl_dataset_phys(ds_next)->ds_deadlist_obj = deadlist_obj;
180 dsl_deadlist_open(&ds->ds_deadlist, mos,
181 dsl_dataset_phys(ds)->ds_deadlist_obj);
182 dsl_deadlist_open(&ds_next->ds_deadlist, mos,
183 dsl_dataset_phys(ds_next)->ds_deadlist_obj);
184 }
185
186 static void
187 dsl_dataset_remove_clones_key(dsl_dataset_t *ds, uint64_t mintxg, dmu_tx_t *tx)
188 {
189 objset_t *mos = ds->ds_dir->dd_pool->dp_meta_objset;
190 zap_cursor_t *zc;
191 zap_attribute_t *za;
192
193 /*
194 * If it is the old version, dd_clones doesn't exist so we can't
195 * find the clones, but dsl_deadlist_remove_key() is a no-op so it
196 * doesn't matter.
197 */
198 if (dsl_dir_phys(ds->ds_dir)->dd_clones == 0)
199 return;
200 zc = kmem_alloc(sizeof (zap_cursor_t), KM_SLEEP);
201 za = kmem_alloc(sizeof (zap_attribute_t), KM_SLEEP);
202
203 for (zap_cursor_init(zc, mos, dsl_dir_phys(ds->ds_dir)->dd_clones);
204 zap_cursor_retrieve(zc, za) == 0;
205 zap_cursor_advance(zc)) {
206 dsl_dataset_t *clone;
207
208 VERIFY0(dsl_dataset_hold_obj(ds->ds_dir->dd_pool,
209 za->za_first_integer, FTAG, &clone));
210 if (clone->ds_dir->dd_origin_txg > mintxg) {
211 dsl_deadlist_remove_key(&clone->ds_deadlist,
212 mintxg, tx);
213 dsl_dataset_remove_clones_key(clone, mintxg, tx);
214 }
215 dsl_dataset_rele(clone, FTAG);
216 }
217 zap_cursor_fini(zc);
218 kmem_free(zc, sizeof (zap_cursor_t));
219 kmem_free(za, sizeof (zap_attribute_t));
220 }
221
222 void
223 dsl_destroy_snapshot_sync_impl(dsl_dataset_t *ds, boolean_t defer, dmu_tx_t *tx)
224 {
225 int err;
226 int after_branch_point = FALSE;
227 dsl_pool_t *dp = ds->ds_dir->dd_pool;
228 spa_t *spa = dp->dp_spa;
229 wbc_data_t *wbc_data = spa_get_wbc_data(spa);
230 objset_t *mos = dp->dp_meta_objset;
231 dsl_dataset_t *ds_prev = NULL;
232 uint64_t obj;
233
234 ASSERT(RRW_WRITE_HELD(&dp->dp_config_rwlock));
235 rrw_enter(&ds->ds_bp_rwlock, RW_READER, FTAG);
236 ASSERT3U(dsl_dataset_phys(ds)->ds_bp.blk_birth, <=, tx->tx_txg);
237 rrw_exit(&ds->ds_bp_rwlock, FTAG);
238 ASSERT(refcount_is_zero(&ds->ds_longholds));
239
240 /*
241 * if an edge snapshot of WBC window is destroyed, the window must be
242 * aborted
243 */
244 mutex_enter(&wbc_data->wbc_lock);
245 if (dsl_dataset_phys(ds)->ds_creation_txg == wbc_data->wbc_finish_txg)
246 wbc_purge_window(spa, tx);
247 mutex_exit(&wbc_data->wbc_lock);
248
249 if (defer &&
250 (ds->ds_userrefs > 0 ||
251 dsl_dataset_phys(ds)->ds_num_children > 1)) {
252 ASSERT(spa_version(dp->dp_spa) >= SPA_VERSION_USERREFS);
253 dmu_buf_will_dirty(ds->ds_dbuf, tx);
254 dsl_dataset_phys(ds)->ds_flags |= DS_FLAG_DEFER_DESTROY;
255 spa_history_log_internal_ds(ds, "defer_destroy", tx, "");
256 return;
257 }
258
259 ASSERT3U(dsl_dataset_phys(ds)->ds_num_children, <=, 1);
260
261 /* We need to log before removing it from the namespace. */
262 spa_history_log_internal_ds(ds, "destroy", tx, "");
263
264 dsl_scan_ds_destroyed(ds, tx);
265
266 obj = ds->ds_object;
267
268 for (spa_feature_t f = 0; f < SPA_FEATURES; f++) {
269 if (ds->ds_feature_inuse[f]) {
270 dsl_dataset_deactivate_feature(obj, f, tx);
271 ds->ds_feature_inuse[f] = B_FALSE;
272 }
273 }
274 if (dsl_dataset_phys(ds)->ds_prev_snap_obj != 0) {
275 ASSERT3P(ds->ds_prev, ==, NULL);
276 VERIFY0(dsl_dataset_hold_obj(dp,
277 dsl_dataset_phys(ds)->ds_prev_snap_obj, FTAG, &ds_prev));
278 after_branch_point =
279 (dsl_dataset_phys(ds_prev)->ds_next_snap_obj != obj);
280
281 dmu_buf_will_dirty(ds_prev->ds_dbuf, tx);
282 if (after_branch_point &&
283 dsl_dataset_phys(ds_prev)->ds_next_clones_obj != 0) {
284 dsl_dataset_remove_from_next_clones(ds_prev, obj, tx);
285 if (dsl_dataset_phys(ds)->ds_next_snap_obj != 0) {
286 VERIFY0(zap_add_int(mos,
287 dsl_dataset_phys(ds_prev)->
288 ds_next_clones_obj,
289 dsl_dataset_phys(ds)->ds_next_snap_obj,
290 tx));
291 }
292 }
293 if (!after_branch_point) {
294 dsl_dataset_phys(ds_prev)->ds_next_snap_obj =
295 dsl_dataset_phys(ds)->ds_next_snap_obj;
296 }
297 }
298
299 dsl_dataset_t *ds_next;
300 uint64_t old_unique;
301 uint64_t used = 0, comp = 0, uncomp = 0;
302
303 VERIFY0(dsl_dataset_hold_obj(dp,
304 dsl_dataset_phys(ds)->ds_next_snap_obj, FTAG, &ds_next));
305 ASSERT3U(dsl_dataset_phys(ds_next)->ds_prev_snap_obj, ==, obj);
306
307 old_unique = dsl_dataset_phys(ds_next)->ds_unique_bytes;
308
309 dmu_buf_will_dirty(ds_next->ds_dbuf, tx);
310 dsl_dataset_phys(ds_next)->ds_prev_snap_obj =
311 dsl_dataset_phys(ds)->ds_prev_snap_obj;
312 dsl_dataset_phys(ds_next)->ds_prev_snap_txg =
313 dsl_dataset_phys(ds)->ds_prev_snap_txg;
314 ASSERT3U(dsl_dataset_phys(ds)->ds_prev_snap_txg, ==,
315 ds_prev ? dsl_dataset_phys(ds_prev)->ds_creation_txg : 0);
316
317 if (ds_next->ds_deadlist.dl_oldfmt) {
318 process_old_deadlist(ds, ds_prev, ds_next,
319 after_branch_point, tx);
320 } else {
321 /* Adjust prev's unique space. */
322 if (ds_prev && !after_branch_point) {
323 dsl_deadlist_space_range(&ds_next->ds_deadlist,
324 dsl_dataset_phys(ds_prev)->ds_prev_snap_txg,
325 dsl_dataset_phys(ds)->ds_prev_snap_txg,
326 &used, &comp, &uncomp);
327 dsl_dataset_phys(ds_prev)->ds_unique_bytes += used;
328 }
329
330 /* Adjust snapused. */
331 dsl_deadlist_space_range(&ds_next->ds_deadlist,
332 dsl_dataset_phys(ds)->ds_prev_snap_txg, UINT64_MAX,
333 &used, &comp, &uncomp);
334 dsl_dir_diduse_space(ds->ds_dir, DD_USED_SNAP,
335 -used, -comp, -uncomp, tx);
336
337 /* Move blocks to be freed to pool's free list. */
338 dsl_deadlist_move_bpobj(&ds_next->ds_deadlist,
339 &dp->dp_free_bpobj, dsl_dataset_phys(ds)->ds_prev_snap_txg,
340 tx);
341 dsl_dir_diduse_space(tx->tx_pool->dp_free_dir,
342 DD_USED_HEAD, used, comp, uncomp, tx);
343
344 /* Merge our deadlist into next's and free it. */
345 dsl_deadlist_merge(&ds_next->ds_deadlist,
346 dsl_dataset_phys(ds)->ds_deadlist_obj, tx);
347 }
348 dsl_deadlist_close(&ds->ds_deadlist);
349 dsl_deadlist_free(mos, dsl_dataset_phys(ds)->ds_deadlist_obj, tx);
350 dmu_buf_will_dirty(ds->ds_dbuf, tx);
351 dsl_dataset_phys(ds)->ds_deadlist_obj = 0;
352
353 /* Collapse range in clone heads */
354 dsl_dataset_remove_clones_key(ds,
355 dsl_dataset_phys(ds)->ds_creation_txg, tx);
356
357 if (ds_next->ds_is_snapshot) {
358 dsl_dataset_t *ds_nextnext;
359
360 /*
361 * Update next's unique to include blocks which
362 * were previously shared by only this snapshot
363 * and it. Those blocks will be born after the
364 * prev snap and before this snap, and will have
365 * died after the next snap and before the one
366 * after that (ie. be on the snap after next's
367 * deadlist).
368 */
369 VERIFY0(dsl_dataset_hold_obj(dp,
370 dsl_dataset_phys(ds_next)->ds_next_snap_obj,
371 FTAG, &ds_nextnext));
372 dsl_deadlist_space_range(&ds_nextnext->ds_deadlist,
373 dsl_dataset_phys(ds)->ds_prev_snap_txg,
374 dsl_dataset_phys(ds)->ds_creation_txg,
375 &used, &comp, &uncomp);
376 dsl_dataset_phys(ds_next)->ds_unique_bytes += used;
377 dsl_dataset_rele(ds_nextnext, FTAG);
378 ASSERT3P(ds_next->ds_prev, ==, NULL);
379
380 /* Collapse range in this head. */
381 dsl_dataset_t *hds;
382 VERIFY0(dsl_dataset_hold_obj(dp,
383 dsl_dir_phys(ds->ds_dir)->dd_head_dataset_obj, FTAG, &hds));
384 dsl_deadlist_remove_key(&hds->ds_deadlist,
385 dsl_dataset_phys(ds)->ds_creation_txg, tx);
386 dsl_dataset_rele(hds, FTAG);
387
388 } else {
389 ASSERT3P(ds_next->ds_prev, ==, ds);
390 dsl_dataset_rele(ds_next->ds_prev, ds_next);
391 ds_next->ds_prev = NULL;
392 if (ds_prev) {
393 VERIFY0(dsl_dataset_hold_obj(dp,
394 dsl_dataset_phys(ds)->ds_prev_snap_obj,
395 ds_next, &ds_next->ds_prev));
396 }
397
398 dsl_dataset_recalc_head_uniq(ds_next);
399
400 /*
401 * Reduce the amount of our unconsumed refreservation
402 * being charged to our parent by the amount of
403 * new unique data we have gained.
404 */
405 if (old_unique < ds_next->ds_reserved) {
406 int64_t mrsdelta;
407 uint64_t new_unique =
408 dsl_dataset_phys(ds_next)->ds_unique_bytes;
409
410 ASSERT(old_unique <= new_unique);
411 mrsdelta = MIN(new_unique - old_unique,
412 ds_next->ds_reserved - old_unique);
413 dsl_dir_diduse_space(ds->ds_dir,
414 DD_USED_REFRSRV, -mrsdelta, 0, 0, tx);
415 }
416 }
417 dsl_dataset_rele(ds_next, FTAG);
418
419 /*
420 * This must be done after the dsl_traverse(), because it will
421 * re-open the objset.
422 */
423 if (ds->ds_objset) {
424 dmu_objset_evict(ds->ds_objset);
425 ds->ds_objset = NULL;
426 }
427
428 /* remove from snapshot namespace */
429 dsl_dataset_t *ds_head;
430 ASSERT(dsl_dataset_phys(ds)->ds_snapnames_zapobj == 0);
431 VERIFY0(dsl_dataset_hold_obj(dp,
432 dsl_dir_phys(ds->ds_dir)->dd_head_dataset_obj, FTAG, &ds_head));
433 VERIFY0(dsl_dataset_get_snapname(ds));
434 #ifdef ZFS_DEBUG
435 {
436 uint64_t val;
437
438 err = dsl_dataset_snap_lookup(ds_head,
439 ds->ds_snapname, &val);
440 ASSERT0(err);
441 ASSERT3U(val, ==, obj);
442 }
443 #endif
444 VERIFY0(dsl_dataset_snap_remove(ds_head, ds->ds_snapname, tx, B_TRUE));
445 dsl_dataset_rele(ds_head, FTAG);
446
447 if (ds_prev != NULL)
448 dsl_dataset_rele(ds_prev, FTAG);
449
450 spa_prop_clear_bootfs(dp->dp_spa, ds->ds_object, tx);
451
452 if (dsl_dataset_phys(ds)->ds_next_clones_obj != 0) {
453 uint64_t count;
454 ASSERT0(zap_count(mos,
455 dsl_dataset_phys(ds)->ds_next_clones_obj, &count) &&
456 count == 0);
457 VERIFY0(dmu_object_free(mos,
458 dsl_dataset_phys(ds)->ds_next_clones_obj, tx));
459 }
460 if (dsl_dataset_phys(ds)->ds_props_obj != 0)
461 VERIFY0(zap_destroy(mos, dsl_dataset_phys(ds)->ds_props_obj,
462 tx));
463 if (dsl_dataset_phys(ds)->ds_userrefs_obj != 0)
464 VERIFY0(zap_destroy(mos, dsl_dataset_phys(ds)->ds_userrefs_obj,
465 tx));
466 dsl_dir_rele(ds->ds_dir, ds);
467 ds->ds_dir = NULL;
468 dmu_object_free_zapified(mos, obj, tx);
469 }
470
471 void
472 dsl_destroy_snapshot_sync(void *arg, dmu_tx_t *tx)
473 {
474 dsl_destroy_snapshot_arg_t *ddsa = arg;
475 const char *dsname = ddsa->ddsa_name;
476 boolean_t defer = ddsa->ddsa_defer;
477
478 dsl_pool_t *dp = dmu_tx_pool(tx);
479 dsl_dataset_t *ds;
480
481 int error = dsl_dataset_hold(dp, dsname, FTAG, &ds);
482 if (error == ENOENT)
483 return;
484 ASSERT0(error);
485
486 if (autosnap_check_name(strchr(dsname, '@')))
487 autosnap_exempt_snapshot(dp->dp_spa, dsname);
488
489 dsl_destroy_snapshot_sync_impl(ds, defer, tx);
490 dsl_dataset_rele(ds, FTAG);
491 }
492
493 /*
494 * The semantics of this function are described in the comment above
495 * lzc_destroy_snaps(). To summarize:
496 *
497 * The snapshots must all be in the same pool.
498 *
499 * Snapshots that don't exist will be silently ignored (considered to be
500 * "already deleted").
501 *
502 * On success, all snaps will be destroyed and this will return 0.
503 * On failure, no snaps will be destroyed, the errlist will be filled in,
504 * and this will return an errno.
505 */
506 int
507 dsl_destroy_snapshots_nvl(nvlist_t *snaps, boolean_t defer,
508 nvlist_t *errlist)
509 {
510 if (nvlist_next_nvpair(snaps, NULL) == NULL)
511 return (0);
512
513 /*
514 * lzc_destroy_snaps() is documented to take an nvlist whose
515 * values "don't matter". We need to convert that nvlist to
516 * one that we know can be converted to LUA. We also don't
517 * care about any duplicate entries because the nvlist will
518 * be converted to a LUA table which should take care of this.
519 */
520 nvlist_t *snaps_normalized;
521 VERIFY0(nvlist_alloc(&snaps_normalized, 0, KM_SLEEP));
522 for (nvpair_t *pair = nvlist_next_nvpair(snaps, NULL);
523 pair != NULL; pair = nvlist_next_nvpair(snaps, pair)) {
524 fnvlist_add_boolean_value(snaps_normalized,
525 nvpair_name(pair), B_TRUE);
526 }
527
528 nvlist_t *arg;
529 VERIFY0(nvlist_alloc(&arg, 0, KM_SLEEP));
530 fnvlist_add_nvlist(arg, "snaps", snaps_normalized);
531 fnvlist_free(snaps_normalized);
532 fnvlist_add_boolean_value(arg, "defer", defer);
533
534 nvlist_t *wrapper;
535 VERIFY0(nvlist_alloc(&wrapper, 0, KM_SLEEP));
536 fnvlist_add_nvlist(wrapper, ZCP_ARG_ARGLIST, arg);
537 fnvlist_free(arg);
538
539 const char *program =
540 "arg = ...\n"
541 "snaps = arg['snaps']\n"
542 "defer = arg['defer']\n"
543 "errors = { }\n"
544 "has_errors = false\n"
545 "for snap, v in pairs(snaps) do\n"
546 " errno = zfs.check.destroy{snap, defer=defer}\n"
547 " zfs.debug('snap: ' .. snap .. ' errno: ' .. errno)\n"
548 " if errno == ENOENT then\n"
549 " snaps[snap] = nil\n"
550 " elseif errno ~= 0 then\n"
551 " errors[snap] = errno\n"
552 " has_errors = true\n"
553 " end\n"
554 "end\n"
555 "if has_errors then\n"
556 " return errors\n"
557 "end\n"
558 "for snap, v in pairs(snaps) do\n"
559 " errno = zfs.sync.destroy{snap, defer=defer}\n"
560 " assert(errno == 0)\n"
561 "end\n"
562 "return { }\n";
563
564 nvlist_t *result = fnvlist_alloc();
565 int error = zcp_eval(nvpair_name(nvlist_next_nvpair(snaps, NULL)),
566 program,
567 B_TRUE,
568 0,
569 zfs_lua_max_memlimit,
570 nvlist_next_nvpair(wrapper, NULL), result);
571 if (error != 0) {
572 char *errorstr = NULL;
573 (void) nvlist_lookup_string(result, ZCP_RET_ERROR, &errorstr);
574 if (errorstr != NULL) {
575 zfs_dbgmsg(errorstr);
576 }
577 return (error);
578 }
579 fnvlist_free(wrapper);
580
581 /*
582 * lzc_destroy_snaps() is documented to fill the errlist with
583 * int32 values, so we need to covert the int64 values that are
584 * returned from LUA.
585 */
586 int rv = 0;
587 nvlist_t *errlist_raw = fnvlist_lookup_nvlist(result, ZCP_RET_RETURN);
588 for (nvpair_t *pair = nvlist_next_nvpair(errlist_raw, NULL);
589 pair != NULL; pair = nvlist_next_nvpair(errlist_raw, pair)) {
590 int32_t val = (int32_t)fnvpair_value_int64(pair);
591 if (rv == 0)
592 rv = val;
593 fnvlist_add_int32(errlist, nvpair_name(pair), val);
594 }
595 fnvlist_free(result);
596 return (rv);
597 }
598
599 int
600 dsl_destroy_snapshot(const char *name, boolean_t defer)
601 {
602 int error;
603 nvlist_t *nvl = fnvlist_alloc();
604 nvlist_t *errlist = fnvlist_alloc();
605
606 fnvlist_add_boolean(nvl, name);
607 error = dsl_destroy_snapshots_nvl(nvl, defer, errlist);
608 fnvlist_free(errlist);
609 fnvlist_free(nvl);
610 return (error);
611 }
612
613 struct killarg {
614 dsl_dataset_t *ds;
615 dmu_tx_t *tx;
616 };
617
618 /* ARGSUSED */
619 static int
620 kill_blkptr(spa_t *spa, zilog_t *zilog, const blkptr_t *bp,
621 const zbookmark_phys_t *zb, const dnode_phys_t *dnp, void *arg)
622 {
623 struct killarg *ka = arg;
624 dmu_tx_t *tx = ka->tx;
625
626 if (bp == NULL || BP_IS_HOLE(bp) || BP_IS_EMBEDDED(bp))
627 return (0);
628
629 if (zb->zb_level == ZB_ZIL_LEVEL) {
630 ASSERT(zilog != NULL);
631 /*
632 * It's a block in the intent log. It has no
633 * accounting, so just free it.
634 */
635 dsl_free(ka->tx->tx_pool, ka->tx->tx_txg, bp);
636 } else {
637 ASSERT(zilog == NULL);
638 ASSERT3U(bp->blk_birth, >,
639 dsl_dataset_phys(ka->ds)->ds_prev_snap_txg);
640 (void) dsl_dataset_block_kill(ka->ds, bp, tx, B_FALSE);
641 }
642
643 return (0);
644 }
645
646 static void
647 old_synchronous_dataset_destroy(dsl_dataset_t *ds, dmu_tx_t *tx)
648 {
649 struct killarg ka;
650
651 /*
652 * Free everything that we point to (that's born after
653 * the previous snapshot, if we are a clone)
654 *
655 * NB: this should be very quick, because we already
656 * freed all the objects in open context.
657 */
658 ka.ds = ds;
659 ka.tx = tx;
660 VERIFY0(traverse_dataset(ds,
661 dsl_dataset_phys(ds)->ds_prev_snap_txg, TRAVERSE_POST,
662 kill_blkptr, &ka));
663 ASSERT(!DS_UNIQUE_IS_ACCURATE(ds) ||
664 dsl_dataset_phys(ds)->ds_unique_bytes == 0);
665 }
666
667 int
668 dsl_destroy_head_check_impl(dsl_dataset_t *ds, int expected_holds)
669 {
670 int error;
671 uint64_t count;
672 objset_t *mos;
673
674 ASSERT(!ds->ds_is_snapshot);
675 if (ds->ds_is_snapshot)
676 return (SET_ERROR(EINVAL));
677
678 if (refcount_count(&ds->ds_longholds) != expected_holds)
679 return (SET_ERROR(EBUSY));
680
681 mos = ds->ds_dir->dd_pool->dp_meta_objset;
682
683 /*
684 * Can't delete a head dataset if there are snapshots of it.
685 * (Except if the only snapshots are from the branch we cloned
686 * from.)
687 */
688 if (ds->ds_prev != NULL &&
689 dsl_dataset_phys(ds->ds_prev)->ds_next_snap_obj == ds->ds_object)
690 return (SET_ERROR(EBUSY));
691
692 /*
693 * Can't delete if there are children of this fs.
694 */
695 error = zap_count(mos,
696 dsl_dir_phys(ds->ds_dir)->dd_child_dir_zapobj, &count);
697 if (error != 0)
698 return (error);
699 if (count != 0)
700 return (SET_ERROR(EEXIST));
701
702 if (dsl_dir_is_clone(ds->ds_dir) && DS_IS_DEFER_DESTROY(ds->ds_prev) &&
703 dsl_dataset_phys(ds->ds_prev)->ds_num_children == 2 &&
704 ds->ds_prev->ds_userrefs == 0) {
705 /* We need to remove the origin snapshot as well. */
706 if (!refcount_is_zero(&ds->ds_prev->ds_longholds))
707 return (SET_ERROR(EBUSY));
708 }
709 return (0);
710 }
711
712 int
713 dsl_destroy_head_check(void *arg, dmu_tx_t *tx)
714 {
715 dsl_destroy_head_arg_t *ddha = arg;
716 dsl_pool_t *dp = dmu_tx_pool(tx);
717 dsl_dataset_t *ds;
718 int error;
719
720 error = dsl_dataset_hold(dp, ddha->ddha_name, FTAG, &ds);
721 if (error != 0)
722 return (error);
723
724 error = dsl_destroy_head_check_impl(ds, 0);
725 dsl_dataset_rele(ds, FTAG);
726 return (error);
727 }
728
729 static void
730 dsl_dir_destroy_sync(uint64_t ddobj, dmu_tx_t *tx)
731 {
732 dsl_dir_t *dd;
733 dsl_pool_t *dp = dmu_tx_pool(tx);
734 objset_t *mos = dp->dp_meta_objset;
735 dd_used_t t;
736
737 ASSERT(RRW_WRITE_HELD(&dmu_tx_pool(tx)->dp_config_rwlock));
738
739 VERIFY0(dsl_dir_hold_obj(dp, ddobj, NULL, FTAG, &dd));
740
741 ASSERT0(dsl_dir_phys(dd)->dd_head_dataset_obj);
742
743 /*
744 * Decrement the filesystem count for all parent filesystems.
745 *
746 * When we receive an incremental stream into a filesystem that already
747 * exists, a temporary clone is created. We never count this temporary
748 * clone, whose name begins with a '%'.
749 */
750 if (dd->dd_myname[0] != '%' && dd->dd_parent != NULL)
751 dsl_fs_ss_count_adjust(dd->dd_parent, -1,
752 DD_FIELD_FILESYSTEM_COUNT, tx);
753
754 /*
755 * Remove our reservation. The impl() routine avoids setting the
756 * actual property, which would require the (already destroyed) ds.
757 */
758 dsl_dir_set_reservation_sync_impl(dd, 0, tx);
759
760 ASSERT0(dsl_dir_phys(dd)->dd_used_bytes);
761 ASSERT0(dsl_dir_phys(dd)->dd_reserved);
762 for (t = 0; t < DD_USED_NUM; t++)
763 ASSERT0(dsl_dir_phys(dd)->dd_used_breakdown[t]);
764
765 VERIFY0(zap_destroy(mos, dsl_dir_phys(dd)->dd_child_dir_zapobj, tx));
766 VERIFY0(zap_destroy(mos, dsl_dir_phys(dd)->dd_props_zapobj, tx));
767 VERIFY0(dsl_deleg_destroy(mos, dsl_dir_phys(dd)->dd_deleg_zapobj, tx));
768 VERIFY0(zap_remove(mos,
769 dsl_dir_phys(dd->dd_parent)->dd_child_dir_zapobj,
770 dd->dd_myname, tx));
771
772 dsl_dir_rele(dd, FTAG);
773 dmu_object_free_zapified(mos, ddobj, tx);
774 }
775
776 void
777 dsl_destroy_head_sync_impl(dsl_dataset_t *ds, dmu_tx_t *tx)
778 {
779 dsl_pool_t *dp = dmu_tx_pool(tx);
780 objset_t *mos = dp->dp_meta_objset;
781 uint64_t obj, ddobj, prevobj = 0;
782 boolean_t rmorigin;
783
784 ASSERT3U(dsl_dataset_phys(ds)->ds_num_children, <=, 1);
785 ASSERT(ds->ds_prev == NULL ||
786 dsl_dataset_phys(ds->ds_prev)->ds_next_snap_obj != ds->ds_object);
787 rrw_enter(&ds->ds_bp_rwlock, RW_READER, FTAG);
788 ASSERT3U(dsl_dataset_phys(ds)->ds_bp.blk_birth, <=, tx->tx_txg);
789 rrw_exit(&ds->ds_bp_rwlock, FTAG);
790 ASSERT(RRW_WRITE_HELD(&dp->dp_config_rwlock));
791
792 /* We need to log before removing it from the namespace. */
793 spa_history_log_internal_ds(ds, "destroy", tx, "");
794
795 rmorigin = (dsl_dir_is_clone(ds->ds_dir) &&
796 DS_IS_DEFER_DESTROY(ds->ds_prev) &&
797 dsl_dataset_phys(ds->ds_prev)->ds_num_children == 2 &&
798 ds->ds_prev->ds_userrefs == 0);
799
800 /* Remove our reservation. */
801 if (ds->ds_reserved != 0) {
802 dsl_dataset_set_refreservation_sync_impl(ds,
803 (ZPROP_SRC_NONE | ZPROP_SRC_LOCAL | ZPROP_SRC_RECEIVED),
804 0, tx);
805 ASSERT0(ds->ds_reserved);
806 }
807
808 obj = ds->ds_object;
809
810 for (spa_feature_t f = 0; f < SPA_FEATURES; f++) {
811 if (ds->ds_feature_inuse[f]) {
812 dsl_dataset_deactivate_feature(obj, f, tx);
813 ds->ds_feature_inuse[f] = B_FALSE;
814 }
815 }
816
817 dsl_scan_ds_destroyed(ds, tx);
818
819 if (dsl_dataset_phys(ds)->ds_prev_snap_obj != 0) {
820 /* This is a clone */
821 ASSERT(ds->ds_prev != NULL);
822 ASSERT3U(dsl_dataset_phys(ds->ds_prev)->ds_next_snap_obj, !=,
823 obj);
824 ASSERT0(dsl_dataset_phys(ds)->ds_next_snap_obj);
825
826 dmu_buf_will_dirty(ds->ds_prev->ds_dbuf, tx);
827 if (dsl_dataset_phys(ds->ds_prev)->ds_next_clones_obj != 0) {
828 dsl_dataset_remove_from_next_clones(ds->ds_prev,
829 obj, tx);
830 }
831
832 ASSERT3U(dsl_dataset_phys(ds->ds_prev)->ds_num_children, >, 1);
833 dsl_dataset_phys(ds->ds_prev)->ds_num_children--;
834 }
835
836 /*
837 * Destroy the deadlist. Unless it's a clone, the
838 * deadlist should be empty. (If it's a clone, it's
839 * safe to ignore the deadlist contents.)
840 */
841 dsl_deadlist_close(&ds->ds_deadlist);
842 dsl_deadlist_free(mos, dsl_dataset_phys(ds)->ds_deadlist_obj, tx);
843 dmu_buf_will_dirty(ds->ds_dbuf, tx);
844 dsl_dataset_phys(ds)->ds_deadlist_obj = 0;
845
846 objset_t *os;
847 VERIFY0(dmu_objset_from_ds(ds, &os));
848
849 if (spa_feature_is_active(dp->dp_spa, SPA_FEATURE_WBC)) {
850 wbc_process_objset(spa_get_wbc_data(dp->dp_spa), os, B_TRUE);
851
852 /*
853 * If WBC was activated for this dataset and it is a root
854 * of WBC-ed tree of datasets then need to decrement WBC
855 * feature flag refcounter, to be sure that 'feature@wbc'
856 * shows correct information about the status of WBC
857 */
858 if (os->os_wbc_root_ds_obj != 0 &&
859 ds->ds_object == os->os_wbc_root_ds_obj)
860 spa_feature_decr(os->os_spa, SPA_FEATURE_WBC, tx);
861 }
862
863 if (!spa_feature_is_enabled(dp->dp_spa, SPA_FEATURE_ASYNC_DESTROY)) {
864 old_synchronous_dataset_destroy(ds, tx);
865 } else {
866 /*
867 * Move the bptree into the pool's list of trees to
868 * clean up and update space accounting information.
869 */
870 uint64_t used, comp, uncomp;
871
872 zil_destroy_sync(dmu_objset_zil(os), tx);
873
874 if (!spa_feature_is_active(dp->dp_spa,
875 SPA_FEATURE_ASYNC_DESTROY)) {
876 dsl_scan_t *scn = dp->dp_scan;
877 spa_feature_incr(dp->dp_spa, SPA_FEATURE_ASYNC_DESTROY,
878 tx);
879 dp->dp_bptree_obj = bptree_alloc(mos, tx);
880 VERIFY0(zap_add(mos,
881 DMU_POOL_DIRECTORY_OBJECT,
882 DMU_POOL_BPTREE_OBJ, sizeof (uint64_t), 1,
883 &dp->dp_bptree_obj, tx));
884 ASSERT(!scn->scn_async_destroying);
885 scn->scn_async_destroying = B_TRUE;
886 }
887
888 used = dsl_dir_phys(ds->ds_dir)->dd_used_bytes;
889 comp = dsl_dir_phys(ds->ds_dir)->dd_compressed_bytes;
890 uncomp = dsl_dir_phys(ds->ds_dir)->dd_uncompressed_bytes;
891
892 ASSERT(!DS_UNIQUE_IS_ACCURATE(ds) ||
893 dsl_dataset_phys(ds)->ds_unique_bytes == used);
894
895 rrw_enter(&ds->ds_bp_rwlock, RW_READER, FTAG);
896 bptree_add(mos, dp->dp_bptree_obj,
897 &dsl_dataset_phys(ds)->ds_bp,
898 dsl_dataset_phys(ds)->ds_prev_snap_txg,
899 used, comp, uncomp, tx);
900 rrw_exit(&ds->ds_bp_rwlock, FTAG);
901 dsl_dir_diduse_space(ds->ds_dir, DD_USED_HEAD,
902 -used, -comp, -uncomp, tx);
903 dsl_dir_diduse_space(dp->dp_free_dir, DD_USED_HEAD,
904 used, comp, uncomp, tx);
905 }
906
907 if (ds->ds_prev != NULL) {
908 if (spa_version(dp->dp_spa) >= SPA_VERSION_DIR_CLONES) {
909 VERIFY0(zap_remove_int(mos,
910 dsl_dir_phys(ds->ds_prev->ds_dir)->dd_clones,
911 ds->ds_object, tx));
912 }
913 prevobj = ds->ds_prev->ds_object;
914 dsl_dataset_rele(ds->ds_prev, ds);
915 ds->ds_prev = NULL;
916 }
917
918 /*
919 * This must be done after the dsl_traverse(), because it will
920 * re-open the objset.
921 */
922 if (ds->ds_objset) {
923 dmu_objset_evict(ds->ds_objset);
924 ds->ds_objset = NULL;
925 }
926
927 /* Erase the link in the dir */
928 dmu_buf_will_dirty(ds->ds_dir->dd_dbuf, tx);
929 dsl_dir_phys(ds->ds_dir)->dd_head_dataset_obj = 0;
930 ddobj = ds->ds_dir->dd_object;
931 ASSERT(dsl_dataset_phys(ds)->ds_snapnames_zapobj != 0);
932 VERIFY0(zap_destroy(mos,
933 dsl_dataset_phys(ds)->ds_snapnames_zapobj, tx));
934
935 if (ds->ds_bookmarks != 0) {
936 VERIFY0(zap_destroy(mos, ds->ds_bookmarks, tx));
937 spa_feature_decr(dp->dp_spa, SPA_FEATURE_BOOKMARKS, tx);
938 }
939
940 spa_prop_clear_bootfs(dp->dp_spa, ds->ds_object, tx);
941
942 ASSERT0(dsl_dataset_phys(ds)->ds_next_clones_obj);
943 ASSERT0(dsl_dataset_phys(ds)->ds_props_obj);
944 ASSERT0(dsl_dataset_phys(ds)->ds_userrefs_obj);
945 dsl_dir_rele(ds->ds_dir, ds);
946 ds->ds_dir = NULL;
947 dmu_object_free_zapified(mos, obj, tx);
948
949 dsl_dir_destroy_sync(ddobj, tx);
950
951 if (rmorigin) {
952 dsl_dataset_t *prev;
953 VERIFY0(dsl_dataset_hold_obj(dp, prevobj, FTAG, &prev));
954 dsl_destroy_snapshot_sync_impl(prev, B_FALSE, tx);
955 dsl_dataset_rele(prev, FTAG);
956 }
957 }
958
959 void
960 dsl_destroy_head_sync(void *arg, dmu_tx_t *tx)
961 {
962 dsl_destroy_head_arg_t *ddha = arg;
963 dsl_pool_t *dp = dmu_tx_pool(tx);
964 dsl_dataset_t *ds;
965
966 VERIFY0(dsl_dataset_hold(dp, ddha->ddha_name, FTAG, &ds));
967 dsl_destroy_head_sync_impl(ds, tx);
968 dsl_dataset_rele(ds, FTAG);
969 }
970
971 static void
972 dsl_destroy_head_begin_sync(void *arg, dmu_tx_t *tx)
973 {
974 dsl_destroy_head_arg_t *ddha = arg;
975 dsl_pool_t *dp = dmu_tx_pool(tx);
976 dsl_dataset_t *ds;
977
978 VERIFY0(dsl_dataset_hold(dp, ddha->ddha_name, FTAG, &ds));
979
980 /* Mark it as inconsistent on-disk, in case we crash */
981 dmu_buf_will_dirty(ds->ds_dbuf, tx);
982 dsl_dataset_phys(ds)->ds_flags |= DS_FLAG_INCONSISTENT;
983
984 spa_history_log_internal_ds(ds, "destroy begin", tx, "");
985 dsl_dataset_rele(ds, FTAG);
986 }
987
988 int
989 dsl_destroy_head(const char *name)
990 {
991 dsl_destroy_head_arg_t ddha;
992 int error;
993 spa_t *spa;
994 boolean_t isenabled;
995
996 #ifdef _KERNEL
997 zfs_destroy_unmount_origin(name);
998 #endif
999
1000 error = spa_open(name, &spa, FTAG);
1001 if (error != 0)
1002 return (error);
1003 isenabled = spa_feature_is_enabled(spa, SPA_FEATURE_ASYNC_DESTROY);
1004
1005 spa_close(spa, FTAG);
1006
1007 ddha.ddha_name = name;
1008
1009 if (!isenabled) {
1010 objset_t *os;
1011
1012 error = dsl_sync_task(name, dsl_destroy_head_check,
1013 dsl_destroy_head_begin_sync, &ddha,
1014 0, ZFS_SPACE_CHECK_NONE);
1015 if (error != 0)
1016 return (error);
1017
1018 /*
1019 * Head deletion is processed in one txg on old pools;
1020 * remove the objects from open context so that the txg sync
1021 * is not too long.
1022 */
1023 error = dmu_objset_own(name, DMU_OST_ANY, B_FALSE, FTAG, &os);
1024 if (error == 0) {
1025 uint64_t prev_snap_txg =
1026 dsl_dataset_phys(dmu_objset_ds(os))->
1027 ds_prev_snap_txg;
1028 for (uint64_t obj = 0; error == 0;
1029 error = dmu_object_next(os, &obj, FALSE,
1030 prev_snap_txg))
1031 (void) dmu_free_long_object(os, obj);
1032 /* sync out all frees */
1033 txg_wait_synced(dmu_objset_pool(os), 0);
1034 dmu_objset_disown(os, FTAG);
1035 }
1036 }
1037
1038 return (dsl_sync_task(name, dsl_destroy_head_check,
1039 dsl_destroy_head_sync, &ddha, 0, ZFS_SPACE_CHECK_NONE));
1040 }
1041
1042 typedef struct {
1043 kmutex_t lock;
1044 list_t list;
1045 } dsl_inconsistent_walker_cb_t;
1046
1047 typedef struct {
1048 char name[ZFS_MAX_DATASET_NAME_LEN];
1049 list_node_t node;
1050 } dsl_inconsistent_node_t;
1051
1052 /* ARGSUSED */
1053 static int
1054 dsl_collect_inconsistent_datasets_cb(dsl_pool_t *dp,
1055 dsl_dataset_t *ds, void *arg)
1056 {
1057 dsl_inconsistent_node_t *ds_node;
1058 dsl_inconsistent_walker_cb_t *walker =
1059 (dsl_inconsistent_walker_cb_t *)arg;
1060
1061 if (!DS_IS_INCONSISTENT(ds))
1062 return (0);
1063
1064 /*
1065 * If the dataset is inconsistent because a resumable receive
1066 * has failed, then do not destroy it.
1067 */
1068 if (dsl_dataset_has_resume_receive_state(ds))
1069 return (0);
1070
1071 ds_node = kmem_alloc(sizeof (dsl_inconsistent_node_t), KM_SLEEP);
1072 dsl_dataset_name(ds, ds_node->name);
1073
1074 mutex_enter(&walker->lock);
1075 list_insert_tail(&walker->list, ds_node);
1076 mutex_exit(&walker->lock);
1077
1078 return (0);
1079 }
1080
1081 /*
1082 * Walk in parallel over the entire pool and gather inconsistent
1083 * datasets namely, those that don't have resume token and destroy them.
1084 */
1085 void
1086 dsl_destroy_inconsistent(dsl_pool_t *dp)
1087 {
1088 dsl_inconsistent_walker_cb_t walker;
1089 dsl_inconsistent_node_t *ds_node;
1090
1091 mutex_init(&walker.lock, NULL, MUTEX_DEFAULT, NULL);
1092 list_create(&walker.list, sizeof (dsl_inconsistent_node_t),
1093 offsetof(dsl_inconsistent_node_t, node));
1094
1095 VERIFY0(dmu_objset_find_dp(dp, dp->dp_root_dir_obj,
1096 dsl_collect_inconsistent_datasets_cb,
1097 &walker, DS_FIND_CHILDREN));
1098
1099 while ((ds_node = list_remove_head(&walker.list)) != NULL) {
1100 (void) dsl_destroy_head(ds_node->name);
1101 kmem_free(ds_node, sizeof (dsl_inconsistent_node_t));
1102 }
1103
1104 list_destroy(&walker.list);
1105 mutex_destroy(&walker.lock);
1106 }
1107
1108 typedef struct {
1109 const char *from_ds;
1110 boolean_t defer;
1111 } dmu_destroy_atomically_arg_t;
1112
1113 static int
1114 dsl_destroy_atomically_sync(void *arg, dmu_tx_t *tx)
1115 {
1116 dmu_destroy_atomically_arg_t *ddaa = arg;
1117 boolean_t defer = ddaa->defer;
1118 dsl_pool_t *dp = dmu_tx_pool(tx);
1119 zfs_ds_collector_entry_t *tail;
1120 list_t namestack;
1121 int err = 0;
1122
1123 /* do not perfrom checks in ioctl */
1124 if (!dmu_tx_is_syncing(tx))
1125 return (0);
1126
1127 ASSERT(dsl_pool_config_held(dp));
1128
1129 if (!spa_feature_is_enabled(dp->dp_spa, SPA_FEATURE_ASYNC_DESTROY))
1130 return (SET_ERROR(ENOTSUP));
1131
1132 /* It is possible than autosnap watches the DS */
1133 if (spa_feature_is_active(dp->dp_spa, SPA_FEATURE_WBC)) {
1134 objset_t *os = NULL;
1135 dsl_dataset_t *ds = NULL;
1136
1137 err = dsl_dataset_hold(dp, ddaa->from_ds, FTAG, &ds);
1138 if (err != 0)
1139 return (err);
1140
1141 err = dmu_objset_from_ds(ds, &os);
1142 if (err != 0) {
1143 dsl_dataset_rele(ds, FTAG);
1144 return (err);
1145 }
1146
1147 if (!dmu_objset_is_snapshot(os)) {
1148 wbc_process_objset(spa_get_wbc_data(dp->dp_spa),
1149 os, B_TRUE);
1150 }
1151
1152 dsl_dataset_rele(ds, FTAG);
1153 }
1154
1155 /* initialize the stack of datasets */
1156 list_create(&namestack, sizeof (zfs_ds_collector_entry_t),
1157 offsetof(zfs_ds_collector_entry_t, node));
1158 tail = dsl_dataset_collector_cache_alloc();
1159
1160 /* push the head */
1161 tail->cookie = 0;
1162 tail->cookie_is_snap = B_FALSE;
1163 (void) strcpy(tail->name, ddaa->from_ds);
1164 list_insert_tail(&namestack, tail);
1165
1166 /* the head is processed at the very end and after all is done */
1167 while (err == 0 && ((tail = list_tail(&namestack)) != NULL)) {
1168 zfs_ds_collector_entry_t *el;
1169 objset_t *os;
1170 dsl_dataset_t *ds;
1171 char *p;
1172
1173 /* init new entry */
1174 el = dsl_dataset_collector_cache_alloc();
1175 el->cookie = 0;
1176 el->cookie_is_snap = B_FALSE;
1177 (void) strcpy(el->name, tail->name);
1178 p = el->name + strlen(el->name);
1179
1180 /* hold the current dataset to traverse its children */
1181 err = dsl_dataset_hold(dp, tail->name, FTAG, &ds);
1182 if (err != 0) {
1183 dsl_dataset_collector_cache_free(el);
1184 break;
1185 }
1186
1187 err = dmu_objset_from_ds(ds, &os);
1188 if (err != 0) {
1189 dsl_dataset_rele(ds, FTAG);
1190 dsl_dataset_collector_cache_free(el);
1191 break;
1192 }
1193
1194 if (dmu_objset_is_snapshot(os)) {
1195 /* traverse clones for snapshots */
1196 err = dmu_clone_list_next(os, MAXNAMELEN,
1197 el->name, NULL, &tail->cookie);
1198 } else {
1199 /* for filesystems traverse fs first, then snaps */
1200 if (!tail->cookie_is_snap) {
1201 *p++ = '/';
1202 do {
1203 *p = '\0';
1204 err = dmu_dir_list_next(os,
1205 MAXNAMELEN - (p - el->name),
1206 p, NULL, &tail->cookie);
1207 } while (err == 0 &&
1208 dataset_name_hidden(el->name));
1209
1210 /* no more fs, move to snapshots */
1211 if (err == ENOENT) {
1212 *(--p) = '\0';
1213 tail->cookie_is_snap = 1;
1214 tail->cookie = 0;
1215 err = 0;
1216 }
1217 }
1218
1219 if (err == 0 && tail->cookie_is_snap) {
1220 *p++ = '@';
1221 *p = '\0';
1222 err = dmu_snapshot_list_next(os,
1223 MAXNAMELEN - (p - el->name),
1224 p, NULL, &tail->cookie, NULL);
1225 }
1226 }
1227
1228 if (err == 0) {
1229 /* a children found, add it and continue */
1230 list_insert_tail(&namestack, el);
1231 dsl_dataset_rele(ds, FTAG);
1232 continue;
1233 }
1234
1235 dsl_dataset_collector_cache_free(el);
1236
1237 if (err != ENOENT) {
1238 dsl_dataset_rele(ds, FTAG);
1239 break;
1240 }
1241
1242 /*
1243 * There are no more children of the dataset, pop it from stack
1244 * and destroy it
1245 */
1246
1247 err = 0;
1248
1249 list_remove(&namestack, tail);
1250
1251 if (dmu_objset_is_snapshot(os)) {
1252 err = dsl_destroy_snapshot_check_impl(ds, defer);
1253 if (err == 0)
1254 dsl_destroy_snapshot_sync_impl(ds, defer, tx);
1255 } else if (strchr(tail->name, '/') != NULL) {
1256 err = dsl_destroy_head_check_impl(ds, 0);
1257 if (err == 0)
1258 dsl_destroy_head_sync_impl(ds, tx);
1259 }
1260
1261 dsl_dataset_rele(ds, FTAG);
1262 dsl_dataset_collector_cache_free(tail);
1263 }
1264
1265 if (err != 0) {
1266 while ((tail = list_remove_tail(&namestack)) != NULL)
1267 dsl_dataset_collector_cache_free(tail);
1268 }
1269
1270 ASSERT(list_head(&namestack) == NULL);
1271
1272 list_destroy(&namestack);
1273
1274 return (err);
1275 }
1276
1277 /*ARGSUSED*/
1278 void
1279 dsl_destroy_atomically_sync_dummy(void *arg, dmu_tx_t *tx)
1280 {
1281 }
1282
1283 int
1284 dsl_destroy_atomically(const char *name, boolean_t defer)
1285 {
1286 dmu_destroy_atomically_arg_t ddaa;
1287
1288 ddaa.from_ds = name;
1289 ddaa.defer = defer;
1290
1291 return (dsl_sync_task(name, dsl_destroy_atomically_sync,
1292 dsl_destroy_atomically_sync_dummy, &ddaa, 0, ZFS_SPACE_CHECK_NONE));
1293 }