From ad0a554614b096698d9969340c4c593690042d5b Mon Sep 17 00:00:00 2001 From: Brian Atkinson Date: Fri, 19 May 2023 16:05:53 -0400 Subject: [PATCH] Hold db_mtx when updating db_state Commit 555ef90 did some general code refactoring for dmu_buf_will_not_fill() and dmu_buf_will_fill(). However, the db_mtx was not held when update db->db_state in those code block. The rest of the dbuf code always holds the db_mtx when updating db_state. This is important because cv_wait() db_changed is used to check for db_state changes. Updating dmu_buf_will_not_fill() and dmu_buf_will_fill() to hold the db_mtx when updating db_state. Reviewed-by: Alexander Motin Reviewed-by: Brian Behlendorf Signed-off-by: Brian Atkinson Closes #14875 --- module/zfs/dbuf.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/module/zfs/dbuf.c b/module/zfs/dbuf.c index 049a62c1c1..272e712586 100644 --- a/module/zfs/dbuf.c +++ b/module/zfs/dbuf.c @@ -2716,8 +2716,10 @@ dmu_buf_will_not_fill(dmu_buf_t *db_fake, dmu_tx_t *tx) { dmu_buf_impl_t *db = (dmu_buf_impl_t *)db_fake; + mutex_enter(&db->db_mtx); db->db_state = DB_NOFILL; DTRACE_SET_STATE(db, "allocating NOFILL buffer"); + mutex_exit(&db->db_mtx); dbuf_noread(db); (void) dbuf_dirty(db, tx); @@ -2736,6 +2738,7 @@ dmu_buf_will_fill(dmu_buf_t *db_fake, dmu_tx_t *tx) ASSERT(db->db.db_object != DMU_META_DNODE_OBJECT || dmu_tx_private_ok(tx)); + mutex_enter(&db->db_mtx); if (db->db_state == DB_NOFILL) { /* * Block cloning: We will be completely overwriting a block @@ -2743,11 +2746,10 @@ dmu_buf_will_fill(dmu_buf_t *db_fake, dmu_tx_t *tx) * pending clone and mark the block as uncached. This will be * as if the clone was never done. */ - mutex_enter(&db->db_mtx); VERIFY(!dbuf_undirty(db, tx)); - mutex_exit(&db->db_mtx); db->db_state = DB_UNCACHED; } + mutex_exit(&db->db_mtx); dbuf_noread(db); (void) dbuf_dirty(db, tx);