Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
google
GitHub Repository: google/crosvm
Path: blob/main/ext2/src/superblock.rs
5394 views
1
// Copyright 2024 The ChromiumOS Authors
2
// Use of this source code is governed by a BSD-style license that can be
3
// found in the LICENSE file.
4
5
//! Defines the superblock structure.
6
7
use anyhow::Result;
8
use zerocopy::FromBytes;
9
use zerocopy::Immutable;
10
use zerocopy::IntoBytes;
11
use zerocopy::KnownLayout;
12
13
use crate::arena::Arena;
14
use crate::arena::BlockId;
15
use crate::blockgroup::BLOCK_SIZE;
16
use crate::builder::Builder;
17
use crate::inode::Inode;
18
19
/// The ext2 superblock.
20
///
21
/// The field names are based on [the specification](https://www.nongnu.org/ext2-doc/ext2.html#superblock).
22
/// Note that this struct only holds the fields at the beginning of the superblock. All fields after
23
/// the fields supported by this structure are filled with zeros.
24
#[repr(C)]
25
#[derive(Default, Debug, Copy, Clone, FromBytes, Immutable, IntoBytes, KnownLayout)]
26
pub(crate) struct SuperBlock {
27
pub inodes_count: u32,
28
pub blocks_count: u32,
29
_r_blocks_count: u32,
30
pub free_blocks_count: u32,
31
pub free_inodes_count: u32,
32
_first_data_block: u32,
33
_log_block_size: u32,
34
log_frag_size: u32,
35
pub blocks_per_group: u32,
36
frags_per_group: u32,
37
pub inodes_per_group: u32,
38
mtime: u32,
39
wtime: u32,
40
_mnt_count: u16,
41
_max_mnt_count: u16,
42
magic: u16,
43
state: u16,
44
errors: u16,
45
_minor_rev_level: u16,
46
_lastcheck: u32,
47
_checkinterval: u32,
48
_creator_os: u32,
49
rev_level: u32,
50
_def_resuid: u16,
51
_def_resgid: u16,
52
first_ino: u32,
53
pub inode_size: u16,
54
pub block_group_nr: u16,
55
feature_compat: u32,
56
feature_incompat: u32,
57
_feature_ro_compat: u32,
58
uuid: [u8; 16],
59
// Add more fields if needed.
60
}
61
62
impl SuperBlock {
63
pub fn new<'a>(arena: &'a Arena<'a>, cfg: &Builder) -> Result<&'a mut SuperBlock> {
64
const EXT2_MAGIC_NUMBER: u16 = 0xEF53;
65
const COMPAT_EXT_ATTR: u32 = 0x8;
66
67
let num_groups = cfg.size / (cfg.blocks_per_group * BLOCK_SIZE as u32);
68
let blocks_per_group = cfg.blocks_per_group;
69
let inodes_per_group = cfg.inodes_per_group;
70
71
let log_block_size = 2; // (1024 << log_block_size) = 4K bytes
72
73
let now = std::time::SystemTime::now()
74
.duration_since(std::time::UNIX_EPOCH)?
75
.as_secs() as u32;
76
77
let uuid = uuid::Uuid::new_v4().into_bytes();
78
let inodes_count = inodes_per_group * num_groups;
79
let blocks_count = blocks_per_group * num_groups;
80
81
// Reserve 10 inodes. Usually inode 11 is used for the lost+found directory.
82
// <https://docs.kernel.org/filesystems/ext4/special_inodes.html>.
83
let first_ino = 11;
84
85
// Superblock is located at 1024 bytes in the first block.
86
let sb = arena.allocate::<SuperBlock>(BlockId::from(0), 1024)?;
87
*sb = Self {
88
inodes_count,
89
blocks_count,
90
free_blocks_count: 0, //blocks_count, // All blocks are free
91
free_inodes_count: inodes_count, // All inodes are free
92
_log_block_size: log_block_size,
93
log_frag_size: log_block_size,
94
blocks_per_group,
95
frags_per_group: blocks_per_group,
96
inodes_per_group,
97
mtime: now,
98
wtime: now,
99
magic: EXT2_MAGIC_NUMBER,
100
state: 1, // clean
101
errors: 1, // continue on errors
102
rev_level: 1, // Rev 1 for variable inode sizes
103
first_ino,
104
inode_size: Inode::INODE_RECORD_SIZE as u16,
105
block_group_nr: 1, // super block is in block group 1
106
feature_compat: COMPAT_EXT_ATTR,
107
feature_incompat: 0x2, // Directory entries contain a type field
108
uuid,
109
..Default::default()
110
};
111
112
Ok(sb)
113
}
114
115
#[inline]
116
pub fn num_groups(&self) -> u16 {
117
(self.inodes_count / self.inodes_per_group) as u16
118
}
119
}
120
121