changeset 12659:bdcaf6c09c92

6957089 race between dedup prefetch and table remove
author George Wilson <George.Wilson@Sun.COM>
date Mon, 21 Jun 2010 09:44:26 -0700
parents abe3f7fcaa24
children 32abd267e35d
files usr/src/uts/common/fs/zfs/ddt.c
diffstat 1 files changed, 11 insertions(+), 7 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/uts/common/fs/zfs/ddt.c	Mon Jun 21 17:30:17 2010 +0100
+++ b/usr/src/uts/common/fs/zfs/ddt.c	Mon Jun 21 09:44:26 2010 -0700
@@ -739,9 +739,9 @@
 		return;
 
 	/*
-	 * We remove the DDT once it's empty and only prefetch dedup blocks
-	 * when there are entries in the DDT.  Thus no locking is required
-	 * as the DDT can't disappear on us.
+	 * We only remove the DDT once all tables are empty and only
+	 * prefetch dedup blocks when there are entries in the DDT.
+	 * Thus no locking is required as the DDT can't disappear on us.
 	 */
 	ddt = ddt_select(spa, bp);
 	ddt_key_fill(&dde.dde_key, bp);
@@ -1077,11 +1077,15 @@
 	}
 
 	for (enum ddt_type type = 0; type < DDT_TYPES; type++) {
+		uint64_t count = 0;
 		for (enum ddt_class class = 0; class < DDT_CLASSES; class++) {
-			if (!ddt_object_exists(ddt, type, class))
-				continue;
-			ddt_object_sync(ddt, type, class, tx);
-			if (ddt_object_count(ddt, type, class) == 0)
+			if (ddt_object_exists(ddt, type, class)) {
+				ddt_object_sync(ddt, type, class, tx);
+				count += ddt_object_count(ddt, type, class);
+			}
+		}
+		for (enum ddt_class class = 0; class < DDT_CLASSES; class++) {
+			if (count == 0 && ddt_object_exists(ddt, type, class))
 				ddt_object_destroy(ddt, type, class, tx);
 		}
 	}