summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexander Motin <[email protected]>2023-12-12 15:59:24 -0500
committerBrian Behlendorf <[email protected]>2024-01-08 16:11:39 -0800
commit9c40ae02199668d1e9a07d14c4ea713b2c5e584e (patch)
tree0fdea5032567857cdee1154f64b8834cbc736e03
parenta701548eb4a8ed47ebda9b28a23e1de80adf1b91 (diff)
dbuf: Set dr_data when unoverriding after clone
Block cloning normally creates dirty record without dr_data. But if the block is read after cloning, it is moved into DB_CACHED state and receives the data buffer. If after that we call dbuf_unoverride() to convert the dirty record into normal write, we should give it the data buffer from dbuf and release one. Reviewed-by: Kay Pedersen <[email protected]> Reviewed-by: Brian Behlendorf <[email protected]> Signed-off-by: Alexander Motin <[email protected]> Sponsored by: iXsystems, Inc. Closes #15654 Closes #15656
-rw-r--r--module/zfs/dbuf.c8
1 files changed, 5 insertions, 3 deletions
diff --git a/module/zfs/dbuf.c b/module/zfs/dbuf.c
index 7691cd85f..e4c59b593 100644
--- a/module/zfs/dbuf.c
+++ b/module/zfs/dbuf.c
@@ -1904,7 +1904,6 @@ dbuf_unoverride(dbuf_dirty_record_t *dr)
dmu_buf_impl_t *db = dr->dr_dbuf;
blkptr_t *bp = &dr->dt.dl.dr_overridden_by;
uint64_t txg = dr->dr_txg;
- boolean_t release;
ASSERT(MUTEX_HELD(&db->db_mtx));
/*
@@ -1925,7 +1924,10 @@ dbuf_unoverride(dbuf_dirty_record_t *dr)
if (!BP_IS_HOLE(bp) && !dr->dt.dl.dr_nopwrite)
zio_free(db->db_objset->os_spa, txg, bp);
- release = !dr->dt.dl.dr_brtwrite;
+ if (dr->dt.dl.dr_brtwrite) {
+ ASSERT0(dr->dt.dl.dr_data);
+ dr->dt.dl.dr_data = db->db_buf;
+ }
dr->dt.dl.dr_override_state = DR_NOT_OVERRIDDEN;
dr->dt.dl.dr_nopwrite = B_FALSE;
dr->dt.dl.dr_brtwrite = B_FALSE;
@@ -1939,7 +1941,7 @@ dbuf_unoverride(dbuf_dirty_record_t *dr)
* the buf thawed to save the effort of freezing &
* immediately re-thawing it.
*/
- if (release)
+ if (dr->dt.dl.dr_data)
arc_release(dr->dt.dl.dr_data, db);
}