tape: fix LEOM handling
This commit is contained in:
		| @ -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); | ||||
|             } | ||||
|         }; | ||||
|  | ||||
| @ -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()?; | ||||
|  | ||||
		Reference in New Issue
	
	Block a user