Package: partman-base
Version: 226
Affects: partman-cros partman-efi partman-lvm partman-md
partman-partitioning partman-prep
Background:
Partman is based on libparted which uses "flags" as an abstraction for
different kinds of partition properties:
- attribute (boot on msdos, legacy_boot and hidden on gpt...)
- type identifier (esp, lvm, raid...)
- type modifier (hidden and lba on msdos)
- name (root and swap on mac)
Attribute flags can be combined but type flags are exclusive. When
sending a SET_FLAGS command with multiple type flags to parted_server,
only the one with the highest priority will be set. Type flag priorities
are as follows:
linux-home > bls_boot > chromeos_kernel > esp > irst > msftdata > diag >
atvrecv > bios_grub > msftres > prep > palo, hp-service > lvm > raid >
swap > boot
When a partition usage ("method") is changed, synchronization scripts
for each supported method/flag are executed in a fixed order and set or
remove a type flag on the partition by performing the following actions:
- send GET_FLAGS and read the current flags
- if the script manages the new method, send SET_FLAGS with current
flags and the managed type flag
- if the script does not manage the new method, send SET_FLAGS with
current flags except the managed type flag
Current synchronization scripts order (may not exist in all
architectures): biosgrub_sync_flag cros_sync_flag efi_sync_flag
lvm_sync_flag prep_sync_flag md_sync_flag
This can lead to unexpected results when changing partition usage.
Problem description:
If the new type flag has a lower priority than the current type flag,
then it is ignored.
When the script which sets a lower priority type flag is executed before
the script which removes a higher priority type flag (or no script
manages it), then the lower priority type flag is not set and the
resulting partition type does not match the new usage.
It is not only confusing when the partition type is informative only
(LVM, RAID...) but it can also be troublesome when the partition type
has a special meaning for platform firmware, boot loaders or operating
systems (ChromeOS kernel, EFI, BIOS boot, PReP).
Some scripts needlessly remove some low priority flags (lvm, raid, swap)
when setting another flag but do not remove higher priority flags which
may still be set (chromeos_kernel, esp, msftdata, bios_grub, msftres...).
Examples:
- gpt: Change a partition usage from "ChromeOS" or "EFI" to "BIOS boot"
-> bios_grub not set.
- gpt, msdos on powerpc, ppc64, ppc64el: Change a partition usage from
"PReP" to "RAID" -> raid not set.
- gpt: Change a partition usage from "FAT16", "FAT32" or "NTFS" to "BIOS
boot", "PReP", "LVM" "RAID" -> msftdata set, new flag not set.
- gpt: Use an existing partition of type "Linux home" or "BLS extended
boot" as "ChromeOS", "EFI" or "BIOS boot" -> old flag set, new flag not set.
- gpt, msdos: Use an existing partition of type "Linux home", "BLS
extended boot" or "Microsoft Reserved" as "PReP", "LVM" or "RAID" -> old
flag set, new flag not set.
Possible mitigations/solutions:
1) Change the execution order of synchronization scripts to match type
flag priorities so that higher priority flags are removed before low
priority flags are set: cros_sync_flag efi_sync_flag biosgrub_sync_flag
prep_sync_flag lvm_sync_flag md_sync_flag.
Downsides: high priority type flags which are not managed by partman
scripts (linux-home, bls_boot, msftdata, msftres...) still cannot be
removed; requires a change in some affected packages.
2) Remove type flags (and keep only attribute and modifier flags) before
setting a type flag in synchronization scripts; the scripts could call a
new function defined in a common library.
Downsides: requires a change in all affected packages; needs to be
updated whenever libparted supports a new flag.
3) Modify parted_server to set only the last type flag when processing a
SET_FLAGS command (all scripts send the new flag last).
Advantage: no need to change affected packages.
Downsides: changes SET_FLAGS behaviour; needs to be updated whenever
libparted supports a new flag.
4) Modify parted_server to add a new SET_FLAG command which sets a
single flag and use it in synchronization scripts.
Downside: requires a change in all affected packages.
I think solution #3 is the best because it requires changes only in
partman-base to fully fix the issue. However modifying parted_server
does not seem easy and my C is rusty, so I began to work on solution #2.
Meanwhile, maybe solution #1 could be implemented quickly even if it
does not fix the issue on existing partitions, at least it fixes the
issue on partitions created by partman.