]> git.hungrycats.org Git - bees/commitdiff
dedup: add physical-extent generation to the logged address format
authorZygo Blaxell <bees@furryterror.org>
Wed, 8 Jul 2026 19:44:25 +0000 (15:44 -0400)
committerZygo Blaxell <bees@furryterror.org>
Sat, 5 Sep 2026 04:03:57 +0000 (00:03 -0400)
The compact address token in dedup/plan log lines, {bytenr+offset[:tag]}, does
not distinguish an extent from a later extent that reused the same bytenr after
the original was freed.  Log analysis that correlates an address across lines
(e.g. deciding whether an extent used as a dedupe src is the same one later
eliminated as a dst) can therefore conflate distinct lifetimes.

Append the physical extent's allocation generation from the extent-tree
EXTENT_ITEM: {bytenr+offset[:tag]/generation}, e.g. {0x1234567000+0x1000:zstd/1234}.
The allocation generation is fixed for one extent's lifetime and changes on
reuse, so it cleanly separates lifetimes.  file_extent_generation is not used:
it is per-reference and differs between reflinks of the same physical extent,
so it cannot identify a physical-extent lifetime.  The value costs one
extent-tree probe, paid only when an address is rendered into a log line.

Assisted-by: Claude-Code:claude-opus-4-8
Signed-off-by: Zygo Blaxell <bees@furryterror.org>
src/bees-util.cc

index b3659e4cb0663563f2722797f769f43d6af774aa..1b52f96cfe894a16491a0f817e6a103b0ad4d1b0 100644 (file)
@@ -469,6 +469,22 @@ bees_extent_addr(const Fd &root_fd, uint64_t subvol, uint64_t inum, uint64_t fil
        } else if (type == BTRFS_FILE_EXTENT_PREALLOC) {
                oss << ":prealloc";
        }
+       // Generation of the physical extent, from the extent-tree EXTENT_ITEM.
+       // A bytenr is reused after its extent is freed and reallocated, so the
+       // same address can name different extents at different times; the
+       // allocation generation changes on reuse and stays fixed for one extent's
+       // lifetime, so it disambiguates lifetimes in log analysis (e.g. telling a
+       // long-lived canonical from a recycled address).  file_extent_generation
+       // is unsuitable — it is per-reference and differs between reflinks of one
+       // physical extent.  This is one extra extent-tree probe per formatted
+       // address; it is only paid when an address is rendered into a log line.
+       {
+               BtrfsExtentItemFetcher beif(root_fd);
+               const auto ei = beif.lower_bound(bytenr);
+               if (!!ei && ei.objectid() == bytenr) {
+                       oss << "/" << ei.extent_generation();
+               }
+       }
        oss << "}";
        return oss.str();
 }