From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: 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) server-digest SHA256) (No client certificate requested) by lists.proxmox.com (Postfix) with ESMTPS id 6BF2F755CC for ; Mon, 12 Jul 2021 15:42:29 +0200 (CEST) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id 5123A16856 for ; Mon, 12 Jul 2021 15:41:59 +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) server-digest SHA256) (No client certificate requested) by firstgate.proxmox.com (Proxmox) with ESMTPS id 5EE071684A for ; Mon, 12 Jul 2021 15:41:57 +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 2C7D741021 for ; Mon, 12 Jul 2021 15:41:57 +0200 (CEST) From: Dominik Csapak To: pbs-devel@lists.proxmox.com Date: Mon, 12 Jul 2021 15:41:55 +0200 Message-Id: <20210712134155.1499025-1-d.csapak@proxmox.com> X-Mailer: git-send-email 2.30.2 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-SPAM-LEVEL: Spam detection results: 0 AWL 0.618 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] tape: changer: sg_pt: query element types separately X-BeenThere: pbs-devel@lists.proxmox.com X-Mailman-Version: 2.1.29 Precedence: list List-Id: Proxmox Backup Server development discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 12 Jul 2021 13:42:29 -0000 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 --- 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( 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 { 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(file: &mut F) -> Result { - - 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( + inquiry: &InquiryInfo, + sg_raw: &mut SgRaw, + element_type: ElementType, + allocation_len: u32, + mut retry: bool, +) -> Result { 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(file: &mut F) -> Result break; } + Ok(result) +} + +/// Read element status. +pub fn read_element_status(file: &mut F) -> Result { + + 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