]> git.proxmox.com Git - mirror_zfs.git/commitdiff
BRT: Fix holes cloning.
authorAlexander Motin <mav@FreeBSD.org>
Mon, 18 Mar 2024 18:19:53 +0000 (14:19 -0400)
committerBrian Behlendorf <behlendorf1@llnl.gov>
Wed, 27 Mar 2024 21:45:27 +0000 (14:45 -0700)
 - 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

module/zfs/dmu.c

index b88cf447d2967f4f07686b18d3336ddc7104d436..753dde6d520599ddd23c6c17298e40f3fdf1118b 100644 (file)
@@ -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);