public inbox for pbs-devel@lists.proxmox.com
 help / color / mirror / Atom feed
From: Dietmar Maurer <dietmar@proxmox.com>
To: pbs-devel@lists.proxmox.com
Subject: [pbs-devel] [PATCH 05/11] tape: fix LEOM handling
Date: Wed,  7 Apr 2021 12:23:02 +0200	[thread overview]
Message-ID: <20210407102308.9750-6-dietmar@proxmox.com> (raw)
In-Reply-To: <20210407102308.9750-1-dietmar@proxmox.com>

---
 src/tape/drive/lto/sg_tape.rs | 57 +++++++++++++++++++++++++++--------
 src/tools/sgutils2.rs         | 26 ++++++++--------
 2 files changed, 57 insertions(+), 26 deletions(-)

diff --git a/src/tape/drive/lto/sg_tape.rs b/src/tape/drive/lto/sg_tape.rs
index 531acbee..fd1a067a 100644
--- a/src/tape/drive/lto/sg_tape.rs
+++ b/src/tape/drive/lto/sg_tape.rs
@@ -75,6 +75,11 @@ impl SgTape {
         Ok(Self { file })
     }
 
+    // fixme: remove - only for testing
+    pub fn file_mut(&mut self) -> &mut File {
+        &mut self.file
+    }
+
     pub fn open<P: AsRef<Path>>(path: P) -> Result<SgTape, Error> {
         // do not wait for media, use O_NONBLOCK
         let file = OpenOptions::new()
@@ -195,9 +200,26 @@ impl SgTape {
         Ok(position.logical_file_id)
     }
 
-    pub fn locate(&mut self) ->  Result<(), Error> {
-        // fixme: impl LOCATE
-        unimplemented!();
+    // fixme: dont use - needs LTO5
+    pub fn locate_file(&mut self, position: u64) ->  Result<(), Error> {
+        let mut sg_raw = SgRaw::new(&mut self.file, 16)?;
+        sg_raw.set_timeout(Self::SCSI_TAPE_DEFAULT_TIMEOUT);
+        let mut cmd = Vec::new();
+        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 move_to_eom(&mut self) ->  Result<(), Error> {
@@ -286,8 +308,15 @@ impl SgTape {
         cmd.extend(&[0, 0, count as u8]); // COUNT
         cmd.push(0); // control byte
 
-        sg_raw.do_command(&cmd)
-            .map_err(|err| proxmox::io_format_err!("write filemark failed - {}", err))?;
+        match sg_raw.do_command(&cmd) {
+            Ok(_) => { /* OK */ }
+            Err(ScsiError::Sense(SenseInfo { sense_key: 0, asc: 0, ascq: 2 })) => {
+                /* LEOM - ignore */
+            }
+            Err(err) => {
+                proxmox::io_bail!("write filemark  failed - {}", err);
+            }
+        }
 
         Ok(())
     }
@@ -360,7 +389,7 @@ impl SgTape {
 
         let transfer_len = data.len();
 
-        if transfer_len > 0xFFFFFF {
+        if transfer_len > 0x800000 {
            proxmox::io_bail!("write failed - data too large");
         }
 
@@ -379,12 +408,15 @@ impl SgTape {
         //println!("WRITE {:?}", cmd);
         //println!("WRITE {:?}", data);
 
-        sg_raw.do_out_command(&cmd, data)
-            .map_err(|err| proxmox::io_format_err!("write failed - {}", err))?;
-
-        // fixme: LEOM?
-
-        Ok(false)
+        match sg_raw.do_out_command(&cmd, data) {
+            Ok(()) => { return Ok(false) }
+            Err(ScsiError::Sense(SenseInfo { sense_key: 0, asc: 0, ascq: 2 })) => {
+                return Ok(true); // LEOM
+            }
+            Err(err) => {
+                proxmox::io_bail!("write failed - {}", err);
+            }
+        }
     }
 
     fn read_block(&mut self, buffer: &mut [u8]) -> Result<BlockReadStatus, std::io::Error> {
@@ -416,7 +448,6 @@ impl SgTape {
                 return Ok(BlockReadStatus::EndOfStream);
             }
             Err(err) => {
-                println!("READ ERR {:?}", err);
                 proxmox::io_bail!("read failed - {}", err);
             }
         };
diff --git a/src/tools/sgutils2.rs b/src/tools/sgutils2.rs
index 987d5738..4edfd9d9 100644
--- a/src/tools/sgutils2.rs
+++ b/src/tools/sgutils2.rs
@@ -203,17 +203,17 @@ struct InquiryPage {
 
 #[repr(C, packed)]
 #[derive(Endian, Debug)]
-struct RequestSenseFixed {
-    response_code: u8,
+pub struct RequestSenseFixed {
+    pub response_code: u8,
     obsolete: u8,
-    flags2: u8,
-    information: [u8;4],
-    additional_sense_len: u8,
-    command_specific_information: [u8;4],
-    additional_sense_code: u8,
-    additional_sense_code_qualifier: u8,
-    field_replacable_unit_code: u8,
-    sense_key_specific: [u8; 3],
+    pub flags2: u8,
+    pub information: [u8;4],
+    pub additional_sense_len: u8,
+    pub command_specific_information: [u8;4],
+    pub additional_sense_code: u8,
+    pub additional_sense_code_qualifier: u8,
+    pub field_replacable_unit_code: u8,
+    pub sense_key_specific: [u8; 3],
 }
 
 #[repr(C, packed)]
@@ -575,15 +575,15 @@ impl <'a, F: AsRawFd> SgRaw<'a, F> {
     /// Run dataout command
     ///
     /// Note: use alloc_page_aligned_buffer to alloc data transfer buffer
-    pub fn do_out_command(&mut self, cmd: &[u8], data: &[u8]) -> Result<(), Error> {
+    pub fn do_out_command(&mut self, cmd: &[u8], data: &[u8]) -> Result<(), ScsiError> {
 
         if !unsafe { sg_is_scsi_cdb(cmd.as_ptr(), cmd.len() as c_int) } {
-            bail!("no valid SCSI command");
+            return Err(format_err!("no valid SCSI command").into());
         }
 
         let page_size = unsafe { libc::sysconf(libc::_SC_PAGESIZE) } as usize;
         if ((data.as_ptr() as usize) & (page_size -1)) != 0 {
-            bail!("wrong transfer buffer alignment");
+            return Err(format_err!("wrong transfer buffer alignment").into());
         }
 
         let mut ptvp = self.create_scsi_pt_obj()?;
-- 
2.20.1




  parent reply	other threads:[~2021-04-07 10:24 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-04-07 10:22 [pbs-devel] [PATCH 00/11] Userspace tape driver Dietmar Maurer
2021-04-07 10:22 ` [pbs-devel] [PATCH 01/11] tape: introduce trait BlockRead Dietmar Maurer
2021-04-07 10:22 ` [pbs-devel] [PATCH 02/11] tape: introduce trait BlockWrite Dietmar Maurer
2021-04-07 10:23 ` [pbs-devel] [PATCH 03/11] tape: implement LTO userspace driver Dietmar Maurer
2021-04-07 10:23 ` [pbs-devel] [PATCH 04/11] tape: implement format/erase Dietmar Maurer
2021-04-07 10:23 ` Dietmar Maurer [this message]
2021-04-07 10:23 ` [pbs-devel] [PATCH 06/11] tape: make fsf/bsf driver specific Dietmar Maurer
2021-04-07 10:23 ` [pbs-devel] [PATCH 07/11] tape: make sure there is a filemark at the end of the tape Dietmar Maurer
2021-04-07 10:23 ` [pbs-devel] [PATCH 08/11] sgutils2: add scsi_mode_sense helper Dietmar Maurer
2021-04-07 10:23 ` [pbs-devel] [PATCH 09/11] tape: correctly set/display drive option Dietmar Maurer
2021-04-07 10:23 ` [pbs-devel] [PATCH 10/11] tape: pmt - re-implement fsr/bsr Dietmar Maurer
2021-04-07 10:23 ` [pbs-devel] [PATCH 11/11] tape: pmt - re-implement lock/unlock command 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=20210407102308.9750-6-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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal