@@ -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} ;
2122use serde:: Deserialize ;
2223
2324use 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} ;
2930use 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" ) ]
136151fn 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" ) ]
146162fn 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
165181fn overlay_transient ( base : impl AsFd ) -> Result < ( ) > {
166182 overlay_state ( base, prepare_mount ( mount_tmpfs ( ) ?) ?, "transient" )
167183}
168184
185+ #[ context( "Opening rootfs" ) ]
169186fn 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" ) ]
188206pub 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" ) ]
194213fn 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" ) ]
221245pub ( 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" ) ]
241266pub 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