Skip to content

cryptsetup-var: encrypt a grown /var in place, report conversion size/progress - #321

Closed
mobileoverlord wants to merge 1 commit into
wrynosefrom
jschneck/cryptsetup-var-grown-fs
Closed

cryptsetup-var: encrypt a grown /var in place, report conversion size/progress#321
mobileoverlord wants to merge 1 commit into
wrynosefrom
jschneck/cryptsetup-var-grown-fs

Conversation

@mobileoverlord

Copy link
Copy Markdown
Contributor

Follow-up to #310/#317 for the OTA scenario: a device deployed with a plaintext /var receives an update that turns var.encrypt on.

Before: encrypt_in_place needs 32 MiB of free tail for the LUKS2 header, but on any deployed device grow-var has already resized the btrfs to fill the partition, so the guard fired (leaves no 32 MiB for a LUKS header - cannot encrypt in place), cryptsetup-var.service failed, /var never mounted, emergency shell. Only fresh flashes (461 M seed inside a 55 G partition, as tested on Thor/Orin) ever converted.

Now:

  • When headroom < 32 MiB and the fs is btrfs: mount on /run/cryptsetup-var-shrink, btrfs filesystem resize -<deficit>M, unmount, then the unchanged --reduce-device-size 32M reencryption. A shrink refusal (tail chunk in use / full) still fails closed with a message saying so.
  • Console line with the MiB being converted, that it is a one-time resumable migration, and --progress-frequency 30 when cryptsetup ≥ 2.4 advertises it — a seeded /var can be tens of GiB and this step runs for minutes with nothing else on screen.

Generic (meta-avocado core); every target using cryptsetup-var gets it. The initramfs already has btrfs-progs and the btrfs module (it mounts /var), and mount (util-linux/busybox).

Not in this PR: bounding the work to used data (shrink to used+slack before encrypting, re-grow after). --device-size still covers btrfs total_bytes, so a 40 G fs with 5 G used encrypts 40 G. That needs a chunk-relocation pass and is a separate trade-off.

Tests: tests/test-cryptsetup-var-inplace.sh 11/11 (new: grown-fs shrink by exact deficit, mount→resize→umount ordering before reencrypt, resulting device-size, console size line, and that a small flashed fs is never shrunk).

…ing converted

Turning rootfs var.encrypt on for a device that already ran plaintext failed
closed: grow-var had resized the btrfs to fill the partition, so
encrypt_in_place found no 32 MiB tail for the LUKS2 header and exited with
'leaves no 32 MiB for a LUKS header' - /var never mounted and the board sat in
the emergency shell after the OTA. Only a fresh flash (fs far smaller than its
expand-to-fill partition) ever worked.

btrfs shrinks online, so when the headroom is short, mount the filesystem on
/run/cryptsetup-var-shrink, 'btrfs filesystem resize' it by exactly the
deficit, unmount, and continue with the same --reduce-device-size 32M
reencryption. A shrink refusal (tail chunk in use, no free space) still fails
closed with a message naming that.

A seeded /var can be tens of GiB and the conversion then runs for many
minutes with nothing on the console: print the MiB being converted, that it
is a one-time resumable migration, and pass --progress-frequency 30 when the
installed cryptsetup (>= 2.4) has it.

tests: grown-fs case (shrink by the deficit, mount->resize->umount before the
reencrypt, device-size covers the result), the small flashed case is not
shrunk, and the console line is present.
@mobileoverlord

Copy link
Copy Markdown
Contributor Author

Merged into wrynose via #316 (rebased, commits preserved). Closing as included.

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