Skip to content

Commit a66ca6b

Browse files
initramfs: Better error handling
Add error contexts to functions. Create wrappers around intrenal functions with error context added Signed-off-by: Johan-Liebert1 <[email protected]>
1 parent a48dad7 commit a66ca6b

File tree

3 files changed

+48
-21
lines changed

3 files changed

+48
-21
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/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ serde = { workspace = true, features = ["derive"] }
1313
composefs.workspace = true
1414
composefs-boot.workspace = true
1515
toml.workspace = true
16+
fn-error-context.workspace = true
1617

1718
[lints]
1819
workspace = true

crates/initramfs/src/mount.rs

Lines changed: 46 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -17,17 +17,20 @@ use rustix::{
1717
fsconfig_create, fsconfig_set_string, fsmount, open_tree, unmount, FsMountFlags,
1818
MountAttrFlags, OpenTreeFlags, UnmountFlags,
1919
},
20+
path,
2021
};
2122
use serde::Deserialize;
2223

2324
use composefs::{
2425
fsverity::{FsVerityHashValue, Sha256HashValue},
25-
mount::{mount_at, FsHandle},
26+
mount::FsHandle,
2627
mountcompat::{overlayfs_set_fd, overlayfs_set_lower_and_data_fds, prepare_mount},
2728
repository::Repository,
2829
};
2930
use composefs_boot::cmdline::get_cmdline_composefs;
3031

32+
use fn_error_context::context;
33+
3134
// Config file
3235
#[derive(Clone, Copy, Debug, Deserialize)]
3336
#[serde(rename_all = "lowercase")]
@@ -100,39 +103,51 @@ pub struct Args {
100103
}
101104

102105
// Helpers
103-
fn open_dir(dirfd: impl AsFd, name: impl AsRef<Path> + Debug) -> rustix::io::Result<OwnedFd> {
104-
openat(
106+
fn mount_at_wrapper(
107+
fs_fd: impl AsFd,
108+
dirfd: impl AsFd,
109+
path: impl path::Arg + Debug + Clone,
110+
) -> Result<()> {
111+
composefs::mount::mount_at(fs_fd, dirfd, path.clone())
112+
.with_context(|| format!("Mounting at path {path:?}"))
113+
}
114+
115+
#[context("Opening dir {name:?}")]
116+
fn open_dir(dirfd: impl AsFd, name: impl AsRef<Path> + Debug) -> Result<OwnedFd> {
117+
let res = openat(
105118
dirfd,
106119
name.as_ref(),
107120
OFlags::PATH | OFlags::DIRECTORY | OFlags::CLOEXEC,
108121
Mode::empty(),
109-
)
110-
.inspect_err(|_| {
111-
eprintln!("Failed to open dir {name:?}");
112-
})
122+
);
123+
124+
Ok(res?)
113125
}
114126

115-
fn ensure_dir(dirfd: impl AsFd, name: &str) -> rustix::io::Result<OwnedFd> {
127+
#[context("Ensure dir")]
128+
fn ensure_dir(dirfd: impl AsFd, name: &str) -> Result<OwnedFd> {
116129
match mkdirat(dirfd.as_fd(), name, 0o700.into()) {
117130
Ok(()) | Err(Errno::EXIST) => {}
118-
Err(err) => Err(err)?,
131+
Err(err) => Err(err).with_context(|| format!("Creating dir {name}"))?,
119132
}
133+
120134
open_dir(dirfd, name)
121135
}
122136

123-
fn bind_mount(fd: impl AsFd, path: &str) -> rustix::io::Result<OwnedFd> {
124-
open_tree(
137+
#[context("Bind mounting to path {path}")]
138+
fn bind_mount(fd: impl AsFd, path: &str) -> Result<OwnedFd> {
139+
let res = open_tree(
125140
fd.as_fd(),
126141
path,
127142
OpenTreeFlags::OPEN_TREE_CLONE
128143
| OpenTreeFlags::OPEN_TREE_CLOEXEC
129144
| OpenTreeFlags::AT_EMPTY_PATH,
130-
)
131-
.inspect_err(|_| {
132-
eprintln!("Open tree failed for {path}");
133-
})
145+
);
146+
147+
Ok(res?)
134148
}
135149

150+
#[context("Mounting tmpfs")]
136151
fn mount_tmpfs() -> Result<OwnedFd> {
137152
let tmpfs = FsHandle::open("tmpfs")?;
138153
fsconfig_create(tmpfs.as_fd())?;
@@ -143,6 +158,7 @@ fn mount_tmpfs() -> Result<OwnedFd> {
143158
)?)
144159
}
145160

161+
#[context("Mounting state as overlay")]
146162
fn overlay_state(base: impl AsFd, state: impl AsFd, source: &str) -> Result<()> {
147163
let upper = ensure_dir(state.as_fd(), "upper")?;
148164
let work = ensure_dir(state.as_fd(), "work")?;
@@ -159,13 +175,14 @@ fn overlay_state(base: impl AsFd, state: impl AsFd, source: &str) -> Result<()>
159175
MountAttrFlags::empty(),
160176
)?;
161177

162-
Ok(mount_at(fs, base, ".")?)
178+
mount_at_wrapper(fs, base, ".").context("Moving mount")
163179
}
164180

165181
fn overlay_transient(base: impl AsFd) -> Result<()> {
166182
overlay_state(base, prepare_mount(mount_tmpfs()?)?, "transient")
167183
}
168184

185+
#[context("Opening rootfs")]
169186
fn open_root_fs(path: &Path) -> Result<OwnedFd> {
170187
let rootfs = open_tree(
171188
CWD,
@@ -185,12 +202,14 @@ fn open_root_fs(path: &Path) -> Result<OwnedFd> {
185202
/// * sysroot - fd for /sysroot
186203
/// * name - Name of the EROFS image to be mounted
187204
/// * insecure - Whether fsverity is optional or not
205+
#[context("Mounting composefs image")]
188206
pub fn mount_composefs_image(sysroot: &OwnedFd, name: &str, insecure: bool) -> Result<OwnedFd> {
189207
let mut repo = Repository::<Sha256HashValue>::open_path(sysroot, "composefs")?;
190208
repo.set_insecure(insecure);
191209
repo.mount(name).context("Failed to mount composefs image")
192210
}
193211

212+
#[context("Mounting subdirectory")]
194213
fn mount_subdir(
195214
new_root: impl AsFd,
196215
state: impl AsFd,
@@ -208,7 +227,11 @@ fn mount_subdir(
208227

209228
match mount_type {
210229
MountType::None => Ok(()),
211-
MountType::Bind => Ok(mount_at(bind_mount(&state, subdir)?, &new_root, subdir)?),
230+
MountType::Bind => Ok(mount_at_wrapper(
231+
bind_mount(&state, subdir)?,
232+
&new_root,
233+
subdir,
234+
)?),
212235
MountType::Overlay => overlay_state(
213236
open_dir(&new_root, subdir)?,
214237
open_dir(&state, subdir)?,
@@ -218,6 +241,7 @@ fn mount_subdir(
218241
}
219242
}
220243

244+
#[context("GPT workaround")]
221245
pub(crate) fn gpt_workaround() -> Result<()> {
222246
// https://github.com/systemd/systemd/issues/35017
223247
let rootdev = stat("/dev/gpt-auto-root");
@@ -238,6 +262,7 @@ pub(crate) fn gpt_workaround() -> Result<()> {
238262
}
239263

240264
/// Sets up /sysroot for switch-root
265+
#[context("Setting up /sysroot")]
241266
pub fn setup_root(args: Args) -> Result<()> {
242267
let config = match std::fs::read_to_string(args.config) {
243268
Ok(text) => toml::from_str(&text)?,
@@ -267,27 +292,27 @@ pub fn setup_root(args: Args) -> Result<()> {
267292
// 6.15 and later. Before 6.15 we can't mount into a floating tree, so mount it first. This
268293
// will leave an abandoned clone of the sysroot mounted under it, but that's OK for now.
269294
if cfg!(feature = "pre-6.15") {
270-
mount_at(&new_root, CWD, &args.sysroot)?;
295+
mount_at_wrapper(&new_root, CWD, &args.sysroot)?;
271296
}
272297

273298
if config.root.transient {
274299
overlay_transient(&new_root)?;
275300
}
276301

277-
match mount_at(&sysroot_clone, &new_root, "sysroot") {
302+
match composefs::mount::mount_at(&sysroot_clone, &new_root, "sysroot") {
278303
Ok(()) | Err(Errno::NOENT) => {}
279304
Err(err) => Err(err)?,
280305
}
281306

282307
// etc + var
283308
let state = open_dir(open_dir(&sysroot, "state/deploy")?, image.to_hex())?;
284-
mount_subdir(&new_root, &state, "etc", config.etc, MountType::Overlay)?;
309+
mount_subdir(&new_root, &state, "etc", config.etc, MountType::Bind)?;
285310
mount_subdir(&new_root, &state, "var", config.var, MountType::Bind)?;
286311

287312
if cfg!(not(feature = "pre-6.15")) {
288313
// Replace the /sysroot with the new composed root filesystem
289314
unmount(&args.sysroot, UnmountFlags::DETACH)?;
290-
mount_at(&new_root, CWD, &args.sysroot)?;
315+
mount_at_wrapper(&new_root, CWD, &args.sysroot)?;
291316
}
292317

293318
Ok(())

0 commit comments

Comments
 (0)