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}