tape: improve EOT error handling
This commit is contained in:
@ -43,6 +43,7 @@ use crate::{
|
||||
tape::{
|
||||
TapeRead,
|
||||
TapeWrite,
|
||||
BlockReadError,
|
||||
drive::{
|
||||
TapeDriver,
|
||||
},
|
||||
@ -320,16 +321,9 @@ impl TapeDriver for LtoTapeHandle {
|
||||
self.sg_tape.format_media(fast)
|
||||
}
|
||||
|
||||
fn read_next_file<'a>(&'a mut self) -> Result<Option<Box<dyn TapeRead + 'a>>, std::io::Error> {
|
||||
fn read_next_file<'a>(&'a mut self) -> Result<Box<dyn TapeRead + 'a>, BlockReadError> {
|
||||
let reader = self.sg_tape.open_reader()?;
|
||||
let handle = match reader {
|
||||
Some(reader) => {
|
||||
let reader: Box<dyn TapeRead> = Box::new(reader);
|
||||
Some(reader)
|
||||
}
|
||||
None => None,
|
||||
};
|
||||
|
||||
let handle: Box<dyn TapeRead> = Box::new(reader);
|
||||
Ok(handle)
|
||||
}
|
||||
|
||||
|
@ -32,7 +32,7 @@ use crate::{
|
||||
},
|
||||
tape::{
|
||||
BlockRead,
|
||||
BlockReadStatus,
|
||||
BlockReadError,
|
||||
BlockWrite,
|
||||
file_formats::{
|
||||
BlockedWriter,
|
||||
@ -526,11 +526,13 @@ impl SgTape {
|
||||
}
|
||||
}
|
||||
|
||||
fn read_block(&mut self, buffer: &mut [u8]) -> Result<BlockReadStatus, std::io::Error> {
|
||||
fn read_block(&mut self, buffer: &mut [u8]) -> Result<usize, BlockReadError> {
|
||||
let transfer_len = buffer.len();
|
||||
|
||||
if transfer_len > 0xFFFFFF {
|
||||
proxmox::io_bail!("read failed - buffer too large");
|
||||
return Err(BlockReadError::Error(
|
||||
proxmox::io_format_err!("read failed - buffer too large")
|
||||
));
|
||||
}
|
||||
|
||||
let mut sg_raw = SgRaw::new(&mut self.file, 0)
|
||||
@ -549,21 +551,25 @@ impl SgTape {
|
||||
let data = match sg_raw.do_in_command(&cmd, buffer) {
|
||||
Ok(data) => data,
|
||||
Err(ScsiError::Sense(SenseInfo { sense_key: 0, asc: 0, ascq: 1 })) => {
|
||||
return Ok(BlockReadStatus::EndOfFile);
|
||||
return Err(BlockReadError::EndOfFile);
|
||||
}
|
||||
Err(ScsiError::Sense(SenseInfo { sense_key: 8, asc: 0, ascq: 5 })) => {
|
||||
return Ok(BlockReadStatus::EndOfStream);
|
||||
return Err(BlockReadError::EndOfStream);
|
||||
}
|
||||
Err(err) => {
|
||||
proxmox::io_bail!("read failed - {}", err);
|
||||
return Err(BlockReadError::Error(
|
||||
proxmox::io_format_err!("read failed - {}", err)
|
||||
));
|
||||
}
|
||||
};
|
||||
|
||||
if data.len() != transfer_len {
|
||||
proxmox::io_bail!("read failed - unexpected block len ({} != {})", data.len(), buffer.len())
|
||||
return Err(BlockReadError::Error(
|
||||
proxmox::io_format_err!("read failed - unexpected block len ({} != {})", data.len(), buffer.len())
|
||||
));
|
||||
}
|
||||
|
||||
Ok(BlockReadStatus::Ok(transfer_len))
|
||||
Ok(transfer_len)
|
||||
}
|
||||
|
||||
pub fn open_writer(&mut self) -> BlockedWriter<SgTapeWriter> {
|
||||
@ -571,12 +577,9 @@ impl SgTape {
|
||||
BlockedWriter::new(writer)
|
||||
}
|
||||
|
||||
pub fn open_reader(&mut self) -> Result<Option<BlockedReader<SgTapeReader>>, std::io::Error> {
|
||||
pub fn open_reader(&mut self) -> Result<BlockedReader<SgTapeReader>, BlockReadError> {
|
||||
let reader = SgTapeReader::new(self);
|
||||
match BlockedReader::open(reader)? {
|
||||
Some(reader) => Ok(Some(reader)),
|
||||
None => Ok(None),
|
||||
}
|
||||
BlockedReader::open(reader)
|
||||
}
|
||||
|
||||
/// Set important drive options
|
||||
@ -702,7 +705,7 @@ impl <'a> SgTapeReader<'a> {
|
||||
|
||||
impl <'a> BlockRead for SgTapeReader<'a> {
|
||||
|
||||
fn read_block(&mut self, buffer: &mut [u8]) -> Result<BlockReadStatus, std::io::Error> {
|
||||
fn read_block(&mut self, buffer: &mut [u8]) -> Result<usize, BlockReadError> {
|
||||
self.sg_tape.read_block(buffer)
|
||||
}
|
||||
}
|
||||
|
@ -44,6 +44,7 @@ use crate::{
|
||||
tape::{
|
||||
TapeWrite,
|
||||
TapeRead,
|
||||
BlockReadError,
|
||||
MediaId,
|
||||
drive::lto::TapeAlertFlags,
|
||||
file_formats::{
|
||||
@ -86,7 +87,7 @@ pub trait TapeDriver {
|
||||
fn format_media(&mut self, fast: bool) -> Result<(), Error>;
|
||||
|
||||
/// Read/Open the next file
|
||||
fn read_next_file<'a>(&'a mut self) -> Result<Option<Box<dyn TapeRead + 'a>>, std::io::Error>;
|
||||
fn read_next_file<'a>(&'a mut self) -> Result<Box<dyn TapeRead + 'a>, BlockReadError>;
|
||||
|
||||
/// Write/Append a new file
|
||||
fn write_file<'a>(&'a mut self) -> Result<Box<dyn TapeWrite + 'a>, std::io::Error>;
|
||||
@ -132,9 +133,17 @@ pub trait TapeDriver {
|
||||
self.rewind()?;
|
||||
|
||||
let label = {
|
||||
let mut reader = match self.read_next_file()? {
|
||||
None => return Ok((None, None)), // tape is empty
|
||||
Some(reader) => reader,
|
||||
let mut reader = match self.read_next_file() {
|
||||
Err(BlockReadError::EndOfStream) => {
|
||||
return Ok((None, None)); // tape is empty
|
||||
}
|
||||
Err(BlockReadError::EndOfFile) => {
|
||||
bail!("got unexpected filemark at BOT");
|
||||
}
|
||||
Err(BlockReadError::Error(err)) => {
|
||||
return Err(err.into());
|
||||
}
|
||||
Ok(reader) => reader,
|
||||
};
|
||||
|
||||
let header: MediaContentHeader = unsafe { reader.read_le_value()? };
|
||||
@ -155,9 +164,17 @@ pub trait TapeDriver {
|
||||
let mut media_id = MediaId { label, media_set_label: None };
|
||||
|
||||
// try to read MediaSet label
|
||||
let mut reader = match self.read_next_file()? {
|
||||
None => return Ok((Some(media_id), None)),
|
||||
Some(reader) => reader,
|
||||
let mut reader = match self.read_next_file() {
|
||||
Err(BlockReadError::EndOfStream) => {
|
||||
return Ok((Some(media_id), None));
|
||||
}
|
||||
Err(BlockReadError::EndOfFile) => {
|
||||
bail!("got unexpected filemark after label");
|
||||
}
|
||||
Err(BlockReadError::Error(err)) => {
|
||||
return Err(err.into());
|
||||
}
|
||||
Ok(reader) => reader,
|
||||
};
|
||||
|
||||
let header: MediaContentHeader = unsafe { reader.read_le_value()? };
|
||||
|
@ -15,6 +15,7 @@ use crate::{
|
||||
tape::{
|
||||
TapeWrite,
|
||||
TapeRead,
|
||||
BlockReadError,
|
||||
changer::{
|
||||
MediaChange,
|
||||
MtxStatus,
|
||||
@ -261,18 +262,18 @@ impl TapeDriver for VirtualTapeHandle {
|
||||
}
|
||||
|
||||
|
||||
fn read_next_file(&mut self) -> Result<Option<Box<dyn TapeRead>>, io::Error> {
|
||||
fn read_next_file(&mut self) -> Result<Box<dyn TapeRead>, BlockReadError> {
|
||||
let mut status = self.load_status()
|
||||
.map_err(|err| io::Error::new(io::ErrorKind::Other, err.to_string()))?;
|
||||
.map_err(|err| BlockReadError::Error(io::Error::new(io::ErrorKind::Other, err.to_string())))?;
|
||||
|
||||
match status.current_tape {
|
||||
Some(VirtualTapeStatus { ref name, ref mut pos }) => {
|
||||
|
||||
let index = self.load_tape_index(name)
|
||||
.map_err(|err| io::Error::new(io::ErrorKind::Other, err.to_string()))?;
|
||||
.map_err(|err| BlockReadError::Error(io::Error::new(io::ErrorKind::Other, err.to_string())))?;
|
||||
|
||||
if *pos >= index.files {
|
||||
return Ok(None); // EOM
|
||||
return Err(BlockReadError::EndOfStream);
|
||||
}
|
||||
|
||||
let path = self.tape_file_path(name, *pos);
|
||||
@ -282,16 +283,15 @@ impl TapeDriver for VirtualTapeHandle {
|
||||
|
||||
*pos += 1;
|
||||
self.store_status(&status)
|
||||
.map_err(|err| io::Error::new(io::ErrorKind::Other, err.to_string()))?;
|
||||
.map_err(|err| BlockReadError::Error(io::Error::new(io::ErrorKind::Other, err.to_string())))?;
|
||||
|
||||
let reader = EmulateTapeReader::new(file);
|
||||
|
||||
match BlockedReader::open(reader)? {
|
||||
Some(reader) => Ok(Some(Box::new(reader))),
|
||||
None => Ok(None),
|
||||
}
|
||||
let reader = BlockedReader::open(reader)?;
|
||||
Ok(Box::new(reader))
|
||||
}
|
||||
None => {
|
||||
return Err(BlockReadError::Error(proxmox::io_format_err!("drive is empty (no tape loaded).")));
|
||||
}
|
||||
None => proxmox::io_bail!("drive is empty (no tape loaded)."),
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user