tape: make sure there is a filemark at the end of the tape
This commit is contained in:
parent
8b2c6f5dbc
commit
7b11a8098d
@ -383,7 +383,7 @@ fn eject(param: Value) -> Result<(), Error> {
|
|||||||
fn eod(param: Value) -> Result<(), Error> {
|
fn eod(param: Value) -> Result<(), Error> {
|
||||||
|
|
||||||
let mut handle = get_tape_handle(¶m)?;
|
let mut handle = get_tape_handle(¶m)?;
|
||||||
handle.move_to_eom()?;
|
handle.move_to_eom(false)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -551,7 +551,7 @@ fn move_to_eom(mut param: Value) -> Result<(), Error> {
|
|||||||
|
|
||||||
let mut drive = open_drive(&config, &drive)?;
|
let mut drive = open_drive(&config, &drive)?;
|
||||||
|
|
||||||
drive.move_to_eom()?;
|
drive.move_to_eom(false)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -215,13 +215,15 @@ impl TapeDriver for LtoTapeHandle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Go to the end of the recorded media (for appending files).
|
/// Go to the end of the recorded media (for appending files).
|
||||||
fn move_to_eom(&mut self) -> Result<(), Error> {
|
fn move_to_eom(&mut self, write_missing_eof: bool) -> Result<(), Error> {
|
||||||
self.sg_tape.move_to_eom()
|
self.sg_tape.move_to_eom(write_missing_eof)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn move_to_last_file(&mut self) -> Result<(), Error> {
|
fn move_to_last_file(&mut self) -> Result<(), Error> {
|
||||||
|
|
||||||
self.move_to_eom()?;
|
self.move_to_eom(false)?;
|
||||||
|
|
||||||
|
self.sg_tape.check_filemark()?;
|
||||||
|
|
||||||
let pos = self.current_file_number()?;
|
let pos = self.current_file_number()?;
|
||||||
|
|
||||||
|
@ -190,8 +190,6 @@ impl SgTape {
|
|||||||
bail!("detecthed partitioned tape - not supported");
|
bail!("detecthed partitioned tape - not supported");
|
||||||
}
|
}
|
||||||
|
|
||||||
println!("DATA: {:?}", page);
|
|
||||||
|
|
||||||
Ok(page)
|
Ok(page)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -222,7 +220,35 @@ impl SgTape {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn move_to_eom(&mut self) -> Result<(), Error> {
|
/// Check if we are positioned after a filemark (or BOT)
|
||||||
|
pub fn check_filemark(&mut self) -> Result<bool, Error> {
|
||||||
|
|
||||||
|
let pos = self.position()?;
|
||||||
|
if pos.logical_object_number == 0 {
|
||||||
|
// at BOT, Ok (no filemark required)
|
||||||
|
return Ok(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Note: SPACE blocks returns Err at filemark
|
||||||
|
match self.space(-1, true) {
|
||||||
|
Ok(_) => {
|
||||||
|
self.space(1, true) // move back to end
|
||||||
|
.map_err(|err| format_err!("check_filemark failed (space forward) - {}", err))?;
|
||||||
|
Ok(false)
|
||||||
|
}
|
||||||
|
Err(ScsiError::Sense(SenseInfo { sense_key: 0, asc: 0, ascq: 1 })) => {
|
||||||
|
// Filemark detected - good
|
||||||
|
self.space(1, false) // move to EOT side of filemark
|
||||||
|
.map_err(|err| format_err!("check_filemark failed (move to EOT side of filemark) - {}", err))?;
|
||||||
|
Ok(true)
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
bail!("check_filemark failed - {:?}", err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn move_to_eom(&mut self, write_missing_eof: bool) -> Result<(), Error> {
|
||||||
let mut sg_raw = SgRaw::new(&mut self.file, 16)?;
|
let mut sg_raw = SgRaw::new(&mut self.file, 16)?;
|
||||||
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();
|
||||||
@ -231,35 +257,60 @@ impl SgTape {
|
|||||||
sg_raw.do_command(&cmd)
|
sg_raw.do_command(&cmd)
|
||||||
.map_err(|err| format_err!("move to EOD failed - {}", err))?;
|
.map_err(|err| format_err!("move to EOD failed - {}", err))?;
|
||||||
|
|
||||||
|
if write_missing_eof {
|
||||||
|
if !self.check_filemark()? {
|
||||||
|
self.write_filemarks(1, false)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn space_filemarks(&mut self, count: isize) -> Result<(), Error> {
|
fn space(&mut self, count: isize, blocks: bool) -> Result<(), ScsiError> {
|
||||||
let mut sg_raw = SgRaw::new(&mut self.file, 16)?;
|
let mut sg_raw = SgRaw::new(&mut self.file, 16)?;
|
||||||
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();
|
||||||
|
|
||||||
// Use short command if possible (supported by all drives)
|
// Use short command if possible (supported by all drives)
|
||||||
if (count <= 0x7fffff) && (count > -0x7fffff) {
|
if (count <= 0x7fffff) && (count > -0x7fffff) {
|
||||||
cmd.extend(&[0x11, 0x01]); // SPACE(6) with filemarks
|
cmd.push(0x11); // SPACE(6)
|
||||||
|
if blocks {
|
||||||
|
cmd.push(0); // blocks
|
||||||
|
} else {
|
||||||
|
cmd.push(1); // filemarks
|
||||||
|
}
|
||||||
cmd.push(((count >> 16) & 0xff) as u8);
|
cmd.push(((count >> 16) & 0xff) as u8);
|
||||||
cmd.push(((count >> 8) & 0xff) as u8);
|
cmd.push(((count >> 8) & 0xff) as u8);
|
||||||
cmd.push((count & 0xff) as u8);
|
cmd.push((count & 0xff) as u8);
|
||||||
cmd.push(0); //control byte
|
cmd.push(0); //control byte
|
||||||
} else {
|
} else {
|
||||||
|
cmd.push(0x91); // SPACE(16)
|
||||||
cmd.extend(&[0x91, 0x01, 0, 0]); // SPACE(16) with filemarks
|
if blocks {
|
||||||
|
cmd.push(0); // blocks
|
||||||
|
} else {
|
||||||
|
cmd.push(1); // filemarks
|
||||||
|
}
|
||||||
|
cmd.extend(&[0, 0]); // reserved
|
||||||
let count: i64 = count as i64;
|
let count: i64 = count as i64;
|
||||||
cmd.extend(&count.to_be_bytes());
|
cmd.extend(&count.to_be_bytes());
|
||||||
cmd.extend(&[0, 0, 0, 0]);
|
cmd.extend(&[0, 0, 0, 0]); // reserved
|
||||||
}
|
}
|
||||||
|
|
||||||
sg_raw.do_command(&cmd)
|
sg_raw.do_command(&cmd)?;
|
||||||
.map_err(|err| format_err!("space filemarks failed - {}", err))?;
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn space_filemarks(&mut self, count: isize) -> Result<(), Error> {
|
||||||
|
self.space(count, false)
|
||||||
|
.map_err(|err| format_err!("space filemarks failed - {}", err))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn space_blocks(&mut self, count: isize) -> Result<(), Error> {
|
||||||
|
self.space(count, true)
|
||||||
|
.map_err(|err| format_err!("space blocks failed - {}", err))
|
||||||
|
}
|
||||||
|
|
||||||
pub fn eject(&mut self) -> Result<(), Error> {
|
pub fn eject(&mut self) -> Result<(), Error> {
|
||||||
let mut sg_raw = SgRaw::new(&mut self.file, 16)?;
|
let mut sg_raw = SgRaw::new(&mut self.file, 16)?;
|
||||||
sg_raw.set_timeout(Self::SCSI_TAPE_DEFAULT_TIMEOUT);
|
sg_raw.set_timeout(Self::SCSI_TAPE_DEFAULT_TIMEOUT);
|
||||||
|
@ -84,8 +84,10 @@ pub trait TapeDriver {
|
|||||||
|
|
||||||
/// Move to end of recorded data
|
/// Move to end of recorded data
|
||||||
///
|
///
|
||||||
/// We assume this flushes the tape write buffer.
|
/// We assume this flushes the tape write buffer. if
|
||||||
fn move_to_eom(&mut self) -> Result<(), Error>;
|
/// write_missing_eof is true, we verify that there is a filemark
|
||||||
|
/// at the end. If not, we write one.
|
||||||
|
fn move_to_eom(&mut self, write_missing_eof: bool) -> Result<(), Error>;
|
||||||
|
|
||||||
/// Move to last file
|
/// Move to last file
|
||||||
fn move_to_last_file(&mut self) -> Result<(), Error>;
|
fn move_to_last_file(&mut self) -> Result<(), Error>;
|
||||||
|
@ -249,7 +249,7 @@ impl TapeDriver for VirtualTapeHandle {
|
|||||||
/// Move to last file
|
/// Move to last file
|
||||||
fn move_to_last_file(&mut self) -> Result<(), Error> {
|
fn move_to_last_file(&mut self) -> Result<(), Error> {
|
||||||
|
|
||||||
self.move_to_eom()?;
|
self.move_to_eom(false)?;
|
||||||
|
|
||||||
if self.current_file_number()? == 0 {
|
if self.current_file_number()? == 0 {
|
||||||
bail!("move_to_last_file failed - media contains no data");
|
bail!("move_to_last_file failed - media contains no data");
|
||||||
@ -347,7 +347,7 @@ impl TapeDriver for VirtualTapeHandle {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn move_to_eom(&mut self) -> Result<(), Error> {
|
fn move_to_eom(&mut self, _write_missing_eof: bool) -> Result<(), Error> {
|
||||||
let mut status = self.load_status()?;
|
let mut status = self.load_status()?;
|
||||||
match status.current_tape {
|
match status.current_tape {
|
||||||
Some(VirtualTapeStatus { ref name, ref mut pos }) => {
|
Some(VirtualTapeStatus { ref name, ref mut pos }) => {
|
||||||
|
@ -297,7 +297,7 @@ impl PoolWriter {
|
|||||||
|
|
||||||
if !status.at_eom {
|
if !status.at_eom {
|
||||||
worker.log(String::from("moving to end of media"));
|
worker.log(String::from("moving to end of media"));
|
||||||
status.drive.move_to_eom()?;
|
status.drive.move_to_eom(true)?;
|
||||||
status.at_eom = true;
|
status.at_eom = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user