diff usr/src/uts/common/fs/zfs/dsl_dataset.c @ 7595:2ff5700c7efc

6747355 finish closing race condition when setting refreservation 6745276 Replication: appliance panic in dsl_dir_transfer_space+0xf6
author Matthew Ahrens <Matthew.Ahrens@Sun.COM>
date Mon, 15 Sep 2008 10:26:45 -0700
parents d29843e8f8a1
children b80e4842ad54
line wrap: on
line diff
--- a/usr/src/uts/common/fs/zfs/dsl_dataset.c	Mon Sep 15 08:52:21 2008 -0700
+++ b/usr/src/uts/common/fs/zfs/dsl_dataset.c	Mon Sep 15 10:26:45 2008 -0700
@@ -103,6 +103,7 @@
 		return;
 	}
 	dmu_buf_will_dirty(ds->ds_dbuf, tx);
+	mutex_enter(&ds->ds_dir->dd_lock);
 	mutex_enter(&ds->ds_lock);
 	delta = parent_delta(ds, used);
 	ds->ds_phys->ds_used_bytes += used;
@@ -114,6 +115,7 @@
 	    compressed, uncompressed, tx);
 	dsl_dir_transfer_space(ds->ds_dir, used - delta,
 	    DD_USED_REFRSRV, DD_USED_HEAD, tx);
+	mutex_exit(&ds->ds_dir->dd_lock);
 }
 
 int
@@ -159,6 +161,7 @@
 		    tx->tx_txg, bp, NULL, NULL, pio ? ARC_NOWAIT : ARC_WAIT);
 		ASSERT(err == 0);
 
+		mutex_enter(&ds->ds_dir->dd_lock);
 		mutex_enter(&ds->ds_lock);
 		ASSERT(ds->ds_phys->ds_unique_bytes >= used ||
 		    !DS_UNIQUE_IS_ACCURATE(ds));
@@ -169,6 +172,7 @@
 		    delta, -compressed, -uncompressed, tx);
 		dsl_dir_transfer_space(ds->ds_dir, -used - delta,
 		    DD_USED_REFRSRV, DD_USED_HEAD, tx);
+		mutex_exit(&ds->ds_dir->dd_lock);
 	} else {
 		dprintf_bp(bp, "putting on dead list: %s", "");
 		VERIFY(0 == bplist_enqueue(&ds->ds_deadlist, bp, tx));
@@ -3005,25 +3009,6 @@
 	return (err);
 }
 
-int64_t
-dsl_dataset_new_refreservation(dsl_dataset_t *ds, uint64_t new_reservation,
-    dmu_tx_t *tx)
-{
-	int64_t delta;
-	uint64_t unique;
-
-	dmu_buf_will_dirty(ds->ds_dbuf, tx);
-
-	mutex_enter(&ds->ds_lock);
-	unique = dsl_dataset_unique(ds);
-	delta = MAX(0, (int64_t)(new_reservation - unique)) -
-	    MAX(0, (int64_t)(ds->ds_reserved - unique));
-	ds->ds_reserved = new_reservation;
-	mutex_exit(&ds->ds_lock);
-
-	return (delta);
-}
-
 static int
 dsl_dataset_set_reservation_check(void *arg1, void *arg2, dmu_tx_t *tx)
 {
@@ -3073,8 +3058,27 @@
 	dsl_dataset_t *ds = arg1;
 	uint64_t *reservationp = arg2;
 	uint64_t new_reservation = *reservationp;
-
-	dsl_dir_new_refreservation(ds->ds_dir, ds, new_reservation, cr, tx);
+	uint64_t unique;
+	int64_t delta;
+
+	dmu_buf_will_dirty(ds->ds_dbuf, tx);
+
+	mutex_enter(&ds->ds_dir->dd_lock);
+	mutex_enter(&ds->ds_lock);
+	unique = dsl_dataset_unique(ds);
+	delta = MAX(0, (int64_t)(new_reservation - unique)) -
+	    MAX(0, (int64_t)(ds->ds_reserved - unique));
+	ds->ds_reserved = new_reservation;
+	mutex_exit(&ds->ds_lock);
+
+	dsl_dir_diduse_space(ds->ds_dir, DD_USED_REFRSRV, delta, 0, 0, tx);
+	mutex_exit(&ds->ds_dir->dd_lock);
+	dsl_prop_set_uint64_sync(ds->ds_dir, "refreservation",
+	    new_reservation, cr, tx);
+
+	spa_history_internal_log(LOG_DS_REFRESERV,
+	    ds->ds_dir->dd_pool->dp_spa, tx, cr, "%lld dataset = %llu",
+	    (longlong_t)new_reservation, ds->ds_object);
 }
 
 int