Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

install: Relax restriction on separate /boot #144

Merged
merged 1 commit into from
Oct 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 38 additions & 25 deletions lib/src/install.rs
Original file line number Diff line number Diff line change
Expand Up @@ -561,7 +561,9 @@ async fn initialize_ostree_root_from_self(
.context("Opening etc/fstab")
.map(BufWriter::new)?
};
writeln!(f, "{}", root_setup.boot.to_fstab())?;
if let Some(boot) = root_setup.boot.as_ref() {
writeln!(f, "{}", boot.to_fstab())?;
}
f.flush()?;

let uname = rustix::system::uname();
Expand Down Expand Up @@ -627,9 +629,10 @@ pub(crate) struct RootSetup {
device: Utf8PathBuf,
rootfs: Utf8PathBuf,
rootfs_fd: Dir,
rootfs_uuid: Option<String>,
/// If true, do not try to remount the root read-only and flush the journal, etc.
skip_finalize: bool,
boot: MountSpec,
boot: Option<MountSpec>,
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Tangentially related...it's in precisely this kind of code refactoring that Rust is great. The compiler found all the places I needed to change.

Copy link
Member

Choose a reason for hiding this comment

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

That is awesome indeed!

kargs: Vec<String>,
}

Expand All @@ -639,10 +642,10 @@ fn require_boot_uuid(spec: &MountSpec) -> Result<&str> {
}

impl RootSetup {
/// Get the UUID= mount specifier for the /boot filesystem. At the current time this is
/// required.
fn get_boot_uuid(&self) -> Result<&str> {
require_boot_uuid(&self.boot)
/// Get the UUID= mount specifier for the /boot filesystem; if there isn't one, the root UUID will
/// be returned.
fn get_boot_uuid(&self) -> Result<Option<&str>> {
self.boot.as_ref().map(require_boot_uuid).transpose()
}

// Drop any open file descriptors and return just the mount path and backing luks device, if any
Expand Down Expand Up @@ -848,7 +851,10 @@ async fn install_to_filesystem_impl(state: &State, rootfs: &mut RootSetup) -> Re
.context("Writing aleph version")?;
}

let boot_uuid = rootfs.get_boot_uuid()?;
let boot_uuid = rootfs
.get_boot_uuid()?
.or(rootfs.rootfs_uuid.as_deref())
.ok_or_else(|| anyhow!("No uuid for boot/root"))?;
crate::bootloader::install_via_bootupd(&rootfs.device, &rootfs.rootfs, boot_uuid)?;
tracing::debug!("Installed bootloader");

Expand Down Expand Up @@ -1010,10 +1016,11 @@ pub(crate) async fn install_to_filesystem(opts: InstallToFilesystemOpts) -> Resu
let (root_mount_spec, root_extra) = if let Some(s) = fsopts.root_mount_spec {
(s, None)
} else {
let mut uuid = inspect
let uuid = inspect
.uuid
.as_deref()
.ok_or_else(|| anyhow!("No filesystem uuid found in target root"))?;
uuid.insert_str(0, "UUID=");
let uuid = format!("UUID={uuid}");
tracing::debug!("root {uuid}");
let opts = match inspect.fstype.as_str() {
"btrfs" => {
Expand All @@ -1026,8 +1033,7 @@ pub(crate) async fn install_to_filesystem(opts: InstallToFilesystemOpts) -> Resu
};
tracing::debug!("Root mount spec: {root_mount_spec}");

// Verify /boot is a separate mount
{
let boot_is_mount = {
let root_dev = rootfs_fd.dir_metadata()?.dev();
let boot_dev = rootfs_fd
.symlink_metadata_optional(BOOT)?
Expand All @@ -1036,17 +1042,20 @@ pub(crate) async fn install_to_filesystem(opts: InstallToFilesystemOpts) -> Resu
})?
.dev();
tracing::debug!("root_dev={root_dev} boot_dev={boot_dev}");
if root_dev == boot_dev {
anyhow::bail!("/{BOOT} must currently be a separate mounted filesystem");
}
}
root_dev != boot_dev
};
// Find the UUID of /boot because we need it for GRUB.
let boot_path = fsopts.root_path.join(BOOT);
let boot_uuid = crate::mount::inspect_filesystem(&boot_path)
.context("Inspecting /{BOOT}")?
.uuid
.ok_or_else(|| anyhow!("No UUID found for /{BOOT}"))?;
tracing::debug!("boot UUID: {boot_uuid}");
let boot_uuid = if boot_is_mount {
let boot_path = fsopts.root_path.join(BOOT);
let u = crate::mount::inspect_filesystem(&boot_path)
.context("Inspecting /{BOOT}")?
.uuid
.ok_or_else(|| anyhow!("No UUID found for /{BOOT}"))?;
Some(u)
} else {
None
};
tracing::debug!("boot UUID: {boot_uuid:?}");

// Find the real underlying backing device for the root. This is currently just required
// for GRUB (BIOS) and in the future zipl (I think).
Expand All @@ -1073,24 +1082,28 @@ pub(crate) async fn install_to_filesystem(opts: InstallToFilesystemOpts) -> Resu

let rootarg = format!("root={root_mount_spec}");
let boot = if let Some(spec) = fsopts.boot_mount_spec {
MountSpec::new(&spec, "/boot")
Some(MountSpec::new(&spec, "/boot"))
} else if let Some(boot_uuid) = boot_uuid.as_deref() {
Some(MountSpec::new_uuid_src(&boot_uuid, "/boot"))
} else {
MountSpec::new_uuid_src(&boot_uuid, "/boot")
None
};
// By default, we inject a boot= karg because things like FIPS compliance currently
// require checking in the initramfs.
let bootarg = format!("boot={}", &boot.source);
let bootarg = boot.as_ref().map(|boot| format!("boot={}", &boot.source));
let kargs = [rootarg]
.into_iter()
.chain(root_extra)
.chain([RW_KARG.to_string(), bootarg])
.chain([RW_KARG.to_string()])
.chain(bootarg)
.collect::<Vec<_>>();

let mut rootfs = RootSetup {
luks_device: None,
device: backing_device.into(),
rootfs: fsopts.root_path,
rootfs_fd,
rootfs_uuid: inspect.uuid.clone(),
boot,
kargs,
skip_finalize: matches!(fsopts.replace, Some(ReplaceMode::Alongside)),
Expand Down
3 changes: 2 additions & 1 deletion lib/src/install/baseline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -368,7 +368,8 @@ pub(crate) fn install_create_rootfs(
device,
rootfs,
rootfs_fd,
boot,
rootfs_uuid: Some(root_uuid.to_string()),
boot: Some(boot),
kargs,
skip_finalize: false,
})
Expand Down
Loading