44//! - We delete the bootloader entry but fail to delete image
55//! - We delete bootloader + image but fail to delete the state/unrefenced objects etc
66
7- use std:: os:: fd:: AsRawFd ;
8-
97use anyhow:: { Context , Result } ;
108use cap_std_ext:: { cap_std:: fs:: Dir , dirext:: CapStdExtDirExt } ;
9+ use composefs:: repository:: GcResult ;
1110use composefs_boot:: bootloader:: { EFI_ADDON_DIR_EXT , EFI_EXT } ;
12- use rustix:: fs:: readlink;
1311
1412use crate :: {
13+ bootc_composefs:: boot:: get_type1_dir_name,
1514 bootc_composefs:: {
16- boot:: { BOOTC_UKI_DIR , BootType , VMLINUZ } ,
15+ boot:: { BOOTC_UKI_DIR , BootType } ,
1716 delete:: { delete_image, delete_staged, delete_state_dir} ,
1817 status:: { get_composefs_status, get_imginfo, list_bootloader_entries} ,
1918 } ,
20- composefs_consts:: STATE_DIR_RELATIVE ,
19+ composefs_consts:: { STATE_DIR_RELATIVE , TYPE1_BOOT_DIR_PREFIX } ,
2120 store:: { BootedComposefs , Storage } ,
2221} ;
2322
@@ -63,7 +62,7 @@ type BootBinary = (BootType, String);
6362
6463/// Collect all BLS Type1 boot binaries and UKI binaries by scanning filesystem
6564///
66- /// Returns a vector of binary type (UKI/Type1) + verity digest of all boot binaries
65+ /// Returns a vector of binary type (UKI/Type1) + name of all boot binaries
6766#[ fn_error_context:: context( "Collecting boot binaries" ) ]
6867fn collect_boot_binaries ( storage : & Storage ) -> Result < Vec < BootBinary > > {
6968 let mut boot_binaries = Vec :: new ( ) ;
@@ -99,62 +98,44 @@ fn collect_uki_binaries(boot_dir: &Dir, boot_binaries: &mut Vec<BootBinary>) ->
9998 Ok ( ( ) )
10099}
101100
102- /// Scan for Type1 boot binaries (kernels + initrds) by looking for directories with verity hashes
101+ /// Scan for Type1 boot binaries (kernels + initrds) by looking for directories with
102+ /// that start with bootc_composefs-
103+ ///
104+ /// Strips the prefix and returns the rest of the string
103105#[ fn_error_context:: context( "Collecting Type1 boot binaries" ) ]
104106fn collect_type1_boot_binaries ( boot_dir : & Dir , boot_binaries : & mut Vec < BootBinary > ) -> Result < ( ) > {
105107 for entry in boot_dir. entries_utf8 ( ) ? {
106108 let entry = entry?;
107- let dir_path = entry. file_name ( ) ?;
109+ let dir_name = entry. file_name ( ) ?;
108110
109111 if !entry. file_type ( ) ?. is_dir ( ) {
110112 continue ;
111113 }
112114
113- // Check if the directory name looks like a verity hash
114- // 128 hex chars for SHA512, 64 hex chars for SHA256
115- // TODO: There might be a better way to do this
116- let valid_len = matches ! ( dir_path. len( ) , 64 | 128 ) ;
117- let valid_hex = dir_path. bytes ( ) . all ( |b| b. is_ascii_hexdigit ( ) ) ;
118-
119- if !( valid_len && valid_hex) {
115+ let Some ( verity) = dir_name. strip_prefix ( TYPE1_BOOT_DIR_PREFIX ) else {
120116 continue ;
121- }
122-
123- let verity_dir = boot_dir
124- . open_dir ( & dir_path)
125- . with_context ( || format ! ( "Opening {dir_path}" ) ) ?;
117+ } ;
126118
127- // Scan inside this directory for kernel and initrd files
128- for file_entry in verity_dir. entries_utf8 ( ) ? {
129- let file_entry = file_entry?;
130- let file_name = file_entry. file_name ( ) ?;
131-
132- // Look for kernel and initrd files
133- if file_name. starts_with ( VMLINUZ ) {
134- boot_binaries. push ( ( BootType :: Bls , dir_path. clone ( ) ) ) ;
135- }
136- }
119+ // The directory name starts with our custom prefix
120+ boot_binaries. push ( ( BootType :: Bls , verity. to_string ( ) ) ) ;
137121 }
138122
139123 Ok ( ( ) )
140124}
141125
142126#[ fn_error_context:: context( "Deleting kernel and initrd" ) ]
143- fn delete_kernel_initrd ( storage : & Storage , entry_to_delete : & str , dry_run : bool ) -> Result < ( ) > {
127+ fn delete_kernel_initrd ( storage : & Storage , dir_to_delete : & str , dry_run : bool ) -> Result < ( ) > {
144128 let boot_dir = storage. require_boot_dir ( ) ?;
145129
146- let path = readlink ( format ! ( "/proc/self/fd/{}" , boot_dir. as_raw_fd( ) ) , [ ] )
147- . context ( "Getting kernel path" ) ?;
148-
149- tracing:: debug!( "Deleting {path:?}/{entry_to_delete}" ) ;
130+ tracing:: debug!( "Deleting Type1 entry {dir_to_delete}" ) ;
150131
151132 if dry_run {
152133 return Ok ( ( ) ) ;
153134 }
154135
155136 boot_dir
156- . remove_dir_all ( entry_to_delete )
157- . with_context ( || anyhow:: anyhow!( "Deleting {entry_to_delete }" ) )
137+ . remove_dir_all ( dir_to_delete )
138+ . with_context ( || anyhow:: anyhow!( "Deleting {dir_to_delete }" ) )
158139}
159140
160141/// Deletes the UKI `uki_id` and any addons specific to it
@@ -217,7 +198,7 @@ pub(crate) async fn composefs_gc(
217198 storage : & Storage ,
218199 booted_cfs : & BootedComposefs ,
219200 dry_run : bool ,
220- ) -> Result < ( ) > {
201+ ) -> Result < GcResult > {
221202 const COMPOSEFS_GC_JOURNAL_ID : & str = "3b2a1f0e9d8c7b6a5f4e3d2c1b0a9f8e7" ;
222203
223204 tracing:: info!(
@@ -238,7 +219,7 @@ pub(crate) async fn composefs_gc(
238219 tracing:: debug!( "bootloader_entries: {bootloader_entries:?}" ) ;
239220
240221 // Bootloader entry is deleted, but the binary (UKI/kernel+initrd) still exists
241- let unrefenced_boot_binaries = boot_binaries
222+ let unreferenced_boot_binaries = boot_binaries
242223 . iter ( )
243224 . filter ( |bin_path| {
244225 // We reuse kernel + initrd if they're the same for two deployments
@@ -248,13 +229,13 @@ pub(crate) async fn composefs_gc(
248229 // filter the ones that are not referenced by any bootloader entry
249230 !bootloader_entries
250231 . iter ( )
251- . any ( |boot_entry| bin_path. 1 . contains ( boot_entry) )
232+ . any ( |boot_entry| bin_path. 1 == * boot_entry)
252233 } )
253234 . collect :: < Vec < _ > > ( ) ;
254235
255- tracing:: debug!( "unrefenced_boot_binaries : {unrefenced_boot_binaries :?}" ) ;
236+ tracing:: debug!( "unreferenced_boot_binaries : {unreferenced_boot_binaries :?}" ) ;
256237
257- if unrefenced_boot_binaries
238+ if unreferenced_boot_binaries
258239 . iter ( )
259240 . find ( |be| be. 1 == booted_cfs_status. verity )
260241 . is_some ( )
@@ -265,9 +246,9 @@ pub(crate) async fn composefs_gc(
265246 )
266247 }
267248
268- for ( ty, verity) in unrefenced_boot_binaries {
249+ for ( ty, verity) in unreferenced_boot_binaries {
269250 match ty {
270- BootType :: Bls => delete_kernel_initrd ( storage, verity, dry_run) ?,
251+ BootType :: Bls => delete_kernel_initrd ( storage, & get_type1_dir_name ( verity) , dry_run) ?,
271252 BootType :: Uki => delete_uki ( storage, verity, dry_run) ?,
272253 }
273254 }
@@ -345,21 +326,5 @@ pub(crate) async fn composefs_gc(
345326 booted_cfs. repo . gc ( & additional_roots) ?
346327 } ;
347328
348- if dry_run {
349- println ! ( "Dry run (no files deleted)" ) ;
350- }
351-
352- println ! (
353- "Objects: {} removed ({} bytes)" ,
354- gc_result. objects_removed, gc_result. objects_bytes
355- ) ;
356-
357- if gc_result. images_pruned > 0 || gc_result. streams_pruned > 0 {
358- println ! (
359- "Pruned symlinks: {} images, {} streams" ,
360- gc_result. images_pruned, gc_result. streams_pruned
361- ) ;
362- }
363-
364- Ok ( ( ) )
329+ Ok ( gc_result)
365330}
0 commit comments