tape: fix LEOM handling
This commit is contained in:
parent
e29f456efc
commit
d26985a600
@ -75,6 +75,11 @@ impl SgTape {
|
|||||||
Ok(Self { file })
|
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> {
|
pub fn open<P: AsRef<Path>>(path: P) -> Result<SgTape, Error> {
|
||||||
// do not wait for media, use O_NONBLOCK
|
// do not wait for media, use O_NONBLOCK
|
||||||
let file = OpenOptions::new()
|
let file = OpenOptions::new()
|
||||||
@ -195,9 +200,26 @@ impl SgTape {
|
|||||||
Ok(position.logical_file_id)
|
Ok(position.logical_file_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn locate(&mut self) -> Result<(), Error> {
|
// fixme: dont use - needs LTO5
|
||||||
// fixme: impl LOCATE
|
pub fn locate_file(&mut self, position: u64) -> Result<(), Error> {
|
||||||
unimplemented!();
|
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> {
|
pub fn move_to_eom(&mut self) -> Result<(), Error> {
|
||||||
@ -286,8 +308,15 @@ impl SgTape {
|
|||||||
cmd.extend(&[0, 0, count as u8]); // COUNT
|
cmd.extend(&[0, 0, count as u8]); // COUNT
|
||||||
cmd.push(0); // control byte
|
cmd.push(0); // control byte
|
||||||
|
|
||||||
sg_raw.do_command(&cmd)
|
match sg_raw.do_command(&cmd) {
|
||||||
.map_err(|err| proxmox::io_format_err!("write filemark failed - {}", err))?;
|
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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -360,7 +389,7 @@ impl SgTape {
|
|||||||
|
|
||||||
let transfer_len = data.len();
|
let transfer_len = data.len();
|
||||||
|
|
||||||
if transfer_len > 0xFFFFFF {
|
if transfer_len > 0x800000 {
|
||||||
proxmox::io_bail!("write failed - data too large");
|
proxmox::io_bail!("write failed - data too large");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -379,12 +408,15 @@ impl SgTape {
|
|||||||
//println!("WRITE {:?}", cmd);
|
//println!("WRITE {:?}", cmd);
|
||||||
//println!("WRITE {:?}", data);
|
//println!("WRITE {:?}", data);
|
||||||
|
|
||||||
sg_raw.do_out_command(&cmd, data)
|
match sg_raw.do_out_command(&cmd, data) {
|
||||||
.map_err(|err| proxmox::io_format_err!("write failed - {}", err))?;
|
Ok(()) => { return Ok(false) }
|
||||||
|
Err(ScsiError::Sense(SenseInfo { sense_key: 0, asc: 0, ascq: 2 })) => {
|
||||||
// fixme: LEOM?
|
return Ok(true); // LEOM
|
||||||
|
}
|
||||||
Ok(false)
|
Err(err) => {
|
||||||
|
proxmox::io_bail!("write failed - {}", err);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_block(&mut self, buffer: &mut [u8]) -> Result<BlockReadStatus, std::io::Error> {
|
fn read_block(&mut self, buffer: &mut [u8]) -> Result<BlockReadStatus, std::io::Error> {
|
||||||
@ -416,7 +448,6 @@ impl SgTape {
|
|||||||
return Ok(BlockReadStatus::EndOfStream);
|
return Ok(BlockReadStatus::EndOfStream);
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
println!("READ ERR {:?}", err);
|
|
||||||
proxmox::io_bail!("read failed - {}", err);
|
proxmox::io_bail!("read failed - {}", err);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -203,17 +203,17 @@ struct InquiryPage {
|
|||||||
|
|
||||||
#[repr(C, packed)]
|
#[repr(C, packed)]
|
||||||
#[derive(Endian, Debug)]
|
#[derive(Endian, Debug)]
|
||||||
struct RequestSenseFixed {
|
pub struct RequestSenseFixed {
|
||||||
response_code: u8,
|
pub response_code: u8,
|
||||||
obsolete: u8,
|
obsolete: u8,
|
||||||
flags2: u8,
|
pub flags2: u8,
|
||||||
information: [u8;4],
|
pub information: [u8;4],
|
||||||
additional_sense_len: u8,
|
pub additional_sense_len: u8,
|
||||||
command_specific_information: [u8;4],
|
pub command_specific_information: [u8;4],
|
||||||
additional_sense_code: u8,
|
pub additional_sense_code: u8,
|
||||||
additional_sense_code_qualifier: u8,
|
pub additional_sense_code_qualifier: u8,
|
||||||
field_replacable_unit_code: u8,
|
pub field_replacable_unit_code: u8,
|
||||||
sense_key_specific: [u8; 3],
|
pub sense_key_specific: [u8; 3],
|
||||||
}
|
}
|
||||||
|
|
||||||
#[repr(C, packed)]
|
#[repr(C, packed)]
|
||||||
@ -575,15 +575,15 @@ impl <'a, F: AsRawFd> SgRaw<'a, F> {
|
|||||||
/// Run dataout command
|
/// Run dataout command
|
||||||
///
|
///
|
||||||
/// Note: use alloc_page_aligned_buffer to alloc data transfer buffer
|
/// 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) } {
|
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;
|
let page_size = unsafe { libc::sysconf(libc::_SC_PAGESIZE) } as usize;
|
||||||
if ((data.as_ptr() as usize) & (page_size -1)) != 0 {
|
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()?;
|
let mut ptvp = self.create_scsi_pt_obj()?;
|
||||||
|
Loading…
Reference in New Issue
Block a user