Skip to content

Commit 0f6496c

Browse files
authored
Merge pull request #909 from cgwalters/clarify-roots
install: Two rootfs cleanups
2 parents 139db98 + 31608bf commit 0f6496c

File tree

2 files changed

+48
-42
lines changed

2 files changed

+48
-42
lines changed

lib/src/install.rs

Lines changed: 40 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ mod osbuild;
1212
pub(crate) mod osconfig;
1313

1414
use std::io::Write;
15-
use std::os::fd::AsFd;
15+
use std::os::fd::{AsFd, AsRawFd};
1616
use std::os::unix::process::CommandExt;
1717
use std::path::Path;
1818
use std::process::Command;
@@ -580,19 +580,17 @@ async fn initialize_ostree_root(state: &State, root_setup: &RootSetup) -> Result
580580
let sepolicy = state.load_policy()?;
581581
let sepolicy = sepolicy.as_ref();
582582
// Load a fd for the mounted target physical root
583-
let rootfs_dir = &root_setup.rootfs_fd;
584-
let rootfs = root_setup.rootfs.as_path();
583+
let rootfs_dir = &root_setup.physical_root;
585584
let cancellable = gio::Cancellable::NONE;
586585

587586
let stateroot = state.stateroot();
588587

589588
let has_ostree = rootfs_dir.try_exists("ostree/repo")?;
590589
if !has_ostree {
591-
Task::new_and_run(
592-
"Initializing ostree layout",
593-
"ostree",
594-
["admin", "init-fs", "--modern", rootfs.as_str()],
595-
)?;
590+
Task::new("Initializing ostree layout", "ostree")
591+
.args(["admin", "init-fs", "--modern", "."])
592+
.cwd(rootfs_dir)?
593+
.run()?;
596594
} else {
597595
println!("Reusing extant ostree layout");
598596

@@ -607,8 +605,7 @@ async fn initialize_ostree_root(state: &State, root_setup: &RootSetup) -> Result
607605
crate::lsm::ensure_dir_labeled(rootfs_dir, "", Some("/".into()), 0o755.into(), sepolicy)?;
608606

609607
// And also label /boot AKA xbootldr, if it exists
610-
let bootdir = rootfs.join("boot");
611-
if bootdir.try_exists()? {
608+
if rootfs_dir.try_exists("boot")? {
612609
crate::lsm::ensure_dir_labeled(rootfs_dir, "boot", None, 0o755.into(), sepolicy)?;
613610
}
614611

@@ -626,7 +623,10 @@ async fn initialize_ostree_root(state: &State, root_setup: &RootSetup) -> Result
626623
.run()?;
627624
}
628625

629-
let sysroot = ostree::Sysroot::new(Some(&gio::File::for_path(rootfs)));
626+
let sysroot = {
627+
let path = format!("/proc/self/fd/{}", rootfs_dir.as_fd().as_raw_fd());
628+
ostree::Sysroot::new(Some(&gio::File::for_path(path)))
629+
};
630630
sysroot.load(cancellable)?;
631631

632632
let stateroot_exists = rootfs_dir.try_exists(format!("ostree/deploy/{stateroot}"))?;
@@ -661,7 +661,6 @@ async fn initialize_ostree_root(state: &State, root_setup: &RootSetup) -> Result
661661
)?;
662662
}
663663

664-
let sysroot = ostree::Sysroot::new(Some(&gio::File::for_path(rootfs)));
665664
sysroot.load(cancellable)?;
666665
let sysroot = SysrootLock::new_from_sysroot(&sysroot).await?;
667666
Ok((Storage::new(sysroot, &temp_run)?, has_ostree))
@@ -780,7 +779,7 @@ async fn install_container(
780779
// SAFETY: There must be a path
781780
let path = sysroot.deployment_dirpath(&deployment);
782781
let root = root_setup
783-
.rootfs_fd
782+
.physical_root
784783
.open_dir(path.as_str())
785784
.context("Opening deployment dir")?;
786785

@@ -793,7 +792,7 @@ async fn install_container(
793792
for d in ["ostree", "boot"] {
794793
let mut pathbuf = Utf8PathBuf::from(d);
795794
crate::lsm::ensure_dir_labeled_recurse(
796-
&root_setup.rootfs_fd,
795+
&root_setup.physical_root,
797796
&mut pathbuf,
798797
policy,
799798
Some(deployment_root_devino),
@@ -903,8 +902,11 @@ fn require_skopeo_with_containers_storage() -> Result<()> {
903902
pub(crate) struct RootSetup {
904903
luks_device: Option<String>,
905904
device_info: crate::blockdev::PartitionTable,
906-
rootfs: Utf8PathBuf,
907-
rootfs_fd: Dir,
905+
/// Absolute path to the location where we've mounted the physical
906+
/// root filesystem for the system we're installing.
907+
physical_root_path: Utf8PathBuf,
908+
/// Directory file descriptor for the above physical root.
909+
physical_root: Dir,
908910
rootfs_uuid: Option<String>,
909911
/// True if we should skip finalizing
910912
skip_finalize: bool,
@@ -926,7 +928,7 @@ impl RootSetup {
926928

927929
// Drop any open file descriptors and return just the mount path and backing luks device, if any
928930
fn into_storage(self) -> (Utf8PathBuf, Option<String>) {
929-
(self.rootfs, self.luks_device)
931+
(self.physical_root_path, self.luks_device)
930932
}
931933
}
932934

@@ -999,24 +1001,29 @@ pub(crate) fn reexecute_self_for_selinux_if_needed(
9991001

10001002
/// Trim, flush outstanding writes, and freeze/thaw the target mounted filesystem;
10011003
/// these steps prepare the filesystem for its first booted use.
1002-
pub(crate) fn finalize_filesystem(fs: &Utf8Path) -> Result<()> {
1003-
let fsname = fs.file_name().unwrap();
1004+
pub(crate) fn finalize_filesystem(
1005+
fsname: &str,
1006+
root: &Dir,
1007+
path: impl AsRef<Utf8Path>,
1008+
) -> Result<()> {
1009+
let path = path.as_ref();
10041010
// fstrim ensures the underlying block device knows about unused space
1005-
Task::new_and_run(
1006-
format!("Trimming {fsname}"),
1007-
"fstrim",
1008-
["--quiet-unsupported", "-v", fs.as_str()],
1009-
)?;
1011+
Task::new(format!("Trimming {fsname}"), "fstrim")
1012+
.args(["--quiet-unsupported", "-v", path.as_str()])
1013+
.cwd(root)?
1014+
.run()?;
10101015
// Remounting readonly will flush outstanding writes and ensure we error out if there were background
10111016
// writeback problems.
10121017
Task::new(format!("Finalizing filesystem {fsname}"), "mount")
1013-
.args(["-o", "remount,ro", fs.as_str()])
1018+
.cwd(root)?
1019+
.args(["-o", "remount,ro", path.as_str()])
10141020
.run()?;
10151021
// Finally, freezing (and thawing) the filesystem will flush the journal, which means the next boot is clean.
10161022
for a in ["-f", "-u"] {
10171023
Task::new("Flushing filesystem journal", "fsfreeze")
10181024
.quiet()
1019-
.args([a, fs.as_str()])
1025+
.cwd(root)?
1026+
.args([a, path.as_str()])
10201027
.run()?;
10211028
}
10221029
Ok(())
@@ -1319,7 +1326,7 @@ async fn install_with_sysroot(
13191326
let (_deployment, aleph) = install_container(state, rootfs, &sysroot, has_ostree).await?;
13201327
// Write the aleph data that captures the system state at the time of provisioning for aid in future debugging.
13211328
rootfs
1322-
.rootfs_fd
1329+
.physical_root
13231330
.atomic_replace_with(BOOTC_ALEPH_PATH, |f| {
13241331
serde_json::to_writer(f, &aleph)?;
13251332
anyhow::Ok(())
@@ -1332,7 +1339,7 @@ async fn install_with_sysroot(
13321339
} else {
13331340
crate::bootloader::install_via_bootupd(
13341341
&rootfs.device_info,
1335-
&rootfs.rootfs,
1342+
&rootfs.physical_root_path,
13361343
&state.config_opts,
13371344
)?;
13381345
}
@@ -1419,10 +1426,9 @@ async fn install_to_filesystem_impl(state: &State, rootfs: &mut RootSetup) -> Re
14191426

14201427
// Finalize mounted filesystems
14211428
if !rootfs.skip_finalize {
1422-
let bootfs = rootfs.boot.as_ref().map(|_| rootfs.rootfs.join("boot"));
1423-
let bootfs = bootfs.as_ref().map(|p| p.as_path());
1424-
for fs in std::iter::once(rootfs.rootfs.as_path()).chain(bootfs) {
1425-
finalize_filesystem(fs)?;
1429+
let bootfs = rootfs.boot.as_ref().map(|_| ("boot", "boot"));
1430+
for (fsname, fs) in std::iter::once(("root", ".")).chain(bootfs) {
1431+
finalize_filesystem(fsname, &rootfs.physical_root, fs)?;
14261432
}
14271433
}
14281434

@@ -1816,8 +1822,8 @@ pub(crate) async fn install_to_filesystem(
18161822
let mut rootfs = RootSetup {
18171823
luks_device: None,
18181824
device_info,
1819-
rootfs: fsopts.root_path,
1820-
rootfs_fd,
1825+
physical_root_path: fsopts.root_path,
1826+
physical_root: rootfs_fd,
18211827
rootfs_uuid: inspect.uuid.clone(),
18221828
boot,
18231829
kargs,

lib/src/install/baseline.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -223,8 +223,8 @@ pub(crate) fn install_create_rootfs(
223223

224224
// Create a temporary directory to use for mount points. Note that we're
225225
// in a mount namespace, so these should not be visible on the host.
226-
let rootfs = mntdir.join("rootfs");
227-
std::fs::create_dir_all(&rootfs)?;
226+
let physical_root_path = mntdir.join("rootfs");
227+
std::fs::create_dir_all(&physical_root_path)?;
228228
let bootfs = mntdir.join("boot");
229229
std::fs::create_dir_all(bootfs)?;
230230

@@ -389,11 +389,11 @@ pub(crate) fn install_create_rootfs(
389389
.chain(bootarg)
390390
.collect::<Vec<_>>();
391391

392-
mount::mount(&rootdev, &rootfs)?;
393-
let target_rootfs = Dir::open_ambient_dir(&rootfs, cap_std::ambient_authority())?;
392+
mount::mount(&rootdev, &physical_root_path)?;
393+
let target_rootfs = Dir::open_ambient_dir(&physical_root_path, cap_std::ambient_authority())?;
394394
crate::lsm::ensure_dir_labeled(&target_rootfs, "", Some("/".into()), 0o755.into(), sepolicy)?;
395-
let rootfs_fd = Dir::open_ambient_dir(&rootfs, cap_std::ambient_authority())?;
396-
let bootfs = rootfs.join("boot");
395+
let physical_root = Dir::open_ambient_dir(&physical_root_path, cap_std::ambient_authority())?;
396+
let bootfs = physical_root_path.join("boot");
397397
// Create the underlying mount point directory, which should be labeled
398398
crate::lsm::ensure_dir_labeled(&target_rootfs, "boot", None, 0o755.into(), sepolicy)?;
399399
if let Some(bootdev) = bootdev {
@@ -422,8 +422,8 @@ pub(crate) fn install_create_rootfs(
422422
Ok(RootSetup {
423423
luks_device,
424424
device_info,
425-
rootfs,
426-
rootfs_fd,
425+
physical_root_path,
426+
physical_root,
427427
rootfs_uuid: Some(root_uuid.to_string()),
428428
boot,
429429
kargs,

0 commit comments

Comments
 (0)