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)) (No client certificate requested) by lists.proxmox.com (Postfix) with ESMTPS id A276A711EF for ; Wed, 7 Apr 2021 12:24:39 +0200 (CEST) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id 98E37F363 for ; Wed, 7 Apr 2021 12:24:09 +0200 (CEST) Received: from elsa.proxmox.com (unknown [94.136.29.99]) by firstgate.proxmox.com (Proxmox) with ESMTP id 1EFF5F33B for ; Wed, 7 Apr 2021 12:24:07 +0200 (CEST) Received: by elsa.proxmox.com (Postfix, from userid 0) id 0F852AEAF24; Wed, 7 Apr 2021 12:24:07 +0200 (CEST) From: Dietmar Maurer To: pbs-devel@lists.proxmox.com Date: Wed, 7 Apr 2021 12:23:02 +0200 Message-Id: <20210407102308.9750-6-dietmar@proxmox.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20210407102308.9750-1-dietmar@proxmox.com> References: <20210407102308.9750-1-dietmar@proxmox.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-SPAM-LEVEL: Spam detection results: 1 KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment RDNS_NONE 1.274 Delivered to internal network by a host with no rDNS SPF_HELO_NONE 0.001 SPF: HELO does not publish an SPF Record SPF_PASS -0.001 SPF: sender matches SPF record URIBL_BLOCKED 0.001 ADMINISTRATOR NOTICE: The query to URIBL was blocked. See http://wiki.apache.org/spamassassin/DnsBlocklists#dnsbl-block for more information. [sgutils2.rs] Subject: [pbs-devel] [PATCH 05/11] tape: fix LEOM handling 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: Wed, 07 Apr 2021 10:24:39 -0000 --- 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>(path: P) -> Result { // 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 { @@ -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