Skip to content

Add LVM volume group support if lvm_vg= is specified#45

Open
NotKit wants to merge 4 commits into
dynpartsfrom
dynparts-lvm
Open

Add LVM volume group support if lvm_vg= is specified#45
NotKit wants to merge 4 commits into
dynpartsfrom
dynparts-lvm

Conversation

@NotKit

@NotKit NotKit commented Oct 16, 2025

Copy link
Copy Markdown

Support LVM-backed userdata and rootfs partitions via lvm_vg= cmdline parameter. Activate LVM early in boot process and check for volumes in the specified volume group. If found, /dev/$vg/userdata is used for userdata and /dev/$vg/rootfs overrides any systempart= setting.

@fredldotme fredldotme left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm wondering if instead of making LVM an optional thing via kernel cmdline, whether we should default to LVM instead. That is, if we really want to remove preexisting partition detection.

EDIT: I remember now, that won't work with our multiple recovery ramdisk copies across ports.

Comment thread scripts/halium Outdated
Comment thread scripts/halium
Comment thread scripts/halium
Comment thread scripts/halium Outdated
@peat-psuwit

Copy link
Copy Markdown

So, by simply adding lvm2 package into the building rootfs, we automatically get an initramfs-tools hook for it automatically. What if we simply rely on that and specify on kernel cmdline systempart=/dev/mapper/${lv}-rootfs datapart=/dev/mapper/${lv}-userdata?

We do call udevadm settle before looking for systempart and datapart; my understanding is that LVM PV scan should be triggered by that; if we're unsure I guess we can try triggering it manually if specified paths doesn't exists as well.

Comment thread scripts/halium
Comment on lines 518 to 521
if [ -b /dev/disk/by-partlabel/super ]; then
tell_kmsg "trying to parse and dmsetup subpartitions from super partition"
/sbin/parse-android-dynparts /dev/disk/by-partlabel/super | sh
fi

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My understanding is that the partition label for the new LVM PV will still be super. Does parse-android-dynparts handle this gracefully?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It will fail, which is ok, since we don't exit on errors.

@NotKit

NotKit commented Oct 22, 2025

Copy link
Copy Markdown
Author

So, by simply adding lvm2 package into the building rootfs, we automatically get an initramfs-tools hook for it automatically. What if we simply rely on that and specify on kernel cmdline systempart=/dev/mapper/${lv}-rootfs datapart=/dev/mapper/${lv}-userdata?

We do call udevadm settle before looking for systempart and datapart; my understanding is that LVM PV scan should be triggered by that; if we're unsure I guess we can try triggering it manually if specified paths doesn't exists as well.

It could be a good idea if we could rely on existing lvm2 hook. However, we need to be to boot both old and new setups with a single build, so then there should be multiple systempart specified somehow? That could be handled gracefully by script, but I'm afraid we might run out of kernel cmdline length on some devices. The reason is, first we introduce LVM boot support and update the recovery through OTA, then on next update, it actually does the conversion.

@fredldotme

Copy link
Copy Markdown

I would recommend Ratchanan's approach, I've been using it in a custom fork of initramfs-tools-halium in $PREVIOUS_DAYJOB as well, but note that there are two changes required to make it work properly:

@NotKit

NotKit commented Jan 24, 2026

Copy link
Copy Markdown
Author

@peat-psuwit thinking of it, what if we don't rely on fixed LVM volume group name and prefix the partitions instead? E. g. ubports-rootfs and ubports-userdata. The intention is to make it possible to co-exist with Droidian/SailfishOS setups, even if it would require manual setup otherwise.

@fredldotme

Copy link
Copy Markdown

How ready is this, now that the recovery portion has been merged?

@JamiKettunen

Copy link
Copy Markdown

I can say that the current state of this would break non-LVM A/B devices using systempart=/dev/disk/by-partlabel/system at least, testing this along with the recovery stuff on OnePlus 6 (enchilada) and just tried booting with usual ext4 userdata since the lvm tooling themselves still need additional fixes

@NotKit
NotKit force-pushed the dynparts-lvm branch 2 times, most recently from ea41d25 to 743bd96 Compare June 25, 2026 09:58
NotKit added 3 commits July 13, 2026 14:46
Activate LVM early in boot and look for volumes in the groups
named by halium_lvm_vg=, comma separated. If a group is found,
/dev/$vg/userdata is used for userdata and /dev/$vg/rootfs
overrides systempart=.
If the ramdisk lacks LVM support or has an incorrect
halium_lvm_vg=, the userdata search falls back to the
raw partition. Because pvcreate only wipes the start of the
partition, old ext4 backup superblocks survive. If e2fsck
runs on the raw partition, it mistakes it for a broken
ext4 filesystem and restores it, overwriting LVM metadata
at offset 4096 and destroying the VG.

To fix this, check for the surviving LVM label at offset
512 via blkid and panic before any write operations occur.

In resize_userdata_if_needed(), resolve $path to its kernel
name before looking it up in /proc/partitions so LVM volumes
report a size.
LVM adds about 900K to the initrd, which devices with a small ramdisk
may not be able to spare. Build both variants from the same branch
so it can be picked by the device adaptation.

lvm2 is only pulled into the chroot when LVM=1, and hooks/halium
includes it only when present. Without it, scripts/halium finds
no volume group and uses the partitions directly.
Some bootloaders fail to boot images with a large ramdisk, so the
recovery ramdisk may be compressed with xz instead of gzip. It is
then named ramdisk-recovery.cpio.xz.

Also link /sbin/init, which run-init expects, to the recovery /init.
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.

4 participants