changeset 13794:7c5e0e746b2c

3129 'zpool reopen' restarts resilvers 3130 ztest failure: Assertion failed: 0 == dmu_objset_destroy(name, B_FALSE) (0x0 == 0x10) Reviewed by: Eric Schrock <eric.schrock@delphix.com> Reviewed by: Matt Ahrens <matthew.ahrens@delphix.com> Reviewed by: Christopher Siden <chris.siden@delphix.com> Reviewed by: Adam Leventhal <ahl@delphix.com> Approved by: Dan McDonald <danmcd@nexenta.com>
author George Wilson <george.wilson@delphix.com>
date Sat, 01 Sep 2012 16:44:00 -0400
parents 10c3656ccf76
children caa31a28c302
files usr/src/uts/common/fs/zfs/dsl_dir.c usr/src/uts/common/fs/zfs/zfs_ioctl.c
diffstat 2 files changed, 17 insertions(+), 5 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/uts/common/fs/zfs/dsl_dir.c	Fri Aug 31 15:12:34 2012 -0500
+++ b/usr/src/uts/common/fs/zfs/dsl_dir.c	Sat Sep 01 16:44:00 2012 -0400
@@ -456,12 +456,14 @@
 	/*
 	 * There should be exactly two holds, both from
 	 * dsl_dataset_destroy: one on the dd directory, and one on its
-	 * head ds.  Otherwise, someone is trying to lookup something
-	 * inside this dir while we want to destroy it.  The
-	 * config_rwlock ensures that nobody else opens it after we
-	 * check.
+	 * head ds.  If there are more holds, then a concurrent thread is
+	 * performing a lookup inside this dir while we're trying to destroy
+	 * it.  To minimize this possibility, we perform this check only
+	 * in syncing context and fail the operation if we encounter
+	 * additional holds.  The dp_config_rwlock ensures that nobody else
+	 * opens it after we check.
 	 */
-	if (dmu_buf_refcount(dd->dd_dbuf) > 2)
+	if (dmu_tx_is_syncing(tx) && dmu_buf_refcount(dd->dd_dbuf) > 2)
 		return (EBUSY);
 
 	err = zap_count(mos, dd->dd_phys->dd_child_dir_zapobj, &count);
--- a/usr/src/uts/common/fs/zfs/zfs_ioctl.c	Fri Aug 31 15:12:34 2012 -0500
+++ b/usr/src/uts/common/fs/zfs/zfs_ioctl.c	Sat Sep 01 16:44:00 2012 -0400
@@ -4335,7 +4335,17 @@
 		return (error);
 
 	spa_vdev_state_enter(spa, SCL_NONE);
+
+	/*
+	 * If a resilver is already in progress then set the
+	 * spa_scrub_reopen flag to B_TRUE so that we don't restart
+	 * the scan as a side effect of the reopen. Otherwise, let
+	 * vdev_open() decided if a resilver is required.
+	 */
+	spa->spa_scrub_reopen = dsl_scan_resilvering(spa->spa_dsl_pool);
 	vdev_reopen(spa->spa_root_vdev);
+	spa->spa_scrub_reopen = B_FALSE;
+
 	(void) spa_vdev_state_exit(spa, NULL, 0);
 	spa_close(spa, FTAG);
 	return (0);