aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrian Atkinson <[email protected]>2023-05-19 16:05:53 -0400
committerGitHub <[email protected]>2023-05-19 13:05:53 -0700
commitad0a554614b096698d9969340c4c593690042d5b (patch)
tree9972b77c07f85550e5b3ae1114a4c0ae434a1ba6
parent577e835f30c9b92ed8126eb4e8fb17cb0e411c04 (diff)
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 <[email protected]> Reviewed-by: Brian Behlendorf <[email protected]> Signed-off-by: Brian Atkinson <[email protected]> Closes #14875
-rw-r--r--module/zfs/dbuf.c6
1 files changed, 4 insertions, 2 deletions
diff --git a/module/zfs/dbuf.c b/module/zfs/dbuf.c
index 049a62c1c..272e71258 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);