[pbs-devel] [PATCH proxmox-backup v3] tape: fix LTO locate_file for HP drives
Dietmar Maurer
dietmar at proxmox.com
Tue Jun 29 08:35:55 CEST 2021
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 at proxmox.com>
Signed-off-by: Dietmar Maurer <dietmar at 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
More information about the pbs-devel
mailing list