public inbox for pbs-devel@lists.proxmox.com
 help / color / mirror / Atom feed
From: Dominik Csapak <d.csapak@proxmox.com>
To: pbs-devel@lists.proxmox.com
Subject: [pbs-devel] [PATCH proxmox-backup] tape: changer: sg_pt: query element types separately
Date: Mon, 12 Jul 2021 15:41:55 +0200	[thread overview]
Message-ID: <20210712134155.1499025-1-d.csapak@proxmox.com> (raw)

some changers do not like the DVCID bit when querying non-drives,
this includes when querying 'all' elements.

To circumvent this, we query each type by itself (like mtx does it),
and only add the DVCID bit for drives (Data Transfer Elements).

Reported by a user in the forum:
https://forum.proxmox.com/threads/ibm-3584-ts3500-support.92291/

Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
---
this patch applies on my last to changer patches. if should squash it
with the second one, please tell, then i send a v2

 src/tape/changer/sg_pt_changer.rs | 109 +++++++++++++++++++++---------
 1 file changed, 77 insertions(+), 32 deletions(-)

diff --git a/src/tape/changer/sg_pt_changer.rs b/src/tape/changer/sg_pt_changer.rs
index da114074..0f719e9b 100644
--- a/src/tape/changer/sg_pt_changer.rs
+++ b/src/tape/changer/sg_pt_changer.rs
@@ -277,19 +277,33 @@ pub fn transfer_medium<F: AsRawFd>(
     Ok(())
 }
 
+#[repr(u8)]
+#[derive(Clone, Copy)]
+enum ElementType {
+    MediumTransport = 1,
+    Storage = 2,
+    ImportExport = 3,
+    DataTransfer = 4,
+}
+
 fn scsi_read_element_status_cdb(
     start_element_address: u16,
     number_of_elements: u16,
+    element_type: ElementType,
     allocation_len: u32,
 ) -> Vec<u8> {
 
     let mut cmd = Vec::new();
     cmd.push(0xB8); // READ ELEMENT STATUS (B8h)
-    cmd.push(1u8<<4); // report all types and volume tags
+    cmd.push(1u8<<4 | (element_type as u8)); // volume tags and given type
     cmd.extend(&start_element_address.to_be_bytes());
 
     cmd.extend(&number_of_elements.to_be_bytes());
-    cmd.push(0b001); //  Mixed=0,CurData=0,DVCID=1
+    let byte6 = match element_type {
+        ElementType::DataTransfer => 0b001, //  Mixed=0,CurData=0,DVCID=1
+        _ => 0b000, // Mixed=0,CurData=0,DVCID=0
+    };
+    cmd.push(byte6); 
     cmd.extend(&allocation_len.to_be_bytes()[1..4]);
     cmd.push(0);
     cmd.push(0);
@@ -297,51 +311,45 @@ fn scsi_read_element_status_cdb(
     cmd
 }
 
-/// Read element status.
-pub fn read_element_status<F: AsRawFd>(file: &mut F) -> Result<MtxStatus, Error> {
-
-    let inquiry = scsi_inquiry(file)?;
-
-    if inquiry.peripheral_type != 8 {
-        bail!("wrong device type (not a scsi changer device)");
-    }
-
-    // first, request address assignment (used for sanity checks)
-    let setup = read_element_address_assignment(file)?;
-
-    let allocation_len: u32 = 0x10000;
-
-    let mut sg_raw = SgRaw::new(file, allocation_len as usize)?;
-    sg_raw.set_timeout(SCSI_CHANGER_DEFAULT_TIMEOUT);
+// query a single element type from the changer
+fn get_element<F: AsRawFd>(
+    inquiry: &InquiryInfo,
+    sg_raw: &mut SgRaw<F>,
+    element_type: ElementType,
+    allocation_len: u32,
+    mut retry: bool,
+) -> Result<DecodedStatusPage, Error> {
 
     let mut start_element_address = 0;
     let number_of_elements: u16 = 1000; // some changers limit the query
 
-    let mut drives = Vec::new();
-    let mut storage_slots = Vec::new();
-    let mut import_export_slots = Vec::new();
-    let mut transports = Vec::new();
-
-    let mut retry = true;
+    let mut result = DecodedStatusPage {
+        last_element_address: None,
+        transports: Vec::new(),
+        drives: Vec::new(),
+        storage_slots: Vec::new(),
+        import_export_slots: Vec::new(),
+    };
 
     loop {
-        let cmd = scsi_read_element_status_cdb(start_element_address, number_of_elements, allocation_len);
+        let cmd = scsi_read_element_status_cdb(start_element_address, number_of_elements, element_type, allocation_len);
 
-        let data = execute_scsi_command(&mut sg_raw, &cmd, "read element status (B8h)", retry)?;
+        let data = execute_scsi_command(sg_raw, &cmd, "read element status (B8h)", retry)?;
 
         let page = decode_element_status_page(&inquiry, &data, start_element_address)?;
 
+        retry = false; // only retry the first command
+
         let returned_number_of_elements = page.transports.len()
             + page.drives.len()
             + page.storage_slots.len()
             + page.import_export_slots.len();
 
-        retry = false; // only retry the first command
-
-        transports.extend(page.transports);
-        drives.extend(page.drives);
-        storage_slots.extend(page.storage_slots);
-        import_export_slots.extend(page.import_export_slots);
+        result.transports.extend(page.transports);
+        result.drives.extend(page.drives);
+        result.storage_slots.extend(page.storage_slots);
+        result.import_export_slots.extend(page.import_export_slots);
+        result.last_element_address = page.last_element_address;
 
         if let Some(last_element_address) = page.last_element_address {
             if last_element_address < start_element_address {
@@ -355,6 +363,43 @@ pub fn read_element_status<F: AsRawFd>(file: &mut F) -> Result<MtxStatus, Error>
         break;
     }
 
+    Ok(result)
+}
+
+/// Read element status.
+pub fn read_element_status<F: AsRawFd>(file: &mut F) -> Result<MtxStatus, Error> {
+
+    let inquiry = scsi_inquiry(file)?;
+
+    if inquiry.peripheral_type != 8 {
+        bail!("wrong device type (not a scsi changer device)");
+    }
+
+    // first, request address assignment (used for sanity checks)
+    let setup = read_element_address_assignment(file)?;
+
+    let allocation_len: u32 = 0x10000;
+
+    let mut sg_raw = SgRaw::new(file, allocation_len as usize)?;
+    sg_raw.set_timeout(SCSI_CHANGER_DEFAULT_TIMEOUT);
+
+    let mut drives = Vec::new();
+    let mut storage_slots = Vec::new();
+    let mut import_export_slots = Vec::new();
+    let mut transports = Vec::new();
+
+    let page = get_element(&inquiry, &mut sg_raw, ElementType::Storage, allocation_len, true)?;
+    storage_slots.extend(page.storage_slots);
+
+    let page = get_element(&inquiry, &mut sg_raw, ElementType::ImportExport, allocation_len, false)?;
+    import_export_slots.extend(page.import_export_slots);
+
+    let page = get_element(&inquiry, &mut sg_raw, ElementType::DataTransfer, allocation_len, false)?;
+    drives.extend(page.drives);
+
+    let page = get_element(&inquiry, &mut sg_raw, ElementType::MediumTransport, allocation_len, false)?;
+    transports.extend(page.transports);
+
     if (setup.transport_element_count as usize) != transports.len() {
         bail!("got wrong number of transport elements");
     }
-- 
2.30.2





                 reply	other threads:[~2021-07-12 13:42 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

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=20210712134155.1499025-1-d.csapak@proxmox.com \
    --to=d.csapak@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