Skip to content

Commit 5ef8946

Browse files
committed
[thin_dump] Prompt for repair only on input errors
Separate output errors from input errors for callers to determine the error type. A broken pipe error (EPIPE) is also treated as an output error since the Rust std library ignores SIGPIPE by default [1][2]. thin_dump then shows the hint if there's any error in metadata, or exit gracefully if it is an output error. [1] rust-lang/rust#13158 [2] rust-lang/rust#62569
1 parent fa3b3c6 commit 5ef8946

File tree

5 files changed

+53
-35
lines changed

5 files changed

+53
-35
lines changed

src/commands/thin_dump.rs

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use std::sync::Arc;
88

99
use crate::commands::utils::*;
1010
use crate::commands::Command;
11+
use crate::error::IoError;
1112
use crate::report::*;
1213
use crate::thin::dump::{dump, ThinDumpOptions};
1314
use crate::thin::metadata_repair::SuperblockOverrides;
@@ -128,13 +129,17 @@ impl<'a> Command<'a> for ThinDumpCommand {
128129
},
129130
};
130131

131-
dump(opts).map_err(|reason| {
132-
report.fatal(&format!("{}", reason));
133-
report.fatal(
134-
"metadata contains errors (run thin_check for details).\n\
135-
perhaps you wanted to run with --repair ?",
136-
);
137-
std::io::Error::from_raw_os_error(libc::EPERM)
138-
})
132+
if let Err(e) = dump(opts) {
133+
if let IoError::Input(reason) = e {
134+
report.fatal(&format!("{:?}", reason));
135+
report.fatal(
136+
"metadata contains errors (run thin_check for details).\n\
137+
perhaps you wanted to run with --repair ?",
138+
);
139+
}
140+
return Err(std::io::Error::from_raw_os_error(libc::EPERM));
141+
}
142+
143+
Ok(())
139144
}
140145
}

src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ pub mod checksum;
2020
pub mod commands;
2121
pub mod copier;
2222
pub mod era;
23+
pub mod error;
2324
pub mod file_utils;
2425
pub mod grid_layout;
2526
pub mod io_engine;

src/shrink/toplevel.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -543,7 +543,9 @@ fn rebuild_metadata(opts: ThinShrinkOptions) -> Result<()> {
543543
let mut w = WriteBatcher::new(output.clone(), sm, output.get_batch_size());
544544
let mut restorer = Restorer::new(&mut w, opts.report);
545545
let mut remapper = DataRemapper::new(&mut restorer, opts.nr_blocks, remaps);
546-
dump_metadata(input, &mut remapper, &sb, &md)
546+
dump_metadata(input, &mut remapper, &sb, &md)?;
547+
548+
Ok(())
547549
}
548550

549551
pub fn shrink(opts: ThinShrinkOptions) -> Result<()> {

src/thin/dump.rs

Lines changed: 33 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use std::path::Path;
66
use std::sync::{Arc, Mutex};
77

88
use crate::checksum;
9+
use crate::error::*;
910
use crate::io_engine::{AsyncIoEngine, Block, IoEngine, SyncIoEngine};
1011
use crate::pdata::btree::{self, *};
1112
use crate::pdata::btree_walker::*;
@@ -205,16 +206,17 @@ fn emit_leaf(v: &mut MappingVisitor, b: &Block) -> Result<()> {
205206
Ok(())
206207
}
207208

208-
fn read_for<T>(engine: Arc<dyn IoEngine>, blocks: &[u64], mut t: T) -> Result<()>
209+
fn read_for<T>(engine: Arc<dyn IoEngine>, blocks: &[u64], mut t: T) -> Result<(), IoError>
209210
where
210211
T: FnMut(Block) -> Result<()>,
211212
{
212213
for cs in blocks.chunks(engine.get_batch_size()) {
213214
for b in engine
214215
.read_many(cs)
215-
.map_err(|_e| anyhow!("read_many failed"))?
216+
.map_err(|_e| IoError::Input(anyhow!("read_many failed")))?
216217
{
217-
t(b.map_err(|_e| anyhow!("read of individual block failed"))?)?;
218+
let blk = b.map_err(|_e| IoError::Input(anyhow!("read of individual block failed")))?;
219+
t(blk).map_err(to_output_err)?;
218220
}
219221
}
220222

@@ -225,7 +227,7 @@ fn emit_leaves(
225227
engine: Arc<dyn IoEngine>,
226228
out: &mut dyn MetadataVisitor,
227229
leaves: &[u64],
228-
) -> Result<()> {
230+
) -> Result<(), IoError> {
229231
let mut v = MappingVisitor::new(out);
230232
let proc = |b| {
231233
emit_leaf(&mut v, &b)?;
@@ -234,14 +236,14 @@ fn emit_leaves(
234236

235237
read_for(engine, leaves, proc)?;
236238
v.end_walk()
237-
.map_err(|e| anyhow!("failed to emit leaves: {}", e))
239+
.map_err(|e| IoError::Output(anyhow!("failed to emit leaves: {}", e)))
238240
}
239241

240242
fn emit_entries(
241243
engine: Arc<dyn IoEngine>,
242244
out: &mut dyn MetadataVisitor,
243245
entries: &[Entry],
244-
) -> Result<()> {
246+
) -> Result<(), IoError> {
245247
let mut leaves = Vec::new();
246248

247249
for e in entries {
@@ -255,7 +257,7 @@ fn emit_entries(
255257
leaves.clear();
256258
}
257259
let str = format!("{}", id);
258-
out.ref_shared(&str)?;
260+
out.ref_shared(&str).map_err(to_output_err)?;
259261
}
260262
}
261263
}
@@ -272,8 +274,9 @@ pub fn dump_metadata(
272274
out: &mut dyn MetadataVisitor,
273275
sb: &Superblock,
274276
md: &Metadata,
275-
) -> Result<()> {
276-
let data_root = unpack::<SMRoot>(&sb.data_sm_root[0..])?;
277+
) -> Result<(), IoError> {
278+
let data_root =
279+
unpack::<SMRoot>(&sb.data_sm_root[0..]).map_err(|e| IoError::Input(e.into()))?;
277280
let out_sb = ir::Superblock {
278281
uuid: "".to_string(),
279282
time: sb.time,
@@ -284,12 +287,13 @@ pub fn dump_metadata(
284287
nr_data_blocks: data_root.nr_blocks,
285288
metadata_snap: None,
286289
};
287-
out.superblock_b(&out_sb)?;
290+
out.superblock_b(&out_sb).map_err(to_output_err)?;
288291

289292
for d in &md.defs {
290-
out.def_shared_b(&format!("{}", d.def_id))?;
293+
out.def_shared_b(&format!("{}", d.def_id))
294+
.map_err(to_output_err)?;
291295
emit_entries(engine.clone(), out, &d.map.entries)?;
292-
out.def_shared_e()?;
296+
out.def_shared_e().map_err(to_output_err)?;
293297
}
294298

295299
for dev in &md.devs {
@@ -300,38 +304,42 @@ pub fn dump_metadata(
300304
creation_time: dev.detail.creation_time,
301305
snap_time: dev.detail.snapshotted_time,
302306
};
303-
out.device_b(&device)?;
307+
out.device_b(&device).map_err(to_output_err)?;
304308
emit_entries(engine.clone(), out, &dev.map.entries)?;
305-
out.device_e()?;
309+
out.device_e().map_err(to_output_err)?;
306310
}
307-
out.superblock_e()?;
308-
out.eof()?;
311+
out.superblock_e().map_err(to_output_err)?;
312+
out.eof().map_err(to_output_err)?;
309313

310314
Ok(())
311315
}
312316

313317
//------------------------------------------
314318

315-
pub fn dump(opts: ThinDumpOptions) -> Result<()> {
316-
let ctx = mk_context(&opts)?;
319+
pub fn dump(opts: ThinDumpOptions) -> Result<(), IoError> {
320+
let ctx = mk_context(&opts).map_err(to_input_err)?;
317321
let sb = if opts.repair {
318322
read_or_rebuild_superblock(
319323
ctx.engine.clone(),
320324
ctx.report.clone(),
321325
SUPERBLOCK_LOCATION,
322326
&opts.overrides,
323-
)?
327+
)
324328
} else if opts.use_metadata_snap {
325-
read_superblock_snap(ctx.engine.as_ref())?
329+
read_superblock_snap(ctx.engine.as_ref())
326330
} else {
327331
read_superblock(ctx.engine.as_ref(), SUPERBLOCK_LOCATION)
328-
.and_then(|sb| sb.overrides(&opts.overrides))?
329-
};
330-
let md = build_metadata(ctx.engine.clone(), &sb)?;
331-
let md = optimise_metadata(md)?;
332+
.and_then(|sb| sb.overrides(&opts.overrides))
333+
}
334+
.map_err(to_input_err)?;
335+
336+
let md = build_metadata(ctx.engine.clone(), &sb).map_err(to_input_err)?;
337+
let md = optimise_metadata(md).map_err(to_input_err)?;
332338

333339
let writer: Box<dyn Write> = if opts.output.is_some() {
334-
Box::new(BufWriter::new(File::create(opts.output.unwrap())?))
340+
Box::new(BufWriter::new(
341+
File::create(opts.output.unwrap()).map_err(|e| IoError::Output(e.into()))?,
342+
))
335343
} else {
336344
Box::new(BufWriter::new(std::io::stdout()))
337345
};

src/thin/repair.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,9 @@ pub fn repair(opts: ThinRepairOptions) -> Result<()> {
7272
);
7373
let mut restorer = Restorer::new(&mut w, ctx.report);
7474

75-
dump_metadata(ctx.engine_in, &mut restorer, &sb, &md)
75+
dump_metadata(ctx.engine_in, &mut restorer, &sb, &md)?;
76+
77+
Ok(())
7678
}
7779

7880
//------------------------------------------

0 commit comments

Comments
 (0)