Skip to content

Commit 86e115e

Browse files
authored
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
1 parent 86063d9 commit 86e115e

File tree

1 file changed

+5
-3
lines changed

1 file changed

+5
-3
lines changed

module/zfs/dbuf.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1919,7 +1919,6 @@ dbuf_unoverride(dbuf_dirty_record_t *dr)
19191919
dmu_buf_impl_t *db = dr->dr_dbuf;
19201920
blkptr_t *bp = &dr->dt.dl.dr_overridden_by;
19211921
uint64_t txg = dr->dr_txg;
1922-
boolean_t release;
19231922

19241923
ASSERT(MUTEX_HELD(&db->db_mtx));
19251924
/*
@@ -1940,7 +1939,10 @@ dbuf_unoverride(dbuf_dirty_record_t *dr)
19401939
if (!BP_IS_HOLE(bp) && !dr->dt.dl.dr_nopwrite)
19411940
zio_free(db->db_objset->os_spa, txg, bp);
19421941

1943-
release = !dr->dt.dl.dr_brtwrite;
1942+
if (dr->dt.dl.dr_brtwrite) {
1943+
ASSERT0P(dr->dt.dl.dr_data);
1944+
dr->dt.dl.dr_data = db->db_buf;
1945+
}
19441946
dr->dt.dl.dr_override_state = DR_NOT_OVERRIDDEN;
19451947
dr->dt.dl.dr_nopwrite = B_FALSE;
19461948
dr->dt.dl.dr_brtwrite = B_FALSE;
@@ -1954,7 +1956,7 @@ dbuf_unoverride(dbuf_dirty_record_t *dr)
19541956
* the buf thawed to save the effort of freezing &
19551957
* immediately re-thawing it.
19561958
*/
1957-
if (release)
1959+
if (dr->dt.dl.dr_data)
19581960
arc_release(dr->dt.dl.dr_data, db);
19591961
}
19601962

0 commit comments

Comments
 (0)