From 86d68d357ac667f8ebab11d230338c10553ab00b Mon Sep 17 00:00:00 2001 From: Gunnar Beutner Date: Tue, 30 Oct 2012 17:41:38 +0100 Subject: [PATCH] Fix a race condition in dbuf_dirty(). We need to wait for pending I/O to finish before trying to clear the dirty record's override state. This problem occurs when multiple threads call dbuf_dirty() for the same dbuf object while it is currently being synced via dmu_sync() but hasn't reached dmu_sync_done() yet: zfs: allocating allocated segment(offset=323629568 size=78336) SPLError: 2283:0:(spl-err.c:48:vpanic()) SPL PANIC Issue #541 --- module/zfs/dbuf.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/module/zfs/dbuf.c b/module/zfs/dbuf.c index 1f6fa93406c9..ea0d6abf5dea 100644 --- a/module/zfs/dbuf.c +++ b/module/zfs/dbuf.c @@ -1115,6 +1115,10 @@ dbuf_dirty(dmu_buf_impl_t *db, dmu_tx_t *tx) DB_DNODE_EXIT(db); if (db->db_level == 0 && db->db_blkid != DMU_BONUS_BLKID) { + /* Wait for pending I/O. */ + while (dr->dt.dl.dr_override_state == DR_IN_DMU_SYNC) + cv_wait(&db->db_changed, &db->db_mtx); + /* * If this buffer has already been written out, * we now need to reset its state.