@@ -88,8 +88,15 @@ fn compute_merged_options(
8888 merged
8989}
9090
91- /// Read the BLS entry file content for a deployment by scanning /boot/loader/entries/.
92- /// We find the entry that matches the deployment's bootconfig options.
91+ /// Read the BLS entry file content for a deployment from /boot/loader/entries/.
92+ ///
93+ /// The BLS entry filename pattern changed in ostree 2024.5:
94+ /// - New: ostree-<index>.conf
95+ /// - Old: ostree-<index>-<stateroot>.conf
96+ ///
97+ /// Since we can't easily reconstruct the index, we read all ostree-*.conf
98+ /// entries and match by checking the `options` line for the deployment's
99+ /// ostree path (which includes the stateroot and deploy serial).
93100fn read_bls_entry_for_deployment (
94101 sysroot : & ostree:: Sysroot ,
95102 deployment : & ostree:: Deployment ,
@@ -103,27 +110,43 @@ fn read_bls_entry_for_deployment(
103110 . path ( )
104111 . ok_or_else ( || anyhow:: anyhow!( "Failed to get boot/loader/entries path" ) ) ?;
105112
106- // The BLS entry filename follows the pattern: ostree-$stateroot-$deployserial.conf
113+ // Build the expected ostree= value from the deployment to match against.
114+ // The ostree= karg format is: /ostree/boot.N/$stateroot/$bootcsum/$bootserial
115+ // where bootcsum is the boot checksum and bootserial is the serial among
116+ // deployments sharing the same bootcsum (NOT the deployserial).
107117 let stateroot = deployment. stateroot ( ) ;
108- let deployserial = deployment. deployserial ( ) ;
118+ let bootserial = deployment. bootserial ( ) ;
109119 let bootcsum = deployment. bootcsum ( ) ;
110- let expected_suffix = format ! ( "{stateroot}- {bootcsum}-{deployserial}.conf " ) ;
120+ let ostree_match = format ! ( "/ {stateroot}/ {bootcsum}/{bootserial} " ) ;
111121
122+ let mut found_entries = Vec :: new ( ) ;
112123 for entry in std:: fs:: read_dir ( & entries_dir)
113124 . with_context ( || format ! ( "Reading {}" , entries_dir. display( ) ) ) ?
114125 {
115126 let entry = entry?;
116127 let name = entry. file_name ( ) ;
117128 let name = name. to_string_lossy ( ) ;
118- if name. ends_with ( & expected_suffix) {
119- return std:: fs:: read_to_string ( entry. path ( ) )
120- . with_context ( || format ! ( "Reading BLS entry {}" , entry. path( ) . display( ) ) ) ;
129+ if !name. starts_with ( "ostree-" ) || !name. ends_with ( ".conf" ) {
130+ continue ;
131+ }
132+ found_entries. push ( name. to_string ( ) ) ;
133+ let content = std:: fs:: read_to_string ( entry. path ( ) )
134+ . with_context ( || format ! ( "Reading BLS entry {}" , entry. path( ) . display( ) ) ) ?;
135+ // Check if this entry's options line contains our deployment's ostree path
136+ if content
137+ . lines ( )
138+ . any ( |line| line. starts_with ( "options " ) && line. contains ( & ostree_match) )
139+ {
140+ return Ok ( content) ;
121141 }
122142 }
123143
124144 anyhow:: bail!(
125- "No BLS entry found matching deployment {stateroot} serial {deployserial} in {}" ,
126- entries_dir. display( )
145+ "No BLS entry found matching deployment {stateroot}/{bootcsum}/{bootserial} in {}. \
146+ Looking for '{}' in options line. Found entries: {:?}",
147+ entries_dir. display( ) ,
148+ ostree_match,
149+ found_entries,
127150 )
128151}
129152
0 commit comments