6733970 assertion failure in dbuf_dirty() via spa_sync_nvlist()
authorTim Haley <Tim.Haley@Sun.COM>
Fri, 05 Sep 2008 16:44:17 -0600
changeset 7497 f6c6be3b6154
parent 7496 e01f48614eac
child 7498 74f1bb26b79b
6733970 assertion failure in dbuf_dirty() via spa_sync_nvlist()
usr/src/uts/common/fs/zfs/spa.c
usr/src/uts/common/fs/zfs/sys/spa.h
--- a/usr/src/uts/common/fs/zfs/spa.c	Fri Sep 05 15:19:28 2008 -0700
+++ b/usr/src/uts/common/fs/zfs/spa.c	Fri Sep 05 16:44:17 2008 -0600
@@ -1985,7 +1985,7 @@
 	 * Create the pool config object.
 	 */
 	spa->spa_config_object = dmu_object_alloc(spa->spa_meta_objset,
-	    DMU_OT_PACKED_NVLIST, 1 << 14,
+	    DMU_OT_PACKED_NVLIST, SPA_CONFIG_BLOCKSIZE,
 	    DMU_OT_PACKED_NVLIST_SIZE, sizeof (uint64_t), tx);
 
 	if (zap_add(spa->spa_meta_objset,
@@ -3690,19 +3690,27 @@
 spa_sync_nvlist(spa_t *spa, uint64_t obj, nvlist_t *nv, dmu_tx_t *tx)
 {
 	char *packed = NULL;
+	size_t bufsize;
 	size_t nvsize = 0;
 	dmu_buf_t *db;
 
 	VERIFY(nvlist_size(nv, &nvsize, NV_ENCODE_XDR) == 0);
 
-	packed = kmem_alloc(nvsize, KM_SLEEP);
+	/*
+	 * Write full (SPA_CONFIG_BLOCKSIZE) blocks of configuration
+	 * information.  This avoids the dbuf_will_dirty() path and
+	 * saves us a pre-read to get data we don't actually care about.
+	 */
+	bufsize = P2ROUNDUP(nvsize, SPA_CONFIG_BLOCKSIZE);
+	packed = kmem_alloc(bufsize, KM_SLEEP);
 
 	VERIFY(nvlist_pack(nv, &packed, &nvsize, NV_ENCODE_XDR,
 	    KM_SLEEP) == 0);
-
-	dmu_write(spa->spa_meta_objset, obj, 0, nvsize, packed, tx);
-
-	kmem_free(packed, nvsize);
+	bzero(packed + nvsize, bufsize - nvsize);
+
+	dmu_write(spa->spa_meta_objset, obj, 0, bufsize, packed, tx);
+
+	kmem_free(packed, bufsize);
 
 	VERIFY(0 == dmu_bonus_hold(spa->spa_meta_objset, obj, FTAG, &db));
 	dmu_buf_will_dirty(db, tx);
--- a/usr/src/uts/common/fs/zfs/sys/spa.h	Fri Sep 05 15:19:28 2008 -0700
+++ b/usr/src/uts/common/fs/zfs/sys/spa.h	Fri Sep 05 16:44:17 2008 -0600
@@ -26,8 +26,6 @@
 #ifndef _SYS_SPA_H
 #define	_SYS_SPA_H
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
 #include <sys/avl.h>
 #include <sys/zfs_context.h>
 #include <sys/nvpair.h>
@@ -89,6 +87,11 @@
 #define	SPA_BLOCKSIZES		(SPA_MAXBLOCKSHIFT - SPA_MINBLOCKSHIFT + 1)
 
 /*
+ * Size of block to hold the configuration data (a packed nvlist)
+ */
+#define	SPA_CONFIG_BLOCKSIZE	(1 << 14)
+
+/*
  * The DVA size encodings for LSIZE and PSIZE support blocks up to 32MB.
  * The ASIZE encoding should be at least 64 times larger (6 more bits)
  * to support up to 4-way RAID-Z mirror mode with worst-case gang block