tape: implement report_desnity
This commit is contained in:
parent
a7188b3a75
commit
b9e0fcbdcd
|
@ -20,6 +20,9 @@ pub use tape_alert_flags::*;
|
|||
mod mam;
|
||||
pub use mam::*;
|
||||
|
||||
mod report_density;
|
||||
pub use report_density::*;
|
||||
|
||||
use proxmox::{
|
||||
sys::error::SysResult,
|
||||
tools::io::{ReadExt, WriteExt},
|
||||
|
@ -103,6 +106,7 @@ pub struct LtoTapeStatus {
|
|||
pub struct SgTape {
|
||||
file: File,
|
||||
info: InquiryInfo,
|
||||
density_code: u8, // drive type
|
||||
encryption_key_loaded: bool,
|
||||
}
|
||||
|
||||
|
@ -120,9 +124,13 @@ impl SgTape {
|
|||
if info.peripheral_type != 1 {
|
||||
bail!("not a tape device (peripheral_type = {})", info.peripheral_type);
|
||||
}
|
||||
|
||||
let density_code = report_density(&mut file)?;
|
||||
|
||||
Ok(Self {
|
||||
file,
|
||||
info,
|
||||
density_code,
|
||||
encryption_key_loaded: false,
|
||||
})
|
||||
}
|
||||
|
@ -194,18 +202,16 @@ impl SgTape {
|
|||
sg_raw.set_timeout(Self::SCSI_TAPE_DEFAULT_TIMEOUT);
|
||||
let mut cmd = Vec::new();
|
||||
|
||||
// Try FORMAT first (requires LTO5 or newer)
|
||||
if self.density_code >= 0x58 { // FORMAT requires LTO5 or newer)
|
||||
cmd.extend(&[0x04, 0, 0, 0, 0, 0]);
|
||||
|
||||
if let Err(err) = sg_raw.do_command(&cmd) {
|
||||
eprintln!("format failed - using erase insead: {}", err);
|
||||
// try rewind/erase instead
|
||||
self.rewind()?;
|
||||
self.erase_media(fast)?
|
||||
} else {
|
||||
sg_raw.do_command(&cmd)?;
|
||||
if !fast {
|
||||
self.erase_media(false)?; // overwrite everything
|
||||
}
|
||||
} else {
|
||||
// try rewind/erase instead
|
||||
self.rewind()?;
|
||||
self.erase_media(fast)?
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
|
|
@ -0,0 +1,69 @@
|
|||
use anyhow::{bail, format_err, Error};
|
||||
use std::io::Read;
|
||||
use endian_trait::Endian;
|
||||
use std::os::unix::io::AsRawFd;
|
||||
|
||||
use proxmox::tools::io::ReadExt;
|
||||
|
||||
use crate::tools::sgutils2::SgRaw;
|
||||
|
||||
#[repr(C, packed)]
|
||||
#[derive(Endian)]
|
||||
struct DesnityDescriptorBlock {
|
||||
primary_density_code: u8,
|
||||
secondary_density_code: u8,
|
||||
flags2: u8,
|
||||
reserved: [u8; 2],
|
||||
bits_per_mm: [u8; 3],
|
||||
media_width: u16,
|
||||
tracks: u16,
|
||||
capacity: u32,
|
||||
organizazion: [u8; 8],
|
||||
density_name: [u8; 8],
|
||||
description: [u8; 20],
|
||||
}
|
||||
|
||||
// Returns the maximum supported drive density code
|
||||
pub fn report_density<F: AsRawFd>(file: &mut F) -> Result<u8, Error> {
|
||||
let alloc_len: u16 = 8192;
|
||||
let mut sg_raw = SgRaw::new(file, alloc_len as usize)?;
|
||||
|
||||
let mut cmd = Vec::new();
|
||||
cmd.extend(&[0x44, 0, 0, 0, 0, 0, 0]); // REPORT DENSITY SUPPORT (MEDIA=0)
|
||||
cmd.extend(&alloc_len.to_be_bytes()); // alloc len
|
||||
cmd.push(0u8); // control byte
|
||||
|
||||
let data = sg_raw.do_command(&cmd)
|
||||
.map_err(|err| format_err!("report density failed - {}", err))?;
|
||||
|
||||
let mut max_density = 0u8;
|
||||
|
||||
proxmox::try_block!({
|
||||
let mut reader = &data[..];
|
||||
|
||||
let page_len: u16 = unsafe { reader.read_be_value()? };
|
||||
let page_len = page_len as usize;
|
||||
|
||||
if (page_len + 2) > data.len() {
|
||||
bail!("invalid page length {} {}", page_len + 2, data.len());
|
||||
} else {
|
||||
// Note: Quantum hh7 returns the allocation_length instead of real data_len
|
||||
reader = &data[2..page_len+2];
|
||||
}
|
||||
let mut reserved = [0u8; 2];
|
||||
reader.read_exact(&mut reserved)?;
|
||||
|
||||
loop {
|
||||
if reader.is_empty() { break; }
|
||||
let block: DesnityDescriptorBlock = unsafe { reader.read_be_value()? };
|
||||
if block.primary_density_code > max_density {
|
||||
max_density = block.primary_density_code;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
||||
}).map_err(|err| format_err!("decode report density failed - {}", err))?;
|
||||
|
||||
Ok(max_density)
|
||||
}
|
Loading…
Reference in New Issue