From mboxrd@z Thu Jan  1 00:00:00 1970
Return-Path: <d.csapak@proxmox.com>
Received: from firstgate.proxmox.com (firstgate.proxmox.com [212.224.123.68])
 (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
 key-exchange X25519 server-signature RSA-PSS (2048 bits))
 (No client certificate requested)
 by lists.proxmox.com (Postfix) with ESMTPS id B9BA5742CD
 for <pbs-devel@lists.proxmox.com>; Mon, 21 Jun 2021 10:18:54 +0200 (CEST)
Received: from firstgate.proxmox.com (localhost [127.0.0.1])
 by firstgate.proxmox.com (Proxmox) with ESMTP id B02AB1979E
 for <pbs-devel@lists.proxmox.com>; Mon, 21 Jun 2021 10:18:24 +0200 (CEST)
Received: from proxmox-new.maurer-it.com (proxmox-new.maurer-it.com
 [94.136.29.106])
 (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
 key-exchange X25519 server-signature RSA-PSS (2048 bits))
 (No client certificate requested)
 by firstgate.proxmox.com (Proxmox) with ESMTPS id DD8A119794
 for <pbs-devel@lists.proxmox.com>; Mon, 21 Jun 2021 10:18:23 +0200 (CEST)
Received: from proxmox-new.maurer-it.com (localhost.localdomain [127.0.0.1])
 by proxmox-new.maurer-it.com (Proxmox) with ESMTP id B0D10406BF
 for <pbs-devel@lists.proxmox.com>; Mon, 21 Jun 2021 10:18:23 +0200 (CEST)
From: Dominik Csapak <d.csapak@proxmox.com>
To: pbs-devel@lists.proxmox.com
Date: Mon, 21 Jun 2021 10:18:21 +0200
Message-Id: <20210621081822.9628-1-d.csapak@proxmox.com>
X-Mailer: git-send-email 2.20.1
MIME-Version: 1.0
Content-Transfer-Encoding: 8bit
X-SPAM-LEVEL: Spam detection results:  0
 AWL 0.859 Adjusted score from AWL reputation of From: address
 BAYES_00                 -1.9 Bayes spam probability is 0 to 1%
 KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment
 SPF_HELO_NONE           0.001 SPF: HELO does not publish an SPF Record
 SPF_PASS               -0.001 SPF: sender matches SPF record
Subject: [pbs-devel] [PATCH proxmox-backup v2 1/2] tape/drive: add
 'set_locate_offset' to TapeDriver Trait
X-BeenThere: pbs-devel@lists.proxmox.com
X-Mailman-Version: 2.1.29
Precedence: list
List-Id: Proxmox Backup Server development discussion
 <pbs-devel.lists.proxmox.com>
List-Unsubscribe: <https://lists.proxmox.com/cgi-bin/mailman/options/pbs-devel>, 
 <mailto:pbs-devel-request@lists.proxmox.com?subject=unsubscribe>
List-Archive: <http://lists.proxmox.com/pipermail/pbs-devel/>
List-Post: <mailto:pbs-devel@lists.proxmox.com>
List-Help: <mailto:pbs-devel-request@lists.proxmox.com?subject=help>
List-Subscribe: <https://lists.proxmox.com/cgi-bin/mailman/listinfo/pbs-devel>, 
 <mailto:pbs-devel-request@lists.proxmox.com?subject=subscribe>
X-List-Received-Date: Mon, 21 Jun 2021 08:18:54 -0000

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

since we only want to move forward when correcting, we keep the default
behaviour (for IBM drives), and have an optional offset
that we can set when we detect a discrepancy in target file number and
the actual file number

Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
---
changes from v1:
* rename to 'locate_offset'

 src/tape/drive/lto/mod.rs      |  4 ++++
 src/tape/drive/lto/sg_tape.rs  | 13 ++++++++++++-
 src/tape/drive/mod.rs          |  4 ++++
 src/tape/drive/virtual_tape.rs | 12 +++++++++++-
 4 files changed, 31 insertions(+), 2 deletions(-)

diff --git a/src/tape/drive/lto/mod.rs b/src/tape/drive/lto/mod.rs
index 8c319b07..d21a5b0c 100644
--- a/src/tape/drive/lto/mod.rs
+++ b/src/tape/drive/lto/mod.rs
@@ -286,6 +286,10 @@ impl TapeDriver for LtoTapeHandle {
         Ok(())
     }
 
+    fn set_locate_offset(&mut self, offset: i64) {
+        self.sg_tape.set_locate_offset(offset);
+    }
+
     fn move_to_file(&mut self, file: u64) -> Result<(), Error> {
         self.locate_file(file)
     }
diff --git a/src/tape/drive/lto/sg_tape.rs b/src/tape/drive/lto/sg_tape.rs
index 25c239a2..b280b2bb 100644
--- a/src/tape/drive/lto/sg_tape.rs
+++ b/src/tape/drive/lto/sg_tape.rs
@@ -122,6 +122,7 @@ pub struct LtoTapeStatus {
 
 pub struct SgTape {
     file: File,
+    locate_offset: i64,
     info: InquiryInfo,
     encryption_key_loaded: bool,
 }
@@ -143,6 +144,7 @@ impl SgTape {
 
         Ok(Self {
             file,
+            locate_offset: 0,
             info,
             encryption_key_loaded: false,
         })
@@ -295,12 +297,21 @@ impl SgTape {
         Ok(())
     }
 
+    pub fn set_locate_offset(&mut self, offset: i64) {
+        self.locate_offset = offset;
+    }
+
     pub fn locate_file(&mut self, position: u64) ->  Result<(), Error> {
         if position == 0 {
             return self.rewind();
         }
 
-        let position = position -1;
+        let position = position - 1;
+        let position = if self.locate_offset < 0 {
+            position.saturating_sub((-self.locate_offset) as u64)
+        } else {
+            position.saturating_add(self.locate_offset as u64)
+        };
 
         let mut sg_raw = SgRaw::new(&mut self.file, 16)?;
         sg_raw.set_timeout(Self::SCSI_TAPE_DEFAULT_TIMEOUT);
diff --git a/src/tape/drive/mod.rs b/src/tape/drive/mod.rs
index 7bc02f9e..8576055a 100644
--- a/src/tape/drive/mod.rs
+++ b/src/tape/drive/mod.rs
@@ -80,9 +80,13 @@ pub trait TapeDriver {
     /// Move to last file
     fn move_to_last_file(&mut self) -> Result<(), Error>;
 
+    /// Set an offset for the locate command
+    fn set_locate_offset(&mut self, offset: i64);
+
     /// Move to given file nr
     fn move_to_file(&mut self, file: u64) -> Result<(), Error>;
 
+
     /// Current file number
     fn current_file_number(&mut self) -> Result<u64, Error>;
 
diff --git a/src/tape/drive/virtual_tape.rs b/src/tape/drive/virtual_tape.rs
index 3c5f9502..ae503def 100644
--- a/src/tape/drive/virtual_tape.rs
+++ b/src/tape/drive/virtual_tape.rs
@@ -56,6 +56,7 @@ impl VirtualTapeDrive {
                 _lock: lock,
                 drive_name: self.name.clone(),
                 max_size: self.max_size.unwrap_or(64*1024*1024),
+                locate_offset: 0,
                 path: std::path::PathBuf::from(&self.path),
             })
         }).map_err(|err: Error| format_err!("open drive '{}' ({}) failed - {}", self.name, self.path, err))
@@ -82,6 +83,7 @@ pub struct VirtualTapeHandle {
     drive_name: String,
     path: std::path::PathBuf,
     max_size: usize,
+    locate_offset: i64,
     _lock: File,
 }
 
@@ -261,6 +263,10 @@ impl TapeDriver for VirtualTapeHandle {
         Ok(())
     }
 
+    fn set_locate_offset(&mut self, offset: i64) {
+        self.locate_offset = offset;
+    }
+
     fn move_to_file(&mut self, file: u64) -> Result<(), Error> {
         let mut status = self.load_status()?;
         match status.current_tape {
@@ -273,7 +279,11 @@ impl TapeDriver for VirtualTapeHandle {
                     bail!("invalid file nr");
                 }
 
-                *pos = file as usize;
+                *pos = if self.locate_offset < 0 {
+                    file.saturating_sub((-self.locate_offset) as u64) as usize
+                } else {
+                    file.saturating_add(self.locate_offset as u64) as usize
+                };
 
                 self.store_status(&status)
                     .map_err(|err| io::Error::new(io::ErrorKind::Other, err.to_string()))?;
-- 
2.20.1