btrfs_diskformat/chunk/
chunk.rs

1use crate::Stripe;
2use static_assertions::const_assert_eq;
3use zerocopy::{
4    CastError, FromBytes as _,
5    little_endian::{U16 as U16LE, U32 as U32LE, U64 as U64LE},
6};
7use zerocopy_derive::*;
8
9/// This structure contains the mapping from a virtualized usable byte range within the backing
10/// storage to a set of one or more stripes on individual backing devices. In addition to the
11/// mapping, hints on optimal I/O parameters for this chunk. It is associated with `CHUNK_ITEM`.
12///
13/// Although the structure definition only contains one stripe member, `CHUNK_ITEM` contain as
14/// many struct [`Stripe`] structures as specified in the [`num_stripes`] and [`sub_stripes`]
15/// fields.
16///
17/// For the dynamically-sized version of this type with the stripes following, see [`ChunkDynamic`].
18///
19/// [`Stripe`]: crate::Stripe
20/// [`num_stripes`]: Chunk::num_stripes
21/// [`sub_stripes`]: Chunk::sub_stripes
22#[derive(Copy, Clone, Debug, Hash, IntoBytes, FromBytes, Unaligned, KnownLayout, Immutable)]
23#[repr(C, packed)]
24pub struct Chunk {
25    /// The size of this chunk, in bytes.
26    pub length: U64LE,
27
28    /// The object ID of the root referencing this chunk. This is always the ID of an extent root.
29    pub owner: U64LE,
30
31    /// The replication stripe length.
32    pub stripe_len: U64LE,
33
34    /// Flags indicating allocation type and replication policy.
35    pub chunk_type: U64LE,
36
37    /// The optimal I/O alignment for this chunk.
38    pub io_align: U32LE,
39
40    /// The optimal I/O width for this chunk.
41    pub io_width: U32LE,
42
43    /// The minimal I/O size for this chunk.
44    pub sector_size: U32LE,
45
46    /// The number of replication stripes.
47    pub num_stripes: U16LE,
48
49    /// The number of sub-stripes. This is only used for RAID-10.
50    ///
51    /// This is 2 for RAID-10, and 1 for all other chunk types.
52    pub sub_stripes: U16LE,
53}
54const_assert_eq!(core::mem::size_of::<Chunk>(), 48);
55
56impl Chunk {
57    /// A convenience method for converting a [`Chunk`] into a [`ChunkDynamic`].
58    ///
59    /// For a safe version, use [`ChunkDynamic::ref_from_prefix_with_elems`].
60    ///
61    /// # Safety
62    /// This function is unsafe because it assumes that the bytes following the `Chunk` structure
63    /// are valid and contain the expected number of `Stripe` structures as specified by
64    /// `num_stripes`. If this assumption is violated, it may lead to undefined behavior.
65    pub unsafe fn into_dynamic(
66        &self,
67        num_stripes: usize,
68    ) -> Result<&ChunkDynamic, CastError<&[u8], ChunkDynamic>> {
69        // This is simple arithmetic, since this is a packed structure.
70        let expected_size =
71            core::mem::size_of::<Chunk>() + num_stripes * core::mem::size_of::<Stripe>();
72
73        // Safety: We assume the bytes for `num_stripes` after the `Chunk` structure are valid, as
74        // part of the contract of this function.
75        let bytes = unsafe {
76            core::slice::from_raw_parts(self as *const Chunk as *const u8, expected_size)
77        };
78
79        ChunkDynamic::ref_from_prefix_with_elems(bytes, num_stripes).map(|(chunk, _)| chunk)
80    }
81}
82
83/// This structure contains the mapping from a virtualized usable byte range within the backing
84/// storage to a set of one or more stripes on individual backing devices. In addition to the
85/// mapping, hints on optimal I/O parameters for this chunk. It is associated with `CHUNK_ITEM`.
86///
87/// For the constant-sized version of the type, see [`Chunk`].`
88#[derive(IntoBytes, FromBytes, Unaligned, KnownLayout, Immutable)]
89#[repr(C, packed)]
90pub struct ChunkDynamic {
91    /// The size of this chunk, in bytes.
92    pub length: U64LE,
93
94    /// The object ID of the root referencing this chunk. This is always the ID of an extent root.
95    pub owner: U64LE,
96
97    /// The replication stripe length.
98    pub stripe_len: U64LE,
99
100    /// Flags indicating allocation type and replication policy.
101    pub chunk_type: U64LE,
102
103    /// The optimal I/O alignment for this chunk.
104    pub io_align: U32LE,
105
106    /// The optimal I/O width for this chunk.
107    pub io_width: U32LE,
108
109    /// The minimal I/O size for this chunk.
110    pub sector_size: U32LE,
111
112    /// The number of replication stripes.
113    pub num_stripes: U16LE,
114
115    /// The number of sub-stripes. This is only used for RAID-10.
116    pub sub_stripes: U16LE,
117
118    /// The first of one or more stripes that map to device extents.
119    pub stripe: [Stripe],
120}