From 1d5ecc9c98f73eb99dca05d5957d19ca2c0f9167 Mon Sep 17 00:00:00 2001 From: Harnoor Lal Date: Tue, 7 Apr 2026 07:48:08 -0700 Subject: [PATCH] fix(check): read root subvol name from fstab instead of hardcoding "root" check_root_mountable hardcoded "root" as the btrfs subvol name the kernel mounts as /. On systems with a non-Fedora layout (openSUSE Timeshift uses @, @home, @var, ...), the gate failed with "Btrfs subvolume 'root' not found" before setup could run, even though the layout was otherwise valid. Replace the hardcoded literal with tools::root_subvol_name, which reads the subvol= mount option from the fstab entry for /. Error messages report the actual name rather than always saying 'root'. Add three regression tests exercising the openSUSE @ layout, the Fedora default, and a missing subvol= option. --- src/check.rs | 49 ++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 46 insertions(+), 3 deletions(-) diff --git a/src/check.rs b/src/check.rs index f85ec96..8b45db8 100644 --- a/src/check.rs +++ b/src/check.rs @@ -347,10 +347,29 @@ fn check_root_mountable(root: &Path) -> Vec { "Root filesystem UUID {} is not a Btrfs partition: {e}. \ This tool requires Btrfs as the root filesystem.", root_uuid.as_str()))); + let fstab_content = match fs::read_to_string(root.join("etc/fstab")) { + Ok(c) => c, + Err(e) => { + results.push(Err(format!( + "Cannot read /etc/fstab to determine root subvolume: {e}. \ + The system may not boot."))); + return results; + } + }; + + let root_subvol_name = match tools::root_subvol_name(&fstab_content) { + Ok(name) => name, + Err(e) => { + results.push(Err(format!( + "{e}. The fstab entry for / must include subvol=."))); + return results; + } + }; + let root_device = root_uuid.clone().into_device_spec(); - results.push(check_btrfs_subvol_exists(&root_device, &tools::SubvolName::new("root".into())).map_err(|e| format!( - "Btrfs subvolume 'root' not found: {e}. \ - The kernel expects to mount subvol=root as /. \ + results.push(check_btrfs_subvol_exists(&root_device, &root_subvol_name).map_err(|e| format!( + "Btrfs subvolume '{root_subvol_name}' not found: {e}. \ + The kernel expects to mount subvol={root_subvol_name} as /. \ Without it, the system drops to an emergency shell."))); results.push(check_file_exists_nonempty(&root.join(&P.systemd_path[1..])).map_err(|_| @@ -478,4 +497,28 @@ mod tests { fs::remove_dir_all(&dir).unwrap(); } + + #[test] + fn root_subvol_name_reads_at_sign_layout() { + let fstab = "\ +UUID=abc / btrfs subvol=@,compress=zstd:1 0 0 +UUID=abc /home btrfs subvol=@home,compress=zstd:1 0 0 +UUID=abc /var btrfs subvol=@var 0 0 +UUID=abc /opt btrfs subvol=@opt 0 0"; + let name = tools::root_subvol_name(fstab).unwrap(); + assert_eq!(name.as_str(), "@"); + } + + #[test] + fn root_subvol_name_reads_fedora_default() { + let fstab = "UUID=abc / btrfs subvol=root,compress=zstd:1 0 0"; + let name = tools::root_subvol_name(fstab).unwrap(); + assert_eq!(name.as_str(), "root"); + } + + #[test] + fn root_subvol_name_errors_without_subvol_option() { + let fstab = "UUID=abc / btrfs defaults 0 0"; + assert!(tools::root_subvol_name(fstab).is_err()); + } }