Skip to content

Leave zeros out of blank targets when reflinks are available - #439

Merged
folbricht merged 1 commit into
masterfrom
null-seed-blank
Sep 26, 2026
Merged

folbricht merged 1 commit into
masterfrom
null-seed-blank

Conversation

@folbricht

Copy link
Copy Markdown
Owner

The null seed skips zero ranges on a blank target, a new or truncated file, but only when reflinks aren't available. With reflinks, it clones the zero block file into the target one filesystem block at a time, filling in holes that already read as zeros. On images with large zero-filled areas that's hundreds of thousands of clone calls, and just as many extents in the result.

This skips zeros on blank targets whether or not reflinks are available. The clone path only runs for targets that aren't blank anymore, so its handling of blank targets goes away.

The cookbook gains a note on the extraction example with seeds: on Btrfs and XFS, the new image shares what it has in common with the seed, zero-filled ranges stay holes, and extracting next to the old image is usually the fastest way to update one kept as a file.

Measured

Debian 12 genericcloud raw images, 3.2 GB of which about 2.2 GB are zeros, on Btrfs. The build from 2026-09-09 is extracted into a new file, with an older build as seed. The output is identical in all cases.

seed time CPU written new space extents
2 days older before 76.9 s 67.5 s 2519 MiB 2460 MiB 493,913
2 days older after 8.4 s 13.7 s 464 MiB 459 MiB 6,667
1 year older before 58.5 s 53.3 s 2757 MiB 2733 MiB 484,889
1 year older after 6.3 s 12.9 s 753 MiB 702 MiB 5,512

"New space" is what the file needs on top of the blocks it shares with the seed, from btrfs filesystem du.

The null seed skipped zero ranges on a blank target, a new or truncated
file, only when reflinks weren't available. With them, it cloned the
zero block file into the target one filesystem block at a time, filling
in holes that read as zeros already.

On Btrfs, extracting a Debian 12 cloud image, 3.2 GB of which 2.2 GB are
zeros, into a new file with the previous build as seed took 77s and
left the file in 494k extents. Skipping the zeros, it takes 8.4s and
leaves 6.7k extents, with the same result.

With that, extracting into a new file with the old image as seed is the
quickest way to update an image kept on a filesystem with reflinks, and
the cookbook says so.
@folbricht
folbricht merged commit d78f7e5 into master Sep 26, 2026
16 of 18 checks passed
@folbricht
folbricht deleted the null-seed-blank branch September 26, 2026 17:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant