Skip to content

Commit 0b8fad6

Browse files
committed
Split mount code into separate helper crate
Prep for using this elsewhere via git dependency, like we're doing now with bootupd for example. Signed-off-by: Colin Walters <[email protected]>
1 parent df879ed commit 0b8fad6

File tree

9 files changed

+79
-45
lines changed

9 files changed

+79
-45
lines changed

Cargo.lock

+16
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ members = [
33
"cli",
44
"system-reinstall-bootc",
55
"lib",
6+
"mount",
67
"ostree-ext",
78
"utils",
89
"blockdev",

lib/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ anstyle = "1.0.6"
1818
anyhow = { workspace = true }
1919
bootc-utils = { path = "../utils" }
2020
bootc-blockdev = { path = "../blockdev" }
21+
bootc-mount = { path = "../mount" }
2122
bootc-tmpfiles = { path = "../tmpfiles" }
2223
bootc-sysusers = { path = "../sysusers" }
2324
camino = { workspace = true, features = ["serde1"] }

lib/src/bootloader.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use fn_error_context::context;
44

55
use crate::task::Task;
66
use bootc_blockdev::PartitionTable;
7+
use bootc_mount as mount;
78

89
/// The name of the mountpoint for efi (as a subdirectory of /boot, or at the toplevel)
910
pub(crate) const EFI_DIR: &str = "efi";
@@ -33,7 +34,7 @@ pub(crate) fn install_via_bootupd(
3334
#[context("Installing bootloader using zipl")]
3435
pub(crate) fn install_via_zipl(device: &PartitionTable, boot_uuid: &str) -> Result<()> {
3536
// Identify the target boot partition from UUID
36-
let fs = crate::mount::inspect_filesystem_by_uuid(boot_uuid)?;
37+
let fs = mount::inspect_filesystem_by_uuid(boot_uuid)?;
3738
let boot_dir = Utf8Path::new(&fs.target);
3839
let maj_min = fs.maj_min;
3940

lib/src/install.rs

+7-7
Original file line numberDiff line numberDiff line change
@@ -55,12 +55,12 @@ use crate::boundimage::{BoundImage, ResolvedBoundImage};
5555
use crate::containerenv::ContainerExecutionInfo;
5656
use crate::deploy::{prepare_for_pull, pull_from_prepared, PreparedImportMeta, PreparedPullResult};
5757
use crate::lsm;
58-
use crate::mount::Filesystem;
5958
use crate::progress_jsonl::ProgressWriter;
6059
use crate::spec::ImageReference;
6160
use crate::store::Storage;
6261
use crate::task::Task;
6362
use crate::utils::sigpolicy_from_opt;
63+
use bootc_mount::Filesystem;
6464

6565
/// The toplevel boot directory
6666
const BOOT: &str = "boot";
@@ -1287,8 +1287,8 @@ async fn prepare_install(
12871287
tracing::debug!("Target image reference: {target_imgref}");
12881288

12891289
// A bit of basic global state setup
1290-
crate::mount::ensure_mirrored_host_mount("/dev")?;
1291-
crate::mount::ensure_mirrored_host_mount("/var/lib/containers")?;
1290+
bootc_mount::ensure_mirrored_host_mount("/dev")?;
1291+
bootc_mount::ensure_mirrored_host_mount("/var/lib/containers")?;
12921292
ensure_var()?;
12931293
setup_tmp_mounts()?;
12941294
// Allocate a temporary directory we can use in various places to avoid
@@ -1763,8 +1763,8 @@ pub(crate) async fn install_to_filesystem(
17631763
{
17641764
tracing::debug!("Mounting host / to {ALONGSIDE_ROOT_MOUNT}");
17651765
std::fs::create_dir(ALONGSIDE_ROOT_MOUNT)?;
1766-
crate::mount::bind_mount_from_pidns(
1767-
crate::mount::PID1,
1766+
bootc_mount::bind_mount_from_pidns(
1767+
bootc_mount::PID1,
17681768
"/".into(),
17691769
ALONGSIDE_ROOT_MOUNT.into(),
17701770
true,
@@ -1829,7 +1829,7 @@ pub(crate) async fn install_to_filesystem(
18291829
}
18301830

18311831
// Gather data about the root filesystem
1832-
let inspect = crate::mount::inspect_filesystem(&fsopts.root_path)?;
1832+
let inspect = bootc_mount::inspect_filesystem(&fsopts.root_path)?;
18331833

18341834
// We support overriding the mount specification for root (i.e. LABEL vs UUID versus
18351835
// raw paths).
@@ -1881,7 +1881,7 @@ pub(crate) async fn install_to_filesystem(
18811881
// Find the UUID of /boot because we need it for GRUB.
18821882
let boot_uuid = if boot_is_mount {
18831883
let boot_path = fsopts.root_path.join(BOOT);
1884-
let u = crate::mount::inspect_filesystem(&boot_path)
1884+
let u = bootc_mount::inspect_filesystem(&boot_path)
18851885
.context("Inspecting /{BOOT}")?
18861886
.uuid
18871887
.ok_or_else(|| anyhow!("No UUID found for /{BOOT}"))?;

lib/src/install/baseline.rs

+4-5
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,9 @@ use super::RootSetup;
2727
use super::State;
2828
use super::RUN_BOOTC;
2929
use super::RW_KARG;
30-
use crate::mount;
31-
#[cfg(feature = "install-to-disk")]
32-
use crate::mount::is_mounted_in_pid1_mountns;
3330
use crate::task::Task;
31+
#[cfg(feature = "install-to-disk")]
32+
use bootc_mount::is_mounted_in_pid1_mountns;
3433

3534
// This ensures we end up under 512 to be small-sized.
3635
pub(crate) const BOOTPN_SIZE_MB: u32 = 510;
@@ -421,15 +420,15 @@ pub(crate) fn install_create_rootfs(
421420
.chain(bootarg)
422421
.collect::<Vec<_>>();
423422

424-
mount::mount(&rootdev, &physical_root_path)?;
423+
bootc_mount::mount(&rootdev, &physical_root_path)?;
425424
let target_rootfs = Dir::open_ambient_dir(&physical_root_path, cap_std::ambient_authority())?;
426425
crate::lsm::ensure_dir_labeled(&target_rootfs, "", Some("/".into()), 0o755.into(), sepolicy)?;
427426
let physical_root = Dir::open_ambient_dir(&physical_root_path, cap_std::ambient_authority())?;
428427
let bootfs = physical_root_path.join("boot");
429428
// Create the underlying mount point directory, which should be labeled
430429
crate::lsm::ensure_dir_labeled(&target_rootfs, "boot", None, 0o755.into(), sepolicy)?;
431430
if let Some(bootdev) = bootdev {
432-
mount::mount(bootdev.node.as_str(), &bootfs)?;
431+
bootc_mount::mount(bootdev.node.as_str(), &bootfs)?;
433432
}
434433
// And we want to label the root mount of /boot
435434
crate::lsm::ensure_dir_labeled(&target_rootfs, "boot", None, 0o755.into(), sepolicy)?;

lib/src/lib.rs

-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@ mod bootloader;
3535
mod containerenv;
3636
mod install;
3737
mod kernel;
38-
pub(crate) mod mount;
3938

4039
#[cfg(feature = "rhsm")]
4140
mod rhsm;

mount/Cargo.toml

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
[package]
2+
description = "Internal mount code"
3+
# Should never be published to crates.io
4+
publish = false
5+
edition = "2021"
6+
license = "MIT OR Apache-2.0"
7+
name = "bootc-mount"
8+
repository = "https://github.com/containers/bootc"
9+
version = "0.0.0"
10+
11+
[dependencies]
12+
anyhow = { workspace = true }
13+
bootc-utils = { path = "../utils" }
14+
camino = { workspace = true, features = ["serde1"] }
15+
fn-error-context = { workspace = true }
16+
rustix = { workspace = true }
17+
libc = {workspace = true}
18+
serde = { workspace = true, features = ["derive"] }
19+
tracing = { workspace = true }
20+
21+
[dev-dependencies]
22+
indoc = "2.0.5"
23+
24+
[lib]
25+
path = "src/mount.rs"

lib/src/mount.rs renamed to mount/src/mount.rs

+23-31
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,8 @@ use rustix::{
2222
};
2323
use serde::Deserialize;
2424

25-
#[cfg(feature = "install-to-disk")]
26-
use crate::task::Task;
27-
2825
/// Well known identifier for pid 1
29-
pub(crate) const PID1: Pid = const {
26+
pub const PID1: Pid = const {
3027
match Pid::from_raw(1) {
3128
Some(v) => v,
3229
None => panic!("Expected to parse pid1"),
@@ -36,21 +33,21 @@ pub(crate) const PID1: Pid = const {
3633
#[derive(Deserialize, Debug)]
3734
#[serde(rename_all = "kebab-case")]
3835
#[allow(dead_code)]
39-
pub(crate) struct Filesystem {
36+
pub struct Filesystem {
4037
// Note if you add an entry to this list, you need to change the --output invocation below too
41-
pub(crate) source: String,
42-
pub(crate) target: String,
38+
pub source: String,
39+
pub target: String,
4340
#[serde(rename = "maj:min")]
44-
pub(crate) maj_min: String,
45-
pub(crate) fstype: String,
46-
pub(crate) options: String,
47-
pub(crate) uuid: Option<String>,
48-
pub(crate) children: Option<Vec<Filesystem>>,
41+
pub maj_min: String,
42+
pub fstype: String,
43+
pub options: String,
44+
pub uuid: Option<String>,
45+
pub children: Option<Vec<Filesystem>>,
4946
}
5047

5148
#[derive(Deserialize, Debug)]
52-
pub(crate) struct Findmnt {
53-
pub(crate) filesystems: Vec<Filesystem>,
49+
pub struct Findmnt {
50+
pub filesystems: Vec<Filesystem>,
5451
}
5552

5653
fn run_findmnt(args: &[&str], path: &str) -> Result<Findmnt> {
@@ -80,20 +77,19 @@ fn findmnt_filesystem(args: &[&str], path: &str) -> Result<Filesystem> {
8077
#[context("Inspecting filesystem {path}")]
8178
/// Inspect a target which must be a mountpoint root - it is an error
8279
/// if the target is not the mount root.
83-
pub(crate) fn inspect_filesystem(path: &Utf8Path) -> Result<Filesystem> {
80+
pub fn inspect_filesystem(path: &Utf8Path) -> Result<Filesystem> {
8481
findmnt_filesystem(&["--mountpoint"], path.as_str())
8582
}
8683

8784
#[context("Inspecting filesystem by UUID {uuid}")]
8885
/// Inspect a filesystem by partition UUID
89-
pub(crate) fn inspect_filesystem_by_uuid(uuid: &str) -> Result<Filesystem> {
86+
pub fn inspect_filesystem_by_uuid(uuid: &str) -> Result<Filesystem> {
9087
findmnt_filesystem(&["--source"], &(format!("UUID={uuid}")))
9188
}
9289

9390
// Check if a specified device contains an already mounted filesystem
9491
// in the root mount namespace
95-
#[cfg(feature = "install-to-disk")]
96-
pub(crate) fn is_mounted_in_pid1_mountns(path: &str) -> Result<bool> {
92+
pub fn is_mounted_in_pid1_mountns(path: &str) -> Result<bool> {
9793
let o = run_findmnt(&["-N"], "1")?;
9894

9995
let mounted = o.filesystems.iter().any(|fs| is_source_mounted(path, fs));
@@ -102,8 +98,7 @@ pub(crate) fn is_mounted_in_pid1_mountns(path: &str) -> Result<bool> {
10298
}
10399

104100
// Recursively check a given filesystem to see if it contains an already mounted source
105-
#[cfg(feature = "install-to-disk")]
106-
pub(crate) fn is_source_mounted(path: &str, mounted_fs: &Filesystem) -> bool {
101+
pub fn is_source_mounted(path: &str, mounted_fs: &Filesystem) -> bool {
107102
if mounted_fs.source.contains(path) {
108103
return true;
109104
}
@@ -120,21 +115,18 @@ pub(crate) fn is_source_mounted(path: &str, mounted_fs: &Filesystem) -> bool {
120115
}
121116

122117
/// Mount a device to the target path.
123-
#[cfg(feature = "install-to-disk")]
124-
pub(crate) fn mount(dev: &str, target: &Utf8Path) -> Result<()> {
125-
Task::new_and_run(
126-
format!("Mounting {target}"),
127-
"mount",
128-
[dev, target.as_str()],
129-
)
118+
pub fn mount(dev: &str, target: &Utf8Path) -> Result<()> {
119+
Command::new("mount")
120+
.args([dev, target.as_str()])
121+
.run_with_cmd_context()
130122
}
131123

132124
/// If the fsid of the passed path matches the fsid of the same path rooted
133125
/// at /proc/1/root, it is assumed that these are indeed the same mounted
134126
/// filesystem between container and host.
135127
/// Path should be absolute.
136128
#[context("Comparing filesystems at {path} and /proc/1/root/{path}")]
137-
pub(crate) fn is_same_as_host(path: &Utf8Path) -> Result<bool> {
129+
pub fn is_same_as_host(path: &Utf8Path) -> Result<bool> {
138130
// Add a leading '/' in case a relative path is passed
139131
let path = Utf8Path::new("/").join(path);
140132

@@ -155,7 +147,7 @@ pub(crate) fn is_same_as_host(path: &Utf8Path) -> Result<bool> {
155147
/// for a mount from that namespace.
156148
#[allow(unsafe_code)]
157149
#[context("Opening mount tree from pid")]
158-
pub(crate) fn open_tree_from_pidns(
150+
pub fn open_tree_from_pidns(
159151
pid: rustix::process::Pid,
160152
path: &Utf8Path,
161153
recursive: bool,
@@ -259,7 +251,7 @@ pub(crate) fn open_tree_from_pidns(
259251

260252
/// Create a bind mount from the mount namespace of the target pid
261253
/// into our mount namespace.
262-
pub(crate) fn bind_mount_from_pidns(
254+
pub fn bind_mount_from_pidns(
263255
pid: Pid,
264256
src: &Utf8Path,
265257
target: &Utf8Path,
@@ -279,7 +271,7 @@ pub(crate) fn bind_mount_from_pidns(
279271

280272
// If the target path is not already mirrored from the host (e.g. via -v /dev:/dev)
281273
// then recursively mount it.
282-
pub(crate) fn ensure_mirrored_host_mount(path: impl AsRef<Utf8Path>) -> Result<()> {
274+
pub fn ensure_mirrored_host_mount(path: impl AsRef<Utf8Path>) -> Result<()> {
283275
let path = path.as_ref();
284276
// If we didn't have this in our filesystem already (e.g. for /var/lib/containers)
285277
// then create it now.

0 commit comments

Comments
 (0)