From: "Max R. Carrara" <m.carrara@proxmox.com>
To: pbs-devel@lists.proxmox.com
Subject: [PATCH proxmox-backup v2 03/10] tape: move tape block structs into separate file module
Date: Fri, 21 Aug 2026 16:02:27 +0200 [thread overview]
Message-ID: <20260821140238.615302-4-m.carrara@proxmox.com> (raw)
In-Reply-To: <20260821140238.615302-1-m.carrara@proxmox.com>
Move `BlockHeader` and `BlockHeaderFlags` into a separate file for
overall better organization and to make future changes a little easier
to follow.
Also, re-export both types as `pub(crate)`, since there is not really
any reason for them to be completely public.
Signed-off-by: Max R. Carrara <m.carrara@proxmox.com>
---
pbs-tape/src/lib.rs | 79 ++------------------------------------
pbs-tape/src/tape_block.rs | 79 ++++++++++++++++++++++++++++++++++++++
2 files changed, 82 insertions(+), 76 deletions(-)
create mode 100644 pbs-tape/src/tape_block.rs
diff --git a/pbs-tape/src/lib.rs b/pbs-tape/src/lib.rs
index 0fe55a749..6cff175dd 100644
--- a/pbs-tape/src/lib.rs
+++ b/pbs-tape/src/lib.rs
@@ -1,7 +1,6 @@
use std::collections::HashSet;
use anyhow::{Error, bail};
-use bitflags::bitflags;
use endian_trait::Endian;
use serde::{Deserialize, Serialize};
use serde_json::Value;
@@ -20,6 +19,9 @@ pub use blocked_reader::BlockedReader;
mod blocked_writer;
pub use blocked_writer::BlockedWriter;
+mod tape_block;
+pub(crate) use tape_block::{BlockHeader, BlockHeaderFlags};
+
mod tape_write;
pub use tape_write::*;
@@ -49,41 +51,6 @@ pub const PROXMOX_BACKUP_MEDIA_LABEL_MAGIC_1_0: [u8; 8] = [42, 5, 191, 60, 176,
// openssl::sha::sha256(b"Proxmox Backup MediaSet Label v1.0")
pub const PROXMOX_BACKUP_MEDIA_SET_LABEL_MAGIC_1_0: [u8; 8] = [8, 96, 99, 249, 47, 151, 83, 216];
-/// Tape Block Header with data payload
-///
-/// All tape files are written as sequence of blocks.
-///
-/// Note: this struct is large, never put this on the stack!
-/// so we use an unsized type to avoid that.
-///
-/// Tape data block are always read/written with a fixed size
-/// (`PROXMOX_TAPE_BLOCK_SIZE`). But they may contain less data, so the
-/// header has an additional size field. For streams of blocks, there
-/// is a sequence number (`seq_nr`) which may be use for additional
-/// error checking.
-#[repr(C, packed)]
-pub struct BlockHeader {
- /// fixed value `PROXMOX_TAPE_BLOCK_HEADER_MAGIC_1_0`
- pub magic: [u8; 8],
- pub flags: BlockHeaderFlags,
- /// size as 3 bytes unsigned, little endian
- pub size: [u8; 3],
- /// block sequence number
- pub seq_nr: u32,
- pub payload: [u8],
-}
-
-bitflags! {
- /// Header flags (e.g. `END_OF_STREAM` or `INCOMPLETE`)
- #[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
- pub struct BlockHeaderFlags: u8 {
- /// Marks the last block in a stream.
- const END_OF_STREAM = 0b00000001;
- /// Mark multivolume streams (when set in the last block)
- const INCOMPLETE = 0b00000010;
- }
-}
-
#[derive(Endian, Copy, Clone, Debug)]
#[repr(C, packed)]
/// Media Content Header
@@ -152,46 +119,6 @@ impl MediaContentHeader {
}
}
-impl BlockHeader {
- pub const SIZE: usize = PROXMOX_TAPE_BLOCK_SIZE;
-
- /// Allocates a new instance on the heap
- pub fn new() -> Box<Self> {
- use std::alloc::{Layout, alloc_zeroed};
-
- // align to PAGESIZE, so that we can use it with SG_IO
- let page_size = unsafe { libc::sysconf(libc::_SC_PAGESIZE) } as usize;
-
- let mut buffer = unsafe {
- let ptr = alloc_zeroed(Layout::from_size_align(Self::SIZE, page_size).unwrap());
- Box::from_raw(core::ptr::slice_from_raw_parts_mut(ptr, Self::SIZE - 16) as *mut Self)
- };
- buffer.magic = PROXMOX_TAPE_BLOCK_HEADER_MAGIC_1_0;
- buffer
- }
-
- /// Set the `size` field
- pub fn set_size(&mut self, size: usize) {
- let size = size.to_le_bytes();
- self.size.copy_from_slice(&size[..3]);
- }
-
- /// Returns the `size` field
- pub fn size(&self) -> usize {
- (self.size[0] as usize) + ((self.size[1] as usize) << 8) + ((self.size[2] as usize) << 16)
- }
-
- /// Set the `seq_nr` field
- pub fn set_seq_nr(&mut self, seq_nr: u32) {
- self.seq_nr = seq_nr.to_le();
- }
-
- /// Returns the `seq_nr` field
- pub fn seq_nr(&self) -> u32 {
- u32::from_le(self.seq_nr)
- }
-}
-
/// Changer element status.
///
/// Drive and slots may be `Empty`, or contain some media, either
diff --git a/pbs-tape/src/tape_block.rs b/pbs-tape/src/tape_block.rs
new file mode 100644
index 000000000..4f9c2192f
--- /dev/null
+++ b/pbs-tape/src/tape_block.rs
@@ -0,0 +1,79 @@
+use bitflags::bitflags;
+
+use crate::PROXMOX_TAPE_BLOCK_HEADER_MAGIC_1_0;
+use crate::PROXMOX_TAPE_BLOCK_SIZE;
+
+/// Tape Block Header with data payload
+///
+/// All tape files are written as sequence of blocks.
+///
+/// Note: this struct is large, never put this on the stack!
+/// so we use an unsized type to avoid that.
+///
+/// Tape data block are always read/written with a fixed size
+/// (`PROXMOX_TAPE_BLOCK_SIZE`). But they may contain less data, so the
+/// header has an additional size field. For streams of blocks, there
+/// is a sequence number (`seq_nr`) which may be use for additional
+/// error checking.
+#[repr(C, packed)]
+pub struct BlockHeader {
+ /// fixed value `PROXMOX_TAPE_BLOCK_HEADER_MAGIC_1_0`
+ pub magic: [u8; 8],
+ pub flags: BlockHeaderFlags,
+ /// size as 3 bytes unsigned, little endian
+ pub size: [u8; 3],
+ /// block sequence number
+ pub seq_nr: u32,
+ pub payload: [u8],
+}
+
+bitflags! {
+ /// Header flags (e.g. `END_OF_STREAM` or `INCOMPLETE`)
+ #[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
+ pub struct BlockHeaderFlags: u8 {
+ /// Marks the last block in a stream.
+ const END_OF_STREAM = 0b00000001;
+ /// Mark multivolume streams (when set in the last block)
+ const INCOMPLETE = 0b00000010;
+ }
+}
+
+impl BlockHeader {
+ pub const SIZE: usize = PROXMOX_TAPE_BLOCK_SIZE;
+
+ /// Allocates a new instance on the heap
+ pub fn new() -> Box<Self> {
+ use std::alloc::{Layout, alloc_zeroed};
+
+ // align to PAGESIZE, so that we can use it with SG_IO
+ let page_size = unsafe { libc::sysconf(libc::_SC_PAGESIZE) } as usize;
+
+ let mut buffer = unsafe {
+ let ptr = alloc_zeroed(Layout::from_size_align(Self::SIZE, page_size).unwrap());
+ Box::from_raw(core::ptr::slice_from_raw_parts_mut(ptr, Self::SIZE - 16) as *mut Self)
+ };
+ buffer.magic = PROXMOX_TAPE_BLOCK_HEADER_MAGIC_1_0;
+ buffer
+ }
+
+ /// Set the `size` field
+ pub fn set_size(&mut self, size: usize) {
+ let size = size.to_le_bytes();
+ self.size.copy_from_slice(&size[..3]);
+ }
+
+ /// Returns the `size` field
+ pub fn size(&self) -> usize {
+ (self.size[0] as usize) + ((self.size[1] as usize) << 8) + ((self.size[2] as usize) << 16)
+ }
+
+ /// Set the `seq_nr` field
+ pub fn set_seq_nr(&mut self, seq_nr: u32) {
+ self.seq_nr = seq_nr.to_le();
+ }
+
+ /// Returns the `seq_nr` field
+ pub fn seq_nr(&self) -> u32 {
+ u32::from_le(self.seq_nr)
+ }
+}
--
2.47.3
next prev parent reply other threads:[~2026-08-21 14:02 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-21 14:02 [PATCH proxmox{,-backup} v2 00/10] Fix Undefined Behavior in Tape Block Header Deallocation Max R. Carrara
2026-08-21 14:02 ` [PATCH proxmox v2 01/10] proxmox-alloc: introduce proxmox-alloc with `LayoutAwareBox<T>` type Max R. Carrara
2026-08-21 14:02 ` [PATCH proxmox v2 02/10] proxmox-alloc: document undefined behavior regarding custom allocs Max R. Carrara
2026-08-21 14:02 ` Max R. Carrara [this message]
2026-08-21 14:02 ` [PATCH proxmox-backup v2 04/10] tape: rename `BlockHeader` and `BlockHeaderFlags` Max R. Carrara
2026-08-21 14:02 ` [PATCH proxmox-backup v2 05/10] tape: blocked_{reader,writer}: rename `buffer` to `tape_block` Max R. Carrara
2026-08-21 14:02 ` [PATCH proxmox-backup v2 06/10] tape: tape block: represent tape block header with its own struct Max R. Carrara
2026-08-21 14:02 ` [PATCH proxmox-backup v2 07/10] tape: tape block: make `payload` field private Max R. Carrara
2026-08-21 14:02 ` [PATCH proxmox-backup v2 08/10] tape: blocked_{reader,writer}: remove haphazard `unsafe` blocks Max R. Carrara
2026-08-21 14:02 ` [PATCH proxmox-backup v2 09/10] tape: tape block: fix undefined behavior on tape block deallocation Max R. Carrara
2026-08-21 14:02 ` [PATCH proxmox-backup v2 10/10] tape: sgutils2: fix undefined behavior in dealloc of buffer Max R. Carrara
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=20260821140238.615302-4-m.carrara@proxmox.com \
--to=m.carrara@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