@@ -10,6 +10,7 @@ use std::path::{Path, PathBuf};
1010use std:: process:: Command ;
1111
1212use anyhow:: { bail, Context , Result } ;
13+ use bootc_utils:: CommandRunExt ;
1314use cap_std:: fs:: Dir ;
1415use cap_std_ext:: cap_std;
1516use fn_error_context:: context;
@@ -22,7 +23,7 @@ use widestring::U16CString;
2223use crate :: bootupd:: RootContext ;
2324use crate :: model:: * ;
2425use crate :: ostreeutil;
25- use crate :: util:: { self , CommandRunExt } ;
26+ use crate :: util;
2627use crate :: { blockdev, filetree} ;
2728use crate :: { component:: * , packagesystem} ;
2829
@@ -256,32 +257,30 @@ impl Component for Efi {
256257 return Ok ( None ) ;
257258 } ;
258259
259- let esp_devices = esp_devices. unwrap_or_default ( ) ;
260- let mut devices = esp_devices. iter ( ) ;
261- let Some ( esp) = devices. next ( ) else {
262- anyhow:: bail!( "Failed to find esp device" ) ;
263- } ;
264-
265- if let Some ( next_esp) = devices. next ( ) {
266- anyhow:: bail!(
267- "Found multiple esp devices {esp} and {next_esp}; not currently supported"
268- ) ;
269- }
270- let destpath = & self . ensure_mounted_esp ( rootcxt. path . as_ref ( ) , Path :: new ( & esp) ) ?;
271-
272- let destdir = & openat:: Dir :: open ( & destpath. join ( "EFI" ) )
273- . with_context ( || format ! ( "opening EFI dir {}" , destpath. display( ) ) ) ?;
274- validate_esp_fstype ( & destdir) ?;
275260 let updated = rootcxt
276261 . sysroot
277262 . sub_dir ( & component_updatedirname ( self ) )
278263 . context ( "opening update dir" ) ?;
279264 let updatef = filetree:: FileTree :: new_from_dir ( & updated) . context ( "reading update dir" ) ?;
280- // For adoption, we should only touch files that we know about.
281- let diff = updatef. relative_diff_to ( & destdir) ?;
282- log:: trace!( "applying adoption diff: {}" , & diff) ;
283- filetree:: apply_diff ( & updated, & destdir, & diff, None )
284- . context ( "applying filesystem changes" ) ?;
265+
266+ let esp_devices = esp_devices. unwrap_or_default ( ) ;
267+ for esp in esp_devices {
268+ let destpath = & self . ensure_mounted_esp ( rootcxt. path . as_ref ( ) , Path :: new ( & esp) ) ?;
269+
270+ let efidir = openat:: Dir :: open ( & destpath. join ( "EFI" ) ) . context ( "opening EFI dir" ) ?;
271+ validate_esp_fstype ( & efidir) ?;
272+
273+ // For adoption, we should only touch files that we know about.
274+ let diff = updatef. relative_diff_to ( & efidir) ?;
275+ log:: trace!( "applying adoption diff: {}" , & diff) ;
276+ filetree:: apply_diff ( & updated, & efidir, & diff, None )
277+ . context ( "applying filesystem changes" ) ?;
278+
279+ // Do the sync before unmount
280+ efidir. syncfs ( ) ?;
281+ drop ( efidir) ;
282+ self . unmount ( ) . context ( "unmount after adopt" ) ?;
283+ }
285284 Ok ( Some ( InstalledContent {
286285 meta : updatemeta. clone ( ) ,
287286 filetree : Some ( updatef) ,
@@ -354,24 +353,21 @@ impl Component for Efi {
354353 let Some ( esp_devices) = blockdev:: find_colocated_esps ( & rootcxt. devices ) ? else {
355354 anyhow:: bail!( "Failed to find all esp devices" ) ;
356355 } ;
357- let mut devices = esp_devices. iter ( ) ;
358- let Some ( esp) = devices. next ( ) else {
359- anyhow:: bail!( "Failed to find esp device" ) ;
360- } ;
361356
362- if let Some ( next_esp) = devices. next ( ) {
363- anyhow:: bail!(
364- "Found multiple esp devices {esp} and {next_esp}; not currently supported"
365- ) ;
357+ for esp in esp_devices {
358+ let destpath = & self . ensure_mounted_esp ( rootcxt. path . as_ref ( ) , Path :: new ( & esp) ) ?;
359+ let destdir = openat:: Dir :: open ( & destpath. join ( "EFI" ) ) . context ( "opening EFI dir" ) ?;
360+ validate_esp_fstype ( & destdir) ?;
361+ log:: trace!( "applying diff: {}" , & diff) ;
362+ filetree:: apply_diff ( & updated, & destdir, & diff, None )
363+ . context ( "applying filesystem changes" ) ?;
364+
365+ // Do the sync before unmount
366+ destdir. syncfs ( ) ?;
367+ drop ( destdir) ;
368+ self . unmount ( ) . context ( "unmount after update" ) ?;
366369 }
367- let destpath = & self . ensure_mounted_esp ( rootcxt. path . as_ref ( ) , Path :: new ( & esp) ) ?;
368-
369- let destdir = & openat:: Dir :: open ( & destpath. join ( "EFI" ) )
370- . with_context ( || format ! ( "opening EFI dir {}" , destpath. display( ) ) ) ?;
371- validate_esp_fstype ( & destdir) ?;
372- log:: trace!( "applying diff: {}" , & diff) ;
373- filetree:: apply_diff ( & updated, & destdir, & diff, None )
374- . context ( "applying filesystem changes" ) ?;
370+
375371 let adopted_from = None ;
376372 Ok ( InstalledContent {
377373 meta : updatemeta,
@@ -430,31 +426,26 @@ impl Component for Efi {
430426 . as_ref ( )
431427 . ok_or_else ( || anyhow:: anyhow!( "No filetree for installed EFI found!" ) ) ?;
432428
429+ let mut errs = Vec :: new ( ) ;
433430 let esp_devices = esp_devices. unwrap_or_default ( ) ;
434- let mut devices = esp_devices. iter ( ) ;
435- let Some ( esp) = devices. next ( ) else {
436- anyhow:: bail!( "Failed to find esp device" ) ;
437- } ;
431+ for esp in esp_devices. iter ( ) {
432+ let destpath = & self . ensure_mounted_esp ( Path :: new ( "/" ) , Path :: new ( & esp) ) ?;
438433
439- if let Some ( next_esp) = devices. next ( ) {
440- anyhow:: bail!(
441- "Found multiple esp devices {esp} and {next_esp}; not currently supported"
442- ) ;
443- }
444- let destpath = & self . ensure_mounted_esp ( Path :: new ( "/" ) , Path :: new ( & esp) ) ?;
434+ let efidir = openat:: Dir :: open ( & destpath. join ( "EFI" ) )
435+ . with_context ( || format ! ( "opening EFI dir {}" , destpath. display( ) ) ) ?;
436+ let diff = currentf. relative_diff_to ( & efidir) ?;
445437
446- let efidir = & openat:: Dir :: open ( & destpath. join ( "EFI" ) )
447- . with_context ( || format ! ( "opening EFI dir {}" , destpath. display( ) ) ) ?;
448-
449- let diff = currentf. relative_diff_to ( & efidir) ?;
450- let mut errs = Vec :: new ( ) ;
451- for f in diff. changes . iter ( ) {
452- errs. push ( format ! ( "Changed: {}" , f) ) ;
453- }
454- for f in diff. removals . iter ( ) {
455- errs. push ( format ! ( "Removed: {}" , f) ) ;
438+ for f in diff. changes . iter ( ) {
439+ errs. push ( format ! ( "Changed: {}" , f) ) ;
440+ }
441+ for f in diff. removals . iter ( ) {
442+ errs. push ( format ! ( "Removed: {}" , f) ) ;
443+ }
444+ assert_eq ! ( diff. additions. len( ) , 0 ) ;
445+ drop ( efidir) ;
446+ self . unmount ( ) . context ( "unmount after validate" ) ?;
456447 }
457- assert_eq ! ( diff . additions . len ( ) , 0 ) ;
448+
458449 if !errs. is_empty ( ) {
459450 Ok ( ValidationResult :: Errors ( errs) )
460451 } else {
0 commit comments