[pbs-devel] [PATCH 05/11] tape: fix LEOM handling
Dietmar Maurer
dietmar at proxmox.com
Wed Apr 7 12:23:02 CEST 2021
---
src/tape/drive/lto/sg_tape.rs | 57 +++++++++++++++++++++++++++--------
src/tools/sgutils2.rs | 26 ++++++++--------
2 files changed, 57 insertions(+), 26 deletions(-)
diff --git a/src/tape/drive/lto/sg_tape.rs b/src/tape/drive/lto/sg_tape.rs
index 531acbee..fd1a067a 100644
--- a/src/tape/drive/lto/sg_tape.rs
+++ b/src/tape/drive/lto/sg_tape.rs
@@ -75,6 +75,11 @@ impl SgTape {
Ok(Self { file })
}
+ // fixme: remove - only for testing
+ pub fn file_mut(&mut self) -> &mut File {
+ &mut self.file
+ }
+
pub fn open<P: AsRef<Path>>(path: P) -> Result<SgTape, Error> {
// do not wait for media, use O_NONBLOCK
let file = OpenOptions::new()
@@ -195,9 +200,26 @@ impl SgTape {
Ok(position.logical_file_id)
}
- pub fn locate(&mut self) -> Result<(), Error> {
- // fixme: impl LOCATE
- unimplemented!();
+ // fixme: dont use - needs LTO5
+ pub fn locate_file(&mut self, position: u64) -> Result<(), Error> {
+ let mut sg_raw = SgRaw::new(&mut self.file, 16)?;
+ sg_raw.set_timeout(Self::SCSI_TAPE_DEFAULT_TIMEOUT);
+ let mut cmd = Vec::new();
+ cmd.extend(&[0x92, 0b000_01_000, 0, 0]); // LOCATE(16) filemarks
+ cmd.extend(&position.to_be_bytes());
+ cmd.extend(&[0, 0, 0, 0]);
+
+ sg_raw.do_command(&cmd)
+ .map_err(|err| format_err!("locate file {} failed - {}", position, err))?;
+
+ // move to other side of filemark
+ cmd.truncate(0);
+ cmd.extend(&[0x11, 0x01, 0, 0, 1, 0]); // SPACE(6) one filemarks
+
+ sg_raw.do_command(&cmd)
+ .map_err(|err| format_err!("locate file {} (space) failed - {}", position, err))?;
+
+ Ok(())
}
pub fn move_to_eom(&mut self) -> Result<(), Error> {
@@ -286,8 +308,15 @@ impl SgTape {
cmd.extend(&[0, 0, count as u8]); // COUNT
cmd.push(0); // control byte
- sg_raw.do_command(&cmd)
- .map_err(|err| proxmox::io_format_err!("write filemark failed - {}", err))?;
+ match sg_raw.do_command(&cmd) {
+ Ok(_) => { /* OK */ }
+ Err(ScsiError::Sense(SenseInfo { sense_key: 0, asc: 0, ascq: 2 })) => {
+ /* LEOM - ignore */
+ }
+ Err(err) => {
+ proxmox::io_bail!("write filemark failed - {}", err);
+ }
+ }
Ok(())
}
@@ -360,7 +389,7 @@ impl SgTape {
let transfer_len = data.len();
- if transfer_len > 0xFFFFFF {
+ if transfer_len > 0x800000 {
proxmox::io_bail!("write failed - data too large");
}
@@ -379,12 +408,15 @@ impl SgTape {
//println!("WRITE {:?}", cmd);
//println!("WRITE {:?}", data);
- sg_raw.do_out_command(&cmd, data)
- .map_err(|err| proxmox::io_format_err!("write failed - {}", err))?;
-
- // fixme: LEOM?
-
- Ok(false)
+ match sg_raw.do_out_command(&cmd, data) {
+ Ok(()) => { return Ok(false) }
+ Err(ScsiError::Sense(SenseInfo { sense_key: 0, asc: 0, ascq: 2 })) => {
+ return Ok(true); // LEOM
+ }
+ Err(err) => {
+ proxmox::io_bail!("write failed - {}", err);
+ }
+ }
}
fn read_block(&mut self, buffer: &mut [u8]) -> Result<BlockReadStatus, std::io::Error> {
@@ -416,7 +448,6 @@ impl SgTape {
return Ok(BlockReadStatus::EndOfStream);
}
Err(err) => {
- println!("READ ERR {:?}", err);
proxmox::io_bail!("read failed - {}", err);
}
};
diff --git a/src/tools/sgutils2.rs b/src/tools/sgutils2.rs
index 987d5738..4edfd9d9 100644
--- a/src/tools/sgutils2.rs
+++ b/src/tools/sgutils2.rs
@@ -203,17 +203,17 @@ struct InquiryPage {
#[repr(C, packed)]
#[derive(Endian, Debug)]
-struct RequestSenseFixed {
- response_code: u8,
+pub struct RequestSenseFixed {
+ pub response_code: u8,
obsolete: u8,
- flags2: u8,
- information: [u8;4],
- additional_sense_len: u8,
- command_specific_information: [u8;4],
- additional_sense_code: u8,
- additional_sense_code_qualifier: u8,
- field_replacable_unit_code: u8,
- sense_key_specific: [u8; 3],
+ pub flags2: u8,
+ pub information: [u8;4],
+ pub additional_sense_len: u8,
+ pub command_specific_information: [u8;4],
+ pub additional_sense_code: u8,
+ pub additional_sense_code_qualifier: u8,
+ pub field_replacable_unit_code: u8,
+ pub sense_key_specific: [u8; 3],
}
#[repr(C, packed)]
@@ -575,15 +575,15 @@ impl <'a, F: AsRawFd> SgRaw<'a, F> {
/// Run dataout command
///
/// Note: use alloc_page_aligned_buffer to alloc data transfer buffer
- pub fn do_out_command(&mut self, cmd: &[u8], data: &[u8]) -> Result<(), Error> {
+ pub fn do_out_command(&mut self, cmd: &[u8], data: &[u8]) -> Result<(), ScsiError> {
if !unsafe { sg_is_scsi_cdb(cmd.as_ptr(), cmd.len() as c_int) } {
- bail!("no valid SCSI command");
+ return Err(format_err!("no valid SCSI command").into());
}
let page_size = unsafe { libc::sysconf(libc::_SC_PAGESIZE) } as usize;
if ((data.as_ptr() as usize) & (page_size -1)) != 0 {
- bail!("wrong transfer buffer alignment");
+ return Err(format_err!("wrong transfer buffer alignment").into());
}
let mut ptvp = self.create_scsi_pt_obj()?;
--
2.20.1
More information about the pbs-devel
mailing list