Skip to content

Commit c5c3751

Browse files
composefs/install: Copy /etc contents to state
For bind mounting /etc we copy the contents of the EROFS' /etc to the deployment's state directory Mounting the EORFS requires help from the initramfs crate, so we also turn it into a library crate. Signed-off-by: Johan-Liebert1 <[email protected]>
1 parent 67c4e8d commit c5c3751

File tree

8 files changed

+73
-8
lines changed

8 files changed

+73
-8
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

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

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -102,8 +102,8 @@ pub struct Args {
102102
pub target: Option<PathBuf>,
103103
}
104104

105-
// Helpers
106-
fn mount_at_wrapper(
105+
/// Wrapper around [`composefs::mount::mount_at`]
106+
pub fn mount_at_wrapper(
107107
fs_fd: impl AsFd,
108108
dirfd: impl AsFd,
109109
path: impl path::Arg + Debug + Clone,
@@ -242,7 +242,8 @@ fn mount_subdir(
242242
}
243243

244244
#[context("GPT workaround")]
245-
pub(crate) fn gpt_workaround() -> Result<()> {
245+
/// Workaround for /dev/gpt-auto-root
246+
pub fn gpt_workaround() -> Result<()> {
246247
// https://github.com/systemd/systemd/issues/35017
247248
let rootdev = stat("/dev/gpt-auto-root");
248249

crates/initramfs/src/main.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,10 @@
11
//! Code for bootc that goes into the initramfs.
22
// SPDX-License-Identifier: Apache-2.0 OR MIT
33

4-
mod mount;
5-
64
use anyhow::Result;
75

86
use clap::Parser;
9-
use mount::{gpt_workaround, setup_root, Args};
7+
use bootc_initramfs_setup::{gpt_workaround, setup_root, Args};
108

119
fn main() -> Result<()> {
1210
let args = Args::parse();

crates/lib/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ bootc-sysusers = { path = "../sysusers" }
2222
bootc-tmpfiles = { path = "../tmpfiles" }
2323
bootc-utils = { package = "bootc-internal-utils", path = "../utils", version = "0.0.0" }
2424
ostree-ext = { path = "../ostree-ext", features = ["bootc"] }
25+
bootc-initramfs-setup = { path = "../initramfs" }
2526

2627
# Workspace dependencies
2728
anstream = { workspace = true }
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
pub(crate) mod state;
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
use std::{
2+
fs::{create_dir_all, remove_dir_all},
3+
process::Command,
4+
};
5+
6+
use anyhow::{Context, Result};
7+
use camino::Utf8PathBuf;
8+
use fn_error_context::context;
9+
10+
use rustix::{
11+
fs::{open, Mode, OFlags, CWD},
12+
mount::{unmount, UnmountFlags},
13+
};
14+
15+
/// Mounts an EROFS image and copies the pristine /etc to the deployment's /etc
16+
#[context("Copying etc")]
17+
pub(crate) fn copy_etc_to_state(
18+
sysroot_path: &Utf8PathBuf,
19+
erofs_id: &String,
20+
state_path: &Utf8PathBuf,
21+
) -> Result<()> {
22+
let sysroot_fd = open(
23+
sysroot_path.as_std_path(),
24+
OFlags::PATH | OFlags::DIRECTORY | OFlags::CLOEXEC,
25+
Mode::empty(),
26+
)
27+
.context("Opening sysroot")?;
28+
29+
let composefs_fd = bootc_initramfs_setup::mount_composefs_image(&sysroot_fd, &erofs_id, false)?;
30+
31+
let uuid = uuid::Uuid::new_v4();
32+
let dir = format!("/var/tmp/{uuid}");
33+
34+
create_dir_all(&dir).context("Creating temp directory")?;
35+
36+
bootc_initramfs_setup::mount_at_wrapper(composefs_fd, CWD, &dir)?;
37+
38+
let output = Command::new("cp")
39+
.args([
40+
"-a",
41+
&format!("{dir}/etc/."),
42+
&format!("{state_path}/etc/."),
43+
])
44+
.output()?;
45+
46+
// Unmount regardless of copy succeeding
47+
unmount(&dir, UnmountFlags::DETACH).context("Unmounting composefs")?;
48+
49+
remove_dir_all(dir).context("Removing temp directory")?;
50+
51+
if !output.status.success() {
52+
anyhow::bail!(
53+
"Copying /etc failed with status {}: {}",
54+
output.status,
55+
String::from_utf8_lossy(&output.stderr)
56+
);
57+
}
58+
59+
Ok(())
60+
}

crates/lib/src/install.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ use serde::{Deserialize, Serialize};
7474

7575
#[cfg(feature = "install-to-disk")]
7676
use self::baseline::InstallBlockDeviceOpts;
77+
use crate::bootc_composefs::state::copy_etc_to_state;
7778
use crate::boundimage::{BoundImage, ResolvedBoundImage};
7879
use crate::composefs_consts::{
7980
BOOT_LOADER_ENTRIES, COMPOSEFS_CMDLINE, COMPOSEFS_STAGED_DEPLOYMENT_FNAME,
@@ -2208,8 +2209,9 @@ pub(crate) fn write_composefs_state(
22082209
) -> Result<()> {
22092210
let state_path = root_path.join(format!("{STATE_DIR_RELATIVE}/{}", deployment_id.to_hex()));
22102211

2211-
create_dir_all(state_path.join("etc/upper"))?;
2212-
create_dir_all(state_path.join("etc/work"))?;
2212+
create_dir_all(state_path.join("etc"))?;
2213+
2214+
copy_etc_to_state(&root_path, &deployment_id.to_hex(), &state_path)?;
22132215

22142216
let actual_var_path = root_path.join(SHARED_VAR_PATH);
22152217
create_dir_all(&actual_var_path)?;

crates/lib/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ mod bootloader;
99
mod boundimage;
1010
mod cfsctl;
1111
pub mod cli;
12+
mod bootc_composefs;
1213
mod composefs_consts;
1314
mod containerenv;
1415
pub(crate) mod deploy;

0 commit comments

Comments
 (0)