Print this page
4574 get_clones_stat does not call zap_count in non-debug kernel
Reviewed by: Matthew Ahrens <mahrens@delphix.com>
Reviewed by: Marcel Telka <marcel@telka.sk>
Approved by:
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/common/fs/zfs/dsl_dataset.c
+++ new/usr/src/uts/common/fs/zfs/dsl_dataset.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
↓ open down ↓ |
14 lines elided |
↑ open up ↑ |
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
23 23 * Copyright (c) 2013 by Delphix. All rights reserved.
24 24 * Copyright (c) 2012, Joyent, Inc. All rights reserved.
25 + * Copyright (c) 2014 RackTop Systems.
25 26 */
26 27
27 28 #include <sys/dmu_objset.h>
28 29 #include <sys/dsl_dataset.h>
29 30 #include <sys/dsl_dir.h>
30 31 #include <sys/dsl_prop.h>
31 32 #include <sys/dsl_synctask.h>
32 33 #include <sys/dmu_traverse.h>
33 34 #include <sys/dmu_impl.h>
34 35 #include <sys/dmu_tx.h>
35 36 #include <sys/arc.h>
36 37 #include <sys/zio.h>
37 38 #include <sys/zap.h>
38 39 #include <sys/zfeature.h>
39 40 #include <sys/unique.h>
40 41 #include <sys/zfs_context.h>
41 42 #include <sys/zfs_ioctl.h>
42 43 #include <sys/spa.h>
43 44 #include <sys/zfs_znode.h>
44 45 #include <sys/zfs_onexit.h>
45 46 #include <sys/zvol.h>
46 47 #include <sys/dsl_scan.h>
47 48 #include <sys/dsl_deadlist.h>
48 49 #include <sys/dsl_destroy.h>
49 50 #include <sys/dsl_userhold.h>
50 51 #include <sys/dsl_bookmark.h>
51 52
52 53 #define SWITCH64(x, y) \
53 54 { \
54 55 uint64_t __tmp = (x); \
55 56 (x) = (y); \
56 57 (y) = __tmp; \
57 58 }
58 59
59 60 #define DS_REF_MAX (1ULL << 62)
60 61
61 62 #define DSL_DEADLIST_BLOCKSIZE SPA_MAXBLOCKSIZE
62 63
63 64 /*
64 65 * Figure out how much of this delta should be propogated to the dsl_dir
65 66 * layer. If there's a refreservation, that space has already been
66 67 * partially accounted for in our ancestors.
67 68 */
68 69 static int64_t
69 70 parent_delta(dsl_dataset_t *ds, int64_t delta)
70 71 {
71 72 uint64_t old_bytes, new_bytes;
72 73
73 74 if (ds->ds_reserved == 0)
74 75 return (delta);
75 76
76 77 old_bytes = MAX(ds->ds_phys->ds_unique_bytes, ds->ds_reserved);
77 78 new_bytes = MAX(ds->ds_phys->ds_unique_bytes + delta, ds->ds_reserved);
78 79
79 80 ASSERT3U(ABS((int64_t)(new_bytes - old_bytes)), <=, ABS(delta));
80 81 return (new_bytes - old_bytes);
81 82 }
82 83
83 84 void
84 85 dsl_dataset_block_born(dsl_dataset_t *ds, const blkptr_t *bp, dmu_tx_t *tx)
85 86 {
86 87 int used = bp_get_dsize_sync(tx->tx_pool->dp_spa, bp);
87 88 int compressed = BP_GET_PSIZE(bp);
88 89 int uncompressed = BP_GET_UCSIZE(bp);
89 90 int64_t delta;
90 91
91 92 dprintf_bp(bp, "ds=%p", ds);
92 93
93 94 ASSERT(dmu_tx_is_syncing(tx));
94 95 /* It could have been compressed away to nothing */
95 96 if (BP_IS_HOLE(bp))
96 97 return;
97 98 ASSERT(BP_GET_TYPE(bp) != DMU_OT_NONE);
98 99 ASSERT(DMU_OT_IS_VALID(BP_GET_TYPE(bp)));
99 100 if (ds == NULL) {
100 101 dsl_pool_mos_diduse_space(tx->tx_pool,
101 102 used, compressed, uncompressed);
102 103 return;
103 104 }
104 105
105 106 dmu_buf_will_dirty(ds->ds_dbuf, tx);
106 107 mutex_enter(&ds->ds_lock);
107 108 delta = parent_delta(ds, used);
108 109 ds->ds_phys->ds_referenced_bytes += used;
109 110 ds->ds_phys->ds_compressed_bytes += compressed;
110 111 ds->ds_phys->ds_uncompressed_bytes += uncompressed;
111 112 ds->ds_phys->ds_unique_bytes += used;
112 113 mutex_exit(&ds->ds_lock);
113 114 dsl_dir_diduse_space(ds->ds_dir, DD_USED_HEAD, delta,
114 115 compressed, uncompressed, tx);
115 116 dsl_dir_transfer_space(ds->ds_dir, used - delta,
116 117 DD_USED_REFRSRV, DD_USED_HEAD, tx);
117 118 }
118 119
119 120 int
120 121 dsl_dataset_block_kill(dsl_dataset_t *ds, const blkptr_t *bp, dmu_tx_t *tx,
121 122 boolean_t async)
122 123 {
123 124 int used = bp_get_dsize_sync(tx->tx_pool->dp_spa, bp);
124 125 int compressed = BP_GET_PSIZE(bp);
125 126 int uncompressed = BP_GET_UCSIZE(bp);
126 127
127 128 if (BP_IS_HOLE(bp))
128 129 return (0);
129 130
130 131 ASSERT(dmu_tx_is_syncing(tx));
131 132 ASSERT(bp->blk_birth <= tx->tx_txg);
132 133
133 134 if (ds == NULL) {
134 135 dsl_free(tx->tx_pool, tx->tx_txg, bp);
135 136 dsl_pool_mos_diduse_space(tx->tx_pool,
136 137 -used, -compressed, -uncompressed);
137 138 return (used);
138 139 }
139 140 ASSERT3P(tx->tx_pool, ==, ds->ds_dir->dd_pool);
140 141
141 142 ASSERT(!dsl_dataset_is_snapshot(ds));
142 143 dmu_buf_will_dirty(ds->ds_dbuf, tx);
143 144
144 145 if (bp->blk_birth > ds->ds_phys->ds_prev_snap_txg) {
145 146 int64_t delta;
146 147
147 148 dprintf_bp(bp, "freeing ds=%llu", ds->ds_object);
148 149 dsl_free(tx->tx_pool, tx->tx_txg, bp);
149 150
150 151 mutex_enter(&ds->ds_lock);
151 152 ASSERT(ds->ds_phys->ds_unique_bytes >= used ||
152 153 !DS_UNIQUE_IS_ACCURATE(ds));
153 154 delta = parent_delta(ds, -used);
154 155 ds->ds_phys->ds_unique_bytes -= used;
155 156 mutex_exit(&ds->ds_lock);
156 157 dsl_dir_diduse_space(ds->ds_dir, DD_USED_HEAD,
157 158 delta, -compressed, -uncompressed, tx);
158 159 dsl_dir_transfer_space(ds->ds_dir, -used - delta,
159 160 DD_USED_REFRSRV, DD_USED_HEAD, tx);
160 161 } else {
161 162 dprintf_bp(bp, "putting on dead list: %s", "");
162 163 if (async) {
163 164 /*
164 165 * We are here as part of zio's write done callback,
165 166 * which means we're a zio interrupt thread. We can't
166 167 * call dsl_deadlist_insert() now because it may block
167 168 * waiting for I/O. Instead, put bp on the deferred
168 169 * queue and let dsl_pool_sync() finish the job.
169 170 */
170 171 bplist_append(&ds->ds_pending_deadlist, bp);
171 172 } else {
172 173 dsl_deadlist_insert(&ds->ds_deadlist, bp, tx);
173 174 }
174 175 ASSERT3U(ds->ds_prev->ds_object, ==,
175 176 ds->ds_phys->ds_prev_snap_obj);
176 177 ASSERT(ds->ds_prev->ds_phys->ds_num_children > 0);
177 178 /* if (bp->blk_birth > prev prev snap txg) prev unique += bs */
178 179 if (ds->ds_prev->ds_phys->ds_next_snap_obj ==
179 180 ds->ds_object && bp->blk_birth >
180 181 ds->ds_prev->ds_phys->ds_prev_snap_txg) {
181 182 dmu_buf_will_dirty(ds->ds_prev->ds_dbuf, tx);
182 183 mutex_enter(&ds->ds_prev->ds_lock);
183 184 ds->ds_prev->ds_phys->ds_unique_bytes += used;
184 185 mutex_exit(&ds->ds_prev->ds_lock);
185 186 }
186 187 if (bp->blk_birth > ds->ds_dir->dd_origin_txg) {
187 188 dsl_dir_transfer_space(ds->ds_dir, used,
188 189 DD_USED_HEAD, DD_USED_SNAP, tx);
189 190 }
190 191 }
191 192 mutex_enter(&ds->ds_lock);
192 193 ASSERT3U(ds->ds_phys->ds_referenced_bytes, >=, used);
193 194 ds->ds_phys->ds_referenced_bytes -= used;
194 195 ASSERT3U(ds->ds_phys->ds_compressed_bytes, >=, compressed);
195 196 ds->ds_phys->ds_compressed_bytes -= compressed;
196 197 ASSERT3U(ds->ds_phys->ds_uncompressed_bytes, >=, uncompressed);
197 198 ds->ds_phys->ds_uncompressed_bytes -= uncompressed;
198 199 mutex_exit(&ds->ds_lock);
199 200
200 201 return (used);
201 202 }
202 203
203 204 uint64_t
204 205 dsl_dataset_prev_snap_txg(dsl_dataset_t *ds)
205 206 {
206 207 uint64_t trysnap = 0;
207 208
208 209 if (ds == NULL)
209 210 return (0);
210 211 /*
211 212 * The snapshot creation could fail, but that would cause an
212 213 * incorrect FALSE return, which would only result in an
213 214 * overestimation of the amount of space that an operation would
214 215 * consume, which is OK.
215 216 *
216 217 * There's also a small window where we could miss a pending
217 218 * snapshot, because we could set the sync task in the quiescing
218 219 * phase. So this should only be used as a guess.
219 220 */
220 221 if (ds->ds_trysnap_txg >
221 222 spa_last_synced_txg(ds->ds_dir->dd_pool->dp_spa))
222 223 trysnap = ds->ds_trysnap_txg;
223 224 return (MAX(ds->ds_phys->ds_prev_snap_txg, trysnap));
224 225 }
225 226
226 227 boolean_t
227 228 dsl_dataset_block_freeable(dsl_dataset_t *ds, const blkptr_t *bp,
228 229 uint64_t blk_birth)
229 230 {
230 231 if (blk_birth <= dsl_dataset_prev_snap_txg(ds) ||
231 232 (bp != NULL && BP_IS_HOLE(bp)))
232 233 return (B_FALSE);
233 234
234 235 ddt_prefetch(dsl_dataset_get_spa(ds), bp);
235 236
236 237 return (B_TRUE);
237 238 }
238 239
239 240 /* ARGSUSED */
240 241 static void
241 242 dsl_dataset_evict(dmu_buf_t *db, void *dsv)
242 243 {
243 244 dsl_dataset_t *ds = dsv;
244 245
245 246 ASSERT(ds->ds_owner == NULL);
246 247
247 248 unique_remove(ds->ds_fsid_guid);
248 249
249 250 if (ds->ds_objset != NULL)
250 251 dmu_objset_evict(ds->ds_objset);
251 252
252 253 if (ds->ds_prev) {
253 254 dsl_dataset_rele(ds->ds_prev, ds);
254 255 ds->ds_prev = NULL;
255 256 }
256 257
257 258 bplist_destroy(&ds->ds_pending_deadlist);
258 259 if (ds->ds_phys->ds_deadlist_obj != 0)
259 260 dsl_deadlist_close(&ds->ds_deadlist);
260 261 if (ds->ds_dir)
261 262 dsl_dir_rele(ds->ds_dir, ds);
262 263
263 264 ASSERT(!list_link_active(&ds->ds_synced_link));
264 265
265 266 mutex_destroy(&ds->ds_lock);
266 267 mutex_destroy(&ds->ds_opening_lock);
267 268 refcount_destroy(&ds->ds_longholds);
268 269
269 270 kmem_free(ds, sizeof (dsl_dataset_t));
270 271 }
271 272
272 273 int
273 274 dsl_dataset_get_snapname(dsl_dataset_t *ds)
274 275 {
275 276 dsl_dataset_phys_t *headphys;
276 277 int err;
277 278 dmu_buf_t *headdbuf;
278 279 dsl_pool_t *dp = ds->ds_dir->dd_pool;
279 280 objset_t *mos = dp->dp_meta_objset;
280 281
281 282 if (ds->ds_snapname[0])
282 283 return (0);
283 284 if (ds->ds_phys->ds_next_snap_obj == 0)
284 285 return (0);
285 286
286 287 err = dmu_bonus_hold(mos, ds->ds_dir->dd_phys->dd_head_dataset_obj,
287 288 FTAG, &headdbuf);
288 289 if (err != 0)
289 290 return (err);
290 291 headphys = headdbuf->db_data;
291 292 err = zap_value_search(dp->dp_meta_objset,
292 293 headphys->ds_snapnames_zapobj, ds->ds_object, 0, ds->ds_snapname);
293 294 dmu_buf_rele(headdbuf, FTAG);
294 295 return (err);
295 296 }
296 297
297 298 int
298 299 dsl_dataset_snap_lookup(dsl_dataset_t *ds, const char *name, uint64_t *value)
299 300 {
300 301 objset_t *mos = ds->ds_dir->dd_pool->dp_meta_objset;
301 302 uint64_t snapobj = ds->ds_phys->ds_snapnames_zapobj;
302 303 matchtype_t mt;
303 304 int err;
304 305
305 306 if (ds->ds_phys->ds_flags & DS_FLAG_CI_DATASET)
306 307 mt = MT_FIRST;
307 308 else
308 309 mt = MT_EXACT;
309 310
310 311 err = zap_lookup_norm(mos, snapobj, name, 8, 1,
311 312 value, mt, NULL, 0, NULL);
312 313 if (err == ENOTSUP && mt == MT_FIRST)
313 314 err = zap_lookup(mos, snapobj, name, 8, 1, value);
314 315 return (err);
315 316 }
316 317
317 318 int
318 319 dsl_dataset_snap_remove(dsl_dataset_t *ds, const char *name, dmu_tx_t *tx)
319 320 {
320 321 objset_t *mos = ds->ds_dir->dd_pool->dp_meta_objset;
321 322 uint64_t snapobj = ds->ds_phys->ds_snapnames_zapobj;
322 323 matchtype_t mt;
323 324 int err;
324 325
325 326 dsl_dir_snap_cmtime_update(ds->ds_dir);
326 327
327 328 if (ds->ds_phys->ds_flags & DS_FLAG_CI_DATASET)
328 329 mt = MT_FIRST;
329 330 else
330 331 mt = MT_EXACT;
331 332
332 333 err = zap_remove_norm(mos, snapobj, name, mt, tx);
333 334 if (err == ENOTSUP && mt == MT_FIRST)
334 335 err = zap_remove(mos, snapobj, name, tx);
335 336 return (err);
336 337 }
337 338
338 339 int
339 340 dsl_dataset_hold_obj(dsl_pool_t *dp, uint64_t dsobj, void *tag,
340 341 dsl_dataset_t **dsp)
341 342 {
342 343 objset_t *mos = dp->dp_meta_objset;
343 344 dmu_buf_t *dbuf;
344 345 dsl_dataset_t *ds;
345 346 int err;
346 347 dmu_object_info_t doi;
347 348
348 349 ASSERT(dsl_pool_config_held(dp));
349 350
350 351 err = dmu_bonus_hold(mos, dsobj, tag, &dbuf);
351 352 if (err != 0)
352 353 return (err);
353 354
354 355 /* Make sure dsobj has the correct object type. */
355 356 dmu_object_info_from_db(dbuf, &doi);
356 357 if (doi.doi_bonus_type != DMU_OT_DSL_DATASET) {
357 358 dmu_buf_rele(dbuf, tag);
358 359 return (SET_ERROR(EINVAL));
359 360 }
360 361
361 362 ds = dmu_buf_get_user(dbuf);
362 363 if (ds == NULL) {
363 364 dsl_dataset_t *winner = NULL;
364 365
365 366 ds = kmem_zalloc(sizeof (dsl_dataset_t), KM_SLEEP);
366 367 ds->ds_dbuf = dbuf;
367 368 ds->ds_object = dsobj;
368 369 ds->ds_phys = dbuf->db_data;
369 370
370 371 mutex_init(&ds->ds_lock, NULL, MUTEX_DEFAULT, NULL);
371 372 mutex_init(&ds->ds_opening_lock, NULL, MUTEX_DEFAULT, NULL);
372 373 mutex_init(&ds->ds_sendstream_lock, NULL, MUTEX_DEFAULT, NULL);
373 374 refcount_create(&ds->ds_longholds);
374 375
375 376 bplist_create(&ds->ds_pending_deadlist);
376 377 dsl_deadlist_open(&ds->ds_deadlist,
377 378 mos, ds->ds_phys->ds_deadlist_obj);
378 379
379 380 list_create(&ds->ds_sendstreams, sizeof (dmu_sendarg_t),
380 381 offsetof(dmu_sendarg_t, dsa_link));
381 382
382 383 if (err == 0) {
383 384 err = dsl_dir_hold_obj(dp,
384 385 ds->ds_phys->ds_dir_obj, NULL, ds, &ds->ds_dir);
385 386 }
386 387 if (err != 0) {
387 388 mutex_destroy(&ds->ds_lock);
388 389 mutex_destroy(&ds->ds_opening_lock);
389 390 refcount_destroy(&ds->ds_longholds);
390 391 bplist_destroy(&ds->ds_pending_deadlist);
391 392 dsl_deadlist_close(&ds->ds_deadlist);
392 393 kmem_free(ds, sizeof (dsl_dataset_t));
393 394 dmu_buf_rele(dbuf, tag);
394 395 return (err);
395 396 }
396 397
397 398 if (!dsl_dataset_is_snapshot(ds)) {
398 399 ds->ds_snapname[0] = '\0';
399 400 if (ds->ds_phys->ds_prev_snap_obj != 0) {
400 401 err = dsl_dataset_hold_obj(dp,
401 402 ds->ds_phys->ds_prev_snap_obj,
402 403 ds, &ds->ds_prev);
403 404 }
404 405 if (doi.doi_type == DMU_OTN_ZAP_METADATA) {
405 406 int zaperr = zap_lookup(mos, ds->ds_object,
406 407 DS_FIELD_BOOKMARK_NAMES,
407 408 sizeof (ds->ds_bookmarks), 1,
408 409 &ds->ds_bookmarks);
409 410 if (zaperr != ENOENT)
410 411 VERIFY0(zaperr);
411 412 }
412 413 } else {
413 414 if (zfs_flags & ZFS_DEBUG_SNAPNAMES)
414 415 err = dsl_dataset_get_snapname(ds);
415 416 if (err == 0 && ds->ds_phys->ds_userrefs_obj != 0) {
416 417 err = zap_count(
417 418 ds->ds_dir->dd_pool->dp_meta_objset,
418 419 ds->ds_phys->ds_userrefs_obj,
419 420 &ds->ds_userrefs);
420 421 }
421 422 }
422 423
423 424 if (err == 0 && !dsl_dataset_is_snapshot(ds)) {
424 425 err = dsl_prop_get_int_ds(ds,
425 426 zfs_prop_to_name(ZFS_PROP_REFRESERVATION),
426 427 &ds->ds_reserved);
427 428 if (err == 0) {
428 429 err = dsl_prop_get_int_ds(ds,
429 430 zfs_prop_to_name(ZFS_PROP_REFQUOTA),
430 431 &ds->ds_quota);
431 432 }
432 433 } else {
433 434 ds->ds_reserved = ds->ds_quota = 0;
434 435 }
435 436
436 437 if (err != 0 || (winner = dmu_buf_set_user_ie(dbuf, ds,
437 438 &ds->ds_phys, dsl_dataset_evict)) != NULL) {
438 439 bplist_destroy(&ds->ds_pending_deadlist);
439 440 dsl_deadlist_close(&ds->ds_deadlist);
440 441 if (ds->ds_prev)
441 442 dsl_dataset_rele(ds->ds_prev, ds);
442 443 dsl_dir_rele(ds->ds_dir, ds);
443 444 mutex_destroy(&ds->ds_lock);
444 445 mutex_destroy(&ds->ds_opening_lock);
445 446 refcount_destroy(&ds->ds_longholds);
446 447 kmem_free(ds, sizeof (dsl_dataset_t));
447 448 if (err != 0) {
448 449 dmu_buf_rele(dbuf, tag);
449 450 return (err);
450 451 }
451 452 ds = winner;
452 453 } else {
453 454 ds->ds_fsid_guid =
454 455 unique_insert(ds->ds_phys->ds_fsid_guid);
455 456 }
456 457 }
457 458 ASSERT3P(ds->ds_dbuf, ==, dbuf);
458 459 ASSERT3P(ds->ds_phys, ==, dbuf->db_data);
459 460 ASSERT(ds->ds_phys->ds_prev_snap_obj != 0 ||
460 461 spa_version(dp->dp_spa) < SPA_VERSION_ORIGIN ||
461 462 dp->dp_origin_snap == NULL || ds == dp->dp_origin_snap);
462 463 *dsp = ds;
463 464 return (0);
464 465 }
465 466
466 467 int
467 468 dsl_dataset_hold(dsl_pool_t *dp, const char *name,
468 469 void *tag, dsl_dataset_t **dsp)
469 470 {
470 471 dsl_dir_t *dd;
471 472 const char *snapname;
472 473 uint64_t obj;
473 474 int err = 0;
474 475
475 476 err = dsl_dir_hold(dp, name, FTAG, &dd, &snapname);
476 477 if (err != 0)
477 478 return (err);
478 479
479 480 ASSERT(dsl_pool_config_held(dp));
480 481 obj = dd->dd_phys->dd_head_dataset_obj;
481 482 if (obj != 0)
482 483 err = dsl_dataset_hold_obj(dp, obj, tag, dsp);
483 484 else
484 485 err = SET_ERROR(ENOENT);
485 486
486 487 /* we may be looking for a snapshot */
487 488 if (err == 0 && snapname != NULL) {
488 489 dsl_dataset_t *ds;
489 490
490 491 if (*snapname++ != '@') {
491 492 dsl_dataset_rele(*dsp, tag);
492 493 dsl_dir_rele(dd, FTAG);
493 494 return (SET_ERROR(ENOENT));
494 495 }
495 496
496 497 dprintf("looking for snapshot '%s'\n", snapname);
497 498 err = dsl_dataset_snap_lookup(*dsp, snapname, &obj);
498 499 if (err == 0)
499 500 err = dsl_dataset_hold_obj(dp, obj, tag, &ds);
500 501 dsl_dataset_rele(*dsp, tag);
501 502
502 503 if (err == 0) {
503 504 mutex_enter(&ds->ds_lock);
504 505 if (ds->ds_snapname[0] == 0)
505 506 (void) strlcpy(ds->ds_snapname, snapname,
506 507 sizeof (ds->ds_snapname));
507 508 mutex_exit(&ds->ds_lock);
508 509 *dsp = ds;
509 510 }
510 511 }
511 512
512 513 dsl_dir_rele(dd, FTAG);
513 514 return (err);
514 515 }
515 516
516 517 int
517 518 dsl_dataset_own_obj(dsl_pool_t *dp, uint64_t dsobj,
518 519 void *tag, dsl_dataset_t **dsp)
519 520 {
520 521 int err = dsl_dataset_hold_obj(dp, dsobj, tag, dsp);
521 522 if (err != 0)
522 523 return (err);
523 524 if (!dsl_dataset_tryown(*dsp, tag)) {
524 525 dsl_dataset_rele(*dsp, tag);
525 526 *dsp = NULL;
526 527 return (SET_ERROR(EBUSY));
527 528 }
528 529 return (0);
529 530 }
530 531
531 532 int
532 533 dsl_dataset_own(dsl_pool_t *dp, const char *name,
533 534 void *tag, dsl_dataset_t **dsp)
534 535 {
535 536 int err = dsl_dataset_hold(dp, name, tag, dsp);
536 537 if (err != 0)
537 538 return (err);
538 539 if (!dsl_dataset_tryown(*dsp, tag)) {
539 540 dsl_dataset_rele(*dsp, tag);
540 541 return (SET_ERROR(EBUSY));
541 542 }
542 543 return (0);
543 544 }
544 545
545 546 /*
546 547 * See the comment above dsl_pool_hold() for details. In summary, a long
547 548 * hold is used to prevent destruction of a dataset while the pool hold
548 549 * is dropped, allowing other concurrent operations (e.g. spa_sync()).
549 550 *
550 551 * The dataset and pool must be held when this function is called. After it
551 552 * is called, the pool hold may be released while the dataset is still held
552 553 * and accessed.
553 554 */
554 555 void
555 556 dsl_dataset_long_hold(dsl_dataset_t *ds, void *tag)
556 557 {
557 558 ASSERT(dsl_pool_config_held(ds->ds_dir->dd_pool));
558 559 (void) refcount_add(&ds->ds_longholds, tag);
559 560 }
560 561
561 562 void
562 563 dsl_dataset_long_rele(dsl_dataset_t *ds, void *tag)
563 564 {
564 565 (void) refcount_remove(&ds->ds_longholds, tag);
565 566 }
566 567
567 568 /* Return B_TRUE if there are any long holds on this dataset. */
568 569 boolean_t
569 570 dsl_dataset_long_held(dsl_dataset_t *ds)
570 571 {
571 572 return (!refcount_is_zero(&ds->ds_longholds));
572 573 }
573 574
574 575 void
575 576 dsl_dataset_name(dsl_dataset_t *ds, char *name)
576 577 {
577 578 if (ds == NULL) {
578 579 (void) strcpy(name, "mos");
579 580 } else {
580 581 dsl_dir_name(ds->ds_dir, name);
581 582 VERIFY0(dsl_dataset_get_snapname(ds));
582 583 if (ds->ds_snapname[0]) {
583 584 (void) strcat(name, "@");
584 585 /*
585 586 * We use a "recursive" mutex so that we
586 587 * can call dprintf_ds() with ds_lock held.
587 588 */
588 589 if (!MUTEX_HELD(&ds->ds_lock)) {
589 590 mutex_enter(&ds->ds_lock);
590 591 (void) strcat(name, ds->ds_snapname);
591 592 mutex_exit(&ds->ds_lock);
592 593 } else {
593 594 (void) strcat(name, ds->ds_snapname);
594 595 }
595 596 }
596 597 }
597 598 }
598 599
599 600 void
600 601 dsl_dataset_rele(dsl_dataset_t *ds, void *tag)
601 602 {
602 603 dmu_buf_rele(ds->ds_dbuf, tag);
603 604 }
604 605
605 606 void
606 607 dsl_dataset_disown(dsl_dataset_t *ds, void *tag)
607 608 {
608 609 ASSERT(ds->ds_owner == tag && ds->ds_dbuf != NULL);
609 610
610 611 mutex_enter(&ds->ds_lock);
611 612 ds->ds_owner = NULL;
612 613 mutex_exit(&ds->ds_lock);
613 614 dsl_dataset_long_rele(ds, tag);
614 615 if (ds->ds_dbuf != NULL)
615 616 dsl_dataset_rele(ds, tag);
616 617 else
617 618 dsl_dataset_evict(NULL, ds);
618 619 }
619 620
620 621 boolean_t
621 622 dsl_dataset_tryown(dsl_dataset_t *ds, void *tag)
622 623 {
623 624 boolean_t gotit = FALSE;
624 625
625 626 mutex_enter(&ds->ds_lock);
626 627 if (ds->ds_owner == NULL && !DS_IS_INCONSISTENT(ds)) {
627 628 ds->ds_owner = tag;
628 629 dsl_dataset_long_hold(ds, tag);
629 630 gotit = TRUE;
630 631 }
631 632 mutex_exit(&ds->ds_lock);
632 633 return (gotit);
633 634 }
634 635
635 636 uint64_t
636 637 dsl_dataset_create_sync_dd(dsl_dir_t *dd, dsl_dataset_t *origin,
637 638 uint64_t flags, dmu_tx_t *tx)
638 639 {
639 640 dsl_pool_t *dp = dd->dd_pool;
640 641 dmu_buf_t *dbuf;
641 642 dsl_dataset_phys_t *dsphys;
642 643 uint64_t dsobj;
643 644 objset_t *mos = dp->dp_meta_objset;
644 645
645 646 if (origin == NULL)
646 647 origin = dp->dp_origin_snap;
647 648
648 649 ASSERT(origin == NULL || origin->ds_dir->dd_pool == dp);
649 650 ASSERT(origin == NULL || origin->ds_phys->ds_num_children > 0);
650 651 ASSERT(dmu_tx_is_syncing(tx));
651 652 ASSERT(dd->dd_phys->dd_head_dataset_obj == 0);
652 653
653 654 dsobj = dmu_object_alloc(mos, DMU_OT_DSL_DATASET, 0,
654 655 DMU_OT_DSL_DATASET, sizeof (dsl_dataset_phys_t), tx);
655 656 VERIFY0(dmu_bonus_hold(mos, dsobj, FTAG, &dbuf));
656 657 dmu_buf_will_dirty(dbuf, tx);
657 658 dsphys = dbuf->db_data;
658 659 bzero(dsphys, sizeof (dsl_dataset_phys_t));
659 660 dsphys->ds_dir_obj = dd->dd_object;
660 661 dsphys->ds_flags = flags;
661 662 dsphys->ds_fsid_guid = unique_create();
662 663 (void) random_get_pseudo_bytes((void*)&dsphys->ds_guid,
663 664 sizeof (dsphys->ds_guid));
664 665 dsphys->ds_snapnames_zapobj =
665 666 zap_create_norm(mos, U8_TEXTPREP_TOUPPER, DMU_OT_DSL_DS_SNAP_MAP,
666 667 DMU_OT_NONE, 0, tx);
667 668 dsphys->ds_creation_time = gethrestime_sec();
668 669 dsphys->ds_creation_txg = tx->tx_txg == TXG_INITIAL ? 1 : tx->tx_txg;
669 670
670 671 if (origin == NULL) {
671 672 dsphys->ds_deadlist_obj = dsl_deadlist_alloc(mos, tx);
672 673 } else {
673 674 dsl_dataset_t *ohds; /* head of the origin snapshot */
674 675
675 676 dsphys->ds_prev_snap_obj = origin->ds_object;
676 677 dsphys->ds_prev_snap_txg =
677 678 origin->ds_phys->ds_creation_txg;
678 679 dsphys->ds_referenced_bytes =
679 680 origin->ds_phys->ds_referenced_bytes;
680 681 dsphys->ds_compressed_bytes =
681 682 origin->ds_phys->ds_compressed_bytes;
682 683 dsphys->ds_uncompressed_bytes =
683 684 origin->ds_phys->ds_uncompressed_bytes;
684 685 dsphys->ds_bp = origin->ds_phys->ds_bp;
685 686 dsphys->ds_flags |= origin->ds_phys->ds_flags;
686 687
687 688 dmu_buf_will_dirty(origin->ds_dbuf, tx);
688 689 origin->ds_phys->ds_num_children++;
689 690
690 691 VERIFY0(dsl_dataset_hold_obj(dp,
691 692 origin->ds_dir->dd_phys->dd_head_dataset_obj, FTAG, &ohds));
692 693 dsphys->ds_deadlist_obj = dsl_deadlist_clone(&ohds->ds_deadlist,
693 694 dsphys->ds_prev_snap_txg, dsphys->ds_prev_snap_obj, tx);
694 695 dsl_dataset_rele(ohds, FTAG);
695 696
696 697 if (spa_version(dp->dp_spa) >= SPA_VERSION_NEXT_CLONES) {
697 698 if (origin->ds_phys->ds_next_clones_obj == 0) {
698 699 origin->ds_phys->ds_next_clones_obj =
699 700 zap_create(mos,
700 701 DMU_OT_NEXT_CLONES, DMU_OT_NONE, 0, tx);
701 702 }
702 703 VERIFY0(zap_add_int(mos,
703 704 origin->ds_phys->ds_next_clones_obj, dsobj, tx));
704 705 }
705 706
706 707 dmu_buf_will_dirty(dd->dd_dbuf, tx);
707 708 dd->dd_phys->dd_origin_obj = origin->ds_object;
708 709 if (spa_version(dp->dp_spa) >= SPA_VERSION_DIR_CLONES) {
709 710 if (origin->ds_dir->dd_phys->dd_clones == 0) {
710 711 dmu_buf_will_dirty(origin->ds_dir->dd_dbuf, tx);
711 712 origin->ds_dir->dd_phys->dd_clones =
712 713 zap_create(mos,
713 714 DMU_OT_DSL_CLONES, DMU_OT_NONE, 0, tx);
714 715 }
715 716 VERIFY0(zap_add_int(mos,
716 717 origin->ds_dir->dd_phys->dd_clones, dsobj, tx));
717 718 }
718 719 }
719 720
720 721 if (spa_version(dp->dp_spa) >= SPA_VERSION_UNIQUE_ACCURATE)
721 722 dsphys->ds_flags |= DS_FLAG_UNIQUE_ACCURATE;
722 723
723 724 dmu_buf_rele(dbuf, FTAG);
724 725
725 726 dmu_buf_will_dirty(dd->dd_dbuf, tx);
726 727 dd->dd_phys->dd_head_dataset_obj = dsobj;
727 728
728 729 return (dsobj);
729 730 }
730 731
731 732 static void
732 733 dsl_dataset_zero_zil(dsl_dataset_t *ds, dmu_tx_t *tx)
733 734 {
734 735 objset_t *os;
735 736
736 737 VERIFY0(dmu_objset_from_ds(ds, &os));
737 738 bzero(&os->os_zil_header, sizeof (os->os_zil_header));
738 739 dsl_dataset_dirty(ds, tx);
739 740 }
740 741
741 742 uint64_t
742 743 dsl_dataset_create_sync(dsl_dir_t *pdd, const char *lastname,
743 744 dsl_dataset_t *origin, uint64_t flags, cred_t *cr, dmu_tx_t *tx)
744 745 {
745 746 dsl_pool_t *dp = pdd->dd_pool;
746 747 uint64_t dsobj, ddobj;
747 748 dsl_dir_t *dd;
748 749
749 750 ASSERT(dmu_tx_is_syncing(tx));
750 751 ASSERT(lastname[0] != '@');
751 752
752 753 ddobj = dsl_dir_create_sync(dp, pdd, lastname, tx);
753 754 VERIFY0(dsl_dir_hold_obj(dp, ddobj, lastname, FTAG, &dd));
754 755
755 756 dsobj = dsl_dataset_create_sync_dd(dd, origin,
756 757 flags & ~DS_CREATE_FLAG_NODIRTY, tx);
757 758
758 759 dsl_deleg_set_create_perms(dd, tx, cr);
759 760
760 761 dsl_dir_rele(dd, FTAG);
761 762
762 763 /*
763 764 * If we are creating a clone, make sure we zero out any stale
764 765 * data from the origin snapshots zil header.
765 766 */
766 767 if (origin != NULL && !(flags & DS_CREATE_FLAG_NODIRTY)) {
767 768 dsl_dataset_t *ds;
768 769
769 770 VERIFY0(dsl_dataset_hold_obj(dp, dsobj, FTAG, &ds));
770 771 dsl_dataset_zero_zil(ds, tx);
771 772 dsl_dataset_rele(ds, FTAG);
772 773 }
773 774
774 775 return (dsobj);
775 776 }
776 777
777 778 /*
778 779 * The unique space in the head dataset can be calculated by subtracting
779 780 * the space used in the most recent snapshot, that is still being used
780 781 * in this file system, from the space currently in use. To figure out
781 782 * the space in the most recent snapshot still in use, we need to take
782 783 * the total space used in the snapshot and subtract out the space that
783 784 * has been freed up since the snapshot was taken.
784 785 */
785 786 void
786 787 dsl_dataset_recalc_head_uniq(dsl_dataset_t *ds)
787 788 {
788 789 uint64_t mrs_used;
789 790 uint64_t dlused, dlcomp, dluncomp;
790 791
791 792 ASSERT(!dsl_dataset_is_snapshot(ds));
792 793
793 794 if (ds->ds_phys->ds_prev_snap_obj != 0)
794 795 mrs_used = ds->ds_prev->ds_phys->ds_referenced_bytes;
795 796 else
796 797 mrs_used = 0;
797 798
798 799 dsl_deadlist_space(&ds->ds_deadlist, &dlused, &dlcomp, &dluncomp);
799 800
800 801 ASSERT3U(dlused, <=, mrs_used);
801 802 ds->ds_phys->ds_unique_bytes =
802 803 ds->ds_phys->ds_referenced_bytes - (mrs_used - dlused);
803 804
804 805 if (spa_version(ds->ds_dir->dd_pool->dp_spa) >=
805 806 SPA_VERSION_UNIQUE_ACCURATE)
806 807 ds->ds_phys->ds_flags |= DS_FLAG_UNIQUE_ACCURATE;
807 808 }
808 809
809 810 void
810 811 dsl_dataset_remove_from_next_clones(dsl_dataset_t *ds, uint64_t obj,
811 812 dmu_tx_t *tx)
812 813 {
813 814 objset_t *mos = ds->ds_dir->dd_pool->dp_meta_objset;
814 815 uint64_t count;
815 816 int err;
816 817
817 818 ASSERT(ds->ds_phys->ds_num_children >= 2);
818 819 err = zap_remove_int(mos, ds->ds_phys->ds_next_clones_obj, obj, tx);
819 820 /*
820 821 * The err should not be ENOENT, but a bug in a previous version
821 822 * of the code could cause upgrade_clones_cb() to not set
822 823 * ds_next_snap_obj when it should, leading to a missing entry.
823 824 * If we knew that the pool was created after
824 825 * SPA_VERSION_NEXT_CLONES, we could assert that it isn't
825 826 * ENOENT. However, at least we can check that we don't have
826 827 * too many entries in the next_clones_obj even after failing to
827 828 * remove this one.
828 829 */
829 830 if (err != ENOENT)
830 831 VERIFY0(err);
831 832 ASSERT0(zap_count(mos, ds->ds_phys->ds_next_clones_obj,
832 833 &count));
833 834 ASSERT3U(count, <=, ds->ds_phys->ds_num_children - 2);
834 835 }
835 836
836 837
837 838 blkptr_t *
838 839 dsl_dataset_get_blkptr(dsl_dataset_t *ds)
839 840 {
840 841 return (&ds->ds_phys->ds_bp);
841 842 }
842 843
843 844 void
844 845 dsl_dataset_set_blkptr(dsl_dataset_t *ds, blkptr_t *bp, dmu_tx_t *tx)
845 846 {
846 847 ASSERT(dmu_tx_is_syncing(tx));
847 848 /* If it's the meta-objset, set dp_meta_rootbp */
848 849 if (ds == NULL) {
849 850 tx->tx_pool->dp_meta_rootbp = *bp;
850 851 } else {
851 852 dmu_buf_will_dirty(ds->ds_dbuf, tx);
852 853 ds->ds_phys->ds_bp = *bp;
853 854 }
854 855 }
855 856
856 857 spa_t *
857 858 dsl_dataset_get_spa(dsl_dataset_t *ds)
858 859 {
859 860 return (ds->ds_dir->dd_pool->dp_spa);
860 861 }
861 862
862 863 void
863 864 dsl_dataset_dirty(dsl_dataset_t *ds, dmu_tx_t *tx)
864 865 {
865 866 dsl_pool_t *dp;
866 867
867 868 if (ds == NULL) /* this is the meta-objset */
868 869 return;
869 870
870 871 ASSERT(ds->ds_objset != NULL);
871 872
872 873 if (ds->ds_phys->ds_next_snap_obj != 0)
873 874 panic("dirtying snapshot!");
874 875
875 876 dp = ds->ds_dir->dd_pool;
876 877
877 878 if (txg_list_add(&dp->dp_dirty_datasets, ds, tx->tx_txg)) {
878 879 /* up the hold count until we can be written out */
879 880 dmu_buf_add_ref(ds->ds_dbuf, ds);
880 881 }
881 882 }
882 883
883 884 boolean_t
884 885 dsl_dataset_is_dirty(dsl_dataset_t *ds)
885 886 {
886 887 for (int t = 0; t < TXG_SIZE; t++) {
887 888 if (txg_list_member(&ds->ds_dir->dd_pool->dp_dirty_datasets,
888 889 ds, t))
889 890 return (B_TRUE);
890 891 }
891 892 return (B_FALSE);
892 893 }
893 894
894 895 static int
895 896 dsl_dataset_snapshot_reserve_space(dsl_dataset_t *ds, dmu_tx_t *tx)
896 897 {
897 898 uint64_t asize;
898 899
899 900 if (!dmu_tx_is_syncing(tx))
900 901 return (0);
901 902
902 903 /*
903 904 * If there's an fs-only reservation, any blocks that might become
904 905 * owned by the snapshot dataset must be accommodated by space
905 906 * outside of the reservation.
906 907 */
907 908 ASSERT(ds->ds_reserved == 0 || DS_UNIQUE_IS_ACCURATE(ds));
908 909 asize = MIN(ds->ds_phys->ds_unique_bytes, ds->ds_reserved);
909 910 if (asize > dsl_dir_space_available(ds->ds_dir, NULL, 0, TRUE))
910 911 return (SET_ERROR(ENOSPC));
911 912
912 913 /*
913 914 * Propagate any reserved space for this snapshot to other
914 915 * snapshot checks in this sync group.
915 916 */
916 917 if (asize > 0)
917 918 dsl_dir_willuse_space(ds->ds_dir, asize, tx);
918 919
919 920 return (0);
920 921 }
921 922
922 923 typedef struct dsl_dataset_snapshot_arg {
923 924 nvlist_t *ddsa_snaps;
924 925 nvlist_t *ddsa_props;
925 926 nvlist_t *ddsa_errors;
926 927 } dsl_dataset_snapshot_arg_t;
927 928
928 929 int
929 930 dsl_dataset_snapshot_check_impl(dsl_dataset_t *ds, const char *snapname,
930 931 dmu_tx_t *tx, boolean_t recv)
931 932 {
932 933 int error;
933 934 uint64_t value;
934 935
935 936 ds->ds_trysnap_txg = tx->tx_txg;
936 937
937 938 if (!dmu_tx_is_syncing(tx))
938 939 return (0);
939 940
940 941 /*
941 942 * We don't allow multiple snapshots of the same txg. If there
942 943 * is already one, try again.
943 944 */
944 945 if (ds->ds_phys->ds_prev_snap_txg >= tx->tx_txg)
945 946 return (SET_ERROR(EAGAIN));
946 947
947 948 /*
948 949 * Check for conflicting snapshot name.
949 950 */
950 951 error = dsl_dataset_snap_lookup(ds, snapname, &value);
951 952 if (error == 0)
952 953 return (SET_ERROR(EEXIST));
953 954 if (error != ENOENT)
954 955 return (error);
955 956
956 957 /*
957 958 * We don't allow taking snapshots of inconsistent datasets, such as
958 959 * those into which we are currently receiving. However, if we are
959 960 * creating this snapshot as part of a receive, this check will be
960 961 * executed atomically with respect to the completion of the receive
961 962 * itself but prior to the clearing of DS_FLAG_INCONSISTENT; in this
962 963 * case we ignore this, knowing it will be fixed up for us shortly in
963 964 * dmu_recv_end_sync().
964 965 */
965 966 if (!recv && DS_IS_INCONSISTENT(ds))
966 967 return (SET_ERROR(EBUSY));
967 968
968 969 error = dsl_dataset_snapshot_reserve_space(ds, tx);
969 970 if (error != 0)
970 971 return (error);
971 972
972 973 return (0);
973 974 }
974 975
975 976 static int
976 977 dsl_dataset_snapshot_check(void *arg, dmu_tx_t *tx)
977 978 {
978 979 dsl_dataset_snapshot_arg_t *ddsa = arg;
979 980 dsl_pool_t *dp = dmu_tx_pool(tx);
980 981 nvpair_t *pair;
981 982 int rv = 0;
982 983
983 984 for (pair = nvlist_next_nvpair(ddsa->ddsa_snaps, NULL);
984 985 pair != NULL; pair = nvlist_next_nvpair(ddsa->ddsa_snaps, pair)) {
985 986 int error = 0;
986 987 dsl_dataset_t *ds;
987 988 char *name, *atp;
988 989 char dsname[MAXNAMELEN];
989 990
990 991 name = nvpair_name(pair);
991 992 if (strlen(name) >= MAXNAMELEN)
992 993 error = SET_ERROR(ENAMETOOLONG);
993 994 if (error == 0) {
994 995 atp = strchr(name, '@');
995 996 if (atp == NULL)
996 997 error = SET_ERROR(EINVAL);
997 998 if (error == 0)
998 999 (void) strlcpy(dsname, name, atp - name + 1);
999 1000 }
1000 1001 if (error == 0)
1001 1002 error = dsl_dataset_hold(dp, dsname, FTAG, &ds);
1002 1003 if (error == 0) {
1003 1004 error = dsl_dataset_snapshot_check_impl(ds,
1004 1005 atp + 1, tx, B_FALSE);
1005 1006 dsl_dataset_rele(ds, FTAG);
1006 1007 }
1007 1008
1008 1009 if (error != 0) {
1009 1010 if (ddsa->ddsa_errors != NULL) {
1010 1011 fnvlist_add_int32(ddsa->ddsa_errors,
1011 1012 name, error);
1012 1013 }
1013 1014 rv = error;
1014 1015 }
1015 1016 }
1016 1017 return (rv);
1017 1018 }
1018 1019
1019 1020 void
1020 1021 dsl_dataset_snapshot_sync_impl(dsl_dataset_t *ds, const char *snapname,
1021 1022 dmu_tx_t *tx)
1022 1023 {
1023 1024 static zil_header_t zero_zil;
1024 1025
1025 1026 dsl_pool_t *dp = ds->ds_dir->dd_pool;
1026 1027 dmu_buf_t *dbuf;
1027 1028 dsl_dataset_phys_t *dsphys;
1028 1029 uint64_t dsobj, crtxg;
1029 1030 objset_t *mos = dp->dp_meta_objset;
1030 1031 objset_t *os;
1031 1032
1032 1033 ASSERT(RRW_WRITE_HELD(&dp->dp_config_rwlock));
1033 1034
1034 1035 /*
1035 1036 * If we are on an old pool, the zil must not be active, in which
1036 1037 * case it will be zeroed. Usually zil_suspend() accomplishes this.
1037 1038 */
1038 1039 ASSERT(spa_version(dmu_tx_pool(tx)->dp_spa) >= SPA_VERSION_FAST_SNAP ||
1039 1040 dmu_objset_from_ds(ds, &os) != 0 ||
1040 1041 bcmp(&os->os_phys->os_zil_header, &zero_zil,
1041 1042 sizeof (zero_zil)) == 0);
1042 1043
1043 1044
1044 1045 /*
1045 1046 * The origin's ds_creation_txg has to be < TXG_INITIAL
1046 1047 */
1047 1048 if (strcmp(snapname, ORIGIN_DIR_NAME) == 0)
1048 1049 crtxg = 1;
1049 1050 else
1050 1051 crtxg = tx->tx_txg;
1051 1052
1052 1053 dsobj = dmu_object_alloc(mos, DMU_OT_DSL_DATASET, 0,
1053 1054 DMU_OT_DSL_DATASET, sizeof (dsl_dataset_phys_t), tx);
1054 1055 VERIFY0(dmu_bonus_hold(mos, dsobj, FTAG, &dbuf));
1055 1056 dmu_buf_will_dirty(dbuf, tx);
1056 1057 dsphys = dbuf->db_data;
1057 1058 bzero(dsphys, sizeof (dsl_dataset_phys_t));
1058 1059 dsphys->ds_dir_obj = ds->ds_dir->dd_object;
1059 1060 dsphys->ds_fsid_guid = unique_create();
1060 1061 (void) random_get_pseudo_bytes((void*)&dsphys->ds_guid,
1061 1062 sizeof (dsphys->ds_guid));
1062 1063 dsphys->ds_prev_snap_obj = ds->ds_phys->ds_prev_snap_obj;
1063 1064 dsphys->ds_prev_snap_txg = ds->ds_phys->ds_prev_snap_txg;
1064 1065 dsphys->ds_next_snap_obj = ds->ds_object;
1065 1066 dsphys->ds_num_children = 1;
1066 1067 dsphys->ds_creation_time = gethrestime_sec();
1067 1068 dsphys->ds_creation_txg = crtxg;
1068 1069 dsphys->ds_deadlist_obj = ds->ds_phys->ds_deadlist_obj;
1069 1070 dsphys->ds_referenced_bytes = ds->ds_phys->ds_referenced_bytes;
1070 1071 dsphys->ds_compressed_bytes = ds->ds_phys->ds_compressed_bytes;
1071 1072 dsphys->ds_uncompressed_bytes = ds->ds_phys->ds_uncompressed_bytes;
1072 1073 dsphys->ds_flags = ds->ds_phys->ds_flags;
1073 1074 dsphys->ds_bp = ds->ds_phys->ds_bp;
1074 1075 dmu_buf_rele(dbuf, FTAG);
1075 1076
1076 1077 ASSERT3U(ds->ds_prev != 0, ==, ds->ds_phys->ds_prev_snap_obj != 0);
1077 1078 if (ds->ds_prev) {
1078 1079 uint64_t next_clones_obj =
1079 1080 ds->ds_prev->ds_phys->ds_next_clones_obj;
1080 1081 ASSERT(ds->ds_prev->ds_phys->ds_next_snap_obj ==
1081 1082 ds->ds_object ||
1082 1083 ds->ds_prev->ds_phys->ds_num_children > 1);
1083 1084 if (ds->ds_prev->ds_phys->ds_next_snap_obj == ds->ds_object) {
1084 1085 dmu_buf_will_dirty(ds->ds_prev->ds_dbuf, tx);
1085 1086 ASSERT3U(ds->ds_phys->ds_prev_snap_txg, ==,
1086 1087 ds->ds_prev->ds_phys->ds_creation_txg);
1087 1088 ds->ds_prev->ds_phys->ds_next_snap_obj = dsobj;
1088 1089 } else if (next_clones_obj != 0) {
1089 1090 dsl_dataset_remove_from_next_clones(ds->ds_prev,
1090 1091 dsphys->ds_next_snap_obj, tx);
1091 1092 VERIFY0(zap_add_int(mos,
1092 1093 next_clones_obj, dsobj, tx));
1093 1094 }
1094 1095 }
1095 1096
1096 1097 /*
1097 1098 * If we have a reference-reservation on this dataset, we will
1098 1099 * need to increase the amount of refreservation being charged
1099 1100 * since our unique space is going to zero.
1100 1101 */
1101 1102 if (ds->ds_reserved) {
1102 1103 int64_t delta;
1103 1104 ASSERT(DS_UNIQUE_IS_ACCURATE(ds));
1104 1105 delta = MIN(ds->ds_phys->ds_unique_bytes, ds->ds_reserved);
1105 1106 dsl_dir_diduse_space(ds->ds_dir, DD_USED_REFRSRV,
1106 1107 delta, 0, 0, tx);
1107 1108 }
1108 1109
1109 1110 dmu_buf_will_dirty(ds->ds_dbuf, tx);
1110 1111 ds->ds_phys->ds_deadlist_obj = dsl_deadlist_clone(&ds->ds_deadlist,
1111 1112 UINT64_MAX, ds->ds_phys->ds_prev_snap_obj, tx);
1112 1113 dsl_deadlist_close(&ds->ds_deadlist);
1113 1114 dsl_deadlist_open(&ds->ds_deadlist, mos, ds->ds_phys->ds_deadlist_obj);
1114 1115 dsl_deadlist_add_key(&ds->ds_deadlist,
1115 1116 ds->ds_phys->ds_prev_snap_txg, tx);
1116 1117
1117 1118 ASSERT3U(ds->ds_phys->ds_prev_snap_txg, <, tx->tx_txg);
1118 1119 ds->ds_phys->ds_prev_snap_obj = dsobj;
1119 1120 ds->ds_phys->ds_prev_snap_txg = crtxg;
1120 1121 ds->ds_phys->ds_unique_bytes = 0;
1121 1122 if (spa_version(dp->dp_spa) >= SPA_VERSION_UNIQUE_ACCURATE)
1122 1123 ds->ds_phys->ds_flags |= DS_FLAG_UNIQUE_ACCURATE;
1123 1124
1124 1125 VERIFY0(zap_add(mos, ds->ds_phys->ds_snapnames_zapobj,
1125 1126 snapname, 8, 1, &dsobj, tx));
1126 1127
1127 1128 if (ds->ds_prev)
1128 1129 dsl_dataset_rele(ds->ds_prev, ds);
1129 1130 VERIFY0(dsl_dataset_hold_obj(dp,
1130 1131 ds->ds_phys->ds_prev_snap_obj, ds, &ds->ds_prev));
1131 1132
1132 1133 dsl_scan_ds_snapshotted(ds, tx);
1133 1134
1134 1135 dsl_dir_snap_cmtime_update(ds->ds_dir);
1135 1136
1136 1137 spa_history_log_internal_ds(ds->ds_prev, "snapshot", tx, "");
1137 1138 }
1138 1139
1139 1140 static void
1140 1141 dsl_dataset_snapshot_sync(void *arg, dmu_tx_t *tx)
1141 1142 {
1142 1143 dsl_dataset_snapshot_arg_t *ddsa = arg;
1143 1144 dsl_pool_t *dp = dmu_tx_pool(tx);
1144 1145 nvpair_t *pair;
1145 1146
1146 1147 for (pair = nvlist_next_nvpair(ddsa->ddsa_snaps, NULL);
1147 1148 pair != NULL; pair = nvlist_next_nvpair(ddsa->ddsa_snaps, pair)) {
1148 1149 dsl_dataset_t *ds;
1149 1150 char *name, *atp;
1150 1151 char dsname[MAXNAMELEN];
1151 1152
1152 1153 name = nvpair_name(pair);
1153 1154 atp = strchr(name, '@');
1154 1155 (void) strlcpy(dsname, name, atp - name + 1);
1155 1156 VERIFY0(dsl_dataset_hold(dp, dsname, FTAG, &ds));
1156 1157
1157 1158 dsl_dataset_snapshot_sync_impl(ds, atp + 1, tx);
1158 1159 if (ddsa->ddsa_props != NULL) {
1159 1160 dsl_props_set_sync_impl(ds->ds_prev,
1160 1161 ZPROP_SRC_LOCAL, ddsa->ddsa_props, tx);
1161 1162 }
1162 1163 dsl_dataset_rele(ds, FTAG);
1163 1164 }
1164 1165 }
1165 1166
1166 1167 /*
1167 1168 * The snapshots must all be in the same pool.
1168 1169 * All-or-nothing: if there are any failures, nothing will be modified.
1169 1170 */
1170 1171 int
1171 1172 dsl_dataset_snapshot(nvlist_t *snaps, nvlist_t *props, nvlist_t *errors)
1172 1173 {
1173 1174 dsl_dataset_snapshot_arg_t ddsa;
1174 1175 nvpair_t *pair;
1175 1176 boolean_t needsuspend;
1176 1177 int error;
1177 1178 spa_t *spa;
1178 1179 char *firstname;
1179 1180 nvlist_t *suspended = NULL;
1180 1181
1181 1182 pair = nvlist_next_nvpair(snaps, NULL);
1182 1183 if (pair == NULL)
1183 1184 return (0);
1184 1185 firstname = nvpair_name(pair);
1185 1186
1186 1187 error = spa_open(firstname, &spa, FTAG);
1187 1188 if (error != 0)
1188 1189 return (error);
1189 1190 needsuspend = (spa_version(spa) < SPA_VERSION_FAST_SNAP);
1190 1191 spa_close(spa, FTAG);
1191 1192
1192 1193 if (needsuspend) {
1193 1194 suspended = fnvlist_alloc();
1194 1195 for (pair = nvlist_next_nvpair(snaps, NULL); pair != NULL;
1195 1196 pair = nvlist_next_nvpair(snaps, pair)) {
1196 1197 char fsname[MAXNAMELEN];
1197 1198 char *snapname = nvpair_name(pair);
1198 1199 char *atp;
1199 1200 void *cookie;
1200 1201
1201 1202 atp = strchr(snapname, '@');
1202 1203 if (atp == NULL) {
1203 1204 error = SET_ERROR(EINVAL);
1204 1205 break;
1205 1206 }
1206 1207 (void) strlcpy(fsname, snapname, atp - snapname + 1);
1207 1208
1208 1209 error = zil_suspend(fsname, &cookie);
1209 1210 if (error != 0)
1210 1211 break;
1211 1212 fnvlist_add_uint64(suspended, fsname,
1212 1213 (uintptr_t)cookie);
1213 1214 }
1214 1215 }
1215 1216
1216 1217 ddsa.ddsa_snaps = snaps;
1217 1218 ddsa.ddsa_props = props;
1218 1219 ddsa.ddsa_errors = errors;
1219 1220
1220 1221 if (error == 0) {
1221 1222 error = dsl_sync_task(firstname, dsl_dataset_snapshot_check,
1222 1223 dsl_dataset_snapshot_sync, &ddsa,
1223 1224 fnvlist_num_pairs(snaps) * 3);
1224 1225 }
1225 1226
1226 1227 if (suspended != NULL) {
1227 1228 for (pair = nvlist_next_nvpair(suspended, NULL); pair != NULL;
1228 1229 pair = nvlist_next_nvpair(suspended, pair)) {
1229 1230 zil_resume((void *)(uintptr_t)
1230 1231 fnvpair_value_uint64(pair));
1231 1232 }
1232 1233 fnvlist_free(suspended);
1233 1234 }
1234 1235
1235 1236 return (error);
1236 1237 }
1237 1238
1238 1239 typedef struct dsl_dataset_snapshot_tmp_arg {
1239 1240 const char *ddsta_fsname;
1240 1241 const char *ddsta_snapname;
1241 1242 minor_t ddsta_cleanup_minor;
1242 1243 const char *ddsta_htag;
1243 1244 } dsl_dataset_snapshot_tmp_arg_t;
1244 1245
1245 1246 static int
1246 1247 dsl_dataset_snapshot_tmp_check(void *arg, dmu_tx_t *tx)
1247 1248 {
1248 1249 dsl_dataset_snapshot_tmp_arg_t *ddsta = arg;
1249 1250 dsl_pool_t *dp = dmu_tx_pool(tx);
1250 1251 dsl_dataset_t *ds;
1251 1252 int error;
1252 1253
1253 1254 error = dsl_dataset_hold(dp, ddsta->ddsta_fsname, FTAG, &ds);
1254 1255 if (error != 0)
1255 1256 return (error);
1256 1257
1257 1258 error = dsl_dataset_snapshot_check_impl(ds, ddsta->ddsta_snapname,
1258 1259 tx, B_FALSE);
1259 1260 if (error != 0) {
1260 1261 dsl_dataset_rele(ds, FTAG);
1261 1262 return (error);
1262 1263 }
1263 1264
1264 1265 if (spa_version(dp->dp_spa) < SPA_VERSION_USERREFS) {
1265 1266 dsl_dataset_rele(ds, FTAG);
1266 1267 return (SET_ERROR(ENOTSUP));
1267 1268 }
1268 1269 error = dsl_dataset_user_hold_check_one(NULL, ddsta->ddsta_htag,
1269 1270 B_TRUE, tx);
1270 1271 if (error != 0) {
1271 1272 dsl_dataset_rele(ds, FTAG);
1272 1273 return (error);
1273 1274 }
1274 1275
1275 1276 dsl_dataset_rele(ds, FTAG);
1276 1277 return (0);
1277 1278 }
1278 1279
1279 1280 static void
1280 1281 dsl_dataset_snapshot_tmp_sync(void *arg, dmu_tx_t *tx)
1281 1282 {
1282 1283 dsl_dataset_snapshot_tmp_arg_t *ddsta = arg;
1283 1284 dsl_pool_t *dp = dmu_tx_pool(tx);
1284 1285 dsl_dataset_t *ds;
1285 1286
1286 1287 VERIFY0(dsl_dataset_hold(dp, ddsta->ddsta_fsname, FTAG, &ds));
1287 1288
1288 1289 dsl_dataset_snapshot_sync_impl(ds, ddsta->ddsta_snapname, tx);
1289 1290 dsl_dataset_user_hold_sync_one(ds->ds_prev, ddsta->ddsta_htag,
1290 1291 ddsta->ddsta_cleanup_minor, gethrestime_sec(), tx);
1291 1292 dsl_destroy_snapshot_sync_impl(ds->ds_prev, B_TRUE, tx);
1292 1293
1293 1294 dsl_dataset_rele(ds, FTAG);
1294 1295 }
1295 1296
1296 1297 int
1297 1298 dsl_dataset_snapshot_tmp(const char *fsname, const char *snapname,
1298 1299 minor_t cleanup_minor, const char *htag)
1299 1300 {
1300 1301 dsl_dataset_snapshot_tmp_arg_t ddsta;
1301 1302 int error;
1302 1303 spa_t *spa;
1303 1304 boolean_t needsuspend;
1304 1305 void *cookie;
1305 1306
1306 1307 ddsta.ddsta_fsname = fsname;
1307 1308 ddsta.ddsta_snapname = snapname;
1308 1309 ddsta.ddsta_cleanup_minor = cleanup_minor;
1309 1310 ddsta.ddsta_htag = htag;
1310 1311
1311 1312 error = spa_open(fsname, &spa, FTAG);
1312 1313 if (error != 0)
1313 1314 return (error);
1314 1315 needsuspend = (spa_version(spa) < SPA_VERSION_FAST_SNAP);
1315 1316 spa_close(spa, FTAG);
1316 1317
1317 1318 if (needsuspend) {
1318 1319 error = zil_suspend(fsname, &cookie);
1319 1320 if (error != 0)
1320 1321 return (error);
1321 1322 }
1322 1323
1323 1324 error = dsl_sync_task(fsname, dsl_dataset_snapshot_tmp_check,
1324 1325 dsl_dataset_snapshot_tmp_sync, &ddsta, 3);
1325 1326
1326 1327 if (needsuspend)
1327 1328 zil_resume(cookie);
1328 1329 return (error);
1329 1330 }
1330 1331
1331 1332
1332 1333 void
1333 1334 dsl_dataset_sync(dsl_dataset_t *ds, zio_t *zio, dmu_tx_t *tx)
1334 1335 {
1335 1336 ASSERT(dmu_tx_is_syncing(tx));
1336 1337 ASSERT(ds->ds_objset != NULL);
1337 1338 ASSERT(ds->ds_phys->ds_next_snap_obj == 0);
1338 1339
1339 1340 /*
1340 1341 * in case we had to change ds_fsid_guid when we opened it,
1341 1342 * sync it out now.
1342 1343 */
1343 1344 dmu_buf_will_dirty(ds->ds_dbuf, tx);
1344 1345 ds->ds_phys->ds_fsid_guid = ds->ds_fsid_guid;
1345 1346
1346 1347 dmu_objset_sync(ds->ds_objset, zio, tx);
1347 1348 }
1348 1349
1349 1350 static void
1350 1351 get_clones_stat(dsl_dataset_t *ds, nvlist_t *nv)
1351 1352 {
1352 1353 uint64_t count = 0;
1353 1354 objset_t *mos = ds->ds_dir->dd_pool->dp_meta_objset;
1354 1355 zap_cursor_t zc;
1355 1356 zap_attribute_t za;
1356 1357 nvlist_t *propval = fnvlist_alloc();
↓ open down ↓ |
1322 lines elided |
↑ open up ↑ |
1357 1358 nvlist_t *val = fnvlist_alloc();
1358 1359
1359 1360 ASSERT(dsl_pool_config_held(ds->ds_dir->dd_pool));
1360 1361
1361 1362 /*
1362 1363 * There may be missing entries in ds_next_clones_obj
1363 1364 * due to a bug in a previous version of the code.
1364 1365 * Only trust it if it has the right number of entries.
1365 1366 */
1366 1367 if (ds->ds_phys->ds_next_clones_obj != 0) {
1367 - ASSERT0(zap_count(mos, ds->ds_phys->ds_next_clones_obj,
1368 + VERIFY0(zap_count(mos, ds->ds_phys->ds_next_clones_obj,
1368 1369 &count));
1369 1370 }
1370 1371 if (count != ds->ds_phys->ds_num_children - 1)
1371 1372 goto fail;
1372 1373 for (zap_cursor_init(&zc, mos, ds->ds_phys->ds_next_clones_obj);
1373 1374 zap_cursor_retrieve(&zc, &za) == 0;
1374 1375 zap_cursor_advance(&zc)) {
1375 1376 dsl_dataset_t *clone;
1376 1377 char buf[ZFS_MAXNAMELEN];
1377 1378 VERIFY0(dsl_dataset_hold_obj(ds->ds_dir->dd_pool,
1378 1379 za.za_first_integer, FTAG, &clone));
1379 1380 dsl_dir_name(clone->ds_dir, buf);
1380 1381 fnvlist_add_boolean(val, buf);
1381 1382 dsl_dataset_rele(clone, FTAG);
1382 1383 }
1383 1384 zap_cursor_fini(&zc);
1384 1385 fnvlist_add_nvlist(propval, ZPROP_VALUE, val);
1385 1386 fnvlist_add_nvlist(nv, zfs_prop_to_name(ZFS_PROP_CLONES), propval);
1386 1387 fail:
1387 1388 nvlist_free(val);
1388 1389 nvlist_free(propval);
1389 1390 }
1390 1391
1391 1392 void
1392 1393 dsl_dataset_stats(dsl_dataset_t *ds, nvlist_t *nv)
1393 1394 {
1394 1395 dsl_pool_t *dp = ds->ds_dir->dd_pool;
1395 1396 uint64_t refd, avail, uobjs, aobjs, ratio;
1396 1397
1397 1398 ASSERT(dsl_pool_config_held(dp));
1398 1399
1399 1400 ratio = ds->ds_phys->ds_compressed_bytes == 0 ? 100 :
1400 1401 (ds->ds_phys->ds_uncompressed_bytes * 100 /
1401 1402 ds->ds_phys->ds_compressed_bytes);
1402 1403
1403 1404 dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_REFRATIO, ratio);
1404 1405 dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_LOGICALREFERENCED,
1405 1406 ds->ds_phys->ds_uncompressed_bytes);
1406 1407
1407 1408 if (dsl_dataset_is_snapshot(ds)) {
1408 1409 dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_COMPRESSRATIO, ratio);
1409 1410 dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_USED,
1410 1411 ds->ds_phys->ds_unique_bytes);
1411 1412 get_clones_stat(ds, nv);
1412 1413 } else {
1413 1414 dsl_dir_stats(ds->ds_dir, nv);
1414 1415 }
1415 1416
1416 1417 dsl_dataset_space(ds, &refd, &avail, &uobjs, &aobjs);
1417 1418 dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_AVAILABLE, avail);
1418 1419 dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_REFERENCED, refd);
1419 1420
1420 1421 dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_CREATION,
1421 1422 ds->ds_phys->ds_creation_time);
1422 1423 dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_CREATETXG,
1423 1424 ds->ds_phys->ds_creation_txg);
1424 1425 dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_REFQUOTA,
1425 1426 ds->ds_quota);
1426 1427 dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_REFRESERVATION,
1427 1428 ds->ds_reserved);
1428 1429 dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_GUID,
1429 1430 ds->ds_phys->ds_guid);
1430 1431 dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_UNIQUE,
1431 1432 ds->ds_phys->ds_unique_bytes);
1432 1433 dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_OBJSETID,
1433 1434 ds->ds_object);
1434 1435 dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_USERREFS,
1435 1436 ds->ds_userrefs);
1436 1437 dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_DEFER_DESTROY,
1437 1438 DS_IS_DEFER_DESTROY(ds) ? 1 : 0);
1438 1439
1439 1440 if (ds->ds_phys->ds_prev_snap_obj != 0) {
1440 1441 uint64_t written, comp, uncomp;
1441 1442 dsl_pool_t *dp = ds->ds_dir->dd_pool;
1442 1443 dsl_dataset_t *prev;
1443 1444
1444 1445 int err = dsl_dataset_hold_obj(dp,
1445 1446 ds->ds_phys->ds_prev_snap_obj, FTAG, &prev);
1446 1447 if (err == 0) {
1447 1448 err = dsl_dataset_space_written(prev, ds, &written,
1448 1449 &comp, &uncomp);
1449 1450 dsl_dataset_rele(prev, FTAG);
1450 1451 if (err == 0) {
1451 1452 dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_WRITTEN,
1452 1453 written);
1453 1454 }
1454 1455 }
1455 1456 }
1456 1457 }
1457 1458
1458 1459 void
1459 1460 dsl_dataset_fast_stat(dsl_dataset_t *ds, dmu_objset_stats_t *stat)
1460 1461 {
1461 1462 dsl_pool_t *dp = ds->ds_dir->dd_pool;
1462 1463 ASSERT(dsl_pool_config_held(dp));
1463 1464
1464 1465 stat->dds_creation_txg = ds->ds_phys->ds_creation_txg;
1465 1466 stat->dds_inconsistent = ds->ds_phys->ds_flags & DS_FLAG_INCONSISTENT;
1466 1467 stat->dds_guid = ds->ds_phys->ds_guid;
1467 1468 stat->dds_origin[0] = '\0';
1468 1469 if (dsl_dataset_is_snapshot(ds)) {
1469 1470 stat->dds_is_snapshot = B_TRUE;
1470 1471 stat->dds_num_clones = ds->ds_phys->ds_num_children - 1;
1471 1472 } else {
1472 1473 stat->dds_is_snapshot = B_FALSE;
1473 1474 stat->dds_num_clones = 0;
1474 1475
1475 1476 if (dsl_dir_is_clone(ds->ds_dir)) {
1476 1477 dsl_dataset_t *ods;
1477 1478
1478 1479 VERIFY0(dsl_dataset_hold_obj(dp,
1479 1480 ds->ds_dir->dd_phys->dd_origin_obj, FTAG, &ods));
1480 1481 dsl_dataset_name(ods, stat->dds_origin);
1481 1482 dsl_dataset_rele(ods, FTAG);
1482 1483 }
1483 1484 }
1484 1485 }
1485 1486
1486 1487 uint64_t
1487 1488 dsl_dataset_fsid_guid(dsl_dataset_t *ds)
1488 1489 {
1489 1490 return (ds->ds_fsid_guid);
1490 1491 }
1491 1492
1492 1493 void
1493 1494 dsl_dataset_space(dsl_dataset_t *ds,
1494 1495 uint64_t *refdbytesp, uint64_t *availbytesp,
1495 1496 uint64_t *usedobjsp, uint64_t *availobjsp)
1496 1497 {
1497 1498 *refdbytesp = ds->ds_phys->ds_referenced_bytes;
1498 1499 *availbytesp = dsl_dir_space_available(ds->ds_dir, NULL, 0, TRUE);
1499 1500 if (ds->ds_reserved > ds->ds_phys->ds_unique_bytes)
1500 1501 *availbytesp += ds->ds_reserved - ds->ds_phys->ds_unique_bytes;
1501 1502 if (ds->ds_quota != 0) {
1502 1503 /*
1503 1504 * Adjust available bytes according to refquota
1504 1505 */
1505 1506 if (*refdbytesp < ds->ds_quota)
1506 1507 *availbytesp = MIN(*availbytesp,
1507 1508 ds->ds_quota - *refdbytesp);
1508 1509 else
1509 1510 *availbytesp = 0;
1510 1511 }
1511 1512 *usedobjsp = ds->ds_phys->ds_bp.blk_fill;
1512 1513 *availobjsp = DN_MAX_OBJECT - *usedobjsp;
1513 1514 }
1514 1515
1515 1516 boolean_t
1516 1517 dsl_dataset_modified_since_snap(dsl_dataset_t *ds, dsl_dataset_t *snap)
1517 1518 {
1518 1519 dsl_pool_t *dp = ds->ds_dir->dd_pool;
1519 1520
1520 1521 ASSERT(dsl_pool_config_held(dp));
1521 1522 if (snap == NULL)
1522 1523 return (B_FALSE);
1523 1524 if (ds->ds_phys->ds_bp.blk_birth >
1524 1525 snap->ds_phys->ds_creation_txg) {
1525 1526 objset_t *os, *os_snap;
1526 1527 /*
1527 1528 * It may be that only the ZIL differs, because it was
1528 1529 * reset in the head. Don't count that as being
1529 1530 * modified.
1530 1531 */
1531 1532 if (dmu_objset_from_ds(ds, &os) != 0)
1532 1533 return (B_TRUE);
1533 1534 if (dmu_objset_from_ds(snap, &os_snap) != 0)
1534 1535 return (B_TRUE);
1535 1536 return (bcmp(&os->os_phys->os_meta_dnode,
1536 1537 &os_snap->os_phys->os_meta_dnode,
1537 1538 sizeof (os->os_phys->os_meta_dnode)) != 0);
1538 1539 }
1539 1540 return (B_FALSE);
1540 1541 }
1541 1542
1542 1543 typedef struct dsl_dataset_rename_snapshot_arg {
1543 1544 const char *ddrsa_fsname;
1544 1545 const char *ddrsa_oldsnapname;
1545 1546 const char *ddrsa_newsnapname;
1546 1547 boolean_t ddrsa_recursive;
1547 1548 dmu_tx_t *ddrsa_tx;
1548 1549 } dsl_dataset_rename_snapshot_arg_t;
1549 1550
1550 1551 /* ARGSUSED */
1551 1552 static int
1552 1553 dsl_dataset_rename_snapshot_check_impl(dsl_pool_t *dp,
1553 1554 dsl_dataset_t *hds, void *arg)
1554 1555 {
1555 1556 dsl_dataset_rename_snapshot_arg_t *ddrsa = arg;
1556 1557 int error;
1557 1558 uint64_t val;
1558 1559
1559 1560 error = dsl_dataset_snap_lookup(hds, ddrsa->ddrsa_oldsnapname, &val);
1560 1561 if (error != 0) {
1561 1562 /* ignore nonexistent snapshots */
1562 1563 return (error == ENOENT ? 0 : error);
1563 1564 }
1564 1565
1565 1566 /* new name should not exist */
1566 1567 error = dsl_dataset_snap_lookup(hds, ddrsa->ddrsa_newsnapname, &val);
1567 1568 if (error == 0)
1568 1569 error = SET_ERROR(EEXIST);
1569 1570 else if (error == ENOENT)
1570 1571 error = 0;
1571 1572
1572 1573 /* dataset name + 1 for the "@" + the new snapshot name must fit */
1573 1574 if (dsl_dir_namelen(hds->ds_dir) + 1 +
1574 1575 strlen(ddrsa->ddrsa_newsnapname) >= MAXNAMELEN)
1575 1576 error = SET_ERROR(ENAMETOOLONG);
1576 1577
1577 1578 return (error);
1578 1579 }
1579 1580
1580 1581 static int
1581 1582 dsl_dataset_rename_snapshot_check(void *arg, dmu_tx_t *tx)
1582 1583 {
1583 1584 dsl_dataset_rename_snapshot_arg_t *ddrsa = arg;
1584 1585 dsl_pool_t *dp = dmu_tx_pool(tx);
1585 1586 dsl_dataset_t *hds;
1586 1587 int error;
1587 1588
1588 1589 error = dsl_dataset_hold(dp, ddrsa->ddrsa_fsname, FTAG, &hds);
1589 1590 if (error != 0)
1590 1591 return (error);
1591 1592
1592 1593 if (ddrsa->ddrsa_recursive) {
1593 1594 error = dmu_objset_find_dp(dp, hds->ds_dir->dd_object,
1594 1595 dsl_dataset_rename_snapshot_check_impl, ddrsa,
1595 1596 DS_FIND_CHILDREN);
1596 1597 } else {
1597 1598 error = dsl_dataset_rename_snapshot_check_impl(dp, hds, ddrsa);
1598 1599 }
1599 1600 dsl_dataset_rele(hds, FTAG);
1600 1601 return (error);
1601 1602 }
1602 1603
1603 1604 static int
1604 1605 dsl_dataset_rename_snapshot_sync_impl(dsl_pool_t *dp,
1605 1606 dsl_dataset_t *hds, void *arg)
1606 1607 {
1607 1608 dsl_dataset_rename_snapshot_arg_t *ddrsa = arg;
1608 1609 dsl_dataset_t *ds;
1609 1610 uint64_t val;
1610 1611 dmu_tx_t *tx = ddrsa->ddrsa_tx;
1611 1612 int error;
1612 1613
1613 1614 error = dsl_dataset_snap_lookup(hds, ddrsa->ddrsa_oldsnapname, &val);
1614 1615 ASSERT(error == 0 || error == ENOENT);
1615 1616 if (error == ENOENT) {
1616 1617 /* ignore nonexistent snapshots */
1617 1618 return (0);
1618 1619 }
1619 1620
1620 1621 VERIFY0(dsl_dataset_hold_obj(dp, val, FTAG, &ds));
1621 1622
1622 1623 /* log before we change the name */
1623 1624 spa_history_log_internal_ds(ds, "rename", tx,
1624 1625 "-> @%s", ddrsa->ddrsa_newsnapname);
1625 1626
1626 1627 VERIFY0(dsl_dataset_snap_remove(hds, ddrsa->ddrsa_oldsnapname, tx));
1627 1628 mutex_enter(&ds->ds_lock);
1628 1629 (void) strcpy(ds->ds_snapname, ddrsa->ddrsa_newsnapname);
1629 1630 mutex_exit(&ds->ds_lock);
1630 1631 VERIFY0(zap_add(dp->dp_meta_objset, hds->ds_phys->ds_snapnames_zapobj,
1631 1632 ds->ds_snapname, 8, 1, &ds->ds_object, tx));
1632 1633
1633 1634 dsl_dataset_rele(ds, FTAG);
1634 1635 return (0);
1635 1636 }
1636 1637
1637 1638 static void
1638 1639 dsl_dataset_rename_snapshot_sync(void *arg, dmu_tx_t *tx)
1639 1640 {
1640 1641 dsl_dataset_rename_snapshot_arg_t *ddrsa = arg;
1641 1642 dsl_pool_t *dp = dmu_tx_pool(tx);
1642 1643 dsl_dataset_t *hds;
1643 1644
1644 1645 VERIFY0(dsl_dataset_hold(dp, ddrsa->ddrsa_fsname, FTAG, &hds));
1645 1646 ddrsa->ddrsa_tx = tx;
1646 1647 if (ddrsa->ddrsa_recursive) {
1647 1648 VERIFY0(dmu_objset_find_dp(dp, hds->ds_dir->dd_object,
1648 1649 dsl_dataset_rename_snapshot_sync_impl, ddrsa,
1649 1650 DS_FIND_CHILDREN));
1650 1651 } else {
1651 1652 VERIFY0(dsl_dataset_rename_snapshot_sync_impl(dp, hds, ddrsa));
1652 1653 }
1653 1654 dsl_dataset_rele(hds, FTAG);
1654 1655 }
1655 1656
1656 1657 int
1657 1658 dsl_dataset_rename_snapshot(const char *fsname,
1658 1659 const char *oldsnapname, const char *newsnapname, boolean_t recursive)
1659 1660 {
1660 1661 dsl_dataset_rename_snapshot_arg_t ddrsa;
1661 1662
1662 1663 ddrsa.ddrsa_fsname = fsname;
1663 1664 ddrsa.ddrsa_oldsnapname = oldsnapname;
1664 1665 ddrsa.ddrsa_newsnapname = newsnapname;
1665 1666 ddrsa.ddrsa_recursive = recursive;
1666 1667
1667 1668 return (dsl_sync_task(fsname, dsl_dataset_rename_snapshot_check,
1668 1669 dsl_dataset_rename_snapshot_sync, &ddrsa, 1));
1669 1670 }
1670 1671
1671 1672 /*
1672 1673 * If we're doing an ownership handoff, we need to make sure that there is
1673 1674 * only one long hold on the dataset. We're not allowed to change anything here
1674 1675 * so we don't permanently release the long hold or regular hold here. We want
1675 1676 * to do this only when syncing to avoid the dataset unexpectedly going away
1676 1677 * when we release the long hold.
1677 1678 */
1678 1679 static int
1679 1680 dsl_dataset_handoff_check(dsl_dataset_t *ds, void *owner, dmu_tx_t *tx)
1680 1681 {
1681 1682 boolean_t held;
1682 1683
1683 1684 if (!dmu_tx_is_syncing(tx))
1684 1685 return (0);
1685 1686
1686 1687 if (owner != NULL) {
1687 1688 VERIFY3P(ds->ds_owner, ==, owner);
1688 1689 dsl_dataset_long_rele(ds, owner);
1689 1690 }
1690 1691
1691 1692 held = dsl_dataset_long_held(ds);
1692 1693
1693 1694 if (owner != NULL)
1694 1695 dsl_dataset_long_hold(ds, owner);
1695 1696
1696 1697 if (held)
1697 1698 return (SET_ERROR(EBUSY));
1698 1699
1699 1700 return (0);
1700 1701 }
1701 1702
1702 1703 typedef struct dsl_dataset_rollback_arg {
1703 1704 const char *ddra_fsname;
1704 1705 void *ddra_owner;
1705 1706 nvlist_t *ddra_result;
1706 1707 } dsl_dataset_rollback_arg_t;
1707 1708
1708 1709 static int
1709 1710 dsl_dataset_rollback_check(void *arg, dmu_tx_t *tx)
1710 1711 {
1711 1712 dsl_dataset_rollback_arg_t *ddra = arg;
1712 1713 dsl_pool_t *dp = dmu_tx_pool(tx);
1713 1714 dsl_dataset_t *ds;
1714 1715 int64_t unused_refres_delta;
1715 1716 int error;
1716 1717
1717 1718 error = dsl_dataset_hold(dp, ddra->ddra_fsname, FTAG, &ds);
1718 1719 if (error != 0)
1719 1720 return (error);
1720 1721
1721 1722 /* must not be a snapshot */
1722 1723 if (dsl_dataset_is_snapshot(ds)) {
1723 1724 dsl_dataset_rele(ds, FTAG);
1724 1725 return (SET_ERROR(EINVAL));
1725 1726 }
1726 1727
1727 1728 /* must have a most recent snapshot */
1728 1729 if (ds->ds_phys->ds_prev_snap_txg < TXG_INITIAL) {
1729 1730 dsl_dataset_rele(ds, FTAG);
1730 1731 return (SET_ERROR(EINVAL));
1731 1732 }
1732 1733
1733 1734 /* must not have any bookmarks after the most recent snapshot */
1734 1735 nvlist_t *proprequest = fnvlist_alloc();
1735 1736 fnvlist_add_boolean(proprequest, zfs_prop_to_name(ZFS_PROP_CREATETXG));
1736 1737 nvlist_t *bookmarks = fnvlist_alloc();
1737 1738 error = dsl_get_bookmarks_impl(ds, proprequest, bookmarks);
1738 1739 fnvlist_free(proprequest);
1739 1740 if (error != 0)
1740 1741 return (error);
1741 1742 for (nvpair_t *pair = nvlist_next_nvpair(bookmarks, NULL);
1742 1743 pair != NULL; pair = nvlist_next_nvpair(bookmarks, pair)) {
1743 1744 nvlist_t *valuenv =
1744 1745 fnvlist_lookup_nvlist(fnvpair_value_nvlist(pair),
1745 1746 zfs_prop_to_name(ZFS_PROP_CREATETXG));
1746 1747 uint64_t createtxg = fnvlist_lookup_uint64(valuenv, "value");
1747 1748 if (createtxg > ds->ds_phys->ds_prev_snap_txg) {
1748 1749 fnvlist_free(bookmarks);
1749 1750 dsl_dataset_rele(ds, FTAG);
1750 1751 return (SET_ERROR(EEXIST));
1751 1752 }
1752 1753 }
1753 1754 fnvlist_free(bookmarks);
1754 1755
1755 1756 error = dsl_dataset_handoff_check(ds, ddra->ddra_owner, tx);
1756 1757 if (error != 0) {
1757 1758 dsl_dataset_rele(ds, FTAG);
1758 1759 return (error);
1759 1760 }
1760 1761
1761 1762 /*
1762 1763 * Check if the snap we are rolling back to uses more than
1763 1764 * the refquota.
1764 1765 */
1765 1766 if (ds->ds_quota != 0 &&
1766 1767 ds->ds_prev->ds_phys->ds_referenced_bytes > ds->ds_quota) {
1767 1768 dsl_dataset_rele(ds, FTAG);
1768 1769 return (SET_ERROR(EDQUOT));
1769 1770 }
1770 1771
1771 1772 /*
1772 1773 * When we do the clone swap, we will temporarily use more space
1773 1774 * due to the refreservation (the head will no longer have any
1774 1775 * unique space, so the entire amount of the refreservation will need
1775 1776 * to be free). We will immediately destroy the clone, freeing
1776 1777 * this space, but the freeing happens over many txg's.
1777 1778 */
1778 1779 unused_refres_delta = (int64_t)MIN(ds->ds_reserved,
1779 1780 ds->ds_phys->ds_unique_bytes);
1780 1781
1781 1782 if (unused_refres_delta > 0 &&
1782 1783 unused_refres_delta >
1783 1784 dsl_dir_space_available(ds->ds_dir, NULL, 0, TRUE)) {
1784 1785 dsl_dataset_rele(ds, FTAG);
1785 1786 return (SET_ERROR(ENOSPC));
1786 1787 }
1787 1788
1788 1789 dsl_dataset_rele(ds, FTAG);
1789 1790 return (0);
1790 1791 }
1791 1792
1792 1793 static void
1793 1794 dsl_dataset_rollback_sync(void *arg, dmu_tx_t *tx)
1794 1795 {
1795 1796 dsl_dataset_rollback_arg_t *ddra = arg;
1796 1797 dsl_pool_t *dp = dmu_tx_pool(tx);
1797 1798 dsl_dataset_t *ds, *clone;
1798 1799 uint64_t cloneobj;
1799 1800 char namebuf[ZFS_MAXNAMELEN];
1800 1801
1801 1802 VERIFY0(dsl_dataset_hold(dp, ddra->ddra_fsname, FTAG, &ds));
1802 1803
1803 1804 dsl_dataset_name(ds->ds_prev, namebuf);
1804 1805 fnvlist_add_string(ddra->ddra_result, "target", namebuf);
1805 1806
1806 1807 cloneobj = dsl_dataset_create_sync(ds->ds_dir, "%rollback",
1807 1808 ds->ds_prev, DS_CREATE_FLAG_NODIRTY, kcred, tx);
1808 1809
1809 1810 VERIFY0(dsl_dataset_hold_obj(dp, cloneobj, FTAG, &clone));
1810 1811
1811 1812 dsl_dataset_clone_swap_sync_impl(clone, ds, tx);
1812 1813 dsl_dataset_zero_zil(ds, tx);
1813 1814
1814 1815 dsl_destroy_head_sync_impl(clone, tx);
1815 1816
1816 1817 dsl_dataset_rele(clone, FTAG);
1817 1818 dsl_dataset_rele(ds, FTAG);
1818 1819 }
1819 1820
1820 1821 /*
1821 1822 * Rolls back the given filesystem or volume to the most recent snapshot.
1822 1823 * The name of the most recent snapshot will be returned under key "target"
1823 1824 * in the result nvlist.
1824 1825 *
1825 1826 * If owner != NULL:
1826 1827 * - The existing dataset MUST be owned by the specified owner at entry
1827 1828 * - Upon return, dataset will still be held by the same owner, whether we
1828 1829 * succeed or not.
1829 1830 *
1830 1831 * This mode is required any time the existing filesystem is mounted. See
1831 1832 * notes above zfs_suspend_fs() for further details.
1832 1833 */
1833 1834 int
1834 1835 dsl_dataset_rollback(const char *fsname, void *owner, nvlist_t *result)
1835 1836 {
1836 1837 dsl_dataset_rollback_arg_t ddra;
1837 1838
1838 1839 ddra.ddra_fsname = fsname;
1839 1840 ddra.ddra_owner = owner;
1840 1841 ddra.ddra_result = result;
1841 1842
1842 1843 return (dsl_sync_task(fsname, dsl_dataset_rollback_check,
1843 1844 dsl_dataset_rollback_sync, &ddra, 1));
1844 1845 }
1845 1846
1846 1847 struct promotenode {
1847 1848 list_node_t link;
1848 1849 dsl_dataset_t *ds;
1849 1850 };
1850 1851
1851 1852 typedef struct dsl_dataset_promote_arg {
1852 1853 const char *ddpa_clonename;
1853 1854 dsl_dataset_t *ddpa_clone;
1854 1855 list_t shared_snaps, origin_snaps, clone_snaps;
1855 1856 dsl_dataset_t *origin_origin; /* origin of the origin */
1856 1857 uint64_t used, comp, uncomp, unique, cloneusedsnap, originusedsnap;
1857 1858 char *err_ds;
1858 1859 } dsl_dataset_promote_arg_t;
1859 1860
1860 1861 static int snaplist_space(list_t *l, uint64_t mintxg, uint64_t *spacep);
1861 1862 static int promote_hold(dsl_dataset_promote_arg_t *ddpa, dsl_pool_t *dp,
1862 1863 void *tag);
1863 1864 static void promote_rele(dsl_dataset_promote_arg_t *ddpa, void *tag);
1864 1865
1865 1866 static int
1866 1867 dsl_dataset_promote_check(void *arg, dmu_tx_t *tx)
1867 1868 {
1868 1869 dsl_dataset_promote_arg_t *ddpa = arg;
1869 1870 dsl_pool_t *dp = dmu_tx_pool(tx);
1870 1871 dsl_dataset_t *hds;
1871 1872 struct promotenode *snap;
1872 1873 dsl_dataset_t *origin_ds;
1873 1874 int err;
1874 1875 uint64_t unused;
1875 1876
1876 1877 err = promote_hold(ddpa, dp, FTAG);
1877 1878 if (err != 0)
1878 1879 return (err);
1879 1880
1880 1881 hds = ddpa->ddpa_clone;
1881 1882
1882 1883 if (hds->ds_phys->ds_flags & DS_FLAG_NOPROMOTE) {
1883 1884 promote_rele(ddpa, FTAG);
1884 1885 return (SET_ERROR(EXDEV));
1885 1886 }
1886 1887
1887 1888 /*
1888 1889 * Compute and check the amount of space to transfer. Since this is
1889 1890 * so expensive, don't do the preliminary check.
1890 1891 */
1891 1892 if (!dmu_tx_is_syncing(tx)) {
1892 1893 promote_rele(ddpa, FTAG);
1893 1894 return (0);
1894 1895 }
1895 1896
1896 1897 snap = list_head(&ddpa->shared_snaps);
1897 1898 origin_ds = snap->ds;
1898 1899
1899 1900 /* compute origin's new unique space */
1900 1901 snap = list_tail(&ddpa->clone_snaps);
1901 1902 ASSERT3U(snap->ds->ds_phys->ds_prev_snap_obj, ==, origin_ds->ds_object);
1902 1903 dsl_deadlist_space_range(&snap->ds->ds_deadlist,
1903 1904 origin_ds->ds_phys->ds_prev_snap_txg, UINT64_MAX,
1904 1905 &ddpa->unique, &unused, &unused);
1905 1906
1906 1907 /*
1907 1908 * Walk the snapshots that we are moving
1908 1909 *
1909 1910 * Compute space to transfer. Consider the incremental changes
1910 1911 * to used by each snapshot:
1911 1912 * (my used) = (prev's used) + (blocks born) - (blocks killed)
1912 1913 * So each snapshot gave birth to:
1913 1914 * (blocks born) = (my used) - (prev's used) + (blocks killed)
1914 1915 * So a sequence would look like:
1915 1916 * (uN - u(N-1) + kN) + ... + (u1 - u0 + k1) + (u0 - 0 + k0)
1916 1917 * Which simplifies to:
1917 1918 * uN + kN + kN-1 + ... + k1 + k0
1918 1919 * Note however, if we stop before we reach the ORIGIN we get:
1919 1920 * uN + kN + kN-1 + ... + kM - uM-1
1920 1921 */
1921 1922 ddpa->used = origin_ds->ds_phys->ds_referenced_bytes;
1922 1923 ddpa->comp = origin_ds->ds_phys->ds_compressed_bytes;
1923 1924 ddpa->uncomp = origin_ds->ds_phys->ds_uncompressed_bytes;
1924 1925 for (snap = list_head(&ddpa->shared_snaps); snap;
1925 1926 snap = list_next(&ddpa->shared_snaps, snap)) {
1926 1927 uint64_t val, dlused, dlcomp, dluncomp;
1927 1928 dsl_dataset_t *ds = snap->ds;
1928 1929
1929 1930 /*
1930 1931 * If there are long holds, we won't be able to evict
1931 1932 * the objset.
1932 1933 */
1933 1934 if (dsl_dataset_long_held(ds)) {
1934 1935 err = SET_ERROR(EBUSY);
1935 1936 goto out;
1936 1937 }
1937 1938
1938 1939 /* Check that the snapshot name does not conflict */
1939 1940 VERIFY0(dsl_dataset_get_snapname(ds));
1940 1941 err = dsl_dataset_snap_lookup(hds, ds->ds_snapname, &val);
1941 1942 if (err == 0) {
1942 1943 (void) strcpy(ddpa->err_ds, snap->ds->ds_snapname);
1943 1944 err = SET_ERROR(EEXIST);
1944 1945 goto out;
1945 1946 }
1946 1947 if (err != ENOENT)
1947 1948 goto out;
1948 1949
1949 1950 /* The very first snapshot does not have a deadlist */
1950 1951 if (ds->ds_phys->ds_prev_snap_obj == 0)
1951 1952 continue;
1952 1953
1953 1954 dsl_deadlist_space(&ds->ds_deadlist,
1954 1955 &dlused, &dlcomp, &dluncomp);
1955 1956 ddpa->used += dlused;
1956 1957 ddpa->comp += dlcomp;
1957 1958 ddpa->uncomp += dluncomp;
1958 1959 }
1959 1960
1960 1961 /*
1961 1962 * If we are a clone of a clone then we never reached ORIGIN,
1962 1963 * so we need to subtract out the clone origin's used space.
1963 1964 */
1964 1965 if (ddpa->origin_origin) {
1965 1966 ddpa->used -= ddpa->origin_origin->ds_phys->ds_referenced_bytes;
1966 1967 ddpa->comp -= ddpa->origin_origin->ds_phys->ds_compressed_bytes;
1967 1968 ddpa->uncomp -=
1968 1969 ddpa->origin_origin->ds_phys->ds_uncompressed_bytes;
1969 1970 }
1970 1971
1971 1972 /* Check that there is enough space here */
1972 1973 err = dsl_dir_transfer_possible(origin_ds->ds_dir, hds->ds_dir,
1973 1974 ddpa->used);
1974 1975 if (err != 0)
1975 1976 goto out;
1976 1977
1977 1978 /*
1978 1979 * Compute the amounts of space that will be used by snapshots
1979 1980 * after the promotion (for both origin and clone). For each,
1980 1981 * it is the amount of space that will be on all of their
1981 1982 * deadlists (that was not born before their new origin).
1982 1983 */
1983 1984 if (hds->ds_dir->dd_phys->dd_flags & DD_FLAG_USED_BREAKDOWN) {
1984 1985 uint64_t space;
1985 1986
1986 1987 /*
1987 1988 * Note, typically this will not be a clone of a clone,
1988 1989 * so dd_origin_txg will be < TXG_INITIAL, so
1989 1990 * these snaplist_space() -> dsl_deadlist_space_range()
1990 1991 * calls will be fast because they do not have to
1991 1992 * iterate over all bps.
1992 1993 */
1993 1994 snap = list_head(&ddpa->origin_snaps);
1994 1995 err = snaplist_space(&ddpa->shared_snaps,
1995 1996 snap->ds->ds_dir->dd_origin_txg, &ddpa->cloneusedsnap);
1996 1997 if (err != 0)
1997 1998 goto out;
1998 1999
1999 2000 err = snaplist_space(&ddpa->clone_snaps,
2000 2001 snap->ds->ds_dir->dd_origin_txg, &space);
2001 2002 if (err != 0)
2002 2003 goto out;
2003 2004 ddpa->cloneusedsnap += space;
2004 2005 }
2005 2006 if (origin_ds->ds_dir->dd_phys->dd_flags & DD_FLAG_USED_BREAKDOWN) {
2006 2007 err = snaplist_space(&ddpa->origin_snaps,
2007 2008 origin_ds->ds_phys->ds_creation_txg, &ddpa->originusedsnap);
2008 2009 if (err != 0)
2009 2010 goto out;
2010 2011 }
2011 2012
2012 2013 out:
2013 2014 promote_rele(ddpa, FTAG);
2014 2015 return (err);
2015 2016 }
2016 2017
2017 2018 static void
2018 2019 dsl_dataset_promote_sync(void *arg, dmu_tx_t *tx)
2019 2020 {
2020 2021 dsl_dataset_promote_arg_t *ddpa = arg;
2021 2022 dsl_pool_t *dp = dmu_tx_pool(tx);
2022 2023 dsl_dataset_t *hds;
2023 2024 struct promotenode *snap;
2024 2025 dsl_dataset_t *origin_ds;
2025 2026 dsl_dataset_t *origin_head;
2026 2027 dsl_dir_t *dd;
2027 2028 dsl_dir_t *odd = NULL;
2028 2029 uint64_t oldnext_obj;
2029 2030 int64_t delta;
2030 2031
2031 2032 VERIFY0(promote_hold(ddpa, dp, FTAG));
2032 2033 hds = ddpa->ddpa_clone;
2033 2034
2034 2035 ASSERT0(hds->ds_phys->ds_flags & DS_FLAG_NOPROMOTE);
2035 2036
2036 2037 snap = list_head(&ddpa->shared_snaps);
2037 2038 origin_ds = snap->ds;
2038 2039 dd = hds->ds_dir;
2039 2040
2040 2041 snap = list_head(&ddpa->origin_snaps);
2041 2042 origin_head = snap->ds;
2042 2043
2043 2044 /*
2044 2045 * We need to explicitly open odd, since origin_ds's dd will be
2045 2046 * changing.
2046 2047 */
2047 2048 VERIFY0(dsl_dir_hold_obj(dp, origin_ds->ds_dir->dd_object,
2048 2049 NULL, FTAG, &odd));
2049 2050
2050 2051 /* change origin's next snap */
2051 2052 dmu_buf_will_dirty(origin_ds->ds_dbuf, tx);
2052 2053 oldnext_obj = origin_ds->ds_phys->ds_next_snap_obj;
2053 2054 snap = list_tail(&ddpa->clone_snaps);
2054 2055 ASSERT3U(snap->ds->ds_phys->ds_prev_snap_obj, ==, origin_ds->ds_object);
2055 2056 origin_ds->ds_phys->ds_next_snap_obj = snap->ds->ds_object;
2056 2057
2057 2058 /* change the origin's next clone */
2058 2059 if (origin_ds->ds_phys->ds_next_clones_obj) {
2059 2060 dsl_dataset_remove_from_next_clones(origin_ds,
2060 2061 snap->ds->ds_object, tx);
2061 2062 VERIFY0(zap_add_int(dp->dp_meta_objset,
2062 2063 origin_ds->ds_phys->ds_next_clones_obj,
2063 2064 oldnext_obj, tx));
2064 2065 }
2065 2066
2066 2067 /* change origin */
2067 2068 dmu_buf_will_dirty(dd->dd_dbuf, tx);
2068 2069 ASSERT3U(dd->dd_phys->dd_origin_obj, ==, origin_ds->ds_object);
2069 2070 dd->dd_phys->dd_origin_obj = odd->dd_phys->dd_origin_obj;
2070 2071 dd->dd_origin_txg = origin_head->ds_dir->dd_origin_txg;
2071 2072 dmu_buf_will_dirty(odd->dd_dbuf, tx);
2072 2073 odd->dd_phys->dd_origin_obj = origin_ds->ds_object;
2073 2074 origin_head->ds_dir->dd_origin_txg =
2074 2075 origin_ds->ds_phys->ds_creation_txg;
2075 2076
2076 2077 /* change dd_clone entries */
2077 2078 if (spa_version(dp->dp_spa) >= SPA_VERSION_DIR_CLONES) {
2078 2079 VERIFY0(zap_remove_int(dp->dp_meta_objset,
2079 2080 odd->dd_phys->dd_clones, hds->ds_object, tx));
2080 2081 VERIFY0(zap_add_int(dp->dp_meta_objset,
2081 2082 ddpa->origin_origin->ds_dir->dd_phys->dd_clones,
2082 2083 hds->ds_object, tx));
2083 2084
2084 2085 VERIFY0(zap_remove_int(dp->dp_meta_objset,
2085 2086 ddpa->origin_origin->ds_dir->dd_phys->dd_clones,
2086 2087 origin_head->ds_object, tx));
2087 2088 if (dd->dd_phys->dd_clones == 0) {
2088 2089 dd->dd_phys->dd_clones = zap_create(dp->dp_meta_objset,
2089 2090 DMU_OT_DSL_CLONES, DMU_OT_NONE, 0, tx);
2090 2091 }
2091 2092 VERIFY0(zap_add_int(dp->dp_meta_objset,
2092 2093 dd->dd_phys->dd_clones, origin_head->ds_object, tx));
2093 2094 }
2094 2095
2095 2096 /* move snapshots to this dir */
2096 2097 for (snap = list_head(&ddpa->shared_snaps); snap;
2097 2098 snap = list_next(&ddpa->shared_snaps, snap)) {
2098 2099 dsl_dataset_t *ds = snap->ds;
2099 2100
2100 2101 /*
2101 2102 * Property callbacks are registered to a particular
2102 2103 * dsl_dir. Since ours is changing, evict the objset
2103 2104 * so that they will be unregistered from the old dsl_dir.
2104 2105 */
2105 2106 if (ds->ds_objset) {
2106 2107 dmu_objset_evict(ds->ds_objset);
2107 2108 ds->ds_objset = NULL;
2108 2109 }
2109 2110
2110 2111 /* move snap name entry */
2111 2112 VERIFY0(dsl_dataset_get_snapname(ds));
2112 2113 VERIFY0(dsl_dataset_snap_remove(origin_head,
2113 2114 ds->ds_snapname, tx));
2114 2115 VERIFY0(zap_add(dp->dp_meta_objset,
2115 2116 hds->ds_phys->ds_snapnames_zapobj, ds->ds_snapname,
2116 2117 8, 1, &ds->ds_object, tx));
2117 2118
2118 2119 /* change containing dsl_dir */
2119 2120 dmu_buf_will_dirty(ds->ds_dbuf, tx);
2120 2121 ASSERT3U(ds->ds_phys->ds_dir_obj, ==, odd->dd_object);
2121 2122 ds->ds_phys->ds_dir_obj = dd->dd_object;
2122 2123 ASSERT3P(ds->ds_dir, ==, odd);
2123 2124 dsl_dir_rele(ds->ds_dir, ds);
2124 2125 VERIFY0(dsl_dir_hold_obj(dp, dd->dd_object,
2125 2126 NULL, ds, &ds->ds_dir));
2126 2127
2127 2128 /* move any clone references */
2128 2129 if (ds->ds_phys->ds_next_clones_obj &&
2129 2130 spa_version(dp->dp_spa) >= SPA_VERSION_DIR_CLONES) {
2130 2131 zap_cursor_t zc;
2131 2132 zap_attribute_t za;
2132 2133
2133 2134 for (zap_cursor_init(&zc, dp->dp_meta_objset,
2134 2135 ds->ds_phys->ds_next_clones_obj);
2135 2136 zap_cursor_retrieve(&zc, &za) == 0;
2136 2137 zap_cursor_advance(&zc)) {
2137 2138 dsl_dataset_t *cnds;
2138 2139 uint64_t o;
2139 2140
2140 2141 if (za.za_first_integer == oldnext_obj) {
2141 2142 /*
2142 2143 * We've already moved the
2143 2144 * origin's reference.
2144 2145 */
2145 2146 continue;
2146 2147 }
2147 2148
2148 2149 VERIFY0(dsl_dataset_hold_obj(dp,
2149 2150 za.za_first_integer, FTAG, &cnds));
2150 2151 o = cnds->ds_dir->dd_phys->dd_head_dataset_obj;
2151 2152
2152 2153 VERIFY0(zap_remove_int(dp->dp_meta_objset,
2153 2154 odd->dd_phys->dd_clones, o, tx));
2154 2155 VERIFY0(zap_add_int(dp->dp_meta_objset,
2155 2156 dd->dd_phys->dd_clones, o, tx));
2156 2157 dsl_dataset_rele(cnds, FTAG);
2157 2158 }
2158 2159 zap_cursor_fini(&zc);
2159 2160 }
2160 2161
2161 2162 ASSERT(!dsl_prop_hascb(ds));
2162 2163 }
2163 2164
2164 2165 /*
2165 2166 * Change space accounting.
2166 2167 * Note, pa->*usedsnap and dd_used_breakdown[SNAP] will either
2167 2168 * both be valid, or both be 0 (resulting in delta == 0). This
2168 2169 * is true for each of {clone,origin} independently.
2169 2170 */
2170 2171
2171 2172 delta = ddpa->cloneusedsnap -
2172 2173 dd->dd_phys->dd_used_breakdown[DD_USED_SNAP];
2173 2174 ASSERT3S(delta, >=, 0);
2174 2175 ASSERT3U(ddpa->used, >=, delta);
2175 2176 dsl_dir_diduse_space(dd, DD_USED_SNAP, delta, 0, 0, tx);
2176 2177 dsl_dir_diduse_space(dd, DD_USED_HEAD,
2177 2178 ddpa->used - delta, ddpa->comp, ddpa->uncomp, tx);
2178 2179
2179 2180 delta = ddpa->originusedsnap -
2180 2181 odd->dd_phys->dd_used_breakdown[DD_USED_SNAP];
2181 2182 ASSERT3S(delta, <=, 0);
2182 2183 ASSERT3U(ddpa->used, >=, -delta);
2183 2184 dsl_dir_diduse_space(odd, DD_USED_SNAP, delta, 0, 0, tx);
2184 2185 dsl_dir_diduse_space(odd, DD_USED_HEAD,
2185 2186 -ddpa->used - delta, -ddpa->comp, -ddpa->uncomp, tx);
2186 2187
2187 2188 origin_ds->ds_phys->ds_unique_bytes = ddpa->unique;
2188 2189
2189 2190 /* log history record */
2190 2191 spa_history_log_internal_ds(hds, "promote", tx, "");
2191 2192
2192 2193 dsl_dir_rele(odd, FTAG);
2193 2194 promote_rele(ddpa, FTAG);
2194 2195 }
2195 2196
2196 2197 /*
2197 2198 * Make a list of dsl_dataset_t's for the snapshots between first_obj
2198 2199 * (exclusive) and last_obj (inclusive). The list will be in reverse
2199 2200 * order (last_obj will be the list_head()). If first_obj == 0, do all
2200 2201 * snapshots back to this dataset's origin.
2201 2202 */
2202 2203 static int
2203 2204 snaplist_make(dsl_pool_t *dp,
2204 2205 uint64_t first_obj, uint64_t last_obj, list_t *l, void *tag)
2205 2206 {
2206 2207 uint64_t obj = last_obj;
2207 2208
2208 2209 list_create(l, sizeof (struct promotenode),
2209 2210 offsetof(struct promotenode, link));
2210 2211
2211 2212 while (obj != first_obj) {
2212 2213 dsl_dataset_t *ds;
2213 2214 struct promotenode *snap;
2214 2215 int err;
2215 2216
2216 2217 err = dsl_dataset_hold_obj(dp, obj, tag, &ds);
2217 2218 ASSERT(err != ENOENT);
2218 2219 if (err != 0)
2219 2220 return (err);
2220 2221
2221 2222 if (first_obj == 0)
2222 2223 first_obj = ds->ds_dir->dd_phys->dd_origin_obj;
2223 2224
2224 2225 snap = kmem_alloc(sizeof (*snap), KM_SLEEP);
2225 2226 snap->ds = ds;
2226 2227 list_insert_tail(l, snap);
2227 2228 obj = ds->ds_phys->ds_prev_snap_obj;
2228 2229 }
2229 2230
2230 2231 return (0);
2231 2232 }
2232 2233
2233 2234 static int
2234 2235 snaplist_space(list_t *l, uint64_t mintxg, uint64_t *spacep)
2235 2236 {
2236 2237 struct promotenode *snap;
2237 2238
2238 2239 *spacep = 0;
2239 2240 for (snap = list_head(l); snap; snap = list_next(l, snap)) {
2240 2241 uint64_t used, comp, uncomp;
2241 2242 dsl_deadlist_space_range(&snap->ds->ds_deadlist,
2242 2243 mintxg, UINT64_MAX, &used, &comp, &uncomp);
2243 2244 *spacep += used;
2244 2245 }
2245 2246 return (0);
2246 2247 }
2247 2248
2248 2249 static void
2249 2250 snaplist_destroy(list_t *l, void *tag)
2250 2251 {
2251 2252 struct promotenode *snap;
2252 2253
2253 2254 if (l == NULL || !list_link_active(&l->list_head))
2254 2255 return;
2255 2256
2256 2257 while ((snap = list_tail(l)) != NULL) {
2257 2258 list_remove(l, snap);
2258 2259 dsl_dataset_rele(snap->ds, tag);
2259 2260 kmem_free(snap, sizeof (*snap));
2260 2261 }
2261 2262 list_destroy(l);
2262 2263 }
2263 2264
2264 2265 static int
2265 2266 promote_hold(dsl_dataset_promote_arg_t *ddpa, dsl_pool_t *dp, void *tag)
2266 2267 {
2267 2268 int error;
2268 2269 dsl_dir_t *dd;
2269 2270 struct promotenode *snap;
2270 2271
2271 2272 error = dsl_dataset_hold(dp, ddpa->ddpa_clonename, tag,
2272 2273 &ddpa->ddpa_clone);
2273 2274 if (error != 0)
2274 2275 return (error);
2275 2276 dd = ddpa->ddpa_clone->ds_dir;
2276 2277
2277 2278 if (dsl_dataset_is_snapshot(ddpa->ddpa_clone) ||
2278 2279 !dsl_dir_is_clone(dd)) {
2279 2280 dsl_dataset_rele(ddpa->ddpa_clone, tag);
2280 2281 return (SET_ERROR(EINVAL));
2281 2282 }
2282 2283
2283 2284 error = snaplist_make(dp, 0, dd->dd_phys->dd_origin_obj,
2284 2285 &ddpa->shared_snaps, tag);
2285 2286 if (error != 0)
2286 2287 goto out;
2287 2288
2288 2289 error = snaplist_make(dp, 0, ddpa->ddpa_clone->ds_object,
2289 2290 &ddpa->clone_snaps, tag);
2290 2291 if (error != 0)
2291 2292 goto out;
2292 2293
2293 2294 snap = list_head(&ddpa->shared_snaps);
2294 2295 ASSERT3U(snap->ds->ds_object, ==, dd->dd_phys->dd_origin_obj);
2295 2296 error = snaplist_make(dp, dd->dd_phys->dd_origin_obj,
2296 2297 snap->ds->ds_dir->dd_phys->dd_head_dataset_obj,
2297 2298 &ddpa->origin_snaps, tag);
2298 2299 if (error != 0)
2299 2300 goto out;
2300 2301
2301 2302 if (snap->ds->ds_dir->dd_phys->dd_origin_obj != 0) {
2302 2303 error = dsl_dataset_hold_obj(dp,
2303 2304 snap->ds->ds_dir->dd_phys->dd_origin_obj,
2304 2305 tag, &ddpa->origin_origin);
2305 2306 if (error != 0)
2306 2307 goto out;
2307 2308 }
2308 2309 out:
2309 2310 if (error != 0)
2310 2311 promote_rele(ddpa, tag);
2311 2312 return (error);
2312 2313 }
2313 2314
2314 2315 static void
2315 2316 promote_rele(dsl_dataset_promote_arg_t *ddpa, void *tag)
2316 2317 {
2317 2318 snaplist_destroy(&ddpa->shared_snaps, tag);
2318 2319 snaplist_destroy(&ddpa->clone_snaps, tag);
2319 2320 snaplist_destroy(&ddpa->origin_snaps, tag);
2320 2321 if (ddpa->origin_origin != NULL)
2321 2322 dsl_dataset_rele(ddpa->origin_origin, tag);
2322 2323 dsl_dataset_rele(ddpa->ddpa_clone, tag);
2323 2324 }
2324 2325
2325 2326 /*
2326 2327 * Promote a clone.
2327 2328 *
2328 2329 * If it fails due to a conflicting snapshot name, "conflsnap" will be filled
2329 2330 * in with the name. (It must be at least MAXNAMELEN bytes long.)
2330 2331 */
2331 2332 int
2332 2333 dsl_dataset_promote(const char *name, char *conflsnap)
2333 2334 {
2334 2335 dsl_dataset_promote_arg_t ddpa = { 0 };
2335 2336 uint64_t numsnaps;
2336 2337 int error;
2337 2338 objset_t *os;
2338 2339
2339 2340 /*
2340 2341 * We will modify space proportional to the number of
2341 2342 * snapshots. Compute numsnaps.
2342 2343 */
2343 2344 error = dmu_objset_hold(name, FTAG, &os);
2344 2345 if (error != 0)
2345 2346 return (error);
2346 2347 error = zap_count(dmu_objset_pool(os)->dp_meta_objset,
2347 2348 dmu_objset_ds(os)->ds_phys->ds_snapnames_zapobj, &numsnaps);
2348 2349 dmu_objset_rele(os, FTAG);
2349 2350 if (error != 0)
2350 2351 return (error);
2351 2352
2352 2353 ddpa.ddpa_clonename = name;
2353 2354 ddpa.err_ds = conflsnap;
2354 2355
2355 2356 return (dsl_sync_task(name, dsl_dataset_promote_check,
2356 2357 dsl_dataset_promote_sync, &ddpa, 2 + numsnaps));
2357 2358 }
2358 2359
2359 2360 int
2360 2361 dsl_dataset_clone_swap_check_impl(dsl_dataset_t *clone,
2361 2362 dsl_dataset_t *origin_head, boolean_t force, void *owner, dmu_tx_t *tx)
2362 2363 {
2363 2364 int64_t unused_refres_delta;
2364 2365
2365 2366 /* they should both be heads */
2366 2367 if (dsl_dataset_is_snapshot(clone) ||
2367 2368 dsl_dataset_is_snapshot(origin_head))
2368 2369 return (SET_ERROR(EINVAL));
2369 2370
2370 2371 /* if we are not forcing, the branch point should be just before them */
2371 2372 if (!force && clone->ds_prev != origin_head->ds_prev)
2372 2373 return (SET_ERROR(EINVAL));
2373 2374
2374 2375 /* clone should be the clone (unless they are unrelated) */
2375 2376 if (clone->ds_prev != NULL &&
2376 2377 clone->ds_prev != clone->ds_dir->dd_pool->dp_origin_snap &&
2377 2378 origin_head->ds_dir != clone->ds_prev->ds_dir)
2378 2379 return (SET_ERROR(EINVAL));
2379 2380
2380 2381 /* the clone should be a child of the origin */
2381 2382 if (clone->ds_dir->dd_parent != origin_head->ds_dir)
2382 2383 return (SET_ERROR(EINVAL));
2383 2384
2384 2385 /* origin_head shouldn't be modified unless 'force' */
2385 2386 if (!force &&
2386 2387 dsl_dataset_modified_since_snap(origin_head, origin_head->ds_prev))
2387 2388 return (SET_ERROR(ETXTBSY));
2388 2389
2389 2390 /* origin_head should have no long holds (e.g. is not mounted) */
2390 2391 if (dsl_dataset_handoff_check(origin_head, owner, tx))
2391 2392 return (SET_ERROR(EBUSY));
2392 2393
2393 2394 /* check amount of any unconsumed refreservation */
2394 2395 unused_refres_delta =
2395 2396 (int64_t)MIN(origin_head->ds_reserved,
2396 2397 origin_head->ds_phys->ds_unique_bytes) -
2397 2398 (int64_t)MIN(origin_head->ds_reserved,
2398 2399 clone->ds_phys->ds_unique_bytes);
2399 2400
2400 2401 if (unused_refres_delta > 0 &&
2401 2402 unused_refres_delta >
2402 2403 dsl_dir_space_available(origin_head->ds_dir, NULL, 0, TRUE))
2403 2404 return (SET_ERROR(ENOSPC));
2404 2405
2405 2406 /* clone can't be over the head's refquota */
2406 2407 if (origin_head->ds_quota != 0 &&
2407 2408 clone->ds_phys->ds_referenced_bytes > origin_head->ds_quota)
2408 2409 return (SET_ERROR(EDQUOT));
2409 2410
2410 2411 return (0);
2411 2412 }
2412 2413
2413 2414 void
2414 2415 dsl_dataset_clone_swap_sync_impl(dsl_dataset_t *clone,
2415 2416 dsl_dataset_t *origin_head, dmu_tx_t *tx)
2416 2417 {
2417 2418 dsl_pool_t *dp = dmu_tx_pool(tx);
2418 2419 int64_t unused_refres_delta;
2419 2420
2420 2421 ASSERT(clone->ds_reserved == 0);
2421 2422 ASSERT(origin_head->ds_quota == 0 ||
2422 2423 clone->ds_phys->ds_unique_bytes <= origin_head->ds_quota);
2423 2424 ASSERT3P(clone->ds_prev, ==, origin_head->ds_prev);
2424 2425
2425 2426 dmu_buf_will_dirty(clone->ds_dbuf, tx);
2426 2427 dmu_buf_will_dirty(origin_head->ds_dbuf, tx);
2427 2428
2428 2429 if (clone->ds_objset != NULL) {
2429 2430 dmu_objset_evict(clone->ds_objset);
2430 2431 clone->ds_objset = NULL;
2431 2432 }
2432 2433
2433 2434 if (origin_head->ds_objset != NULL) {
2434 2435 dmu_objset_evict(origin_head->ds_objset);
2435 2436 origin_head->ds_objset = NULL;
2436 2437 }
2437 2438
2438 2439 unused_refres_delta =
2439 2440 (int64_t)MIN(origin_head->ds_reserved,
2440 2441 origin_head->ds_phys->ds_unique_bytes) -
2441 2442 (int64_t)MIN(origin_head->ds_reserved,
2442 2443 clone->ds_phys->ds_unique_bytes);
2443 2444
2444 2445 /*
2445 2446 * Reset origin's unique bytes, if it exists.
2446 2447 */
2447 2448 if (clone->ds_prev) {
2448 2449 dsl_dataset_t *origin = clone->ds_prev;
2449 2450 uint64_t comp, uncomp;
2450 2451
2451 2452 dmu_buf_will_dirty(origin->ds_dbuf, tx);
2452 2453 dsl_deadlist_space_range(&clone->ds_deadlist,
2453 2454 origin->ds_phys->ds_prev_snap_txg, UINT64_MAX,
2454 2455 &origin->ds_phys->ds_unique_bytes, &comp, &uncomp);
2455 2456 }
2456 2457
2457 2458 /* swap blkptrs */
2458 2459 {
2459 2460 blkptr_t tmp;
2460 2461 tmp = origin_head->ds_phys->ds_bp;
2461 2462 origin_head->ds_phys->ds_bp = clone->ds_phys->ds_bp;
2462 2463 clone->ds_phys->ds_bp = tmp;
2463 2464 }
2464 2465
2465 2466 /* set dd_*_bytes */
2466 2467 {
2467 2468 int64_t dused, dcomp, duncomp;
2468 2469 uint64_t cdl_used, cdl_comp, cdl_uncomp;
2469 2470 uint64_t odl_used, odl_comp, odl_uncomp;
2470 2471
2471 2472 ASSERT3U(clone->ds_dir->dd_phys->
2472 2473 dd_used_breakdown[DD_USED_SNAP], ==, 0);
2473 2474
2474 2475 dsl_deadlist_space(&clone->ds_deadlist,
2475 2476 &cdl_used, &cdl_comp, &cdl_uncomp);
2476 2477 dsl_deadlist_space(&origin_head->ds_deadlist,
2477 2478 &odl_used, &odl_comp, &odl_uncomp);
2478 2479
2479 2480 dused = clone->ds_phys->ds_referenced_bytes + cdl_used -
2480 2481 (origin_head->ds_phys->ds_referenced_bytes + odl_used);
2481 2482 dcomp = clone->ds_phys->ds_compressed_bytes + cdl_comp -
2482 2483 (origin_head->ds_phys->ds_compressed_bytes + odl_comp);
2483 2484 duncomp = clone->ds_phys->ds_uncompressed_bytes +
2484 2485 cdl_uncomp -
2485 2486 (origin_head->ds_phys->ds_uncompressed_bytes + odl_uncomp);
2486 2487
2487 2488 dsl_dir_diduse_space(origin_head->ds_dir, DD_USED_HEAD,
2488 2489 dused, dcomp, duncomp, tx);
2489 2490 dsl_dir_diduse_space(clone->ds_dir, DD_USED_HEAD,
2490 2491 -dused, -dcomp, -duncomp, tx);
2491 2492
2492 2493 /*
2493 2494 * The difference in the space used by snapshots is the
2494 2495 * difference in snapshot space due to the head's
2495 2496 * deadlist (since that's the only thing that's
2496 2497 * changing that affects the snapused).
2497 2498 */
2498 2499 dsl_deadlist_space_range(&clone->ds_deadlist,
2499 2500 origin_head->ds_dir->dd_origin_txg, UINT64_MAX,
2500 2501 &cdl_used, &cdl_comp, &cdl_uncomp);
2501 2502 dsl_deadlist_space_range(&origin_head->ds_deadlist,
2502 2503 origin_head->ds_dir->dd_origin_txg, UINT64_MAX,
2503 2504 &odl_used, &odl_comp, &odl_uncomp);
2504 2505 dsl_dir_transfer_space(origin_head->ds_dir, cdl_used - odl_used,
2505 2506 DD_USED_HEAD, DD_USED_SNAP, tx);
2506 2507 }
2507 2508
2508 2509 /* swap ds_*_bytes */
2509 2510 SWITCH64(origin_head->ds_phys->ds_referenced_bytes,
2510 2511 clone->ds_phys->ds_referenced_bytes);
2511 2512 SWITCH64(origin_head->ds_phys->ds_compressed_bytes,
2512 2513 clone->ds_phys->ds_compressed_bytes);
2513 2514 SWITCH64(origin_head->ds_phys->ds_uncompressed_bytes,
2514 2515 clone->ds_phys->ds_uncompressed_bytes);
2515 2516 SWITCH64(origin_head->ds_phys->ds_unique_bytes,
2516 2517 clone->ds_phys->ds_unique_bytes);
2517 2518
2518 2519 /* apply any parent delta for change in unconsumed refreservation */
2519 2520 dsl_dir_diduse_space(origin_head->ds_dir, DD_USED_REFRSRV,
2520 2521 unused_refres_delta, 0, 0, tx);
2521 2522
2522 2523 /*
2523 2524 * Swap deadlists.
2524 2525 */
2525 2526 dsl_deadlist_close(&clone->ds_deadlist);
2526 2527 dsl_deadlist_close(&origin_head->ds_deadlist);
2527 2528 SWITCH64(origin_head->ds_phys->ds_deadlist_obj,
2528 2529 clone->ds_phys->ds_deadlist_obj);
2529 2530 dsl_deadlist_open(&clone->ds_deadlist, dp->dp_meta_objset,
2530 2531 clone->ds_phys->ds_deadlist_obj);
2531 2532 dsl_deadlist_open(&origin_head->ds_deadlist, dp->dp_meta_objset,
2532 2533 origin_head->ds_phys->ds_deadlist_obj);
2533 2534
2534 2535 dsl_scan_ds_clone_swapped(origin_head, clone, tx);
2535 2536
2536 2537 spa_history_log_internal_ds(clone, "clone swap", tx,
2537 2538 "parent=%s", origin_head->ds_dir->dd_myname);
2538 2539 }
2539 2540
2540 2541 /*
2541 2542 * Given a pool name and a dataset object number in that pool,
2542 2543 * return the name of that dataset.
2543 2544 */
2544 2545 int
2545 2546 dsl_dsobj_to_dsname(char *pname, uint64_t obj, char *buf)
2546 2547 {
2547 2548 dsl_pool_t *dp;
2548 2549 dsl_dataset_t *ds;
2549 2550 int error;
2550 2551
2551 2552 error = dsl_pool_hold(pname, FTAG, &dp);
2552 2553 if (error != 0)
2553 2554 return (error);
2554 2555
2555 2556 error = dsl_dataset_hold_obj(dp, obj, FTAG, &ds);
2556 2557 if (error == 0) {
2557 2558 dsl_dataset_name(ds, buf);
2558 2559 dsl_dataset_rele(ds, FTAG);
2559 2560 }
2560 2561 dsl_pool_rele(dp, FTAG);
2561 2562
2562 2563 return (error);
2563 2564 }
2564 2565
2565 2566 int
2566 2567 dsl_dataset_check_quota(dsl_dataset_t *ds, boolean_t check_quota,
2567 2568 uint64_t asize, uint64_t inflight, uint64_t *used, uint64_t *ref_rsrv)
2568 2569 {
2569 2570 int error = 0;
2570 2571
2571 2572 ASSERT3S(asize, >, 0);
2572 2573
2573 2574 /*
2574 2575 * *ref_rsrv is the portion of asize that will come from any
2575 2576 * unconsumed refreservation space.
2576 2577 */
2577 2578 *ref_rsrv = 0;
2578 2579
2579 2580 mutex_enter(&ds->ds_lock);
2580 2581 /*
2581 2582 * Make a space adjustment for reserved bytes.
2582 2583 */
2583 2584 if (ds->ds_reserved > ds->ds_phys->ds_unique_bytes) {
2584 2585 ASSERT3U(*used, >=,
2585 2586 ds->ds_reserved - ds->ds_phys->ds_unique_bytes);
2586 2587 *used -= (ds->ds_reserved - ds->ds_phys->ds_unique_bytes);
2587 2588 *ref_rsrv =
2588 2589 asize - MIN(asize, parent_delta(ds, asize + inflight));
2589 2590 }
2590 2591
2591 2592 if (!check_quota || ds->ds_quota == 0) {
2592 2593 mutex_exit(&ds->ds_lock);
2593 2594 return (0);
2594 2595 }
2595 2596 /*
2596 2597 * If they are requesting more space, and our current estimate
2597 2598 * is over quota, they get to try again unless the actual
2598 2599 * on-disk is over quota and there are no pending changes (which
2599 2600 * may free up space for us).
2600 2601 */
2601 2602 if (ds->ds_phys->ds_referenced_bytes + inflight >= ds->ds_quota) {
2602 2603 if (inflight > 0 ||
2603 2604 ds->ds_phys->ds_referenced_bytes < ds->ds_quota)
2604 2605 error = SET_ERROR(ERESTART);
2605 2606 else
2606 2607 error = SET_ERROR(EDQUOT);
2607 2608 }
2608 2609 mutex_exit(&ds->ds_lock);
2609 2610
2610 2611 return (error);
2611 2612 }
2612 2613
2613 2614 typedef struct dsl_dataset_set_qr_arg {
2614 2615 const char *ddsqra_name;
2615 2616 zprop_source_t ddsqra_source;
2616 2617 uint64_t ddsqra_value;
2617 2618 } dsl_dataset_set_qr_arg_t;
2618 2619
2619 2620
2620 2621 /* ARGSUSED */
2621 2622 static int
2622 2623 dsl_dataset_set_refquota_check(void *arg, dmu_tx_t *tx)
2623 2624 {
2624 2625 dsl_dataset_set_qr_arg_t *ddsqra = arg;
2625 2626 dsl_pool_t *dp = dmu_tx_pool(tx);
2626 2627 dsl_dataset_t *ds;
2627 2628 int error;
2628 2629 uint64_t newval;
2629 2630
2630 2631 if (spa_version(dp->dp_spa) < SPA_VERSION_REFQUOTA)
2631 2632 return (SET_ERROR(ENOTSUP));
2632 2633
2633 2634 error = dsl_dataset_hold(dp, ddsqra->ddsqra_name, FTAG, &ds);
2634 2635 if (error != 0)
2635 2636 return (error);
2636 2637
2637 2638 if (dsl_dataset_is_snapshot(ds)) {
2638 2639 dsl_dataset_rele(ds, FTAG);
2639 2640 return (SET_ERROR(EINVAL));
2640 2641 }
2641 2642
2642 2643 error = dsl_prop_predict(ds->ds_dir,
2643 2644 zfs_prop_to_name(ZFS_PROP_REFQUOTA),
2644 2645 ddsqra->ddsqra_source, ddsqra->ddsqra_value, &newval);
2645 2646 if (error != 0) {
2646 2647 dsl_dataset_rele(ds, FTAG);
2647 2648 return (error);
2648 2649 }
2649 2650
2650 2651 if (newval == 0) {
2651 2652 dsl_dataset_rele(ds, FTAG);
2652 2653 return (0);
2653 2654 }
2654 2655
2655 2656 if (newval < ds->ds_phys->ds_referenced_bytes ||
2656 2657 newval < ds->ds_reserved) {
2657 2658 dsl_dataset_rele(ds, FTAG);
2658 2659 return (SET_ERROR(ENOSPC));
2659 2660 }
2660 2661
2661 2662 dsl_dataset_rele(ds, FTAG);
2662 2663 return (0);
2663 2664 }
2664 2665
2665 2666 static void
2666 2667 dsl_dataset_set_refquota_sync(void *arg, dmu_tx_t *tx)
2667 2668 {
2668 2669 dsl_dataset_set_qr_arg_t *ddsqra = arg;
2669 2670 dsl_pool_t *dp = dmu_tx_pool(tx);
2670 2671 dsl_dataset_t *ds;
2671 2672 uint64_t newval;
2672 2673
2673 2674 VERIFY0(dsl_dataset_hold(dp, ddsqra->ddsqra_name, FTAG, &ds));
2674 2675
2675 2676 dsl_prop_set_sync_impl(ds,
2676 2677 zfs_prop_to_name(ZFS_PROP_REFQUOTA),
2677 2678 ddsqra->ddsqra_source, sizeof (ddsqra->ddsqra_value), 1,
2678 2679 &ddsqra->ddsqra_value, tx);
2679 2680
2680 2681 VERIFY0(dsl_prop_get_int_ds(ds,
2681 2682 zfs_prop_to_name(ZFS_PROP_REFQUOTA), &newval));
2682 2683
2683 2684 if (ds->ds_quota != newval) {
2684 2685 dmu_buf_will_dirty(ds->ds_dbuf, tx);
2685 2686 ds->ds_quota = newval;
2686 2687 }
2687 2688 dsl_dataset_rele(ds, FTAG);
2688 2689 }
2689 2690
2690 2691 int
2691 2692 dsl_dataset_set_refquota(const char *dsname, zprop_source_t source,
2692 2693 uint64_t refquota)
2693 2694 {
2694 2695 dsl_dataset_set_qr_arg_t ddsqra;
2695 2696
2696 2697 ddsqra.ddsqra_name = dsname;
2697 2698 ddsqra.ddsqra_source = source;
2698 2699 ddsqra.ddsqra_value = refquota;
2699 2700
2700 2701 return (dsl_sync_task(dsname, dsl_dataset_set_refquota_check,
2701 2702 dsl_dataset_set_refquota_sync, &ddsqra, 0));
2702 2703 }
2703 2704
2704 2705 static int
2705 2706 dsl_dataset_set_refreservation_check(void *arg, dmu_tx_t *tx)
2706 2707 {
2707 2708 dsl_dataset_set_qr_arg_t *ddsqra = arg;
2708 2709 dsl_pool_t *dp = dmu_tx_pool(tx);
2709 2710 dsl_dataset_t *ds;
2710 2711 int error;
2711 2712 uint64_t newval, unique;
2712 2713
2713 2714 if (spa_version(dp->dp_spa) < SPA_VERSION_REFRESERVATION)
2714 2715 return (SET_ERROR(ENOTSUP));
2715 2716
2716 2717 error = dsl_dataset_hold(dp, ddsqra->ddsqra_name, FTAG, &ds);
2717 2718 if (error != 0)
2718 2719 return (error);
2719 2720
2720 2721 if (dsl_dataset_is_snapshot(ds)) {
2721 2722 dsl_dataset_rele(ds, FTAG);
2722 2723 return (SET_ERROR(EINVAL));
2723 2724 }
2724 2725
2725 2726 error = dsl_prop_predict(ds->ds_dir,
2726 2727 zfs_prop_to_name(ZFS_PROP_REFRESERVATION),
2727 2728 ddsqra->ddsqra_source, ddsqra->ddsqra_value, &newval);
2728 2729 if (error != 0) {
2729 2730 dsl_dataset_rele(ds, FTAG);
2730 2731 return (error);
2731 2732 }
2732 2733
2733 2734 /*
2734 2735 * If we are doing the preliminary check in open context, the
2735 2736 * space estimates may be inaccurate.
2736 2737 */
2737 2738 if (!dmu_tx_is_syncing(tx)) {
2738 2739 dsl_dataset_rele(ds, FTAG);
2739 2740 return (0);
2740 2741 }
2741 2742
2742 2743 mutex_enter(&ds->ds_lock);
2743 2744 if (!DS_UNIQUE_IS_ACCURATE(ds))
2744 2745 dsl_dataset_recalc_head_uniq(ds);
2745 2746 unique = ds->ds_phys->ds_unique_bytes;
2746 2747 mutex_exit(&ds->ds_lock);
2747 2748
2748 2749 if (MAX(unique, newval) > MAX(unique, ds->ds_reserved)) {
2749 2750 uint64_t delta = MAX(unique, newval) -
2750 2751 MAX(unique, ds->ds_reserved);
2751 2752
2752 2753 if (delta >
2753 2754 dsl_dir_space_available(ds->ds_dir, NULL, 0, B_TRUE) ||
2754 2755 (ds->ds_quota > 0 && newval > ds->ds_quota)) {
2755 2756 dsl_dataset_rele(ds, FTAG);
2756 2757 return (SET_ERROR(ENOSPC));
2757 2758 }
2758 2759 }
2759 2760
2760 2761 dsl_dataset_rele(ds, FTAG);
2761 2762 return (0);
2762 2763 }
2763 2764
2764 2765 void
2765 2766 dsl_dataset_set_refreservation_sync_impl(dsl_dataset_t *ds,
2766 2767 zprop_source_t source, uint64_t value, dmu_tx_t *tx)
2767 2768 {
2768 2769 uint64_t newval;
2769 2770 uint64_t unique;
2770 2771 int64_t delta;
2771 2772
2772 2773 dsl_prop_set_sync_impl(ds, zfs_prop_to_name(ZFS_PROP_REFRESERVATION),
2773 2774 source, sizeof (value), 1, &value, tx);
2774 2775
2775 2776 VERIFY0(dsl_prop_get_int_ds(ds,
2776 2777 zfs_prop_to_name(ZFS_PROP_REFRESERVATION), &newval));
2777 2778
2778 2779 dmu_buf_will_dirty(ds->ds_dbuf, tx);
2779 2780 mutex_enter(&ds->ds_dir->dd_lock);
2780 2781 mutex_enter(&ds->ds_lock);
2781 2782 ASSERT(DS_UNIQUE_IS_ACCURATE(ds));
2782 2783 unique = ds->ds_phys->ds_unique_bytes;
2783 2784 delta = MAX(0, (int64_t)(newval - unique)) -
2784 2785 MAX(0, (int64_t)(ds->ds_reserved - unique));
2785 2786 ds->ds_reserved = newval;
2786 2787 mutex_exit(&ds->ds_lock);
2787 2788
2788 2789 dsl_dir_diduse_space(ds->ds_dir, DD_USED_REFRSRV, delta, 0, 0, tx);
2789 2790 mutex_exit(&ds->ds_dir->dd_lock);
2790 2791 }
2791 2792
2792 2793 static void
2793 2794 dsl_dataset_set_refreservation_sync(void *arg, dmu_tx_t *tx)
2794 2795 {
2795 2796 dsl_dataset_set_qr_arg_t *ddsqra = arg;
2796 2797 dsl_pool_t *dp = dmu_tx_pool(tx);
2797 2798 dsl_dataset_t *ds;
2798 2799
2799 2800 VERIFY0(dsl_dataset_hold(dp, ddsqra->ddsqra_name, FTAG, &ds));
2800 2801 dsl_dataset_set_refreservation_sync_impl(ds,
2801 2802 ddsqra->ddsqra_source, ddsqra->ddsqra_value, tx);
2802 2803 dsl_dataset_rele(ds, FTAG);
2803 2804 }
2804 2805
2805 2806 int
2806 2807 dsl_dataset_set_refreservation(const char *dsname, zprop_source_t source,
2807 2808 uint64_t refreservation)
2808 2809 {
2809 2810 dsl_dataset_set_qr_arg_t ddsqra;
2810 2811
2811 2812 ddsqra.ddsqra_name = dsname;
2812 2813 ddsqra.ddsqra_source = source;
2813 2814 ddsqra.ddsqra_value = refreservation;
2814 2815
2815 2816 return (dsl_sync_task(dsname, dsl_dataset_set_refreservation_check,
2816 2817 dsl_dataset_set_refreservation_sync, &ddsqra, 0));
2817 2818 }
2818 2819
2819 2820 /*
2820 2821 * Return (in *usedp) the amount of space written in new that is not
2821 2822 * present in oldsnap. New may be a snapshot or the head. Old must be
2822 2823 * a snapshot before new, in new's filesystem (or its origin). If not then
2823 2824 * fail and return EINVAL.
2824 2825 *
2825 2826 * The written space is calculated by considering two components: First, we
2826 2827 * ignore any freed space, and calculate the written as new's used space
2827 2828 * minus old's used space. Next, we add in the amount of space that was freed
2828 2829 * between the two snapshots, thus reducing new's used space relative to old's.
2829 2830 * Specifically, this is the space that was born before old->ds_creation_txg,
2830 2831 * and freed before new (ie. on new's deadlist or a previous deadlist).
2831 2832 *
2832 2833 * space freed [---------------------]
2833 2834 * snapshots ---O-------O--------O-------O------
2834 2835 * oldsnap new
2835 2836 */
2836 2837 int
2837 2838 dsl_dataset_space_written(dsl_dataset_t *oldsnap, dsl_dataset_t *new,
2838 2839 uint64_t *usedp, uint64_t *compp, uint64_t *uncompp)
2839 2840 {
2840 2841 int err = 0;
2841 2842 uint64_t snapobj;
2842 2843 dsl_pool_t *dp = new->ds_dir->dd_pool;
2843 2844
2844 2845 ASSERT(dsl_pool_config_held(dp));
2845 2846
2846 2847 *usedp = 0;
2847 2848 *usedp += new->ds_phys->ds_referenced_bytes;
2848 2849 *usedp -= oldsnap->ds_phys->ds_referenced_bytes;
2849 2850
2850 2851 *compp = 0;
2851 2852 *compp += new->ds_phys->ds_compressed_bytes;
2852 2853 *compp -= oldsnap->ds_phys->ds_compressed_bytes;
2853 2854
2854 2855 *uncompp = 0;
2855 2856 *uncompp += new->ds_phys->ds_uncompressed_bytes;
2856 2857 *uncompp -= oldsnap->ds_phys->ds_uncompressed_bytes;
2857 2858
2858 2859 snapobj = new->ds_object;
2859 2860 while (snapobj != oldsnap->ds_object) {
2860 2861 dsl_dataset_t *snap;
2861 2862 uint64_t used, comp, uncomp;
2862 2863
2863 2864 if (snapobj == new->ds_object) {
2864 2865 snap = new;
2865 2866 } else {
2866 2867 err = dsl_dataset_hold_obj(dp, snapobj, FTAG, &snap);
2867 2868 if (err != 0)
2868 2869 break;
2869 2870 }
2870 2871
2871 2872 if (snap->ds_phys->ds_prev_snap_txg ==
2872 2873 oldsnap->ds_phys->ds_creation_txg) {
2873 2874 /*
2874 2875 * The blocks in the deadlist can not be born after
2875 2876 * ds_prev_snap_txg, so get the whole deadlist space,
2876 2877 * which is more efficient (especially for old-format
2877 2878 * deadlists). Unfortunately the deadlist code
2878 2879 * doesn't have enough information to make this
2879 2880 * optimization itself.
2880 2881 */
2881 2882 dsl_deadlist_space(&snap->ds_deadlist,
2882 2883 &used, &comp, &uncomp);
2883 2884 } else {
2884 2885 dsl_deadlist_space_range(&snap->ds_deadlist,
2885 2886 0, oldsnap->ds_phys->ds_creation_txg,
2886 2887 &used, &comp, &uncomp);
2887 2888 }
2888 2889 *usedp += used;
2889 2890 *compp += comp;
2890 2891 *uncompp += uncomp;
2891 2892
2892 2893 /*
2893 2894 * If we get to the beginning of the chain of snapshots
2894 2895 * (ds_prev_snap_obj == 0) before oldsnap, then oldsnap
2895 2896 * was not a snapshot of/before new.
2896 2897 */
2897 2898 snapobj = snap->ds_phys->ds_prev_snap_obj;
2898 2899 if (snap != new)
2899 2900 dsl_dataset_rele(snap, FTAG);
2900 2901 if (snapobj == 0) {
2901 2902 err = SET_ERROR(EINVAL);
2902 2903 break;
2903 2904 }
2904 2905
2905 2906 }
2906 2907 return (err);
2907 2908 }
2908 2909
2909 2910 /*
2910 2911 * Return (in *usedp) the amount of space that will be reclaimed if firstsnap,
2911 2912 * lastsnap, and all snapshots in between are deleted.
2912 2913 *
2913 2914 * blocks that would be freed [---------------------------]
2914 2915 * snapshots ---O-------O--------O-------O--------O
2915 2916 * firstsnap lastsnap
2916 2917 *
2917 2918 * This is the set of blocks that were born after the snap before firstsnap,
2918 2919 * (birth > firstsnap->prev_snap_txg) and died before the snap after the
2919 2920 * last snap (ie, is on lastsnap->ds_next->ds_deadlist or an earlier deadlist).
2920 2921 * We calculate this by iterating over the relevant deadlists (from the snap
2921 2922 * after lastsnap, backward to the snap after firstsnap), summing up the
2922 2923 * space on the deadlist that was born after the snap before firstsnap.
2923 2924 */
2924 2925 int
2925 2926 dsl_dataset_space_wouldfree(dsl_dataset_t *firstsnap,
2926 2927 dsl_dataset_t *lastsnap,
2927 2928 uint64_t *usedp, uint64_t *compp, uint64_t *uncompp)
2928 2929 {
2929 2930 int err = 0;
2930 2931 uint64_t snapobj;
2931 2932 dsl_pool_t *dp = firstsnap->ds_dir->dd_pool;
2932 2933
2933 2934 ASSERT(dsl_dataset_is_snapshot(firstsnap));
2934 2935 ASSERT(dsl_dataset_is_snapshot(lastsnap));
2935 2936
2936 2937 /*
2937 2938 * Check that the snapshots are in the same dsl_dir, and firstsnap
2938 2939 * is before lastsnap.
2939 2940 */
2940 2941 if (firstsnap->ds_dir != lastsnap->ds_dir ||
2941 2942 firstsnap->ds_phys->ds_creation_txg >
2942 2943 lastsnap->ds_phys->ds_creation_txg)
2943 2944 return (SET_ERROR(EINVAL));
2944 2945
2945 2946 *usedp = *compp = *uncompp = 0;
2946 2947
2947 2948 snapobj = lastsnap->ds_phys->ds_next_snap_obj;
2948 2949 while (snapobj != firstsnap->ds_object) {
2949 2950 dsl_dataset_t *ds;
2950 2951 uint64_t used, comp, uncomp;
2951 2952
2952 2953 err = dsl_dataset_hold_obj(dp, snapobj, FTAG, &ds);
2953 2954 if (err != 0)
2954 2955 break;
2955 2956
2956 2957 dsl_deadlist_space_range(&ds->ds_deadlist,
2957 2958 firstsnap->ds_phys->ds_prev_snap_txg, UINT64_MAX,
2958 2959 &used, &comp, &uncomp);
2959 2960 *usedp += used;
2960 2961 *compp += comp;
2961 2962 *uncompp += uncomp;
2962 2963
2963 2964 snapobj = ds->ds_phys->ds_prev_snap_obj;
2964 2965 ASSERT3U(snapobj, !=, 0);
2965 2966 dsl_dataset_rele(ds, FTAG);
2966 2967 }
2967 2968 return (err);
2968 2969 }
2969 2970
2970 2971 /*
2971 2972 * Return TRUE if 'earlier' is an earlier snapshot in 'later's timeline.
2972 2973 * For example, they could both be snapshots of the same filesystem, and
2973 2974 * 'earlier' is before 'later'. Or 'earlier' could be the origin of
2974 2975 * 'later's filesystem. Or 'earlier' could be an older snapshot in the origin's
2975 2976 * filesystem. Or 'earlier' could be the origin's origin.
2976 2977 *
2977 2978 * If non-zero, earlier_txg is used instead of earlier's ds_creation_txg.
2978 2979 */
2979 2980 boolean_t
2980 2981 dsl_dataset_is_before(dsl_dataset_t *later, dsl_dataset_t *earlier,
2981 2982 uint64_t earlier_txg)
2982 2983 {
2983 2984 dsl_pool_t *dp = later->ds_dir->dd_pool;
2984 2985 int error;
2985 2986 boolean_t ret;
2986 2987
2987 2988 ASSERT(dsl_pool_config_held(dp));
2988 2989 ASSERT(dsl_dataset_is_snapshot(earlier) || earlier_txg != 0);
2989 2990
2990 2991 if (earlier_txg == 0)
2991 2992 earlier_txg = earlier->ds_phys->ds_creation_txg;
2992 2993
2993 2994 if (dsl_dataset_is_snapshot(later) &&
2994 2995 earlier_txg >= later->ds_phys->ds_creation_txg)
2995 2996 return (B_FALSE);
2996 2997
2997 2998 if (later->ds_dir == earlier->ds_dir)
2998 2999 return (B_TRUE);
2999 3000 if (!dsl_dir_is_clone(later->ds_dir))
3000 3001 return (B_FALSE);
3001 3002
3002 3003 if (later->ds_dir->dd_phys->dd_origin_obj == earlier->ds_object)
3003 3004 return (B_TRUE);
3004 3005 dsl_dataset_t *origin;
3005 3006 error = dsl_dataset_hold_obj(dp,
3006 3007 later->ds_dir->dd_phys->dd_origin_obj, FTAG, &origin);
3007 3008 if (error != 0)
3008 3009 return (B_FALSE);
3009 3010 ret = dsl_dataset_is_before(origin, earlier, earlier_txg);
3010 3011 dsl_dataset_rele(origin, FTAG);
3011 3012 return (ret);
3012 3013 }
3013 3014
3014 3015
3015 3016 void
3016 3017 dsl_dataset_zapify(dsl_dataset_t *ds, dmu_tx_t *tx)
3017 3018 {
3018 3019 objset_t *mos = ds->ds_dir->dd_pool->dp_meta_objset;
3019 3020 dmu_object_zapify(mos, ds->ds_object, DMU_OT_DSL_DATASET, tx);
3020 3021 }
↓ open down ↓ |
1643 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX