diff --git a/pbs-tape/src/sg_tape.rs b/pbs-tape/src/sg_tape.rs index 0417a088..dcf53b72 100644 --- a/pbs-tape/src/sg_tape.rs +++ b/pbs-tape/src/sg_tape.rs @@ -26,8 +26,11 @@ pub use report_density::*; use proxmox_io::{ReadExt, WriteExt}; use proxmox_sys::error::SysResult; -use pbs_api_types::{Lp17VolumeStatistics, LtoDriveAndMediaStatus, MamAttribute, TapeDensity}; +use pbs_api_types::{ + Lp17VolumeStatistics, LtoDriveAndMediaStatus, LtoTapeDrive, MamAttribute, TapeDensity, +}; +use crate::linux_list_drives::open_lto_tape_device; use crate::{ sgutils2::{ alloc_page_aligned_buffer, scsi_cmd_mode_select10, scsi_cmd_mode_select6, scsi_inquiry, @@ -129,6 +132,43 @@ impl SgTape { }) } + /// Open a tape device + /// + /// This does additional checks: + /// + /// - check if it is a non-rewinding tape device + /// - check if drive is ready (tape loaded) + /// - check block size + /// - for autoloader only, try to reload ejected tapes + pub fn open_lto_drive(config: &LtoTapeDrive) -> Result { + proxmox_lang::try_block!({ + let file = open_lto_tape_device(&config.path)?; + + let mut handle = SgTape::new(file)?; + + if handle.test_unit_ready().is_err() { + // for autoloader only, try to reload ejected tapes + if config.changer.is_some() { + let _ = handle.load(); // just try, ignore error + } + } + + handle.wait_until_ready(None)?; + + handle.set_default_options()?; + + Ok(handle) + }) + .map_err(|err: Error| { + format_err!( + "open drive '{}' ({}) failed - {}", + config.name, + config.path, + err + ) + }) + } + /// Access to file descriptor - useful for testing pub fn file_mut(&mut self) -> &mut File { &mut self.file diff --git a/src/api2/tape/drive.rs b/src/api2/tape/drive.rs index 19c8e78a..633a236d 100644 --- a/src/api2/tape/drive.rs +++ b/src/api2/tape/drive.rs @@ -36,8 +36,7 @@ use crate::{ changer::update_changer_online_status, drive::{ get_tape_device_state, lock_tape_device, media_changer, open_drive, - open_lto_tape_drive, required_media_changer, set_tape_device_state, LtoTapeHandle, - TapeDriver, + required_media_changer, set_tape_device_state, LtoTapeHandle, TapeDriver, }, encryption_keys::insert_key, file_formats::{MediaLabel, MediaSetLabel}, @@ -1192,7 +1191,7 @@ pub async fn cartridge_memory(drive: String) -> Result, Error> "reading cartridge memory".to_string(), move |config| { let drive_config: LtoTapeDrive = config.lookup("lto", &drive)?; - let mut handle = open_lto_tape_drive(&drive_config)?; + let mut handle = LtoTapeHandle::open_lto_drive(&drive_config)?; handle.cartridge_memory() }, @@ -1222,7 +1221,7 @@ pub async fn volume_statistics(drive: String) -> Result Result { let handle = if let Some(name) = param["drive"].as_str() { let (config, _digest) = pbs_config::drive::config()?; let drive: LtoTapeDrive = config.lookup("lto", name)?; log::info!("using device {}", drive.path); - open_lto_tape_drive(&drive)? + LtoTapeHandle::open_lto_drive(&drive)? } else if let Some(device) = param["device"].as_str() { log::info!("using device {}", device); LtoTapeHandle::new(open_lto_tape_device(device)?)? @@ -40,7 +40,7 @@ fn get_tape_handle(param: &Value) -> Result { let (config, _digest) = pbs_config::drive::config()?; let drive: LtoTapeDrive = config.lookup("lto", &name)?; log::info!("using device {}", drive.path); - open_lto_tape_drive(&drive)? + LtoTapeHandle::open_lto_drive(&drive)? } else { let (config, _digest) = pbs_config::drive::config()?; @@ -56,7 +56,7 @@ fn get_tape_handle(param: &Value) -> Result { let name = drive_names[0]; let drive: LtoTapeDrive = config.lookup("lto", name)?; log::info!("using device {}", drive.path); - open_lto_tape_drive(&drive)? + LtoTapeHandle::open_lto_drive(&drive)? } else { bail!("no drive/device specified"); } diff --git a/src/tape/drive/lto/mod.rs b/src/tape/drive/lto/mod.rs index 2605a701..3ff989bb 100644 --- a/src/tape/drive/lto/mod.rs +++ b/src/tape/drive/lto/mod.rs @@ -23,7 +23,6 @@ use pbs_api_types::{ }; use pbs_key_config::KeyConfig; use pbs_tape::{ - linux_list_drives::open_lto_tape_device, sg_tape::{SgTape, TapeAlertFlags}, BlockReadError, MediaContentHeader, TapeRead, TapeWrite, }; @@ -34,43 +33,6 @@ use crate::tape::{ file_formats::{MediaSetLabel, PROXMOX_BACKUP_MEDIA_SET_LABEL_MAGIC_1_0}, }; -/// Open a tape device -/// -/// This does additional checks: -/// -/// - check if it is a non-rewinding tape device -/// - check if drive is ready (tape loaded) -/// - check block size -/// - for autoloader only, try to reload ejected tapes -pub fn open_lto_tape_drive(config: &LtoTapeDrive) -> Result { - proxmox_lang::try_block!({ - let file = open_lto_tape_device(&config.path)?; - - let mut handle = LtoTapeHandle::new(file)?; - - if handle.sg_tape.test_unit_ready().is_err() { - // for autoloader only, try to reload ejected tapes - if config.changer.is_some() { - let _ = handle.sg_tape.load(); // just try, ignore error - } - } - - handle.sg_tape.wait_until_ready(None)?; - - handle.set_default_options()?; - - Ok(handle) - }) - .map_err(|err: Error| { - format_err!( - "open drive '{}' ({}) failed - {}", - config.name, - config.path, - err - ) - }) -} - /// Lto Tape device handle pub struct LtoTapeHandle { sg_tape: SgTape, @@ -83,6 +45,18 @@ impl LtoTapeHandle { Ok(Self { sg_tape }) } + /// Open a tape device + /// + /// since this calls [SgTape::open_lto_drive], it does some internal checks. + /// See [SgTape] docs for details. + pub fn open_lto_drive(config: &LtoTapeDrive) -> Result { + let sg_tape = SgTape::open_lto_drive(config)?; + + let handle = Self { sg_tape }; + + Ok(handle) + } + /// Set all options we need/want pub fn set_default_options(&mut self) -> Result<(), Error> { self.sg_tape.set_default_options()?; diff --git a/src/tape/drive/mod.rs b/src/tape/drive/mod.rs index 86f01201..97673282 100644 --- a/src/tape/drive/mod.rs +++ b/src/tape/drive/mod.rs @@ -280,7 +280,7 @@ pub fn open_drive(config: &SectionConfigData, drive: &str) -> Result { let tape = LtoTapeDrive::deserialize(config)?; - let handle = open_lto_tape_drive(&tape)?; + let handle = LtoTapeHandle::open_lto_drive(&tape)?; Ok(Box::new(handle)) } ty => bail!("unknown drive type '{}' - internal error", ty), @@ -449,7 +449,7 @@ pub fn request_and_load_media( } } - let mut handle = match open_lto_tape_drive(&drive_config) { + let mut handle = match LtoTapeHandle::open_lto_drive(&drive_config) { Ok(handle) => handle, Err(err) => { update_and_log_request_error(