6952867 recursive rw_enter in dsl_dataset_clone_swap
authorChris Kirby <Chris.Kirby@oracle.com>
Mon, 28 Jun 2010 09:58:49 -0600
changeset 12711 7ba0ca9a0395
parent 12710 66c9c36f2046
child 12712 15cc5e08cfc0
6952867 recursive rw_enter in dsl_dataset_clone_swap
usr/src/uts/common/fs/zfs/dsl_dataset.c
--- a/usr/src/uts/common/fs/zfs/dsl_dataset.c	Mon Jun 28 09:19:17 2010 -0600
+++ b/usr/src/uts/common/fs/zfs/dsl_dataset.c	Mon Jun 28 09:58:49 2010 -0600
@@ -3139,9 +3139,14 @@
 	ASSERT(clone->ds_owner);
 	ASSERT(origin_head->ds_owner);
 retry:
-	/* Need exclusive access for the swap */
-	rw_enter(&clone->ds_rwlock, RW_WRITER);
-	if (!rw_tryenter(&origin_head->ds_rwlock, RW_WRITER)) {
+	/*
+	 * Need exclusive access for the swap. If we're swapping these
+	 * datasets back after an error, we already hold the locks.
+	 */
+	if (!RW_WRITE_HELD(&clone->ds_rwlock))
+		rw_enter(&clone->ds_rwlock, RW_WRITER);
+	if (!RW_WRITE_HELD(&origin_head->ds_rwlock) &&
+	    !rw_tryenter(&origin_head->ds_rwlock, RW_WRITER)) {
 		rw_exit(&clone->ds_rwlock);
 		rw_enter(&origin_head->ds_rwlock, RW_WRITER);
 		if (!rw_tryenter(&clone->ds_rwlock, RW_WRITER)) {