From: Dominik Csapak <d.csapak@proxmox.com>
To: pbs-devel@lists.proxmox.com
Subject: [pbs-devel] [PATCH proxmox-backup 2/2] tape: write informational MAM attributes on tapes
Date: Tue, 14 May 2024 16:12:48 +0200 [thread overview]
Message-ID: <20240514141248.1614306-2-d.csapak@proxmox.com> (raw)
In-Reply-To: <20240514141248.1614306-1-d.csapak@proxmox.com>
namely:
Vendor: Proxmox
Name: Backup Server
Version: current running package version
User Label Text: the label text
Media Pool: the current media pool
write it on labeling and when writing a new media-set to a tape.
While we currently don't use this info for anything, this can help users
to identify tapes, even with different backup software.
If we need it in the future, we can e.g. make decisions based on these
fields (e.g. the version).
On format, delete them again.
Note that some VTLs don't correctly delete the attributes from the
virtual tapes.
Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
---
pbs-tape/Cargo.toml | 1 +
pbs-tape/src/sg_tape.rs | 39 ++++++++++++++++++++++
pbs-tape/src/sg_tape/mam.rs | 61 +++++++++++++++++++++++++++++++++-
src/api2/tape/drive.rs | 2 ++
src/tape/drive/lto/mod.rs | 6 ++++
src/tape/drive/mod.rs | 5 +++
src/tape/drive/virtual_tape.rs | 4 +++
7 files changed, 117 insertions(+), 1 deletion(-)
diff --git a/pbs-tape/Cargo.toml b/pbs-tape/Cargo.toml
index 970315b7a..f4110706b 100644
--- a/pbs-tape/Cargo.toml
+++ b/pbs-tape/Cargo.toml
@@ -34,4 +34,5 @@ proxmox-schema = { workspace = true, features = [ "api-macro" ] }
proxmox-router = { workspace = true, features = ["cli", "server"] }
pbs-api-types.workspace = true
+pbs-buildcfg.workspace = true
pbs-config.workspace = true
diff --git a/pbs-tape/src/sg_tape.rs b/pbs-tape/src/sg_tape.rs
index f30481b31..058c14ae9 100644
--- a/pbs-tape/src/sg_tape.rs
+++ b/pbs-tape/src/sg_tape.rs
@@ -295,6 +295,8 @@ impl SgTape {
self.erase_media(fast)?
}
+ self.clear_mam_attributes();
+
Ok(())
}
}
@@ -1048,6 +1050,43 @@ impl SgTape {
Ok(status)
}
+
+ /// Tries to write useful attributes to the MAM like Vendor/Application/Version
+ pub fn write_mam_attributes(&mut self, label: Option<String>, pool: Option<String>) {
+ let version = format!(
+ "{}-{}",
+ pbs_buildcfg::PROXMOX_PKG_VERSION,
+ pbs_buildcfg::PROXMOX_PKG_RELEASE
+ );
+ let mut attribute_list: Vec<(u16, &[u8])> = vec![
+ (0x08_00, b"Proxmox"),
+ (0x08_01, b"Backup Server"),
+ (0x08_02, version.as_bytes()),
+ ];
+ if let Some(ref label) = label {
+ attribute_list.push((0x08_03, label.as_bytes()));
+ }
+
+ if let Some(ref pool) = pool {
+ attribute_list.push((0x08_08, pool.as_bytes()));
+ }
+
+ for (id, data) in attribute_list {
+ if let Err(err) = write_mam_attribute(&mut self.file, id, data) {
+ log::warn!("could not set MAM Attribute {id:x}: {err}");
+ }
+ }
+ }
+
+ // clear all custom set mam attributes
+ fn clear_mam_attributes(&mut self) {
+ for attr in [0x08_00, 0x08_01, 0x08_02, 0x08_03, 0x08_08] {
+ // ignore error
+ if let Err(err) = write_mam_attribute(&mut self.file, attr, b"") {
+ log::warn!("could not clear MAM attribute {attr:x}: {err}");
+ }
+ }
+ }
}
pub struct SgTapeReader<'a> {
diff --git a/pbs-tape/src/sg_tape/mam.rs b/pbs-tape/src/sg_tape/mam.rs
index 74e09c6d6..4e995d0b9 100644
--- a/pbs-tape/src/sg_tape/mam.rs
+++ b/pbs-tape/src/sg_tape/mam.rs
@@ -8,7 +8,7 @@ use proxmox_io::ReadExt;
use pbs_api_types::MamAttribute;
-use crate::sgutils2::SgRaw;
+use crate::sgutils2::{alloc_page_aligned_buffer, SgRaw};
use super::TapeAlertFlags;
@@ -143,6 +143,65 @@ fn read_tape_mam<F: AsRawFd>(file: &mut F) -> Result<Vec<u8>, Error> {
.map(|v| v.to_vec())
}
+/// Write attribute to MAM
+pub fn write_mam_attribute<F: AsRawFd>(
+ file: &mut F,
+ attribute_id: u16,
+ data: &[u8],
+) -> Result<(), Error> {
+ let mut sg_raw = SgRaw::new(file, 0)?;
+
+ let mut parameters = Vec::new();
+
+ let attribute = MAM_ATTRIBUTE_NAMES
+ .get(&attribute_id)
+ .ok_or_else(|| format_err!("MAM attribute '{attribute_id:x}' unknown"))?;
+
+ let mut attr_data = Vec::new();
+ attr_data.extend(attribute_id.to_be_bytes());
+ attr_data.push(match attribute.format {
+ MamFormat::BINARY | MamFormat::DEC => 0x00,
+ MamFormat::ASCII => 0x01,
+ MamFormat::TEXT => 0x02,
+ });
+ let len = if data.is_empty() { 0 } else { attribute.len };
+ attr_data.extend(len.to_be_bytes());
+ attr_data.extend(data);
+ if !data.is_empty() && data.len() < attribute.len as usize {
+ attr_data.resize(attr_data.len() - data.len() + attribute.len as usize, 0);
+ } else if data.len() > u16::MAX as usize {
+ bail!("data to long");
+ }
+
+ parameters.extend(attr_data);
+
+ let mut data_out = alloc_page_aligned_buffer(parameters.len() + 4)?;
+ data_out[..4].copy_from_slice(&(parameters.len() as u32).to_be_bytes());
+ data_out[4..].copy_from_slice(¶meters);
+
+ let mut cmd = vec![
+ 0x8d, // WRITE ATTRIBUTE CDB (8Dh)
+ 0x01, // WTC=1
+ 0x00, // reserved
+ 0x00, // reserved
+ 0x00, // reserved
+ 0x00, // Volume Number
+ 0x00, // reserved
+ 0x00, // Partition Number
+ 0x00, // reserved
+ 0x00, // reserved
+ ];
+ cmd.extend((data_out.len() as u32).to_be_bytes());
+ cmd.extend([
+ 0x00, // reserved
+ 0x00, // reserved
+ ]);
+
+ sg_raw.do_out_command(&cmd, &data_out)?;
+
+ Ok(())
+}
+
/// Read Medium auxiliary memory attributes (cartridge memory) using raw SCSI command.
pub fn read_mam_attributes<F: AsRawFd>(file: &mut F) -> Result<Vec<MamAttribute>, Error> {
let data = read_tape_mam(file)?;
diff --git a/src/api2/tape/drive.rs b/src/api2/tape/drive.rs
index 7a791e09b..c6fc9f9c2 100644
--- a/src/api2/tape/drive.rs
+++ b/src/api2/tape/drive.rs
@@ -606,6 +606,8 @@ fn write_media_label(
drive.rewind()?;
+ drive.write_additional_attributes(Some(media_id.label.label_text), pool);
+
Ok(())
}
diff --git a/src/tape/drive/lto/mod.rs b/src/tape/drive/lto/mod.rs
index f3143c907..23e043ce6 100644
--- a/src/tape/drive/lto/mod.rs
+++ b/src/tape/drive/lto/mod.rs
@@ -225,6 +225,8 @@ impl TapeDriver for LtoTapeHandle {
self.set_encryption(encrypt_fingerprint)?;
+ self.write_additional_attributes(None, Some(media_set_label.pool.clone()));
+
Ok(())
}
@@ -272,6 +274,10 @@ impl TapeDriver for LtoTapeHandle {
fn get_volume_statistics(&mut self) -> Result<pbs_api_types::Lp17VolumeStatistics, Error> {
self.volume_statistics()
}
+
+ fn write_additional_attributes(&mut self, label: Option<String>, pool: Option<String>) {
+ self.sg_tape.write_mam_attributes(label, pool)
+ }
}
fn run_sg_tape_cmd(subcmd: &str, args: &[&str], fd: RawFd) -> Result<String, Error> {
diff --git a/src/tape/drive/mod.rs b/src/tape/drive/mod.rs
index b21a62d20..b912b234d 100644
--- a/src/tape/drive/mod.rs
+++ b/src/tape/drive/mod.rs
@@ -245,6 +245,11 @@ pub trait TapeDriver {
/// Returns volume statistics from a loaded tape
fn get_volume_statistics(&mut self) -> Result<pbs_api_types::Lp17VolumeStatistics, Error>;
+
+ /// Writes additional attributes on the drive, like the vendor/application/etc. (e.g. on MAM)
+ ///
+ /// Since it's not fatal when it does not work, it only logs warnings in that case
+ fn write_additional_attributes(&mut self, label: Option<String>, pool: Option<String>);
}
/// A boxed implementor of [`MediaChange`].
diff --git a/src/tape/drive/virtual_tape.rs b/src/tape/drive/virtual_tape.rs
index c183e2681..866e4d323 100644
--- a/src/tape/drive/virtual_tape.rs
+++ b/src/tape/drive/virtual_tape.rs
@@ -465,6 +465,10 @@ impl TapeDriver for VirtualTapeHandle {
fn get_volume_statistics(&mut self) -> Result<pbs_api_types::Lp17VolumeStatistics, Error> {
Ok(Default::default())
}
+
+ fn write_additional_attributes(&mut self, _label: Option<String>, _pool: Option<String>) {
+ // not implemented
+ }
}
impl MediaChange for VirtualTapeHandle {
--
2.39.2
_______________________________________________
pbs-devel mailing list
pbs-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pbs-devel
next prev parent reply other threads:[~2024-05-14 14:12 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-05-14 14:12 [pbs-devel] [PATCH proxmox-backup 1/2] tape: correct mam format for some attributes Dominik Csapak
2024-05-14 14:12 ` Dominik Csapak [this message]
2024-05-22 17:24 ` [pbs-devel] [PATCH proxmox-backup 2/2] tape: write informational MAM attributes on tapes Thomas Lamprecht
2024-05-23 6:09 ` Dominik Csapak
2024-05-23 8:10 ` Thomas Lamprecht
2024-05-23 8:22 ` Dominik Csapak
2024-05-23 8:25 ` Dominik Csapak
2024-05-15 7:36 ` [pbs-devel] applied: [PATCH proxmox-backup 1/2] tape: correct mam format for some attributes Dietmar Maurer
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20240514141248.1614306-2-d.csapak@proxmox.com \
--to=d.csapak@proxmox.com \
--cc=pbs-devel@lists.proxmox.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox