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