tape: provide 'open_lto_drive' methods for LtoTapeHandle and SgTape

Prepares for the use in sg-tape-cmd, since we want to use the SgTape
directly instead of LtoTapeHandle.

Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
This commit is contained in:
Dominik Csapak 2024-01-22 12:50:27 +01:00 committed by Thomas Lamprecht
parent 8cc8aa510f
commit b5f8626706
5 changed files with 62 additions and 49 deletions

View File

@ -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<Self, Error> {
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

View File

@ -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<Vec<MamAttribute>, 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<Lp17VolumeStatistics, Er
"reading volume statistics".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.volume_statistics()
},

View File

@ -19,14 +19,14 @@ use pbs_api_types::{
use pbs_tape::linux_list_drives::{check_tape_is_lto_tape_device, open_lto_tape_device};
use proxmox_backup::tape::drive::{open_lto_tape_drive, LtoTapeHandle, TapeDriver};
use proxmox_backup::tape::drive::{LtoTapeHandle, TapeDriver};
fn get_tape_handle(param: &Value) -> Result<LtoTapeHandle, Error> {
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<LtoTapeHandle, Error> {
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<LtoTapeHandle, Error> {
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");
}

View File

@ -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<LtoTapeHandle, Error> {
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<Self, Error> {
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()?;

View File

@ -280,7 +280,7 @@ pub fn open_drive(config: &SectionConfigData, drive: &str) -> Result<Box<dyn Tap
}
"lto" => {
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(