From bbbf662d208aa44a379f122fe3b93c3a36394c79 Mon Sep 17 00:00:00 2001 From: Dietmar Maurer Date: Thu, 6 May 2021 10:51:59 +0200 Subject: [PATCH] tape: use LOCATE(16) SCSI command Turns out this works on LTO4 and newer. --- src/tape/drive/lto/mod.rs | 25 +------------------------ src/tape/drive/lto/sg_tape.rs | 26 ++++++++++++++++++++++++++ 2 files changed, 27 insertions(+), 24 deletions(-) diff --git a/src/tape/drive/lto/mod.rs b/src/tape/drive/lto/mod.rs index 3894b0346..8c319b07e 100644 --- a/src/tape/drive/lto/mod.rs +++ b/src/tape/drive/lto/mod.rs @@ -215,31 +215,8 @@ impl LtoTapeHandle { } /// Position the tape after filemark count. Count 0 means BOT. - /// - /// Note: we dont use LOCATE(10), because that needs LTO5 pub fn locate_file(&mut self, position: u64) -> Result<(), Error> { - - if position == 0 { - return self.rewind(); - } - - let current_position = self.current_file_number()?; - - if current_position == position { - // make sure we are immediated afer the filemark - self.sg_tape.space_filemarks(-1)?; - self.sg_tape.space_filemarks(1)?; - } else if current_position < position { - let diff = position - current_position; - self.sg_tape.space_filemarks(diff.try_into()?)?; - } else { - let diff = current_position - position + 1; - self.sg_tape.space_filemarks(-diff.try_into()?)?; - // move to EOT side of filemark - self.sg_tape.space_filemarks(1)?; - } - - Ok(()) + self.sg_tape.locate_file(position) } pub fn erase_media(&mut self, fast: bool) -> Result<(), Error> { diff --git a/src/tape/drive/lto/sg_tape.rs b/src/tape/drive/lto/sg_tape.rs index b07a58465..46fc09824 100644 --- a/src/tape/drive/lto/sg_tape.rs +++ b/src/tape/drive/lto/sg_tape.rs @@ -295,6 +295,32 @@ impl SgTape { Ok(()) } + pub fn locate_file(&mut self, position: u64) -> Result<(), Error> { + if position == 0 { + return 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(); + // Note: LOCATE(16) works for LTO4 or newer + cmd.extend(&[0x92, 0b000_01_000, 0, 0]); // LOCATE(16) filemarks + cmd.extend(&position.to_be_bytes()); + cmd.extend(&[0, 0, 0, 0]); + + sg_raw.do_command(&cmd) + .map_err(|err| format_err!("locate file {} failed - {}", position, err))?; + + // move to other side of filemark + cmd.truncate(0); + cmd.extend(&[0x11, 0x01, 0, 0, 1, 0]); // SPACE(6) one filemarks + + sg_raw.do_command(&cmd) + .map_err(|err| format_err!("locate file {} (space) failed - {}", position, err))?; + + Ok(()) + } + pub fn position(&mut self) -> Result { let expected_size = std::mem::size_of::();