Skip to content

Commit 32d98e5

Browse files
StaticHeader::setup Improve error reporting
1 parent 65c47da commit 32d98e5

File tree

1 file changed

+96
-48
lines changed
  • src/engine/strat_engine/backstore/metadata

1 file changed

+96
-48
lines changed

src/engine/strat_engine/backstore/metadata/bda.rs

Lines changed: 96 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -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)]
280323
pub 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

Comments
 (0)