tape: add read_medium_configuration_page() to detect WORM media
And use it inside format_media().
This commit is contained in:
parent
8369ade880
commit
5e169f387c
@ -94,6 +94,23 @@ impl DataCompressionModePage {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[repr(C, packed)]
|
||||||
|
#[derive(Endian)]
|
||||||
|
struct MediumConfigurationModePage {
|
||||||
|
page_code: u8, // 0x1d
|
||||||
|
page_length: u8, // 0x1e
|
||||||
|
flags2: u8,
|
||||||
|
reserved: [u8;29],
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MediumConfigurationModePage {
|
||||||
|
|
||||||
|
pub fn is_worm(&self) -> bool {
|
||||||
|
(self.flags2 & 1) == 1
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct LtoTapeStatus {
|
pub struct LtoTapeStatus {
|
||||||
pub block_length: u32,
|
pub block_length: u32,
|
||||||
@ -199,11 +216,21 @@ impl SgTape {
|
|||||||
/// Format media, single partition
|
/// Format media, single partition
|
||||||
pub fn format_media(&mut self, fast: bool) -> Result<(), Error> {
|
pub fn format_media(&mut self, fast: bool) -> Result<(), Error> {
|
||||||
|
|
||||||
// get info about loaded media first
|
// try to get info about loaded media first
|
||||||
let (_head, block_descriptor, _) = self.read_compression_page()?;
|
let (has_format, is_worm) = match self.read_medium_configuration_page() {
|
||||||
|
Ok((_head, block_descriptor, page)) => {
|
||||||
|
// FORMAT requires LTO5 or newer
|
||||||
|
let has_format = block_descriptor.density_code >= 0x58;
|
||||||
|
let is_worm = page.is_worm();
|
||||||
|
(has_format, is_worm)
|
||||||
|
}
|
||||||
|
Err(_) => {
|
||||||
|
// LTO3 and older do not supprt medium configuration mode page
|
||||||
|
(false, false)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/* todo: howto detect WORM media?
|
if is_worm {
|
||||||
if MediumType::is_worm(xx) {
|
|
||||||
// We cannot FORMAT WORM media! Instead we check if its empty.
|
// We cannot FORMAT WORM media! Instead we check if its empty.
|
||||||
|
|
||||||
self.move_to_eom(false)?;
|
self.move_to_eom(false)?;
|
||||||
@ -212,28 +239,28 @@ impl SgTape {
|
|||||||
bail!("format failed - detected WORM media with data.");
|
bail!("format failed - detected WORM media with data.");
|
||||||
}
|
}
|
||||||
|
|
||||||
return Ok(());
|
Ok(())
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
self.rewind()?;
|
|
||||||
|
|
||||||
let mut sg_raw = SgRaw::new(&mut self.file, 16)?;
|
|
||||||
sg_raw.set_timeout(Self::SCSI_TAPE_DEFAULT_TIMEOUT);
|
|
||||||
let mut cmd = Vec::new();
|
|
||||||
|
|
||||||
if block_descriptor.density_code >= 0x58 { // FORMAT requires LTO5 or newer
|
|
||||||
cmd.extend(&[0x04, 0, 0, 0, 0, 0]); // FORMAT
|
|
||||||
sg_raw.do_command(&cmd)?;
|
|
||||||
if !fast {
|
|
||||||
self.erase_media(false)?; // overwrite everything
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// try rewind/erase instead
|
self.rewind()?;
|
||||||
self.erase_media(fast)?
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
let mut sg_raw = SgRaw::new(&mut self.file, 16)?;
|
||||||
|
sg_raw.set_timeout(Self::SCSI_TAPE_DEFAULT_TIMEOUT);
|
||||||
|
let mut cmd = Vec::new();
|
||||||
|
|
||||||
|
if has_format {
|
||||||
|
cmd.extend(&[0x04, 0, 0, 0, 0, 0]); // FORMAT
|
||||||
|
sg_raw.do_command(&cmd)?;
|
||||||
|
if !fast {
|
||||||
|
self.erase_media(false)?; // overwrite everything
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// try rewind/erase instead
|
||||||
|
self.erase_media(fast)?
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Lock/Unlock drive door
|
/// Lock/Unlock drive door
|
||||||
@ -668,6 +695,30 @@ impl SgTape {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn read_medium_configuration_page(
|
||||||
|
&mut self,
|
||||||
|
) -> Result<(ModeParameterHeader, ModeBlockDescriptor, MediumConfigurationModePage), Error> {
|
||||||
|
|
||||||
|
let (head, block_descriptor, page): (_,_, MediumConfigurationModePage)
|
||||||
|
= scsi_mode_sense(&mut self.file, false, 0x1d, 0)?;
|
||||||
|
|
||||||
|
proxmox::try_block!({
|
||||||
|
if (page.page_code & 0b0011_1111) != 0x1d {
|
||||||
|
bail!("wrong page code {}", page.page_code);
|
||||||
|
}
|
||||||
|
if page.page_length != 0x1e {
|
||||||
|
bail!("wrong page length {}", page.page_length);
|
||||||
|
}
|
||||||
|
|
||||||
|
let block_descriptor = match block_descriptor {
|
||||||
|
Some(block_descriptor) => block_descriptor,
|
||||||
|
None => bail!("missing block descriptor"),
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok((head, block_descriptor, page))
|
||||||
|
}).map_err(|err| format_err!("read_medium_configuration failed - {}", err))
|
||||||
|
}
|
||||||
|
|
||||||
fn read_compression_page(
|
fn read_compression_page(
|
||||||
&mut self,
|
&mut self,
|
||||||
) -> Result<(ModeParameterHeader, ModeBlockDescriptor, DataCompressionModePage), Error> {
|
) -> Result<(ModeParameterHeader, ModeBlockDescriptor, DataCompressionModePage), Error> {
|
||||||
@ -675,16 +726,21 @@ impl SgTape {
|
|||||||
let (head, block_descriptor, page): (_,_, DataCompressionModePage)
|
let (head, block_descriptor, page): (_,_, DataCompressionModePage)
|
||||||
= scsi_mode_sense(&mut self.file, false, 0x0f, 0)?;
|
= scsi_mode_sense(&mut self.file, false, 0x0f, 0)?;
|
||||||
|
|
||||||
if !(page.page_code == 0x0f && page.page_length == 0x0e) {
|
proxmox::try_block!({
|
||||||
bail!("read_compression_page: got strange page code/length");
|
if (page.page_code & 0b0011_1111) != 0x0f {
|
||||||
}
|
bail!("wrong page code {}", page.page_code);
|
||||||
|
}
|
||||||
|
if page.page_length != 0x0e {
|
||||||
|
bail!("wrong page length {}", page.page_length);
|
||||||
|
}
|
||||||
|
|
||||||
let block_descriptor = match block_descriptor {
|
let block_descriptor = match block_descriptor {
|
||||||
Some(block_descriptor) => block_descriptor,
|
Some(block_descriptor) => block_descriptor,
|
||||||
None => bail!("read_compression_page failed: missing block descriptor"),
|
None => bail!("missing block descriptor"),
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok((head, block_descriptor, page))
|
Ok((head, block_descriptor, page))
|
||||||
|
}).map_err(|err| format_err!("read_compression_page failed: {}", err))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Read drive options/status
|
/// Read drive options/status
|
||||||
|
Loading…
Reference in New Issue
Block a user