diff usr/src/uts/common/fs/zfs/dsl_dataset.c @ 1544:938876158511

PSARC 2006/077 zpool clear PSARC 2006/139 FMA for ZFS 6284889 arc should replace the znode cache 6333006 DMU & DSL should not panic upon I/O error 6333092 concurrent reads to a file not scaling with number of readers 6338081 ZFS/FMA phase 1 6338386 need persistent error log 6341326 i/o error causes arc buf hash table corruption 6341639 zfs backup/restore should compute/verify checksum of backup stream 6348002 out of space due to changing properties 6354724 inaccurate error message from zfs restore 6354872 dmu_sync() blows predictive accounting 6355416 zpool scrubbing consumes all memory, system hung 6363995 df should only load libzfs when it encounters a ZFS filesystem 6366320 zfs backup/restore doesn't like signals 6368892 mount -m support needed for legacy mounts 6368902 boot archive fstat support needed for ZFS Mountroot 6369424 BFU complains when bfu'ing a ZFS root filesystem 6374062 mountroot support needed for ZFS 6376356 dirtying dbuf obj=43 lvl=0 blkid=0 but not tx_held 6378391 unused members of dmu_objset_stats_t 6378392 clean up zfs_cmd_t structure 6378685 buf_init should allocate its hash table more carefully 6378976 ziltest should be a first class citizen 6381086 zdb segfaults if there is a spa deferred-free bplist 6381203 deadlock due to i/o while assigning (tc_lock held) 6381209 freed space is not immediately available 6381344 'zpool clear' 6381345 FAULTED devices should really be UNAVAIL 6381346 import should mark devices as persistently unavailable 6383272 recursive mutex_enter() during log replay with zfs root 6386326 origin property is not displayed 6386354 libzfs does too much in its _init section, calls exit(1) 6386624 zpool should not complain about non-existent devices from libdiskmgt 6386910 spa needs to be i/o error hardened 6387735 need a mechanism to inject faults into ZFS 6387736 internal ZFS utilities should be placed in an ON-private package 6389928 libzfs should ship a lint library 6390609 malformed vdev config panics on zpool_create() 6390677 version number checking makes upgrades challenging 6390713 ztest hangs in zil_suspend() 6391873 metadata compression should be turned back on 6392113 ztest sometimes reports leaked blocks because ZIL isn't resilvered 6393004 minor memory leak in unique_insert()
author eschrock
date Fri, 03 Mar 2006 20:08:16 -0800
parents 36d72fe4da29
children 1efa8b3d1296
line wrap: on
line diff
--- a/usr/src/uts/common/fs/zfs/dsl_dataset.c	Fri Mar 03 17:59:43 2006 -0800
+++ b/usr/src/uts/common/fs/zfs/dsl_dataset.c	Fri Mar 03 20:08:16 2006 -0800
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -146,7 +145,7 @@
 		    -used, -compressed, -uncompressed, tx);
 	} else {
 		dprintf_bp(bp, "putting on dead list: %s", "");
-		bplist_enqueue(&ds->ds_deadlist, bp, tx);
+		VERIFY(0 == bplist_enqueue(&ds->ds_deadlist, bp, tx));
 		/* if (bp->blk_birth > prev prev snap txg) prev unique += bs */
 		if (ds->ds_phys->ds_prev_snap_obj != 0) {
 			ASSERT3U(ds->ds_prev->ds_object, ==,
@@ -175,14 +174,14 @@
 	mutex_exit(&ds->ds_lock);
 }
 
-int
-dsl_dataset_block_freeable(dsl_dataset_t *ds, uint64_t blk_birth, dmu_tx_t *tx)
+uint64_t
+dsl_dataset_prev_snap_txg(dsl_dataset_t *ds)
 {
-	uint64_t prev_snap_txg;
+	uint64_t txg;
 	dsl_dir_t *dd;
-	/* ASSERT that it is not a snapshot */
+
 	if (ds == NULL)
-		return (TRUE);
+		return (0);
 	/*
 	 * The snapshot creation could fail, but that would cause an
 	 * incorrect FALSE return, which would only result in an
@@ -195,13 +194,19 @@
 	 */
 	dd = ds->ds_dir;
 	mutex_enter(&dd->dd_lock);
-	if (dd->dd_sync_func == dsl_dataset_snapshot_sync &&
-	    dd->dd_sync_txg < tx->tx_txg)
-		prev_snap_txg = dd->dd_sync_txg;
+	if (dd->dd_sync_func == dsl_dataset_snapshot_sync)
+		txg = dd->dd_sync_txg;
 	else
-		prev_snap_txg = ds->ds_phys->ds_prev_snap_txg;
+		txg = ds->ds_phys->ds_prev_snap_txg;
 	mutex_exit(&dd->dd_lock);
-	return (blk_birth > prev_snap_txg);
+
+	return (txg);
+}
+
+int
+dsl_dataset_block_freeable(dsl_dataset_t *ds, uint64_t blk_birth)
+{
+	return (blk_birth > dsl_dataset_prev_snap_txg(ds));
 }
 
 /* ARGSUSED */
@@ -236,7 +241,7 @@
 	kmem_free(ds, sizeof (dsl_dataset_t));
 }
 
-static void
+static int
 dsl_dataset_get_snapname(dsl_dataset_t *ds)
 {
 	dsl_dataset_phys_t *headphys;
@@ -246,34 +251,37 @@
 	objset_t *mos = dp->dp_meta_objset;
 
 	if (ds->ds_snapname[0])
-		return;
+		return (0);
 	if (ds->ds_phys->ds_next_snap_obj == 0)
-		return;
+		return (0);
 
-	headdbuf = dmu_bonus_hold_tag(mos,
-	    ds->ds_dir->dd_phys->dd_head_dataset_obj, FTAG);
-	dmu_buf_read(headdbuf);
+	err = dmu_bonus_hold(mos, ds->ds_dir->dd_phys->dd_head_dataset_obj,
+	    FTAG, &headdbuf);
+	if (err)
+		return (err);
 	headphys = headdbuf->db_data;
 	err = zap_value_search(dp->dp_meta_objset,
 	    headphys->ds_snapnames_zapobj, ds->ds_object, ds->ds_snapname);
-	ASSERT(err == 0);
-	dmu_buf_rele_tag(headdbuf, FTAG);
+	dmu_buf_rele(headdbuf, FTAG);
+	return (err);
 }
 
-dsl_dataset_t *
+int
 dsl_dataset_open_obj(dsl_pool_t *dp, uint64_t dsobj, const char *snapname,
-    int mode, void *tag)
+    int mode, void *tag, dsl_dataset_t **dsp)
 {
 	uint64_t weight = ds_refcnt_weight[DS_MODE_LEVEL(mode)];
 	objset_t *mos = dp->dp_meta_objset;
 	dmu_buf_t *dbuf;
 	dsl_dataset_t *ds;
+	int err;
 
 	ASSERT(RW_LOCK_HELD(&dp->dp_config_rwlock) ||
 	    dsl_pool_sync_context(dp));
 
-	dbuf = dmu_bonus_hold_tag(mos, dsobj, tag);
-	dmu_buf_read(dbuf);
+	err = dmu_bonus_hold(mos, dsobj, tag, &dbuf);
+	if (err)
+		return (err);
 	ds = dmu_buf_get_user(dbuf);
 	if (ds == NULL) {
 		dsl_dataset_t *winner;
@@ -282,47 +290,60 @@
 		ds->ds_dbuf = dbuf;
 		ds->ds_object = dsobj;
 		ds->ds_phys = dbuf->db_data;
-		ds->ds_dir = dsl_dir_open_obj(dp,
-		    ds->ds_phys->ds_dir_obj, NULL, ds);
 
-		bplist_open(&ds->ds_deadlist,
+		err = bplist_open(&ds->ds_deadlist,
 		    mos, ds->ds_phys->ds_deadlist_obj);
+		if (err == 0) {
+			err = dsl_dir_open_obj(dp,
+			    ds->ds_phys->ds_dir_obj, NULL, ds, &ds->ds_dir);
+		}
+		if (err) {
+			/*
+			 * we don't really need to close the blist if we
+			 * just opened it.
+			 */
+			kmem_free(ds, sizeof (dsl_dataset_t));
+			dmu_buf_rele(dbuf, tag);
+			return (err);
+		}
 
 		if (ds->ds_dir->dd_phys->dd_head_dataset_obj == dsobj) {
 			ds->ds_snapname[0] = '\0';
 			if (ds->ds_phys->ds_prev_snap_obj) {
-				ds->ds_prev =
-				    dsl_dataset_open_obj(dp,
+				err = dsl_dataset_open_obj(dp,
 				    ds->ds_phys->ds_prev_snap_obj, NULL,
-				    DS_MODE_NONE, ds);
+				    DS_MODE_NONE, ds, &ds->ds_prev);
 			}
 		} else {
 			if (snapname) {
 #ifdef ZFS_DEBUG
 				dsl_dataset_phys_t *headphys;
-				int err;
-				dmu_buf_t *headdbuf = dmu_bonus_hold_tag(mos,
-				    ds->ds_dir->dd_phys->
-				    dd_head_dataset_obj, FTAG);
-				dmu_buf_read(headdbuf);
-				headphys = headdbuf->db_data;
-				uint64_t foundobj;
-				err = zap_lookup(dp->dp_meta_objset,
-				    headphys->ds_snapnames_zapobj,
-				    snapname, sizeof (foundobj), 1, &foundobj);
-				ASSERT3U(err, ==, 0);
-				ASSERT3U(foundobj, ==, dsobj);
-				dmu_buf_rele_tag(headdbuf, FTAG);
+				dmu_buf_t *headdbuf;
+				err = dmu_bonus_hold(mos,
+				    ds->ds_dir->dd_phys->dd_head_dataset_obj,
+				    FTAG, &headdbuf);
+				if (err == 0) {
+					headphys = headdbuf->db_data;
+					uint64_t foundobj;
+					err = zap_lookup(dp->dp_meta_objset,
+					    headphys->ds_snapnames_zapobj,
+					    snapname, sizeof (foundobj), 1,
+					    &foundobj);
+					ASSERT3U(foundobj, ==, dsobj);
+					dmu_buf_rele(headdbuf, FTAG);
+				}
 #endif
 				(void) strcat(ds->ds_snapname, snapname);
 			} else if (zfs_flags & ZFS_DEBUG_SNAPNAMES) {
-				dsl_dataset_get_snapname(ds);
+				err = dsl_dataset_get_snapname(ds);
 			}
 		}
 
-		winner = dmu_buf_set_user_ie(dbuf, ds, &ds->ds_phys,
-		    dsl_dataset_evict);
-		if (winner) {
+		if (err == 0) {
+			winner = dmu_buf_set_user_ie(dbuf, ds, &ds->ds_phys,
+			    dsl_dataset_evict);
+		}
+		if (err || winner) {
 			bplist_close(&ds->ds_deadlist);
 			if (ds->ds_prev) {
 				dsl_dataset_close(ds->ds_prev,
@@ -330,6 +351,10 @@
 			}
 			dsl_dir_close(ds->ds_dir, ds);
 			kmem_free(ds, sizeof (dsl_dataset_t));
+			if (err) {
+				dmu_buf_rele(dbuf, tag);
+				return (err);
+			}
 			ds = winner;
 		} else {
 			uint64_t new =
@@ -349,12 +374,13 @@
 	    (ds->ds_open_refcount + weight > DOS_REF_MAX)) {
 		mutex_exit(&ds->ds_lock);
 		dsl_dataset_close(ds, DS_MODE_NONE, tag);
-		return (NULL);
+		return (EBUSY);
 	}
 	ds->ds_open_refcount += weight;
 	mutex_exit(&ds->ds_lock);
 
-	return (ds);
+	*dsp = ds;
+	return (0);
 }
 
 int
@@ -368,9 +394,9 @@
 	dsl_dataset_t *ds = NULL;
 	int err = 0;
 
-	dd = dsl_dir_open_spa(spa, name, FTAG, &tail);
-	if (dd == NULL)
-		return (ENOENT);
+	err = dsl_dir_open_spa(spa, name, FTAG, &dd, &tail);
+	if (err)
+		return (err);
 
 	dp = dd->dd_pool;
 	obj = dd->dd_phys->dd_head_dataset_obj;
@@ -384,7 +410,10 @@
 	if (tail != NULL) {
 		objset_t *mos = dp->dp_meta_objset;
 
-		ds = dsl_dataset_open_obj(dp, obj, NULL, DS_MODE_NONE, tag);
+		err = dsl_dataset_open_obj(dp, obj, NULL,
+		    DS_MODE_NONE, tag, &ds);
+		if (err)
+			goto out;
 		obj = ds->ds_phys->ds_snapnames_zapobj;
 		dsl_dataset_close(ds, DS_MODE_NONE, tag);
 		ds = NULL;
@@ -405,9 +434,7 @@
 		if (err)
 			goto out;
 	}
-	ds = dsl_dataset_open_obj(dp, obj, tail, mode, tag);
-	if (ds == NULL)
-		err = EBUSY;
+	err = dsl_dataset_open_obj(dp, obj, tail, mode, tag, &ds);
 
 out:
 	rw_exit(&dp->dp_config_rwlock);
@@ -433,7 +460,7 @@
 		(void) strcpy(name, "mos");
 	} else {
 		dsl_dir_name(ds->ds_dir, name);
-		dsl_dataset_get_snapname(ds);
+		VERIFY(0 == dsl_dataset_get_snapname(ds));
 		if (ds->ds_snapname[0]) {
 			(void) strcat(name, "@");
 			if (!MUTEX_HELD(&ds->ds_lock)) {
@@ -462,7 +489,7 @@
 	    mode, ds->ds_open_refcount);
 	mutex_exit(&ds->ds_lock);
 
-	dmu_buf_rele_tag(ds->ds_dbuf, tag);
+	dmu_buf_rele(ds->ds_dbuf, tag);
 }
 
 void
@@ -476,16 +503,16 @@
 	dsl_dir_t *dd;
 
 	dsl_dir_create_root(mos, ddobjp, tx);
-	dd = dsl_dir_open_obj(dp, *ddobjp, NULL, FTAG);
-	ASSERT(dd != NULL);
+	VERIFY(0 == dsl_dir_open_obj(dp, *ddobjp, NULL, FTAG, &dd));
 
 	dsobj = dmu_object_alloc(mos, DMU_OT_DSL_DATASET, 0,
 	    DMU_OT_DSL_DATASET, sizeof (dsl_dataset_phys_t), tx);
-	dbuf = dmu_bonus_hold(mos, dsobj);
+	VERIFY(0 == dmu_bonus_hold(mos, dsobj, FTAG, &dbuf));
 	dmu_buf_will_dirty(dbuf, tx);
 	dsphys = dbuf->db_data;
 	dsphys->ds_dir_obj = dd->dd_object;
 	dsphys->ds_fsid_guid = unique_create();
+	unique_remove(dsphys->ds_fsid_guid); /* it isn't open yet */
 	(void) random_get_pseudo_bytes((void*)&dsphys->ds_guid,
 	    sizeof (dsphys->ds_guid));
 	dsphys->ds_snapnames_zapobj =
@@ -494,13 +521,14 @@
 	dsphys->ds_creation_txg = tx->tx_txg;
 	dsphys->ds_deadlist_obj =
 	    bplist_create(mos, DSL_DEADLIST_BLOCKSIZE, tx);
-	dmu_buf_rele(dbuf);
+	dmu_buf_rele(dbuf, FTAG);
 
 	dmu_buf_will_dirty(dd->dd_dbuf, tx);
 	dd->dd_phys->dd_head_dataset_obj = dsobj;
 	dsl_dir_close(dd, FTAG);
 
-	ds = dsl_dataset_open_obj(dp, dsobj, NULL, DS_MODE_NONE, FTAG);
+	VERIFY(0 ==
+	    dsl_dataset_open_obj(dp, dsobj, NULL, DS_MODE_NONE, FTAG, &ds));
 	(void) dmu_objset_create_impl(dp->dp_spa, ds, DMU_OST_ZFS, tx);
 	dsl_dataset_close(ds, DS_MODE_NONE, FTAG);
 }
@@ -537,14 +565,13 @@
 	err = dsl_dir_create_sync(pds, lastname, tx);
 	if (err)
 		return (err);
-	dd = dsl_dir_open_spa(dp->dp_spa, fullname, FTAG, NULL);
-	ASSERT(dd != NULL);
+	VERIFY(0 == dsl_dir_open_spa(dp->dp_spa, fullname, FTAG, &dd, NULL));
 
 	/* This is the point of no (unsuccessful) return */
 
 	dsobj = dmu_object_alloc(mos, DMU_OT_DSL_DATASET, 0,
 	    DMU_OT_DSL_DATASET, sizeof (dsl_dataset_phys_t), tx);
-	dbuf = dmu_bonus_hold(mos, dsobj);
+	VERIFY(0 == dmu_bonus_hold(mos, dsobj, FTAG, &dbuf));
 	dmu_buf_will_dirty(dbuf, tx);
 	dsphys = dbuf->db_data;
 	dsphys->ds_dir_obj = dd->dd_object;
@@ -576,7 +603,7 @@
 		dmu_buf_will_dirty(dd->dd_dbuf, tx);
 		dd->dd_phys->dd_clone_parent_obj = clone_parent->ds_object;
 	}
-	dmu_buf_rele(dbuf);
+	dmu_buf_rele(dbuf, FTAG);
 
 	dmu_buf_will_dirty(dd->dd_dbuf, tx);
 	dd->dd_phys->dd_head_dataset_obj = dsobj;
@@ -594,9 +621,9 @@
 	dsl_dir_t *dd;
 	const char *tail;
 
-	dd = dsl_dir_open(name, FTAG, &tail);
-	if (dd == NULL)
-		return (ENOENT);
+	err = dsl_dir_open(name, FTAG, &dd, &tail);
+	if (err)
+		return (err);
 
 	dp = dd->dd_pool;
 	if (tail != NULL) {
@@ -631,10 +658,12 @@
 		 * dsl_dataset_destroy_sync() to destroy the head dataset.
 		 */
 		rw_enter(&dp->dp_config_rwlock, RW_READER);
-		pds = dsl_dir_open_obj(dd->dd_pool,
-		    dd->dd_phys->dd_parent_obj, NULL, FTAG);
+		err = dsl_dir_open_obj(dd->dd_pool,
+		    dd->dd_phys->dd_parent_obj, NULL, FTAG, &pds);
 		dsl_dir_close(dd, FTAG);
 		rw_exit(&dp->dp_config_rwlock);
+		if (err)
+			return (err);
 
 		(void) strcpy(buf, name);
 		cp = strrchr(buf, '/') + 1;
@@ -657,9 +686,9 @@
 	dsl_dir_t *dd;
 	const char *tail;
 
-	dd = dsl_dir_open(name, FTAG, &tail);
-	if (dd == NULL)
-		return (ENOENT);
+	err = dsl_dir_open(name, FTAG, &dd, &tail);
+	if (err)
+		return (err);
 
 	if (tail != NULL) {
 		dsl_dir_close(dd, FTAG);
@@ -777,11 +806,14 @@
 {
 	objset_t *mos = dd->dd_pool->dp_meta_objset;
 	dsl_dataset_t *ds;
+	int err;
 
 	if (dd->dd_phys->dd_head_dataset_obj == 0)
 		return (EINVAL);
-	ds = dsl_dataset_open_obj(dd->dd_pool,
-	    dd->dd_phys->dd_head_dataset_obj, NULL, DS_MODE_NONE, FTAG);
+	err = dsl_dataset_open_obj(dd->dd_pool,
+	    dd->dd_phys->dd_head_dataset_obj, NULL, DS_MODE_NONE, FTAG, &ds);
+	if (err)
+		return (err);
 
 	if (ds->ds_phys->ds_prev_snap_txg == 0) {
 		/*
@@ -823,7 +855,8 @@
 	bplist_destroy(mos, ds->ds_phys->ds_deadlist_obj, tx);
 	ds->ds_phys->ds_deadlist_obj =
 	    bplist_create(mos, DSL_DEADLIST_BLOCKSIZE, tx);
-	bplist_open(&ds->ds_deadlist, mos, ds->ds_phys->ds_deadlist_obj);
+	VERIFY(0 == bplist_open(&ds->ds_deadlist, mos,
+	    ds->ds_phys->ds_deadlist_obj));
 	dprintf("new deadlist obj = %llx\n", ds->ds_phys->ds_deadlist_obj);
 
 	{
@@ -891,27 +924,23 @@
 		drop_lock = TRUE;
 	}
 
-	ds = dsl_dataset_open_obj(dd->dd_pool,
+	err = dsl_dataset_open_obj(dd->dd_pool,
 	    dd->dd_phys->dd_head_dataset_obj, NULL,
-	    snapname ? DS_MODE_NONE : DS_MODE_EXCLUSIVE, FTAG);
+	    snapname ? DS_MODE_NONE : DS_MODE_EXCLUSIVE, FTAG, &ds);
 
-	if (snapname) {
+	if (err == 0 && snapname) {
 		err = zap_lookup(mos, ds->ds_phys->ds_snapnames_zapobj,
 		    snapname, 8, 1, &obj);
 		dsl_dataset_close(ds, DS_MODE_NONE, FTAG);
-		if (err) {
-			if (drop_lock)
-				rw_exit(&dp->dp_config_rwlock);
-			return (err);
+		if (err == 0) {
+			err = dsl_dataset_open_obj(dd->dd_pool, obj, NULL,
+			    DS_MODE_EXCLUSIVE, FTAG, &ds);
 		}
-
-		ds = dsl_dataset_open_obj(dd->dd_pool, obj, NULL,
-		    DS_MODE_EXCLUSIVE, FTAG);
 	}
-	if (ds == NULL) {
+	if (err) {
 		if (drop_lock)
 			rw_exit(&dp->dp_config_rwlock);
-		return (EBUSY);
+		return (err);
 	}
 
 	obj = ds->ds_object;
@@ -942,22 +971,25 @@
 	 * them.  Try again.
 	 */
 	if (ds->ds_phys->ds_bp.blk_birth >= tx->tx_txg) {
-		mutex_exit(&ds->ds_lock);
 		dsl_dataset_close(ds, DS_MODE_NONE, FTAG);
 		if (drop_lock)
 			rw_exit(&dp->dp_config_rwlock);
 		return (EAGAIN);
 	}
 
-	/* THE POINT OF NO (unsuccessful) RETURN */
-
 	if (ds->ds_phys->ds_prev_snap_obj != 0) {
 		if (ds->ds_prev) {
 			ds_prev = ds->ds_prev;
 		} else {
-			ds_prev = dsl_dataset_open_obj(dd->dd_pool,
+			err = dsl_dataset_open_obj(dd->dd_pool,
 			    ds->ds_phys->ds_prev_snap_obj, NULL,
-			    DS_MODE_NONE, FTAG);
+			    DS_MODE_NONE, FTAG, &ds_prev);
+			if (err) {
+				dsl_dataset_close(ds, DS_MODE_NONE, FTAG);
+				if (drop_lock)
+					rw_exit(&dp->dp_config_rwlock);
+				return (err);
+			}
 		}
 		after_branch_point =
 		    (ds_prev->ds_phys->ds_next_snap_obj != obj);
@@ -974,6 +1006,8 @@
 		}
 	}
 
+	/* THE POINT OF NO (unsuccessful) RETURN */
+
 	ASSERT3P(tx->tx_pool, ==, dd->dd_pool);
 	zio = zio_root(dp->dp_spa, NULL, NULL, ZIO_FLAG_MUSTSUCCEED);
 
@@ -983,8 +1017,9 @@
 
 		spa_scrub_restart(dp->dp_spa, tx->tx_txg);
 
-		ds_next = dsl_dataset_open_obj(dd->dd_pool,
-		    ds->ds_phys->ds_next_snap_obj, NULL, DS_MODE_NONE, FTAG);
+		VERIFY(0 == dsl_dataset_open_obj(dd->dd_pool,
+		    ds->ds_phys->ds_next_snap_obj, NULL,
+		    DS_MODE_NONE, FTAG, &ds_next));
 		ASSERT3U(ds_next->ds_phys->ds_prev_snap_obj, ==, obj);
 
 		dmu_buf_will_dirty(ds_next->ds_dbuf, tx);
@@ -1006,7 +1041,8 @@
 		while (bplist_iterate(&ds_next->ds_deadlist, &itor,
 		    &bp) == 0) {
 			if (bp.blk_birth <= ds->ds_phys->ds_prev_snap_txg) {
-				bplist_enqueue(&ds->ds_deadlist, &bp, tx);
+				VERIFY(0 == bplist_enqueue(&ds->ds_deadlist,
+				    &bp, tx));
 				if (ds_prev && !after_branch_point &&
 				    bp.blk_birth >
 				    ds_prev->ds_phys->ds_prev_snap_txg) {
@@ -1030,8 +1066,8 @@
 		/* set next's deadlist to our deadlist */
 		ds_next->ds_phys->ds_deadlist_obj =
 		    ds->ds_phys->ds_deadlist_obj;
-		bplist_open(&ds_next->ds_deadlist, mos,
-		    ds_next->ds_phys->ds_deadlist_obj);
+		VERIFY(0 == bplist_open(&ds_next->ds_deadlist, mos,
+		    ds_next->ds_phys->ds_deadlist_obj));
 		ds->ds_phys->ds_deadlist_obj = 0;
 
 		if (ds_next->ds_phys->ds_next_snap_obj != 0) {
@@ -1049,9 +1085,9 @@
 			 */
 			dsl_dataset_t *ds_after_next;
 
-			ds_after_next = dsl_dataset_open_obj(dd->dd_pool,
+			VERIFY(0 == dsl_dataset_open_obj(dd->dd_pool,
 			    ds_next->ds_phys->ds_next_snap_obj, NULL,
-			    DS_MODE_NONE, FTAG);
+			    DS_MODE_NONE, FTAG, &ds_after_next));
 			itor = 0;
 			while (bplist_iterate(&ds_after_next->ds_deadlist,
 			    &itor, &bp) == 0) {
@@ -1078,9 +1114,9 @@
 			dsl_dataset_close(ds_next->ds_prev, DS_MODE_NONE,
 			    ds_next);
 			if (ds_prev) {
-				ds_next->ds_prev = dsl_dataset_open_obj(
-				    dd->dd_pool, ds->ds_phys->ds_prev_snap_obj,
-				    NULL, DS_MODE_NONE, ds_next);
+				VERIFY(0 == dsl_dataset_open_obj(dd->dd_pool,
+				    ds->ds_phys->ds_prev_snap_obj, NULL,
+				    DS_MODE_NONE, ds_next, &ds_next->ds_prev));
 			} else {
 				ds_next->ds_prev = NULL;
 			}
@@ -1144,8 +1180,9 @@
 	} else {
 		/* remove from snapshot namespace */
 		dsl_dataset_t *ds_head;
-		ds_head = dsl_dataset_open_obj(dd->dd_pool,
-		    dd->dd_phys->dd_head_dataset_obj, NULL, DS_MODE_NONE, FTAG);
+		VERIFY(0 == dsl_dataset_open_obj(dd->dd_pool,
+		    dd->dd_phys->dd_head_dataset_obj, NULL,
+		    DS_MODE_NONE, FTAG, &ds_head));
 #ifdef ZFS_DEBUG
 		{
 			uint64_t val;
@@ -1195,8 +1232,10 @@
 
 	if (dd->dd_phys->dd_head_dataset_obj == 0)
 		return (EINVAL);
-	ds = dsl_dataset_open_obj(dp, dd->dd_phys->dd_head_dataset_obj, NULL,
-	    DS_MODE_NONE, FTAG);
+	err = dsl_dataset_open_obj(dp, dd->dd_phys->dd_head_dataset_obj, NULL,
+	    DS_MODE_NONE, FTAG, &ds);
+	if (err)
+		return (err);
 
 	err = zap_lookup(mos, ds->ds_phys->ds_snapnames_zapobj,
 	    snapname, 8, 1, &value);
@@ -1217,7 +1256,7 @@
 
 	dsobj = dmu_object_alloc(mos, DMU_OT_DSL_DATASET, 0,
 	    DMU_OT_DSL_DATASET, sizeof (dsl_dataset_phys_t), tx);
-	dbuf = dmu_bonus_hold(mos, dsobj);
+	VERIFY(0 == dmu_bonus_hold(mos, dsobj, FTAG, &dbuf));
 	dmu_buf_will_dirty(dbuf, tx);
 	dsphys = dbuf->db_data;
 	dsphys->ds_dir_obj = dd->dd_object;
@@ -1237,13 +1276,14 @@
 	dsphys->ds_uncompressed_bytes = ds->ds_phys->ds_uncompressed_bytes;
 	dsphys->ds_restoring = ds->ds_phys->ds_restoring;
 	dsphys->ds_bp = ds->ds_phys->ds_bp;
-	dmu_buf_rele(dbuf);
+	dmu_buf_rele(dbuf, FTAG);
 
 	if (ds->ds_phys->ds_prev_snap_obj != 0) {
 		dsl_dataset_t *ds_prev;
 
-		ds_prev = dsl_dataset_open_obj(dp,
-		    ds->ds_phys->ds_prev_snap_obj, NULL, DS_MODE_NONE, FTAG);
+		VERIFY(0 == dsl_dataset_open_obj(dp,
+		    ds->ds_phys->ds_prev_snap_obj, NULL,
+		    DS_MODE_NONE, FTAG, &ds_prev));
 		ASSERT(ds_prev->ds_phys->ds_next_snap_obj ==
 		    ds->ds_object ||
 		    ds_prev->ds_phys->ds_num_children > 1);
@@ -1266,7 +1306,8 @@
 	ds->ds_phys->ds_unique_bytes = 0;
 	ds->ds_phys->ds_deadlist_obj =
 	    bplist_create(mos, DSL_DEADLIST_BLOCKSIZE, tx);
-	bplist_open(&ds->ds_deadlist, mos, ds->ds_phys->ds_deadlist_obj);
+	VERIFY(0 == bplist_open(&ds->ds_deadlist, mos,
+	    ds->ds_phys->ds_deadlist_obj));
 
 	dprintf("snap '%s' -> obj %llu\n", snapname, dsobj);
 	err = zap_add(mos, ds->ds_phys->ds_snapnames_zapobj,
@@ -1275,8 +1316,9 @@
 
 	if (ds->ds_prev)
 		dsl_dataset_close(ds->ds_prev, DS_MODE_NONE, ds);
-	ds->ds_prev = dsl_dataset_open_obj(dp,
-	    ds->ds_phys->ds_prev_snap_obj, snapname, DS_MODE_NONE, ds);
+	VERIFY(0 == dsl_dataset_open_obj(dp,
+	    ds->ds_phys->ds_prev_snap_obj, snapname,
+	    DS_MODE_NONE, ds, &ds->ds_prev));
 
 	rw_exit(&dp->dp_config_rwlock);
 	dsl_dataset_close(ds, DS_MODE_NONE, FTAG);
@@ -1295,7 +1337,7 @@
 	dsl_dir_dirty(ds->ds_dir, tx);
 	bplist_close(&ds->ds_deadlist);
 
-	dmu_buf_remove_ref(ds->ds_dbuf, ds);
+	dmu_buf_rele(ds->ds_dbuf, ds);
 }
 
 void
@@ -1319,7 +1361,6 @@
 	dds->dds_creation_txg = ds->ds_phys->ds_creation_txg;
 	dds->dds_space_refd = ds->ds_phys->ds_used_bytes;
 	dds->dds_fsid_guid = ds->ds_phys->ds_fsid_guid;
-	dds->dds_guid = ds->ds_phys->ds_guid;
 
 	if (ds->ds_phys->ds_next_snap_obj) {
 		/*
@@ -1332,8 +1373,6 @@
 		dds->dds_uncompressed_bytes =
 		    ds->ds_phys->ds_uncompressed_bytes;
 	}
-
-	dds->dds_objset_obj = ds->ds_object;
 }
 
 dsl_pool_t *
@@ -1375,10 +1414,11 @@
 	}
 
 	/* new fs better exist */
-	nds = dsl_dir_open_spa(dd->dd_pool->dp_spa, ora->newname, FTAG, &tail);
-	if (nds == NULL) {
+	err = dsl_dir_open_spa(dd->dd_pool->dp_spa, ora->newname,
+	    FTAG, &nds, &tail);
+	if (err) {
 		dsl_dataset_close(snds, DS_MODE_STANDARD, FTAG);
-		return (ENOENT);
+		return (err);
 	}
 
 	dsl_dir_close(nds, FTAG);
@@ -1397,8 +1437,12 @@
 
 	tail++;
 
-	fsds = dsl_dataset_open_obj(dd->dd_pool,
-	    dd->dd_phys->dd_head_dataset_obj, NULL, DS_MODE_NONE, FTAG);
+	err = dsl_dataset_open_obj(dd->dd_pool,
+	    dd->dd_phys->dd_head_dataset_obj, NULL, DS_MODE_NONE, FTAG, &fsds);
+	if (err) {
+		dsl_dataset_close(snds, DS_MODE_STANDARD, FTAG);
+		return (err);
+	}
 
 	/* new name better not be in use */
 	err = zap_lookup(mos, fsds->ds_phys->ds_snapnames_zapobj,
@@ -1414,7 +1458,7 @@
 	/* The point of no (unsuccessful) return */
 
 	rw_enter(&dd->dd_pool->dp_config_rwlock, RW_WRITER);
-	dsl_dataset_get_snapname(snds);
+	VERIFY(0 == dsl_dataset_get_snapname(snds));
 	err = zap_remove(mos, fsds->ds_phys->ds_snapnames_zapobj,
 	    snds->ds_snapname, tx);
 	ASSERT3U(err, ==, 0);
@@ -1440,9 +1484,9 @@
 	struct osrenamearg ora;
 	int err;
 
-	dd = dsl_dir_open(osname, FTAG, &tail);
-	if (dd == NULL)
-		return (ENOENT);
+	err = dsl_dir_open(osname, FTAG, &dd, &tail);
+	if (err)
+		return (err);
 	if (tail == NULL) {
 		err = dsl_dir_sync_task(dd,
 		    dsl_dir_rename_sync, (void*)newname, 1<<12);