@@ -12,7 +12,7 @@ mod osbuild;
1212pub ( crate ) mod osconfig;
1313
1414use std:: io:: Write ;
15- use std:: os:: fd:: AsFd ;
15+ use std:: os:: fd:: { AsFd , AsRawFd } ;
1616use std:: os:: unix:: process:: CommandExt ;
1717use std:: path:: Path ;
1818use 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<()> {
903902pub ( 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,
0 commit comments