Skip to content

Commit

Permalink
BRT: Fix holes cloning.
Browse files Browse the repository at this point in the history
 - When reading L0 block pointers handle buffers without ones and
without dirty records as a holes.  Those appear when dnode size
was increased, but the end was never written, so there are no new
indirection levels to store the pointers.  It makes no sense to
return EAGAIN here, since sync won't create new indirection levels
until there will be actual writes.
 - When cloning blocks always set destination logical birth time
to the current TXG.  Otherwise if we are cloning over existing
data, newly created holes may not be properly replicated later.
While there, stop messing with physical birth time, it was already
copied as part of the pointer and should already be zero for holes.

Signed-off-by:	Alexander Motin <[email protected]>
Sponsored by:	iXsystems, Inc.
Closes: #15994
  • Loading branch information
amotin committed Mar 18, 2024
1 parent 8f2f6cd commit 7afb0a0
Showing 1 changed file with 7 additions and 14 deletions.
21 changes: 7 additions & 14 deletions module/zfs/dmu.c
Original file line number Diff line number Diff line change
Expand Up @@ -2257,11 +2257,13 @@ dmu_read_l0_bps(objset_t *os, uint64_t object, uint64_t offset, uint64_t length,

if (bp == NULL) {
/*
* The block was created in this transaction group,
* so it has no BP yet.
* The file size was increased, but the block was never
* written, otherwise we would either have the block
* pointer or the dirty record and would not get here.
* It is effectively a hole, so report it as such.
*/
error = SET_ERROR(EAGAIN);
goto out;
BP_ZERO(&bps[i]);
continue;
}
/*
* Make sure we clone only data blocks.
Expand Down Expand Up @@ -2353,18 +2355,9 @@ dmu_brt_clone(objset_t *os, uint64_t object, uint64_t offset, uint64_t length,
ASSERT3U(dr->dr_txg, ==, tx->tx_txg);
dl = &dr->dt.dl;
dl->dr_overridden_by = *bp;
dl->dr_overridden_by.blk_birth = dr->dr_txg;
dl->dr_brtwrite = B_TRUE;
dl->dr_override_state = DR_OVERRIDDEN;
if (BP_IS_HOLE(bp)) {
dl->dr_overridden_by.blk_birth = 0;
dl->dr_overridden_by.blk_phys_birth = 0;
} else {
dl->dr_overridden_by.blk_birth = dr->dr_txg;
if (!BP_IS_EMBEDDED(bp)) {
dl->dr_overridden_by.blk_phys_birth =
BP_PHYSICAL_BIRTH(bp);
}
}

mutex_exit(&db->db_mtx);

Expand Down

0 comments on commit 7afb0a0

Please sign in to comment.