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 <mail@mkwg.de> Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov> Signed-off-by: Alexander Motin <mav@FreeBSD.org> Sponsored by: iXsystems, Inc. Closes #15654 Closes #15656
This commit is contained in:
parent
a701548eb4
commit
9c40ae0219
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue