tape: implement report_desnity

This commit is contained in:
Dietmar Maurer 2021-04-22 13:53:26 +02:00
parent a7188b3a75
commit b9e0fcbdcd
2 changed files with 84 additions and 9 deletions

View File

@ -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(())

View File

@ -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)
}