224 if (ds->ds_trysnap_txg >
225 spa_last_synced_txg(ds->ds_dir->dd_pool->dp_spa))
226 trysnap = ds->ds_trysnap_txg;
227 return (MAX(ds->ds_phys->ds_prev_snap_txg, trysnap));
228 }
229
230 boolean_t
231 dsl_dataset_block_freeable(dsl_dataset_t *ds, const blkptr_t *bp,
232 uint64_t blk_birth)
233 {
234 if (blk_birth <= dsl_dataset_prev_snap_txg(ds))
235 return (B_FALSE);
236
237 ddt_prefetch(dsl_dataset_get_spa(ds), bp);
238
239 return (B_TRUE);
240 }
241
242 /* ARGSUSED */
243 static void
244 dsl_dataset_evict(dmu_buf_t *db, void *dsv)
245 {
246 dsl_dataset_t *ds = dsv;
247
248 ASSERT(ds->ds_owner == NULL);
249
250 unique_remove(ds->ds_fsid_guid);
251
252 if (ds->ds_objset != NULL)
253 dmu_objset_evict(ds->ds_objset);
254
255 if (ds->ds_prev) {
256 dsl_dataset_rele(ds->ds_prev, ds);
257 ds->ds_prev = NULL;
258 }
259
260 bplist_destroy(&ds->ds_pending_deadlist);
261 if (ds->ds_phys->ds_deadlist_obj != 0)
262 dsl_deadlist_close(&ds->ds_deadlist);
263 if (ds->ds_dir)
264 dsl_dir_rele(ds->ds_dir, ds);
265
266 ASSERT(!list_link_active(&ds->ds_synced_link));
267
268 mutex_destroy(&ds->ds_lock);
269 mutex_destroy(&ds->ds_opening_lock);
270 refcount_destroy(&ds->ds_longholds);
271
272 kmem_free(ds, sizeof (dsl_dataset_t));
273 }
274
275 int
276 dsl_dataset_get_snapname(dsl_dataset_t *ds)
277 {
278 dsl_dataset_phys_t *headphys;
279 int err;
280 dmu_buf_t *headdbuf;
281 dsl_pool_t *dp = ds->ds_dir->dd_pool;
282 objset_t *mos = dp->dp_meta_objset;
283
284 if (ds->ds_snapname[0])
285 return (0);
286 if (ds->ds_phys->ds_next_snap_obj == 0)
287 return (0);
288
289 err = dmu_bonus_hold(mos, ds->ds_dir->dd_phys->dd_head_dataset_obj,
290 FTAG, &headdbuf);
291 if (err != 0)
292 return (err);
293 headphys = headdbuf->db_data;
294 err = zap_value_search(dp->dp_meta_objset,
342 dsl_dataset_hold_obj(dsl_pool_t *dp, uint64_t dsobj, void *tag,
343 dsl_dataset_t **dsp)
344 {
345 objset_t *mos = dp->dp_meta_objset;
346 dmu_buf_t *dbuf;
347 dsl_dataset_t *ds;
348 int err;
349 dmu_object_info_t doi;
350
351 ASSERT(dsl_pool_config_held(dp));
352
353 err = dmu_bonus_hold(mos, dsobj, tag, &dbuf);
354 if (err != 0)
355 return (err);
356
357 /* Make sure dsobj has the correct object type. */
358 dmu_object_info_from_db(dbuf, &doi);
359 if (doi.doi_type != DMU_OT_DSL_DATASET)
360 return (SET_ERROR(EINVAL));
361
362 ds = dmu_buf_get_user(dbuf);
363 if (ds == NULL) {
364 dsl_dataset_t *winner = NULL;
365
366 ds = kmem_zalloc(sizeof (dsl_dataset_t), KM_SLEEP);
367 ds->ds_dbuf = dbuf;
368 ds->ds_object = dsobj;
369 ds->ds_phys = dbuf->db_data;
370
371 mutex_init(&ds->ds_lock, NULL, MUTEX_DEFAULT, NULL);
372 mutex_init(&ds->ds_opening_lock, NULL, MUTEX_DEFAULT, NULL);
373 mutex_init(&ds->ds_sendstream_lock, NULL, MUTEX_DEFAULT, NULL);
374 refcount_create(&ds->ds_longholds);
375
376 bplist_create(&ds->ds_pending_deadlist);
377 dsl_deadlist_open(&ds->ds_deadlist,
378 mos, ds->ds_phys->ds_deadlist_obj);
379
380 list_create(&ds->ds_sendstreams, sizeof (dmu_sendarg_t),
381 offsetof(dmu_sendarg_t, dsa_link));
382
383 if (err == 0) {
384 err = dsl_dir_hold_obj(dp,
385 ds->ds_phys->ds_dir_obj, NULL, ds, &ds->ds_dir);
386 }
387 if (err != 0) {
388 mutex_destroy(&ds->ds_lock);
389 mutex_destroy(&ds->ds_opening_lock);
409 err = zap_count(
410 ds->ds_dir->dd_pool->dp_meta_objset,
411 ds->ds_phys->ds_userrefs_obj,
412 &ds->ds_userrefs);
413 }
414 }
415
416 if (err == 0 && !dsl_dataset_is_snapshot(ds)) {
417 err = dsl_prop_get_int_ds(ds,
418 zfs_prop_to_name(ZFS_PROP_REFRESERVATION),
419 &ds->ds_reserved);
420 if (err == 0) {
421 err = dsl_prop_get_int_ds(ds,
422 zfs_prop_to_name(ZFS_PROP_REFQUOTA),
423 &ds->ds_quota);
424 }
425 } else {
426 ds->ds_reserved = ds->ds_quota = 0;
427 }
428
429 if (err != 0 || (winner = dmu_buf_set_user_ie(dbuf, ds,
430 &ds->ds_phys, dsl_dataset_evict)) != NULL) {
431 bplist_destroy(&ds->ds_pending_deadlist);
432 dsl_deadlist_close(&ds->ds_deadlist);
433 if (ds->ds_prev)
434 dsl_dataset_rele(ds->ds_prev, ds);
435 dsl_dir_rele(ds->ds_dir, ds);
436 mutex_destroy(&ds->ds_lock);
437 mutex_destroy(&ds->ds_opening_lock);
438 refcount_destroy(&ds->ds_longholds);
439 kmem_free(ds, sizeof (dsl_dataset_t));
440 if (err != 0) {
441 dmu_buf_rele(dbuf, tag);
442 return (err);
443 }
444 ds = winner;
445 } else {
446 ds->ds_fsid_guid =
447 unique_insert(ds->ds_phys->ds_fsid_guid);
448 }
449 }
450 ASSERT3P(ds->ds_dbuf, ==, dbuf);
615 }
616
617 void
618 dsl_dataset_rele(dsl_dataset_t *ds, void *tag)
619 {
620 dmu_buf_rele(ds->ds_dbuf, tag);
621 }
622
623 void
624 dsl_dataset_disown(dsl_dataset_t *ds, void *tag)
625 {
626 ASSERT(ds->ds_owner == tag && ds->ds_dbuf != NULL);
627
628 mutex_enter(&ds->ds_lock);
629 ds->ds_owner = NULL;
630 mutex_exit(&ds->ds_lock);
631 dsl_dataset_long_rele(ds, tag);
632 if (ds->ds_dbuf != NULL)
633 dsl_dataset_rele(ds, tag);
634 else
635 dsl_dataset_evict(NULL, ds);
636 }
637
638 boolean_t
639 dsl_dataset_tryown(dsl_dataset_t *ds, void *tag)
640 {
641 boolean_t gotit = FALSE;
642
643 mutex_enter(&ds->ds_lock);
644 if (ds->ds_owner == NULL && !DS_IS_INCONSISTENT(ds)) {
645 ds->ds_owner = tag;
646 dsl_dataset_long_hold(ds, tag);
647 gotit = TRUE;
648 }
649 mutex_exit(&ds->ds_lock);
650 return (gotit);
651 }
652
653 uint64_t
654 dsl_dataset_create_sync_dd(dsl_dir_t *dd, dsl_dataset_t *origin,
655 uint64_t flags, dmu_tx_t *tx)
|
224 if (ds->ds_trysnap_txg >
225 spa_last_synced_txg(ds->ds_dir->dd_pool->dp_spa))
226 trysnap = ds->ds_trysnap_txg;
227 return (MAX(ds->ds_phys->ds_prev_snap_txg, trysnap));
228 }
229
230 boolean_t
231 dsl_dataset_block_freeable(dsl_dataset_t *ds, const blkptr_t *bp,
232 uint64_t blk_birth)
233 {
234 if (blk_birth <= dsl_dataset_prev_snap_txg(ds))
235 return (B_FALSE);
236
237 ddt_prefetch(dsl_dataset_get_spa(ds), bp);
238
239 return (B_TRUE);
240 }
241
242 /* ARGSUSED */
243 static void
244 dsl_dataset_evict_impl(dsl_dataset_t *ds, boolean_t evict_deadlist)
245 {
246
247 ASSERT(ds->ds_owner == NULL);
248
249 ds->ds_dbuf = NULL;
250
251 unique_remove(ds->ds_fsid_guid);
252
253 if (ds->ds_objset != NULL)
254 dmu_objset_evict(ds->ds_objset);
255
256 if (ds->ds_prev) {
257 dsl_dataset_rele(ds->ds_prev, ds);
258 ds->ds_prev = NULL;
259 }
260
261 bplist_destroy(&ds->ds_pending_deadlist);
262 if (evict_deadlist)
263 dsl_deadlist_close(&ds->ds_deadlist);
264 if (ds->ds_dir)
265 dsl_dir_rele(ds->ds_dir, ds);
266
267 ASSERT(!list_link_active(&ds->ds_synced_link));
268
269 mutex_destroy(&ds->ds_lock);
270 mutex_destroy(&ds->ds_opening_lock);
271 refcount_destroy(&ds->ds_longholds);
272
273 kmem_free(ds, sizeof (dsl_dataset_t));
274 }
275
276 /* ARGSUSED */
277 static void
278 dsl_dataset_evict(dmu_buf_user_t *dbu)
279 {
280 dsl_dataset_evict_impl((dsl_dataset_t *)dbu, B_TRUE);
281 }
282
283 int
284 dsl_dataset_get_snapname(dsl_dataset_t *ds)
285 {
286 dsl_dataset_phys_t *headphys;
287 int err;
288 dmu_buf_t *headdbuf;
289 dsl_pool_t *dp = ds->ds_dir->dd_pool;
290 objset_t *mos = dp->dp_meta_objset;
291
292 if (ds->ds_snapname[0])
293 return (0);
294 if (ds->ds_phys->ds_next_snap_obj == 0)
295 return (0);
296
297 err = dmu_bonus_hold(mos, ds->ds_dir->dd_phys->dd_head_dataset_obj,
298 FTAG, &headdbuf);
299 if (err != 0)
300 return (err);
301 headphys = headdbuf->db_data;
302 err = zap_value_search(dp->dp_meta_objset,
350 dsl_dataset_hold_obj(dsl_pool_t *dp, uint64_t dsobj, void *tag,
351 dsl_dataset_t **dsp)
352 {
353 objset_t *mos = dp->dp_meta_objset;
354 dmu_buf_t *dbuf;
355 dsl_dataset_t *ds;
356 int err;
357 dmu_object_info_t doi;
358
359 ASSERT(dsl_pool_config_held(dp));
360
361 err = dmu_bonus_hold(mos, dsobj, tag, &dbuf);
362 if (err != 0)
363 return (err);
364
365 /* Make sure dsobj has the correct object type. */
366 dmu_object_info_from_db(dbuf, &doi);
367 if (doi.doi_type != DMU_OT_DSL_DATASET)
368 return (SET_ERROR(EINVAL));
369
370 ds = (dsl_dataset_t *)dmu_buf_get_user(dbuf);
371 if (ds == NULL) {
372 dsl_dataset_t *winner = NULL;
373
374 ds = kmem_zalloc(sizeof (dsl_dataset_t), KM_SLEEP);
375 ds->ds_dbuf = dbuf;
376 ds->ds_object = dsobj;
377
378 mutex_init(&ds->ds_lock, NULL, MUTEX_DEFAULT, NULL);
379 mutex_init(&ds->ds_opening_lock, NULL, MUTEX_DEFAULT, NULL);
380 mutex_init(&ds->ds_sendstream_lock, NULL, MUTEX_DEFAULT, NULL);
381 refcount_create(&ds->ds_longholds);
382
383 bplist_create(&ds->ds_pending_deadlist);
384 dsl_deadlist_open(&ds->ds_deadlist,
385 mos, ds->ds_phys->ds_deadlist_obj);
386
387 list_create(&ds->ds_sendstreams, sizeof (dmu_sendarg_t),
388 offsetof(dmu_sendarg_t, dsa_link));
389
390 if (err == 0) {
391 err = dsl_dir_hold_obj(dp,
392 ds->ds_phys->ds_dir_obj, NULL, ds, &ds->ds_dir);
393 }
394 if (err != 0) {
395 mutex_destroy(&ds->ds_lock);
396 mutex_destroy(&ds->ds_opening_lock);
416 err = zap_count(
417 ds->ds_dir->dd_pool->dp_meta_objset,
418 ds->ds_phys->ds_userrefs_obj,
419 &ds->ds_userrefs);
420 }
421 }
422
423 if (err == 0 && !dsl_dataset_is_snapshot(ds)) {
424 err = dsl_prop_get_int_ds(ds,
425 zfs_prop_to_name(ZFS_PROP_REFRESERVATION),
426 &ds->ds_reserved);
427 if (err == 0) {
428 err = dsl_prop_get_int_ds(ds,
429 zfs_prop_to_name(ZFS_PROP_REFQUOTA),
430 &ds->ds_quota);
431 }
432 } else {
433 ds->ds_reserved = ds->ds_quota = 0;
434 }
435
436 dmu_buf_init_user(&ds->db_evict, dsl_dataset_evict);
437 if (err == 0)
438 winner = (dsl_dataset_t *)
439 dmu_buf_set_user_ie(dbuf, &ds->db_evict);
440
441 if (err || winner) {
442 bplist_destroy(&ds->ds_pending_deadlist);
443 dsl_deadlist_close(&ds->ds_deadlist);
444 if (ds->ds_prev)
445 dsl_dataset_rele(ds->ds_prev, ds);
446 dsl_dir_rele(ds->ds_dir, ds);
447 mutex_destroy(&ds->ds_lock);
448 mutex_destroy(&ds->ds_opening_lock);
449 refcount_destroy(&ds->ds_longholds);
450 kmem_free(ds, sizeof (dsl_dataset_t));
451 if (err != 0) {
452 dmu_buf_rele(dbuf, tag);
453 return (err);
454 }
455 ds = winner;
456 } else {
457 ds->ds_fsid_guid =
458 unique_insert(ds->ds_phys->ds_fsid_guid);
459 }
460 }
461 ASSERT3P(ds->ds_dbuf, ==, dbuf);
626 }
627
628 void
629 dsl_dataset_rele(dsl_dataset_t *ds, void *tag)
630 {
631 dmu_buf_rele(ds->ds_dbuf, tag);
632 }
633
634 void
635 dsl_dataset_disown(dsl_dataset_t *ds, void *tag)
636 {
637 ASSERT(ds->ds_owner == tag && ds->ds_dbuf != NULL);
638
639 mutex_enter(&ds->ds_lock);
640 ds->ds_owner = NULL;
641 mutex_exit(&ds->ds_lock);
642 dsl_dataset_long_rele(ds, tag);
643 if (ds->ds_dbuf != NULL)
644 dsl_dataset_rele(ds, tag);
645 else
646 dsl_dataset_evict_impl(ds, B_FALSE);
647 }
648
649 boolean_t
650 dsl_dataset_tryown(dsl_dataset_t *ds, void *tag)
651 {
652 boolean_t gotit = FALSE;
653
654 mutex_enter(&ds->ds_lock);
655 if (ds->ds_owner == NULL && !DS_IS_INCONSISTENT(ds)) {
656 ds->ds_owner = tag;
657 dsl_dataset_long_hold(ds, tag);
658 gotit = TRUE;
659 }
660 mutex_exit(&ds->ds_lock);
661 return (gotit);
662 }
663
664 uint64_t
665 dsl_dataset_create_sync_dd(dsl_dir_t *dd, dsl_dataset_t *origin,
666 uint64_t flags, dmu_tx_t *tx)
|