1fa9e406ahrens/*
2fa9e406ahrens * CDDL HEADER START
3fa9e406ahrens *
4fa9e406ahrens * The contents of this file are subject to the terms of the
5ea8dc4beschrock * Common Development and Distribution License (the "License").
6ea8dc4beschrock * You may not use this file except in compliance with the License.
7fa9e406ahrens *
8fa9e406ahrens * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9fa9e406ahrens * or http://www.opensolaris.org/os/licensing.
10fa9e406ahrens * See the License for the specific language governing permissions
11fa9e406ahrens * and limitations under the License.
12fa9e406ahrens *
13fa9e406ahrens * When distributing Covered Code, include this CDDL HEADER in each
14fa9e406ahrens * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15fa9e406ahrens * If applicable, add the following below this CDDL HEADER, with the
16fa9e406ahrens * fields enclosed by brackets "[]" replaced with your own identifying
17fa9e406ahrens * information: Portions Copyright [yyyy] [name of copyright owner]
18fa9e406ahrens *
19fa9e406ahrens * CDDL HEADER END
20fa9e406ahrens */
211c17160Kevin Crowe
22fa9e406ahrens/*
235afc78aChris Kirby * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
24000cce6Brad Lewis * Copyright (c) 2011, 2017 by Delphix. All rights reserved.
25a2afb61Jerry Jelinek * Copyright (c) 2014, Joyent, Inc. All rights reserved.
2603d1795Alexander Stetsenko * Copyright (c) 2014 RackTop Systems.
27bc9014eJustin Gibbs * Copyright (c) 2014 Spectra Logic Corporation, All rights reserved.
28c3d26abMatthew Ahrens * Copyright (c) 2014 Integros [integros.com]
295f7a8e6Dan McDonald * Copyright 2016, OmniTI Computer Consulting, Inc. All rights reserved.
301c17160Kevin Crowe * Copyright 2017 Nexenta Systems, Inc.
31fa9e406ahrens */
32fa9e406ahrens
33fa9e406ahrens#include <sys/dmu_objset.h>
34fa9e406ahrens#include <sys/dsl_dataset.h>
35fa9e406ahrens#include <sys/dsl_dir.h>
3699653d4eschrock#include <sys/dsl_prop.h>
371d452cfahrens#include <sys/dsl_synctask.h>
38fa9e406ahrens#include <sys/dmu_traverse.h>
394e3c9f4Bill Pijewski#include <sys/dmu_impl.h>
40fa9e406ahrens#include <sys/dmu_tx.h>
41fa9e406ahrens#include <sys/arc.h>
42fa9e406ahrens#include <sys/zio.h>
43fa9e406ahrens#include <sys/zap.h>
44ad135b5Christopher Siden#include <sys/zfeature.h>
45fa9e406ahrens#include <sys/unique.h>
46fa9e406ahrens#include <sys/zfs_context.h>
47cdf5b4cmmusante#include <sys/zfs_ioctl.h>
48ecd6cf8marks#include <sys/spa.h>
498671400Serapheim Dimitropoulos#include <sys/spa_impl.h>
505cabbc6Prashanth Sreenivasa#include <sys/vdev.h>
51088f389ahrens#include <sys/zfs_znode.h>
52c99e4bdChris Kirby#include <sys/zfs_onexit.h>
53842727cChris Kirby#include <sys/zvol.h>
543f9d6adLin Ling#include <sys/dsl_scan.h>
55cde58dbMatthew Ahrens#include <sys/dsl_deadlist.h>
563b2aab1Matthew Ahrens#include <sys/dsl_destroy.h>
573b2aab1Matthew Ahrens#include <sys/dsl_userhold.h>
5878f1710Matthew Ahrens#include <sys/dsl_bookmark.h>
590fa1b3cPaul Dagnelie#include <sys/dmu_recv.h>
6045818eeMatthew Ahrens#include <sys/zio_checksum.h>
619c3fd12Matthew Ahrens#include <sys/zio_compress.h>
629c3fd12Matthew Ahrens#include <zfs_fletcher.h>
63e193023bonwick
64b515258Matthew Ahrens/*
65b515258Matthew Ahrens * The SPA supports block sizes up to 16MB.  However, very large blocks
66b515258Matthew Ahrens * can have an impact on i/o latency (e.g. tying up a spinning disk for
67b515258Matthew Ahrens * ~300ms), and also potentially on the memory allocator.  Therefore,
68b515258Matthew Ahrens * we do not allow the recordsize to be set larger than zfs_max_recordsize
69b515258Matthew Ahrens * (default 1MB).  Larger blocks can be created by changing this tunable,
70b515258Matthew Ahrens * and pools with larger blocks can always be imported and used, regardless
71b515258Matthew Ahrens * of this setting.
72b515258Matthew Ahrens */
73b515258Matthew Ahrensint zfs_max_recordsize = 1 * 1024 * 1024;
74b515258Matthew Ahrens
75cde58dbMatthew Ahrens#define	SWITCH64(x, y) \
76cde58dbMatthew Ahrens	{ \
77cde58dbMatthew Ahrens		uint64_t __tmp = (x); \
78cde58dbMatthew Ahrens		(x) = (y); \
79cde58dbMatthew Ahrens		(y) = __tmp; \
80cde58dbMatthew Ahrens	}
81cde58dbMatthew Ahrens
8255434c7ek#define	DS_REF_MAX	(1ULL << 62)
83fa9e406ahrens
84c137962Justin T. Gibbsextern inline dsl_dataset_phys_t *dsl_dataset_phys(dsl_dataset_t *ds);
85c137962Justin T. Gibbs
865cabbc6Prashanth Sreenivasastatic void dsl_dataset_set_remap_deadlist_object(dsl_dataset_t *ds,
875cabbc6Prashanth Sreenivasa    uint64_t obj, dmu_tx_t *tx);
885cabbc6Prashanth Sreenivasastatic void dsl_dataset_unset_remap_deadlist_object(dsl_dataset_t *ds,
895cabbc6Prashanth Sreenivasa    dmu_tx_t *tx);
905cabbc6Prashanth Sreenivasa
915f7a8e6Dan McDonaldextern int spa_asize_inflation;
925f7a8e6Dan McDonald
93bfaed0bAndriy Gaponstatic zil_header_t zero_zil;
94bfaed0bAndriy Gapon
95a979902ck/*
96a979902ck * Figure out how much of this delta should be propogated to the dsl_dir
97a979902ck * layer.  If there's a refreservation, that space has already been
98a979902ck * partially accounted for in our ancestors.
99a979902ck */
100a979902ckstatic int64_t
101a979902ckparent_delta(dsl_dataset_t *ds, int64_t delta)
102a979902ck{
103c137962Justin T. Gibbs	dsl_dataset_phys_t *ds_phys;
104a979902ck	uint64_t old_bytes, new_bytes;
105a979902ck
106a979902ck	if (ds->ds_reserved == 0)
107a979902ck		return (delta);
108a979902ck
109c137962Justin T. Gibbs	ds_phys = dsl_dataset_phys(ds);
110c137962Justin T. Gibbs	old_bytes = MAX(ds_phys->ds_unique_bytes, ds->ds_reserved);
111c137962Justin T. Gibbs	new_bytes = MAX(ds_phys->ds_unique_bytes + delta, ds->ds_reserved);
112a979902ck
113a979902ck	ASSERT3U(ABS((int64_t)(new_bytes - old_bytes)), <=, ABS(delta));
114a979902ck	return (new_bytes - old_bytes);
115a979902ck}
116fa9e406ahrens
117fa9e406ahrensvoid
118b24ab67Jeff Bonwickdsl_dataset_block_born(dsl_dataset_t *ds, const blkptr_t *bp, dmu_tx_t *tx)
119fa9e406ahrens{
120b24ab67Jeff Bonwick	int used = bp_get_dsize_sync(tx->tx_pool->dp_spa, bp);
121fa9e406ahrens	int compressed = BP_GET_PSIZE(bp);
122fa9e406ahrens	int uncompressed = BP_GET_UCSIZE(bp);
123a979902ck	int64_t delta;
124fa9e406ahrens
1253f9d6adLin Ling	dprintf_bp(bp, "ds=%p", ds);
126fa9e406ahrens
127fa9e406ahrens	ASSERT(dmu_tx_is_syncing(tx));
128fa9e406ahrens	/* It could have been compressed away to nothing */
129fa9e406ahrens	if (BP_IS_HOLE(bp))
130fa9e406ahrens		return;
131fa9e406ahrens	ASSERT(BP_GET_TYPE(bp) != DMU_OT_NONE);
132ad135b5Christopher Siden	ASSERT(DMU_OT_IS_VALID(BP_GET_TYPE(bp)));
133fa9e406ahrens	if (ds == NULL) {
134ce636f8Matthew Ahrens		dsl_pool_mos_diduse_space(tx->tx_pool,
135ce636f8Matthew Ahrens		    used, compressed, uncompressed);
136fa9e406ahrens		return;
137fa9e406ahrens	}
1383f9d6adLin Ling
139bfaed0bAndriy Gapon	ASSERT3U(bp->blk_birth, >, dsl_dataset_phys(ds)->ds_prev_snap_txg);
140b62969fMatthew Ahrens	dmu_buf_will_dirty(ds->ds_dbuf, tx);
141fa9e406ahrens	mutex_enter(&ds->ds_lock);
142a979902ck	delta = parent_delta(ds, used);
143c137962Justin T. Gibbs	dsl_dataset_phys(ds)->ds_referenced_bytes += used;
144c137962Justin T. Gibbs	dsl_dataset_phys(ds)->ds_compressed_bytes += compressed;
145c137962Justin T. Gibbs	dsl_dataset_phys(ds)->ds_uncompressed_bytes += uncompressed;
146c137962Justin T. Gibbs	dsl_dataset_phys(ds)->ds_unique_bytes += used;
14745818eeMatthew Ahrens
148ca0cc39Matthew Ahrens	if (BP_GET_LSIZE(bp) > SPA_OLD_MAXBLOCKSIZE) {
149ca0cc39Matthew Ahrens		ds->ds_feature_activation_needed[SPA_FEATURE_LARGE_BLOCKS] =
150ca0cc39Matthew Ahrens		    B_TRUE;
151ca0cc39Matthew Ahrens	}
15245818eeMatthew Ahrens
15345818eeMatthew Ahrens	spa_feature_t f = zio_checksum_to_feature(BP_GET_CHECKSUM(bp));
15445818eeMatthew Ahrens	if (f != SPA_FEATURE_NONE)
15545818eeMatthew Ahrens		ds->ds_feature_activation_needed[f] = B_TRUE;
15645818eeMatthew Ahrens
157fa9e406ahrens	mutex_exit(&ds->ds_lock);
15874e7dc9Matthew Ahrens	dsl_dir_diduse_space(ds->ds_dir, DD_USED_HEAD, delta,
15974e7dc9Matthew Ahrens	    compressed, uncompressed, tx);
16074e7dc9Matthew Ahrens	dsl_dir_transfer_space(ds->ds_dir, used - delta,
16174e7dc9Matthew Ahrens	    DD_USED_REFRSRV, DD_USED_HEAD, tx);
162fa9e406ahrens}
163fa9e406ahrens
1645cabbc6Prashanth Sreenivasa/*
1655cabbc6Prashanth Sreenivasa * Called when the specified segment has been remapped, and is thus no
1665cabbc6Prashanth Sreenivasa * longer referenced in the head dataset.  The vdev must be indirect.
1675cabbc6Prashanth Sreenivasa *
1685cabbc6Prashanth Sreenivasa * If the segment is referenced by a snapshot, put it on the remap deadlist.
1695cabbc6Prashanth Sreenivasa * Otherwise, add this segment to the obsolete spacemap.
1705cabbc6Prashanth Sreenivasa */
1715cabbc6Prashanth Sreenivasavoid
1725cabbc6Prashanth Sreenivasadsl_dataset_block_remapped(dsl_dataset_t *ds, uint64_t vdev, uint64_t offset,
1735cabbc6Prashanth Sreenivasa    uint64_t size, uint64_t birth, dmu_tx_t *tx)
1745cabbc6Prashanth Sreenivasa{
1755cabbc6Prashanth Sreenivasa	spa_t *spa = ds->ds_dir->dd_pool->dp_spa;
1765cabbc6Prashanth Sreenivasa
1775cabbc6Prashanth Sreenivasa	ASSERT(dmu_tx_is_syncing(tx));
1785cabbc6Prashanth Sreenivasa	ASSERT(birth <= tx->tx_txg);
1795cabbc6Prashanth Sreenivasa	ASSERT(!ds->ds_is_snapshot);
1805cabbc6Prashanth Sreenivasa
1815cabbc6Prashanth Sreenivasa	if (birth > dsl_dataset_phys(ds)->ds_prev_snap_txg) {
1825cabbc6Prashanth Sreenivasa		spa_vdev_indirect_mark_obsolete(spa, vdev, offset, size, tx);
1835cabbc6Prashanth Sreenivasa	} else {
1845cabbc6Prashanth Sreenivasa		blkptr_t fakebp;
1855cabbc6Prashanth Sreenivasa		dva_t *dva = &fakebp.blk_dva[0];
1865cabbc6Prashanth Sreenivasa
1875cabbc6Prashanth Sreenivasa		ASSERT(ds != NULL);
1885cabbc6Prashanth Sreenivasa
1895cabbc6Prashanth Sreenivasa		mutex_enter(&ds->ds_remap_deadlist_lock);
1905cabbc6Prashanth Sreenivasa		if (!dsl_dataset_remap_deadlist_exists(ds)) {
1915cabbc6Prashanth Sreenivasa			dsl_dataset_create_remap_deadlist(ds, tx);
1925cabbc6Prashanth Sreenivasa		}
1935cabbc6Prashanth Sreenivasa		mutex_exit(&ds->ds_remap_deadlist_lock);
1945cabbc6Prashanth Sreenivasa
1955cabbc6Prashanth Sreenivasa		BP_ZERO(&fakebp);
1965cabbc6Prashanth Sreenivasa		fakebp.blk_birth = birth;
1975cabbc6Prashanth Sreenivasa		DVA_SET_VDEV(dva, vdev);
1985cabbc6Prashanth Sreenivasa		DVA_SET_OFFSET(dva, offset);
1995cabbc6Prashanth Sreenivasa		DVA_SET_ASIZE(dva, size);
2005cabbc6Prashanth Sreenivasa
2015cabbc6Prashanth Sreenivasa		dsl_deadlist_insert(&ds->ds_remap_deadlist, &fakebp, tx);
2025cabbc6Prashanth Sreenivasa	}
2035cabbc6Prashanth Sreenivasa}
2045cabbc6Prashanth Sreenivasa
205cdb0ab7maybeeint
206b24ab67Jeff Bonwickdsl_dataset_block_kill(dsl_dataset_t *ds, const blkptr_t *bp, dmu_tx_t *tx,
207b24ab67Jeff Bonwick    boolean_t async)
208fa9e406ahrens{
2098671400Serapheim Dimitropoulos	spa_t *spa = dmu_tx_pool(tx)->dp_spa;
2108671400Serapheim Dimitropoulos
2118671400Serapheim Dimitropoulos	int used = bp_get_dsize_sync(spa, bp);
21243466aaMax Grossman	int compressed = BP_GET_PSIZE(bp);
21343466aaMax Grossman	int uncompressed = BP_GET_UCSIZE(bp);
21443466aaMax Grossman
215fa9e406ahrens	if (BP_IS_HOLE(bp))
216cdb0ab7maybee		return (0);
217fa9e406ahrens
218b24ab67Jeff Bonwick	ASSERT(dmu_tx_is_syncing(tx));
219b24ab67Jeff Bonwick	ASSERT(bp->blk_birth <= tx->tx_txg);
220b24ab67Jeff Bonwick
221fa9e406ahrens	if (ds == NULL) {
222b24ab67Jeff Bonwick		dsl_free(tx->tx_pool, tx->tx_txg, bp);
223ce636f8Matthew Ahrens		dsl_pool_mos_diduse_space(tx->tx_pool,
224ce636f8Matthew Ahrens		    -used, -compressed, -uncompressed);
225cdb0ab7maybee		return (used);
226fa9e406ahrens	}
227fa9e406ahrens	ASSERT3P(tx->tx_pool, ==, ds->ds_dir->dd_pool);
228fa9e406ahrens
229bc9014eJustin Gibbs	ASSERT(!ds->ds_is_snapshot);
230fa9e406ahrens	dmu_buf_will_dirty(ds->ds_dbuf, tx);
231fa9e406ahrens
232c137962Justin T. Gibbs	if (bp->blk_birth > dsl_dataset_phys(ds)->ds_prev_snap_txg) {
233a979902ck		int64_t delta;
234c717a56maybee
2353f9d6adLin Ling		dprintf_bp(bp, "freeing ds=%llu", ds->ds_object);
236b24ab67Jeff Bonwick		dsl_free(tx->tx_pool, tx->tx_txg, bp);
237fa9e406ahrens
238fa9e406ahrens		mutex_enter(&ds->ds_lock);
239c137962Justin T. Gibbs		ASSERT(dsl_dataset_phys(ds)->ds_unique_bytes >= used ||
240a979902ck		    !DS_UNIQUE_IS_ACCURATE(ds));
241a979902ck		delta = parent_delta(ds, -used);
242c137962Justin T. Gibbs		dsl_dataset_phys(ds)->ds_unique_bytes -= used;
243fa9e406ahrens		mutex_exit(&ds->ds_lock);
24474e7dc9Matthew Ahrens		dsl_dir_diduse_space(ds->ds_dir, DD_USED_HEAD,
245a979902ck		    delta, -compressed, -uncompressed, tx);
24674e7dc9Matthew Ahrens		dsl_dir_transfer_space(ds->ds_dir, -used - delta,
24774e7dc9Matthew Ahrens		    DD_USED_REFRSRV, DD_USED_HEAD, tx);
248fa9e406ahrens	} else {
249fa9e406ahrens		dprintf_bp(bp, "putting on dead list: %s", "");
250b24ab67Jeff Bonwick		if (async) {
251b24ab67Jeff Bonwick			/*
252b24ab67Jeff Bonwick			 * We are here as part of zio's write done callback,
253b24ab67Jeff Bonwick			 * which means we're a zio interrupt thread.  We can't
254cde58dbMatthew Ahrens			 * call dsl_deadlist_insert() now because it may block
255b24ab67Jeff Bonwick			 * waiting for I/O.  Instead, put bp on the deferred
256b24ab67Jeff Bonwick			 * queue and let dsl_pool_sync() finish the job.
257b24ab67Jeff Bonwick			 */
258cde58dbMatthew Ahrens			bplist_append(&ds->ds_pending_deadlist, bp);
259b24ab67Jeff Bonwick		} else {
260cde58dbMatthew Ahrens			dsl_deadlist_insert(&ds->ds_deadlist, bp, tx);
261b24ab67Jeff Bonwick		}
262a4611edahrens		ASSERT3U(ds->ds_prev->ds_object, ==,
263c137962Justin T. Gibbs		    dsl_dataset_phys(ds)->ds_prev_snap_obj);
264c137962Justin T. Gibbs		ASSERT(dsl_dataset_phys(ds->ds_prev)->ds_num_children > 0);
265fa9e406ahrens		/* if (bp->blk_birth > prev prev snap txg) prev unique += bs */
266c137962Justin T. Gibbs		if (dsl_dataset_phys(ds->ds_prev)->ds_next_snap_obj ==
267a4611edahrens		    ds->ds_object && bp->blk_birth >
268c137962Justin T. Gibbs		    dsl_dataset_phys(ds->ds_prev)->ds_prev_snap_txg) {
269a4611edahrens			dmu_buf_will_dirty(ds->ds_prev->ds_dbuf, tx);
270a4611edahrens			mutex_enter(&ds->ds_prev->ds_lock);
271c137962Justin T. Gibbs			dsl_dataset_phys(ds->ds_prev)->ds_unique_bytes += used;
272a4611edahrens			mutex_exit(&ds->ds_prev->ds_lock);
273fa9e406ahrens		}
2743f9d6adLin Ling		if (bp->blk_birth > ds->ds_dir->dd_origin_txg) {
27574e7dc9Matthew Ahrens			dsl_dir_transfer_space(ds->ds_dir, used,
27674e7dc9Matthew Ahrens			    DD_USED_HEAD, DD_USED_SNAP, tx);
27774e7dc9Matthew Ahrens		}
278fa9e406ahrens	}
279fa9e406ahrens	mutex_enter(&ds->ds_lock);
280c137962Justin T. Gibbs	ASSERT3U(dsl_dataset_phys(ds)->ds_referenced_bytes, >=, used);
281c137962Justin T. Gibbs	dsl_dataset_phys(ds)->ds_referenced_bytes -= used;
282c137962Justin T. Gibbs	ASSERT3U(dsl_dataset_phys(ds)->ds_compressed_bytes, >=, compressed);
283c137962Justin T. Gibbs	dsl_dataset_phys(ds)->ds_compressed_bytes -= compressed;
284c137962Justin T. Gibbs	ASSERT3U(dsl_dataset_phys(ds)->ds_uncompressed_bytes, >=, uncompressed);
285c137962Justin T. Gibbs	dsl_dataset_phys(ds)->ds_uncompressed_bytes -= uncompressed;
286fa9e406ahrens	mutex_exit(&ds->ds_lock);
287cdb0ab7maybee
288cdb0ab7maybee	return (used);
289fa9e406ahrens}
290fa9e406ahrens
29140510e8Josef 'Jeff' Sipek/*
29240510e8Josef 'Jeff' Sipek * We have to release the fsid syncronously or we risk that a subsequent
29340510e8Josef 'Jeff' Sipek * mount of the same dataset will fail to unique_insert the fsid.  This
29440510e8Josef 'Jeff' Sipek * failure would manifest itself as the fsid of this dataset changing
29540510e8Josef 'Jeff' Sipek * between mounts which makes NFS clients quite unhappy.
29640510e8Josef 'Jeff' Sipek */
297fa9e406ahrensstatic void
29840510e8Josef 'Jeff' Sipekdsl_dataset_evict_sync(void *dbu)
299fa9e406ahrens{
300bc9014eJustin Gibbs	dsl_dataset_t *ds = dbu;
301fa9e406ahrens
3023b2aab1Matthew Ahrens	ASSERT(ds->ds_owner == NULL);
303fa9e406ahrens
30491ebeefahrens	unique_remove(ds->ds_fsid_guid);
30540510e8Josef 'Jeff' Sipek}
30640510e8Josef 'Jeff' Sipek
30740510e8Josef 'Jeff' Sipekstatic void
30840510e8Josef 'Jeff' Sipekdsl_dataset_evict_async(void *dbu)
30940510e8Josef 'Jeff' Sipek{
31040510e8Josef 'Jeff' Sipek	dsl_dataset_t *ds = dbu;
31140510e8Josef 'Jeff' Sipek
31240510e8Josef 'Jeff' Sipek	ASSERT(ds->ds_owner == NULL);
31340510e8Josef 'Jeff' Sipek
31440510e8Josef 'Jeff' Sipek	ds->ds_dbuf = NULL;
315fa9e406ahrens
316503ad85Matthew Ahrens	if (ds->ds_objset != NULL)
317503ad85Matthew Ahrens		dmu_objset_evict(ds->ds_objset);
318fa9e406ahrens
319fa9e406ahrens	if (ds->ds_prev) {
3203b2aab1Matthew Ahrens		dsl_dataset_rele(ds->ds_prev, ds);
321fa9e406ahrens		ds->ds_prev = NULL;
322fa9e406ahrens	}
323fa9e406ahrens
324cde58dbMatthew Ahrens	bplist_destroy(&ds->ds_pending_deadlist);
3255cabbc6Prashanth Sreenivasa	if (dsl_deadlist_is_open(&ds->ds_deadlist))
326cde58dbMatthew Ahrens		dsl_deadlist_close(&ds->ds_deadlist);
3275cabbc6Prashanth Sreenivasa	if (dsl_deadlist_is_open(&ds->ds_remap_deadlist))
3285cabbc6Prashanth Sreenivasa		dsl_deadlist_close(&ds->ds_remap_deadlist);
329745cd3cmaybee	if (ds->ds_dir)
330bc9014eJustin Gibbs		dsl_dir_async_rele(ds->ds_dir, ds);
331fa9e406ahrens
33291ebeefahrens	ASSERT(!list_link_active(&ds->ds_synced_link));
333fa9e406ahrens
33403bad06Justin Gibbs	list_destroy(&ds->ds_prop_cbs);
3355ad8204nd	mutex_destroy(&ds->ds_lock);
33691ebeefahrens	mutex_destroy(&ds->ds_opening_lock);
337d2b3cbbJorgen Lundman	mutex_destroy(&ds->ds_sendstream_lock);
3385cabbc6Prashanth Sreenivasa	mutex_destroy(&ds->ds_remap_deadlist_lock);
339e914aceTim Schumacher	zfs_refcount_destroy(&ds->ds_longholds);
340c166b69Paul Dagnelie	rrw_destroy(&ds->ds_bp_rwlock);
3415ad8204nd
342fa9e406ahrens	kmem_free(ds, sizeof (dsl_dataset_t));
343fa9e406ahrens}
344fa9e406ahrens
3453b2aab1Matthew Ahrensint
346fa9e406ahrensdsl_dataset_get_snapname(dsl_dataset_t *ds)
347fa9e406ahrens{
348fa9e406ahrens	dsl_dataset_phys_t *headphys;
349fa9e406ahrens	int err;
350fa9e406ahrens	dmu_buf_t *headdbuf;
351fa9e406ahrens	dsl_pool_t *dp = ds->ds_dir->dd_pool;
352fa9e406ahrens	objset_t *mos = dp->dp_meta_objset;
353fa9e406ahrens
354fa9e406ahrens	if (ds->ds_snapname[0])
355ea8dc4beschrock		return (0);
356c137962Justin T. Gibbs	if (dsl_dataset_phys(ds)->ds_next_snap_obj == 0)
357ea8dc4beschrock		return (0);
358fa9e406ahrens
359c137962Justin T. Gibbs	err = dmu_bonus_hold(mos, dsl_dir_phys(ds->ds_dir)->dd_head_dataset_obj,
360ea8dc4beschrock	    FTAG, &headdbuf);
3613b2aab1Matthew Ahrens	if (err != 0)
362ea8dc4beschrock		return (err);
363fa9e406ahrens	headphys = headdbuf->db_data;
364fa9e406ahrens	err = zap_value_search(dp->dp_meta_objset,
365e743726ahrens	    headphys->ds_snapnames_zapobj, ds->ds_object, 0, ds->ds_snapname);
366ea8dc4beschrock	dmu_buf_rele(headdbuf, FTAG);
367ea8dc4beschrock	return (err);
368fa9e406ahrens}
369fa9e406ahrens
3703b2aab1Matthew Ahrensint
371745cd3cmaybeedsl_dataset_snap_lookup(dsl_dataset_t *ds, const char *name, uint64_t *value)
372ab04eb8timh{
373745cd3cmaybee	objset_t *mos = ds->ds_dir->dd_pool->dp_meta_objset;
374c137962Justin T. Gibbs	uint64_t snapobj = dsl_dataset_phys(ds)->ds_snapnames_zapobj;
3751c17160Kevin Crowe	matchtype_t mt = 0;
376ab04eb8timh	int err;
377ab04eb8timh
378c137962Justin T. Gibbs	if (dsl_dataset_phys(ds)->ds_flags & DS_FLAG_CI_DATASET)
3791c17160Kevin Crowe		mt = MT_NORMALIZE;
380ab04eb8timh
381745cd3cmaybee	err = zap_lookup_norm(mos, snapobj, name, 8, 1,
382ab04eb8timh	    value, mt, NULL, 0, NULL);
3831c17160Kevin Crowe	if (err == ENOTSUP && (mt & MT_NORMALIZE))
384745cd3cmaybee		err = zap_lookup(mos, snapobj, name, 8, 1, value);
385ab04eb8timh	return (err);
386ab04eb8timh}
387ab04eb8timh
3883b2aab1Matthew Ahrensint
389a2afb61Jerry Jelinekdsl_dataset_snap_remove(dsl_dataset_t *ds, const char *name, dmu_tx_t *tx,
390a2afb61Jerry Jelinek    boolean_t adj_cnt)
391ab04eb8timh{
392745cd3cmaybee	objset_t *mos = ds->ds_dir->dd_pool->dp_meta_objset;
393c137962Justin T. Gibbs	uint64_t snapobj = dsl_dataset_phys(ds)->ds_snapnames_zapobj;
3941c17160Kevin Crowe	matchtype_t mt = 0;
395ab04eb8timh	int err;
396ab04eb8timh
39771eb053Chris Kirby	dsl_dir_snap_cmtime_update(ds->ds_dir);
39871eb053Chris Kirby
399c137962Justin T. Gibbs	if (dsl_dataset_phys(ds)->ds_flags & DS_FLAG_CI_DATASET)
4001c17160Kevin Crowe		mt = MT_NORMALIZE;
401ab04eb8timh
402745cd3cmaybee	err = zap_remove_norm(mos, snapobj, name, mt, tx);
4031c17160Kevin Crowe	if (err == ENOTSUP && (mt & MT_NORMALIZE))
404745cd3cmaybee		err = zap_remove(mos, snapobj, name, tx);
405a2afb61Jerry Jelinek
406a2afb61Jerry Jelinek	if (err == 0 && adj_cnt)
407a2afb61Jerry Jelinek		dsl_fs_ss_count_adjust(ds->ds_dir, -1,
408a2afb61Jerry Jelinek		    DD_FIELD_SNAPSHOT_COUNT, tx);
409a2afb61Jerry Jelinek
410ab04eb8timh	return (err);
411ab04eb8timh}
412ab04eb8timh
413e57a022Justin T. Gibbsboolean_t
414e57a022Justin T. Gibbsdsl_dataset_try_add_ref(dsl_pool_t *dp, dsl_dataset_t *ds, void *tag)
415e57a022Justin T. Gibbs{
4169d47decJustin T. Gibbs	dmu_buf_t *dbuf = ds->ds_dbuf;
4179d47decJustin T. Gibbs	boolean_t result = B_FALSE;
4189d47decJustin T. Gibbs
4199d47decJustin T. Gibbs	if (dbuf != NULL && dmu_buf_try_add_ref(dbuf, dp->dp_meta_objset,
4209d47decJustin T. Gibbs	    ds->ds_object, DMU_BONUS_BLKID, tag)) {
4219d47decJustin T. Gibbs
4229d47decJustin T. Gibbs		if (ds == dmu_buf_get_user(dbuf))
4239d47decJustin T. Gibbs			result = B_TRUE;
4249d47decJustin T. Gibbs		else
4259d47decJustin T. Gibbs			dmu_buf_rele(dbuf, tag);
4269d47decJustin T. Gibbs	}
4279d47decJustin T. Gibbs
4289d47decJustin T. Gibbs	return (result);
429e57a022Justin T. Gibbs}
430e57a022Justin T. Gibbs
4313b2aab1Matthew Ahrensint
4323b2aab1Matthew Ahrensdsl_dataset_hold_obj(dsl_pool_t *dp, uint64_t dsobj, void *tag,
433745cd3cmaybee    dsl_dataset_t **dsp)
434fa9e406ahrens{
435fa9e406ahrens	objset_t *mos = dp->dp_meta_objset;
436fa9e406ahrens	dmu_buf_t *dbuf;
437fa9e406ahrens	dsl_dataset_t *ds;
438ea8dc4beschrock	int err;
439a7f53a5Chris Kirby	dmu_object_info_t doi;
440fa9e406ahrens
4413b2aab1Matthew Ahrens	ASSERT(dsl_pool_config_held(dp));
442fa9e406ahrens
443ea8dc4beschrock	err = dmu_bonus_hold(mos, dsobj, tag, &dbuf);
4443b2aab1Matthew Ahrens	if (err != 0)
445ea8dc4beschrock		return (err);
446a7f53a5Chris Kirby
447a7f53a5Chris Kirby	/* Make sure dsobj has the correct object type. */
448a7f53a5Chris Kirby	dmu_object_info_from_db(dbuf, &doi);
4492acef22Matthew Ahrens	if (doi.doi_bonus_type != DMU_OT_DSL_DATASET) {
450b287be1Will Andrews		dmu_buf_rele(dbuf, tag);
451be6fd75Matthew Ahrens		return (SET_ERROR(EINVAL));
452b287be1Will Andrews	}
453a7f53a5Chris Kirby
454fa9e406ahrens	ds = dmu_buf_get_user(dbuf);
455fa9e406ahrens	if (ds == NULL) {
456d5285caGeorge Wilson		dsl_dataset_t *winner = NULL;
457fa9e406ahrens
458fa9e406ahrens		ds = kmem_zalloc(sizeof (dsl_dataset_t), KM_SLEEP);
459fa9e406ahrens		ds->ds_dbuf = dbuf;
460fa9e406ahrens		ds->ds_object = dsobj;
461bc9014eJustin Gibbs		ds->ds_is_snapshot = dsl_dataset_phys(ds)->ds_num_children != 0;
462fa9e406ahrens
4635cabbc6Prashanth Sreenivasa		err = dsl_dir_hold_obj(dp, dsl_dataset_phys(ds)->ds_dir_obj,
4645cabbc6Prashanth Sreenivasa		    NULL, ds, &ds->ds_dir);
4655cabbc6Prashanth Sreenivasa		if (err != 0) {
4665cabbc6Prashanth Sreenivasa			kmem_free(ds, sizeof (dsl_dataset_t));
4675cabbc6Prashanth Sreenivasa			dmu_buf_rele(dbuf, tag);
4685cabbc6Prashanth Sreenivasa			return (err);
4695cabbc6Prashanth Sreenivasa		}
4705cabbc6Prashanth Sreenivasa
4715ad8204nd		mutex_init(&ds->ds_lock, NULL, MUTEX_DEFAULT, NULL);
47291ebeefahrens		mutex_init(&ds->ds_opening_lock, NULL, MUTEX_DEFAULT, NULL);
4734e3c9f4Bill Pijewski		mutex_init(&ds->ds_sendstream_lock, NULL, MUTEX_DEFAULT, NULL);
4745cabbc6Prashanth Sreenivasa		mutex_init(&ds->ds_remap_deadlist_lock,
4755cabbc6Prashanth Sreenivasa		    NULL, MUTEX_DEFAULT, NULL);
476c166b69Paul Dagnelie		rrw_init(&ds->ds_bp_rwlock, B_FALSE);
477e914aceTim Schumacher		zfs_refcount_create(&ds->ds_longholds);
4785ad8204nd
479cde58dbMatthew Ahrens		bplist_create(&ds->ds_pending_deadlist);
480cde58dbMatthew Ahrens
4814e3c9f4Bill Pijewski		list_create(&ds->ds_sendstreams, sizeof (dmu_sendarg_t),
4824e3c9f4Bill Pijewski		    offsetof(dmu_sendarg_t, dsa_link));
4834e3c9f4Bill Pijewski
48403bad06Justin Gibbs		list_create(&ds->ds_prop_cbs, sizeof (dsl_prop_cb_record_t),
48503bad06Justin Gibbs		    offsetof(dsl_prop_cb_record_t, cbr_ds_node));
48603bad06Justin Gibbs
487b515258Matthew Ahrens		if (doi.doi_type == DMU_OTN_ZAP_METADATA) {
488ca0cc39Matthew Ahrens			for (spa_feature_t f = 0; f < SPA_FEATURES; f++) {
489ca0cc39Matthew Ahrens				if (!(spa_feature_table[f].fi_flags &
490ca0cc39Matthew Ahrens				    ZFEATURE_FLAG_PER_DATASET))
491ca0cc39Matthew Ahrens					continue;
492ca0cc39Matthew Ahrens				err = zap_contains(mos, dsobj,
493ca0cc39Matthew Ahrens				    spa_feature_table[f].fi_guid);
494ca0cc39Matthew Ahrens				if (err == 0) {
495ca0cc39Matthew Ahrens					ds->ds_feature_inuse[f] = B_TRUE;
496ca0cc39Matthew Ahrens				} else {
497ca0cc39Matthew Ahrens					ASSERT3U(err, ==, ENOENT);
498ca0cc39Matthew Ahrens					err = 0;
499ca0cc39Matthew Ahrens				}
500e1f3c20Justin T. Gibbs			}
501b515258Matthew Ahrens		}
502b515258Matthew Ahrens
503bc9014eJustin Gibbs		if (!ds->ds_is_snapshot) {
504fa9e406ahrens			ds->ds_snapname[0] = '\0';
505c137962Justin T. Gibbs			if (dsl_dataset_phys(ds)->ds_prev_snap_obj != 0) {
5063b2aab1Matthew Ahrens				err = dsl_dataset_hold_obj(dp,
507c137962Justin T. Gibbs				    dsl_dataset_phys(ds)->ds_prev_snap_obj,
508745cd3cmaybee				    ds, &ds->ds_prev);
509fa9e406ahrens			}
51078f1710Matthew Ahrens			if (doi.doi_type == DMU_OTN_ZAP_METADATA) {
51178f1710Matthew Ahrens				int zaperr = zap_lookup(mos, ds->ds_object,
51278f1710Matthew Ahrens				    DS_FIELD_BOOKMARK_NAMES,
51378f1710Matthew Ahrens				    sizeof (ds->ds_bookmarks), 1,
51478f1710Matthew Ahrens				    &ds->ds_bookmarks);
51578f1710Matthew Ahrens				if (zaperr != ENOENT)
51678f1710Matthew Ahrens					VERIFY0(zaperr);
51778f1710Matthew Ahrens			}
518842727cChris Kirby		} else {
519842727cChris Kirby			if (zfs_flags & ZFS_DEBUG_SNAPNAMES)
520842727cChris Kirby				err = dsl_dataset_get_snapname(ds);
521c137962Justin T. Gibbs			if (err == 0 &&
522c137962Justin T. Gibbs			    dsl_dataset_phys(ds)->ds_userrefs_obj != 0) {
523842727cChris Kirby				err = zap_count(
524842727cChris Kirby				    ds->ds_dir->dd_pool->dp_meta_objset,
525c137962Justin T. Gibbs				    dsl_dataset_phys(ds)->ds_userrefs_obj,
526842727cChris Kirby				    &ds->ds_userrefs);
527842727cChris Kirby			}
528fa9e406ahrens		}
529fa9e406ahrens
530bc9014eJustin Gibbs		if (err == 0 && !ds->ds_is_snapshot) {
5313b2aab1Matthew Ahrens			err = dsl_prop_get_int_ds(ds,
5323b2aab1Matthew Ahrens			    zfs_prop_to_name(ZFS_PROP_REFRESERVATION),
5333b2aab1Matthew Ahrens			    &ds->ds_reserved);
534cb625fbck			if (err == 0) {
5353b2aab1Matthew Ahrens				err = dsl_prop_get_int_ds(ds,
5363b2aab1Matthew Ahrens				    zfs_prop_to_name(ZFS_PROP_REFQUOTA),
5373b2aab1Matthew Ahrens				    &ds->ds_quota);
538cb625fbck			}
539cb625fbck		} else {
540cb625fbck			ds->ds_reserved = ds->ds_quota = 0;
541cb625fbck		}
542cb625fbck
543eb63303Tom Caputi		if (err == 0 && ds->ds_dir->dd_crypto_obj != 0 &&
544eb63303Tom Caputi		    ds->ds_is_snapshot &&
545eb63303Tom Caputi		    zap_contains(mos, dsobj, DS_FIELD_IVSET_GUID) != 0) {
546eb63303Tom Caputi			dp->dp_spa->spa_errata =
547eb63303Tom Caputi			    ZPOOL_ERRATA_ZOL_8308_ENCRYPTION;
548eb63303Tom Caputi		}
549eb63303Tom Caputi
5505cabbc6Prashanth Sreenivasa		dsl_deadlist_open(&ds->ds_deadlist,
5515cabbc6Prashanth Sreenivasa		    mos, dsl_dataset_phys(ds)->ds_deadlist_obj);
5525cabbc6Prashanth Sreenivasa		uint64_t remap_deadlist_obj =
5535cabbc6Prashanth Sreenivasa		    dsl_dataset_get_remap_deadlist_object(ds);
5545cabbc6Prashanth Sreenivasa		if (remap_deadlist_obj != 0) {
5555cabbc6Prashanth Sreenivasa			dsl_deadlist_open(&ds->ds_remap_deadlist, mos,
5565cabbc6Prashanth Sreenivasa			    remap_deadlist_obj);
5575cabbc6Prashanth Sreenivasa		}
5585cabbc6Prashanth Sreenivasa
55940510e8Josef 'Jeff' Sipek		dmu_buf_init_user(&ds->ds_dbu, dsl_dataset_evict_sync,
56040510e8Josef 'Jeff' Sipek		    dsl_dataset_evict_async, &ds->ds_dbuf);
561bc9014eJustin Gibbs		if (err == 0)
562bc9014eJustin Gibbs			winner = dmu_buf_set_user_ie(dbuf, &ds->ds_dbu);
563bc9014eJustin Gibbs
564bc9014eJustin Gibbs		if (err != 0 || winner != NULL) {
565cde58dbMatthew Ahrens			bplist_destroy(&ds->ds_pending_deadlist);
566cde58dbMatthew Ahrens			dsl_deadlist_close(&ds->ds_deadlist);
5675cabbc6Prashanth Sreenivasa			if (dsl_deadlist_is_open(&ds->ds_remap_deadlist))
5685cabbc6Prashanth Sreenivasa				dsl_deadlist_close(&ds->ds_remap_deadlist);
569745cd3cmaybee			if (ds->ds_prev)
5703b2aab1Matthew Ahrens				dsl_dataset_rele(ds->ds_prev, ds);
5713b2aab1Matthew Ahrens			dsl_dir_rele(ds->ds_dir, ds);
572ad027c0Jorgen Lundman			list_destroy(&ds->ds_prop_cbs);
573ad027c0Jorgen Lundman			list_destroy(&ds->ds_sendstreams);
5745ad8204nd			mutex_destroy(&ds->ds_lock);
57591ebeefahrens			mutex_destroy(&ds->ds_opening_lock);
576d2b3cbbJorgen Lundman			mutex_destroy(&ds->ds_sendstream_lock);
577ad027c0Jorgen Lundman			mutex_destroy(&ds->ds_remap_deadlist_lock);
578e914aceTim Schumacher			zfs_refcount_destroy(&ds->ds_longholds);
579ad027c0Jorgen Lundman			rrw_destroy(&ds->ds_bp_rwlock);
580fa9e406ahrens			kmem_free(ds, sizeof (dsl_dataset_t));
5813b2aab1Matthew Ahrens			if (err != 0) {
582ea8dc4beschrock				dmu_buf_rele(dbuf, tag);
583ea8dc4beschrock				return (err);
584ea8dc4beschrock			}
585fa9e406ahrens			ds = winner;
586fa9e406ahrens		} else {
58791ebeefahrens			ds->ds_fsid_guid =
588c137962Justin T. Gibbs			    unique_insert(dsl_dataset_phys(ds)->ds_fsid_guid);
58940510e8Josef 'Jeff' Sipek			if (ds->ds_fsid_guid !=
59040510e8Josef 'Jeff' Sipek			    dsl_dataset_phys(ds)->ds_fsid_guid) {
59140510e8Josef 'Jeff' Sipek				zfs_dbgmsg("ds_fsid_guid changed from "
59240510e8Josef 'Jeff' Sipek				    "%llx to %llx for pool %s dataset id %llu",
59340510e8Josef 'Jeff' Sipek				    (long long)
59440510e8Josef 'Jeff' Sipek				    dsl_dataset_phys(ds)->ds_fsid_guid,
59540510e8Josef 'Jeff' Sipek				    (long long)ds->ds_fsid_guid,
59640510e8Josef 'Jeff' Sipek				    spa_name(dp->dp_spa),
59740510e8Josef 'Jeff' Sipek				    dsobj);
59840510e8Josef 'Jeff' Sipek			}
599fa9e406ahrens		}
600fa9e406ahrens	}
601eb63303Tom Caputi
602fa9e406ahrens	ASSERT3P(ds->ds_dbuf, ==, dbuf);
603c137962Justin T. Gibbs	ASSERT3P(dsl_dataset_phys(ds), ==, dbuf->db_data);
604c137962Justin T. Gibbs	ASSERT(dsl_dataset_phys(ds)->ds_prev_snap_obj != 0 ||
605afc6333ahrens	    spa_version(dp->dp_spa) < SPA_VERSION_ORIGIN ||
60684db2a6ahrens	    dp->dp_origin_snap == NULL || ds == dp->dp_origin_snap);
607ea8dc4beschrock	*dsp = ds;
608eb63303Tom Caputi
609ea8dc4beschrock	return (0);
610fa9e406ahrens}
611fa9e406ahrens
612745cd3cmaybeeint
613eb63303Tom Caputidsl_dataset_create_key_mapping(dsl_dataset_t *ds)
614eb63303Tom Caputi{
615eb63303Tom Caputi	dsl_dir_t *dd = ds->ds_dir;
616eb63303Tom Caputi
617eb63303Tom Caputi	if (dd->dd_crypto_obj == 0)
618eb63303Tom Caputi		return (0);
619eb63303Tom Caputi
620eb63303Tom Caputi	return (spa_keystore_create_mapping(dd->dd_pool->dp_spa,
621eb63303Tom Caputi	    ds, ds, &ds->ds_key_mapping));
622eb63303Tom Caputi}
623eb63303Tom Caputi
624eb63303Tom Caputiint
625eb63303Tom Caputidsl_dataset_hold_obj_flags(dsl_pool_t *dp, uint64_t dsobj,
626eb63303Tom Caputi    ds_hold_flags_t flags, void *tag, dsl_dataset_t **dsp)
627eb63303Tom Caputi{
628eb63303Tom Caputi	int err;
629eb63303Tom Caputi
630eb63303Tom Caputi	err = dsl_dataset_hold_obj(dp, dsobj, tag, dsp);
631eb63303Tom Caputi	if (err != 0)
632eb63303Tom Caputi		return (err);
633eb63303Tom Caputi
634eb63303Tom Caputi	ASSERT3P(*dsp, !=, NULL);
635eb63303Tom Caputi
636eb63303Tom Caputi	if (flags & DS_HOLD_FLAG_DECRYPT) {
637eb63303Tom Caputi		err = dsl_dataset_create_key_mapping(*dsp);
638eb63303Tom Caputi		if (err != 0)
639eb63303Tom Caputi			dsl_dataset_rele(*dsp, tag);
640eb63303Tom Caputi	}
641eb63303Tom Caputi
642eb63303Tom Caputi	return (err);
643eb63303Tom Caputi}
644eb63303Tom Caputi
645eb63303Tom Caputiint
646eb63303Tom Caputidsl_dataset_hold_flags(dsl_pool_t *dp, const char *name, ds_hold_flags_t flags,
647503ad85Matthew Ahrens    void *tag, dsl_dataset_t **dsp)
648745cd3cmaybee{
649fa9e406ahrens	dsl_dir_t *dd;
650745cd3cmaybee	const char *snapname;
651fa9e406ahrens	uint64_t obj;
652fa9e406ahrens	int err = 0;
653a2cdcddPaul Dagnelie	dsl_dataset_t *ds;
654fa9e406ahrens
6553b2aab1Matthew Ahrens	err = dsl_dir_hold(dp, name, FTAG, &dd, &snapname);
6563b2aab1Matthew Ahrens	if (err != 0)
657ea8dc4beschrock		return (err);
658fa9e406ahrens
6593b2aab1Matthew Ahrens	ASSERT(dsl_pool_config_held(dp));
660c137962Justin T. Gibbs	obj = dsl_dir_phys(dd)->dd_head_dataset_obj;
6613b2aab1Matthew Ahrens	if (obj != 0)
662eb63303Tom Caputi		err = dsl_dataset_hold_obj_flags(dp, obj, flags, tag, &ds);
663745cd3cmaybee	else
664be6fd75Matthew Ahrens		err = SET_ERROR(ENOENT);
665fa9e406ahrens
666745cd3cmaybee	/* we may be looking for a snapshot */
667745cd3cmaybee	if (err == 0 && snapname != NULL) {
668a2cdcddPaul Dagnelie		dsl_dataset_t *snap_ds;
669fa9e406ahrens
670745cd3cmaybee		if (*snapname++ != '@') {
671eb63303Tom Caputi			dsl_dataset_rele_flags(ds, flags, tag);
6723b2aab1Matthew Ahrens			dsl_dir_rele(dd, FTAG);
673be6fd75Matthew Ahrens			return (SET_ERROR(ENOENT));
674fa9e406ahrens		}
675fa9e406ahrens
676745cd3cmaybee		dprintf("looking for snapshot '%s'\n", snapname);
677a2cdcddPaul Dagnelie		err = dsl_dataset_snap_lookup(ds, snapname, &obj);
678eb63303Tom Caputi		if (err == 0) {
679eb63303Tom Caputi			err = dsl_dataset_hold_obj_flags(dp, obj, flags, tag,
680eb63303Tom Caputi			    &snap_ds);
681eb63303Tom Caputi		}
682eb63303Tom Caputi		dsl_dataset_rele_flags(ds, flags, tag);
683745cd3cmaybee
6843b2aab1Matthew Ahrens		if (err == 0) {
685a2cdcddPaul Dagnelie			mutex_enter(&snap_ds->ds_lock);
686a2cdcddPaul Dagnelie			if (snap_ds->ds_snapname[0] == 0)
687a2cdcddPaul Dagnelie				(void) strlcpy(snap_ds->ds_snapname, snapname,
688a2cdcddPaul Dagnelie				    sizeof (snap_ds->ds_snapname));
689a2cdcddPaul Dagnelie			mutex_exit(&snap_ds->ds_lock);
690a2cdcddPaul Dagnelie			ds = snap_ds;
691fa9e406ahrens		}
692fa9e406ahrens	}
693a2cdcddPaul Dagnelie	if (err == 0)
694