aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Motin <mav@FreeBSD.org>2024-03-18 18:19:53 +0000
committerBrian Behlendorf <behlendorf1@llnl.gov>2024-03-27 21:45:27 +0000
commita89d209bb60c3f32881da7624bd01d28023da4f4 (patch)
tree5ead860a25d8347074151a47b3d68a2230e42515
parent8cd8ccca5383dcdd9bf55d4d22921a6b43b4ebe1 (diff)
downloadsrc-a89d209bb60c3f32881da7624bd01d28023da4f4.tar.gz
src-a89d209bb60c3f32881da7624bd01d28023da4f4.zip
BRT: Fix holes cloning.
- 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 set destination hole logical birth time to the current TXG. Otherwise if we are cloning over existing data, newly created holes may not be properly replicated later. Use BP_SET_BIRTH() when possible to not replicate its logic. Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov> Signed-off-by: Alexander Motin <mav@FreeBSD.org> Sponsored by: iXsystems, Inc. Closes #15994 Closes #16007
-rw-r--r--module/zfs/dmu.c26
1 files changed, 13 insertions, 13 deletions
diff --git a/module/zfs/dmu.c b/module/zfs/dmu.c
index b88cf447d296..753dde6d5205 100644
--- a/module/zfs/dmu.c
+++ b/module/zfs/dmu.c
@@ -2265,11 +2265,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.
@@ -2361,19 +2363,17 @@ 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_brtwrite = B_TRUE;
- dl->dr_override_state = DR_OVERRIDDEN;
- if (BP_IS_HOLE(bp)) {
- BP_SET_LOGICAL_BIRTH(&dl->dr_overridden_by, 0);
- BP_SET_PHYSICAL_BIRTH(&dl->dr_overridden_by, 0);
- } else {
- BP_SET_LOGICAL_BIRTH(&dl->dr_overridden_by,
- dr->dr_txg);
+ if (!BP_IS_HOLE(bp) || BP_GET_LOGICAL_BIRTH(bp) != 0) {
if (!BP_IS_EMBEDDED(bp)) {
- BP_SET_PHYSICAL_BIRTH(&dl->dr_overridden_by,
+ BP_SET_BIRTH(&dl->dr_overridden_by, dr->dr_txg,
BP_GET_BIRTH(bp));
+ } else {
+ BP_SET_LOGICAL_BIRTH(&dl->dr_overridden_by,
+ dr->dr_txg);
}
}
+ dl->dr_brtwrite = B_TRUE;
+ dl->dr_override_state = DR_OVERRIDDEN;
mutex_exit(&db->db_mtx);