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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.