@@ -178,7 +178,11 @@ impl BDA {
178178 F : Read + Seek + SyncAll ,
179179 {
180180 let header = match StaticHeader :: setup ( f) ? {
181- Some ( header) => header,
181+ Some ( SetupResult :: Ok ( header) ) => header,
182+ Some ( SetupResult :: OkWithError ( header, err) ) => {
183+ setup_warn ( & header, err) ;
184+ header
185+ }
182186 None => return Ok ( None ) ,
183187 } ;
184188
@@ -272,10 +276,49 @@ impl BDA {
272276 where
273277 F : Read + Seek + SyncAll ,
274278 {
275- StaticHeader :: setup ( f) . map ( |sh| sh. map ( |sh| ( sh. pool_uuid , sh. dev_uuid ) ) )
279+ match StaticHeader :: setup ( f) {
280+ Ok ( Some ( SetupResult :: Ok ( sh) ) ) => Ok ( Some ( ( sh. pool_uuid , sh. dev_uuid ) ) ) ,
281+ Ok ( Some ( SetupResult :: OkWithError ( sh, err) ) ) => {
282+ setup_warn ( & sh, err) ;
283+ Ok ( Some ( ( sh. pool_uuid , sh. dev_uuid ) ) )
284+ }
285+ Ok ( None ) => Ok ( None ) ,
286+ Err ( err) => Err ( err) ,
287+ }
276288 }
277289}
278290
291+ fn setup_warn ( header : & StaticHeader , err : StratisError ) {
292+ warn ! (
293+ "Experienced an I/O error while attempting to repair an ill-formed, \
294+ unreadable, or stale signature block: {:?}.\n \
295+ Returning device \" {:?}\" from pool \" {:?}\" .",
296+ err, header. dev_uuid, header. pool_uuid
297+ ) ;
298+ }
299+
300+ fn bda_write_check < F > (
301+ f : & mut F ,
302+ bda_buf : & [ u8 ] ,
303+ which : MetadataLocation ,
304+ header : StaticHeader ,
305+ ) -> StratisResult < Option < SetupResult > >
306+ where
307+ F : Read + Seek + SyncAll ,
308+ {
309+ Ok ( match BDA :: write ( f, & bda_buf, which) {
310+ Ok ( _) => Some ( SetupResult :: Ok ( header) ) ,
311+ Err ( err) => Some ( SetupResult :: OkWithError ( header, StratisError :: Io ( err) ) ) ,
312+ } )
313+ }
314+
315+ #[ derive( Debug ) ]
316+ #[ must_use]
317+ pub enum SetupResult {
318+ Ok ( StaticHeader ) ,
319+ OkWithError ( StaticHeader , StratisError ) ,
320+ }
321+
279322#[ derive( Eq , PartialEq ) ]
280323pub struct StaticHeader {
281324 blkdev_size : Sectors ,
@@ -312,17 +355,23 @@ impl StaticHeader {
312355 }
313356
314357 /// Try to find a valid StaticHeader on a device.
358+ ///
315359 /// Return the latest copy that validates as a Stratis BDA, however verify both
316360 /// copies and if one validates but one does not, re-write the one that is incorrect. If both
317361 /// copies are valid, but one is newer than the other, rewrite the older one to match.
362+ ///
318363 /// Return None if it's not a Stratis device.
364+ ///
319365 /// Return an error if the metadata seems to indicate that the device is
320366 /// a Stratis device, but no well-formed signature block could be read.
367+ ///
321368 /// Return an error if neither sigblock location can be read.
369+ ///
322370 /// Return an error if the sigblocks differ in some unaccountable way.
323- /// Returns an error if a write intended to repair an ill-formed,
324- /// unreadable, or stale signature block failed.
325- fn setup < F > ( f : & mut F ) -> StratisResult < Option < StaticHeader > >
371+ ///
372+ /// Return the latest copy alongside the associated error if a write intended to repair
373+ /// an ill-formed, unreadable, or stale signature failed.
374+ fn setup < F > ( f : & mut F ) -> StratisResult < Option < SetupResult > >
326375 where
327376 F : Read + Seek + SyncAll ,
328377 {
@@ -332,43 +381,40 @@ impl StaticHeader {
332381 StaticHeader :: sigblock_from_buf ( & buf_loc_1) ,
333382 StaticHeader :: sigblock_from_buf ( & buf_loc_2) ,
334383 ) {
335- ( Ok ( loc_1) , Ok ( loc_2) ) => match ( loc_1, loc_2) {
336- ( Some ( loc_1) , Some ( loc_2) ) => {
337- if loc_1 == loc_2 {
338- Ok ( Some ( loc_1) )
339- } else if loc_1. initialization_time == loc_2. initialization_time {
340- // Inexplicable disagreement among static headers
341- let err_str =
342- "Appeared to be a Stratis device, but signature blocks disagree." ;
343- Err ( StratisError :: Engine ( ErrorEnum :: Invalid , err_str. into ( ) ) )
344- } else if loc_1. initialization_time > loc_2. initialization_time {
345- // If the first header block is newer, overwrite second with
346- // contents of first.
347- BDA :: write ( f, & buf_loc_1, MetadataLocation :: Second ) ?;
348- Ok ( Some ( loc_1) )
349- } else {
350- // The second header block must be newer, so overwrite first
351- // with contents of second.
352- BDA :: write ( f, & buf_loc_2, MetadataLocation :: First ) ?;
353- Ok ( Some ( loc_2) )
384+ ( Ok ( loc_1) , Ok ( loc_2) ) => {
385+ match ( loc_1, loc_2) {
386+ ( Some ( loc_1) , Some ( loc_2) ) => {
387+ if loc_1 == loc_2 {
388+ Ok ( Some ( SetupResult :: Ok ( loc_1) ) )
389+ } else if loc_1. initialization_time == loc_2. initialization_time {
390+ // Inexplicable disagreement among static headers
391+ let err_str = "Appeared to be a Stratis device, but signature blocks disagree." ;
392+ Err ( StratisError :: Engine ( ErrorEnum :: Invalid , err_str. into ( ) ) )
393+ } else if loc_1. initialization_time > loc_2. initialization_time {
394+ // If the first header block is newer, overwrite second with
395+ // contents of first.
396+ bda_write_check ( f, & buf_loc_1, MetadataLocation :: Second , loc_1)
397+ } else {
398+ // The second header block must be newer, so overwrite first
399+ // with contents of second.
400+ bda_write_check ( f, & buf_loc_2, MetadataLocation :: First , loc_2)
401+ }
402+ }
403+ ( None , None ) => Ok ( None ) ,
404+ ( Some ( loc_1) , None ) => {
405+ // Copy 1 has valid Stratis BDA, copy 2 has no magic, re-write copy 2
406+ bda_write_check ( f, & buf_loc_1, MetadataLocation :: Second , loc_1)
407+ }
408+ ( None , Some ( loc_2) ) => {
409+ // Copy 2 has valid Stratis BDA, copy 1 has no magic, re-write copy 1
410+ bda_write_check ( f, & buf_loc_2, MetadataLocation :: First , loc_2)
354411 }
355412 }
356- ( None , None ) => Ok ( None ) ,
357- ( Some ( loc_1) , None ) => {
358- // Copy 1 has valid Stratis BDA, copy 2 has no magic, re-write copy 2
359- BDA :: write ( f, & buf_loc_1, MetadataLocation :: Second ) ?;
360- Ok ( Some ( loc_1) )
361- }
362- ( None , Some ( loc_2) ) => {
363- // Copy 2 has valid Stratis BDA, copy 1 has no magic, re-write copy 1
364- BDA :: write ( f, & buf_loc_2, MetadataLocation :: First ) ?;
365- Ok ( Some ( loc_2) )
366- }
367- } ,
413+ }
368414 ( Ok ( loc_1) , Err ( loc_2) ) => {
369- if loc_1 . is_some ( ) {
370- BDA :: write ( f , & buf_loc_1 , MetadataLocation :: Second ) ? ;
371- Ok ( loc_1)
415+ // Re-write copy 2
416+ if let Some ( loc_1 ) = loc_1 {
417+ bda_write_check ( f , & buf_loc_1 , MetadataLocation :: Second , loc_1)
372418 } else {
373419 // Location 1 doesn't have a signature, but location 2 did, but it got an error,
374420 // lets return the error instead as this appears to be a stratis device that
@@ -377,9 +423,9 @@ impl StaticHeader {
377423 }
378424 }
379425 ( Err ( loc_1) , Ok ( loc_2) ) => {
380- if loc_2 . is_some ( ) {
381- BDA :: write ( f , & buf_loc_2 , MetadataLocation :: First ) ? ;
382- Ok ( loc_2)
426+ // Re-write copy 1
427+ if let Some ( loc_2 ) = loc_2 {
428+ bda_write_check ( f , & buf_loc_2 , MetadataLocation :: First , loc_2)
383429 } else {
384430 // Location 2 doesn't have a signature, but location 1 did, but it got an error,
385431 // lets return the error instead as this appears to be a stratis device that
@@ -395,10 +441,11 @@ impl StaticHeader {
395441 // Copy 1 read OK, 2 resulted in an IO error
396442 ( Ok ( buf_loc_1) , Err ( _) ) => match StaticHeader :: sigblock_from_buf ( & buf_loc_1) {
397443 Ok ( loc_1) => {
398- if loc_1. is_some ( ) {
399- BDA :: write ( f, & buf_loc_1, MetadataLocation :: Second ) ?;
444+ if let Some ( loc_1) = loc_1 {
445+ bda_write_check ( f, & buf_loc_1, MetadataLocation :: Second , loc_1)
446+ } else {
447+ Ok ( None )
400448 }
401- Ok ( loc_1)
402449 }
403450 Err ( e) => {
404451 // Unable to determine if location 2 has a signature, but location 1 did,
@@ -410,10 +457,11 @@ impl StaticHeader {
410457 // Copy 2 read OK, 1 resulted in IO Error
411458 ( Err ( _) , Ok ( buf_loc_2) ) => match StaticHeader :: sigblock_from_buf ( & buf_loc_2) {
412459 Ok ( loc_2) => {
413- if loc_2. is_some ( ) {
414- BDA :: write ( f, & buf_loc_2, MetadataLocation :: First ) ?;
460+ if let Some ( loc_2) = loc_2 {
461+ bda_write_check ( f, & buf_loc_2, MetadataLocation :: First , loc_2)
462+ } else {
463+ Ok ( None )
415464 }
416- Ok ( loc_2)
417465 }
418466 Err ( e) => {
419467 // Unable to determine if location 1 has a signature, but location 2 did,
0 commit comments