tape: implement report_desnity
This commit is contained in:
parent
a7188b3a75
commit
b9e0fcbdcd
|
@ -20,6 +20,9 @@ pub use tape_alert_flags::*;
|
||||||
mod mam;
|
mod mam;
|
||||||
pub use mam::*;
|
pub use mam::*;
|
||||||
|
|
||||||
|
mod report_density;
|
||||||
|
pub use report_density::*;
|
||||||
|
|
||||||
use proxmox::{
|
use proxmox::{
|
||||||
sys::error::SysResult,
|
sys::error::SysResult,
|
||||||
tools::io::{ReadExt, WriteExt},
|
tools::io::{ReadExt, WriteExt},
|
||||||
|
@ -103,6 +106,7 @@ pub struct LtoTapeStatus {
|
||||||
pub struct SgTape {
|
pub struct SgTape {
|
||||||
file: File,
|
file: File,
|
||||||
info: InquiryInfo,
|
info: InquiryInfo,
|
||||||
|
density_code: u8, // drive type
|
||||||
encryption_key_loaded: bool,
|
encryption_key_loaded: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -120,9 +124,13 @@ impl SgTape {
|
||||||
if info.peripheral_type != 1 {
|
if info.peripheral_type != 1 {
|
||||||
bail!("not a tape device (peripheral_type = {})", info.peripheral_type);
|
bail!("not a tape device (peripheral_type = {})", info.peripheral_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let density_code = report_density(&mut file)?;
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
file,
|
file,
|
||||||
info,
|
info,
|
||||||
|
density_code,
|
||||||
encryption_key_loaded: false,
|
encryption_key_loaded: false,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -194,18 +202,16 @@ impl SgTape {
|
||||||
sg_raw.set_timeout(Self::SCSI_TAPE_DEFAULT_TIMEOUT);
|
sg_raw.set_timeout(Self::SCSI_TAPE_DEFAULT_TIMEOUT);
|
||||||
let mut cmd = Vec::new();
|
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]);
|
cmd.extend(&[0x04, 0, 0, 0, 0, 0]);
|
||||||
|
sg_raw.do_command(&cmd)?;
|
||||||
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 {
|
|
||||||
if !fast {
|
if !fast {
|
||||||
self.erase_media(false)?; // overwrite everything
|
self.erase_media(false)?; // overwrite everything
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
// try rewind/erase instead
|
||||||
|
self.rewind()?;
|
||||||
|
self.erase_media(fast)?
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
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