From: Dietmar Maurer <dietmar@proxmox.com>
To: pbs-devel@lists.proxmox.com
Subject: [pbs-devel] [PATCH proxmox-backup v3] tape: fix LTO locate_file for HP drives
Date: Tue, 29 Jun 2021 08:35:55 +0200 [thread overview]
Message-ID: <20210629063555.3132270-1-dietmar@proxmox.com> (raw)
Add test code to the first locate_file command, compute locate_offset.
Subsequent locate_file commands use that offset.
Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
Signed-off-by: Dietmar Maurer <dietmar@proxmox.com>
---
This is based on Dominiks patches:
[PATCH proxmox-backup v2 1/2] tape/drive: add 'set_locate_offset' to TapeDriver Trait
[PATCH proxmox-backup v2 2/2] api2/tape/restore: use file offset to compensate for some tape drives
Canges in v3:
- Do not mofify the TapeDriver Trait. Instzead, do everything inside sg_tage.rs
- Add special case for locate_file(1)
src/tape/drive/lto/sg_tape.rs | 69 +++++++++++++++++++++++++++++++----
1 file changed, 61 insertions(+), 8 deletions(-)
diff --git a/src/tape/drive/lto/sg_tape.rs b/src/tape/drive/lto/sg_tape.rs
index 25c239a2..4508f6f3 100644
--- a/src/tape/drive/lto/sg_tape.rs
+++ b/src/tape/drive/lto/sg_tape.rs
@@ -3,6 +3,7 @@ use std::fs::{File, OpenOptions};
use std::os::unix::fs::OpenOptionsExt;
use std::os::unix::io::AsRawFd;
use std::path::Path;
+use std::convert::TryFrom;
use anyhow::{bail, format_err, Error};
use endian_trait::Endian;
@@ -122,6 +123,7 @@ pub struct LtoTapeStatus {
pub struct SgTape {
file: File,
+ locate_offset: Option<i64>,
info: InquiryInfo,
encryption_key_loaded: bool,
}
@@ -145,6 +147,7 @@ impl SgTape {
file,
info,
encryption_key_loaded: false,
+ locate_offset: None,
})
}
@@ -300,26 +303,76 @@ impl SgTape {
return self.rewind();
}
- let position = position -1;
+ const SPACE_ONE_FILEMARK: &[u8] = &[0x11, 0x01, 0, 0, 1, 0];
+
+ // Special case for position 1, because LOCATE 0 does not work
+ if position == 1 {
+ self.rewind()?;
+ let mut sg_raw = SgRaw::new(&mut self.file, 16)?;
+ sg_raw.set_timeout(Self::SCSI_TAPE_DEFAULT_TIMEOUT);
+ sg_raw.do_command(SPACE_ONE_FILEMARK)
+ .map_err(|err| format_err!("locate file {} (space) failed - {}", position, err))?;
+ return 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();
+
// Note: LOCATE(16) works for LTO4 or newer
+ //
+ // It seems the LOCATE command behaves slightly different across vendors
+ // e.g. for IBM drives, LOCATE 1 moves to File #2, but
+ // for HP drives, LOCATE 1 move to File #1
+
+ let fixed_position = if let Some(locate_offset) = self.locate_offset {
+ if locate_offset < 0 {
+ position.saturating_sub((-locate_offset) as u64)
+ } else {
+ position.saturating_add(locate_offset as u64)
+ }
+ } else {
+ position
+ };
+ // always sub(1), so that it works for IBM drives without locate_offset
+ let fixed_position = fixed_position.saturating_sub(1);
+
+ let mut cmd = Vec::new();
cmd.extend(&[0x92, 0b000_01_000, 0, 0]); // LOCATE(16) filemarks
- cmd.extend(&position.to_be_bytes());
+ cmd.extend(&fixed_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)
+ // LOCATE always position at the BOT side of the filemark, so
+ // we need to move to other side of filemark
+ sg_raw.do_command(SPACE_ONE_FILEMARK)
.map_err(|err| format_err!("locate file {} (space) failed - {}", position, err))?;
+ if self.locate_offset.is_none() {
+ // check if we landed at correct position
+ let current_file = self.current_file_number()?;
+ if current_file != position {
+ let offset: i64 =
+ i64::try_from((position as i128) - (current_file as i128)).map_err(|err| {
+ format_err!(
+ "locate_file: offset between {} and {} invalid: {}",
+ position,
+ current_file,
+ err
+ )
+ })?;
+ self.locate_offset = Some(offset);
+ self.locate_file(position)?;
+ let current_file = self.current_file_number()?;
+ if current_file != position {
+ bail!("locate_file: compensating offset did not work, aborting...");
+ }
+ } else {
+ self.locate_offset = Some(0);
+ }
+ }
+
Ok(())
}
--
2.30.2
next reply other threads:[~2021-06-29 6:36 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-06-29 6:35 Dietmar Maurer [this message]
2021-06-30 7:13 ` [pbs-devel] applied: " Dietmar Maurer
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20210629063555.3132270-1-dietmar@proxmox.com \
--to=dietmar@proxmox.com \
--cc=pbs-devel@lists.proxmox.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.