tape: implement report_desnity
This commit is contained in:
		| @ -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) | ||||
|         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 { | ||||
|         if self.density_code >= 0x58 { // FORMAT requires LTO5 or newer) | ||||
|             cmd.extend(&[0x04, 0, 0, 0, 0, 0]); | ||||
|             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(()) | ||||
|  | ||||
							
								
								
									
										69
									
								
								src/tape/drive/lto/sg_tape/report_density.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										69
									
								
								src/tape/drive/lto/sg_tape/report_density.rs
									
									
									
									
									
										Normal 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) | ||||
| } | ||||
		Reference in New Issue
	
	Block a user