2023-07-25 07:03:06 -07:00
use vapfs ::{ Index , Timestamp } ;
2023-07-27 09:28:06 -07:00
use crate ::crc32 ;
2023-07-25 07:03:06 -07:00
/// # Magic
/// Constant value that identifies the Superblock as a valid VapUFS filesystem
pub const MAGIC : u64 = 0x766170554653 ;
/// # Superblock
/// The primary struct of a VapUFS filesystem, contains metadata about the filesystem.
2023-09-10 00:02:26 -07:00
/// Located at byte offset 2048 of the block device.
2023-07-25 07:03:06 -07:00
/// All values are big-endian unless otherwise specified.
2023-08-12 16:38:37 -07:00
/// Directly after (i.e. the next block after) the Superblock are the free data blocks bitmap and the free inodes bitmap.
2023-07-25 07:03:06 -07:00
/// Free data blocks bitmap is data_block_count / 8 bytes long (rounded up).
/// Free inodes bitmap is inode_count / 8 bytes long (rounded up).
#[ repr(C) ]
2023-08-11 15:04:54 -07:00
#[ derive(Copy, Clone) ]
2023-07-25 07:03:06 -07:00
pub struct Superblock {
/// magic number that identifies the Superblock as a valid VapUFS filesystem
pub magic : u64 ,
2023-09-10 00:02:26 -07:00
/// size of each block in bytes, must be *at least* 2048 bytes
2023-07-25 07:03:06 -07:00
pub block_size : u32 ,
/// location of first data block in blocks
pub first_data_block : Index ,
/// location of first inode block in blocks
pub first_inode_block : Index ,
/// location of first journal block in blocks
pub first_journal_block : Index ,
/// total count of inodes, including unused inodes
pub inode_count : Index ,
/// total count of data blocks, including unused blocks
pub data_block_count : Index ,
/// total count of blocks dedicated to journal
pub journal_block_count : Index ,
/// total count of inodes in use
pub allocated_inode_count : Index ,
/// total count of data blocks in use
pub allocated_data_block_count : Index ,
/// timestamp of creation
pub creation_time : Timestamp ,
/// timestamp of last modification
pub last_modification_time : Timestamp ,
2023-07-27 09:28:06 -07:00
/// crc32 checksum of this Superblock
pub checksum : u32 ,
2023-08-07 15:15:39 -07:00
/// index of the current journal entry being processed
/// incremented after a journal entry is committed, set to 0 if past max
pub journal_position : u32 ,
2023-07-25 07:03:06 -07:00
/// reserved values for expansion
2023-07-27 09:28:06 -07:00
pub reserved : [ u64 ; 7 ] ,
2023-07-25 07:03:06 -07:00
// 156 bytes used so far
2023-08-12 16:38:37 -07:00
// next block is used by the free data blocks bitmap and the free inodes bitmap
2023-07-25 07:03:06 -07:00
}
2023-07-27 09:28:06 -07:00
impl Superblock {
/// in-place conversion from the storage representation (big endian) to the native representation
pub fn convert_big_endian_to_native ( & mut self ) {
#[ cfg(target_endian = " little " ) ]
{
self . magic = u64 ::from_be ( self . magic ) ;
self . block_size = u32 ::from_be ( self . block_size ) ;
self . first_data_block = u64 ::from_be ( self . first_data_block ) ;
self . first_inode_block = u64 ::from_be ( self . first_inode_block ) ;
self . first_journal_block = u64 ::from_be ( self . first_journal_block ) ;
self . inode_count = u64 ::from_be ( self . inode_count ) ;
self . data_block_count = u64 ::from_be ( self . data_block_count ) ;
self . journal_block_count = u64 ::from_be ( self . journal_block_count ) ;
self . allocated_inode_count = u64 ::from_be ( self . allocated_inode_count ) ;
self . allocated_data_block_count = u64 ::from_be ( self . allocated_data_block_count ) ;
self . creation_time = u64 ::from_be ( self . creation_time ) ;
self . last_modification_time = u64 ::from_be ( self . last_modification_time ) ;
for i in 0 .. 8 {
self . reserved [ i ] = u64 ::from_be ( self . reserved [ i ] ) ;
}
}
}
/// in-place conversion from the native representation to the storage representation (big endian)
pub fn convert_native_to_big_endian ( & mut self ) {
#[ cfg(target_endian = " little " ) ]
{
self . magic = u64 ::to_be ( self . magic ) ;
self . block_size = u32 ::to_be ( self . block_size ) ;
self . first_data_block = u64 ::to_be ( self . first_data_block ) ;
self . first_inode_block = u64 ::to_be ( self . first_inode_block ) ;
self . first_journal_block = u64 ::to_be ( self . first_journal_block ) ;
self . inode_count = u64 ::to_be ( self . inode_count ) ;
self . data_block_count = u64 ::to_be ( self . data_block_count ) ;
self . journal_block_count = u64 ::to_be ( self . journal_block_count ) ;
self . allocated_inode_count = u64 ::to_be ( self . allocated_inode_count ) ;
self . allocated_data_block_count = u64 ::to_be ( self . allocated_data_block_count ) ;
self . creation_time = u64 ::to_be ( self . creation_time ) ;
self . last_modification_time = u64 ::to_be ( self . last_modification_time ) ;
for i in 0 .. 8 {
self . reserved [ i ] = u64 ::to_be ( self . reserved [ i ] ) ;
}
}
}
/// returns true if the crc32 checksum is currently valid
/// returns false otherwise
pub fn is_checksum_valid ( & self ) -> bool {
let mut buf = [ 0 ; core ::mem ::size_of ::< Self > ( ) - ( 8 * 8 ) ] ; // don't hash last 7 u64s, the reserved u32, or the checksum
unsafe {
core ::ptr ::copy ( self as * const Self as * const u8 , buf . as_mut_ptr ( ) , buf . len ( ) ) ;
}
let checksum = crc32 ::crc32 ( & buf ) ;
checksum = = self . checksum
}
/// updates the crc32 checksum
pub fn recalculate_checksum ( & mut self ) {
let mut buf = [ 0 ; core ::mem ::size_of ::< Self > ( ) - ( 8 * 8 ) ] ; // don't hash last 7 u64s, the reserved u32, or the checksum
unsafe {
core ::ptr ::copy ( self as * const Self as * const u8 , buf . as_mut_ptr ( ) , buf . len ( ) ) ;
}
let checksum = crc32 ::crc32 ( & buf ) ;
self . checksum = checksum ;
}
}
2023-07-25 07:03:06 -07:00
/// # UNIXPermissions
/// UNIX permissions
#[ repr(u16) ]
pub enum UNIXMode {
/// Read, Other
Read = 1 < < 0 ,
/// Write, Other
Write = 1 < < 1 ,
/// Execute, Other
Execute = 1 < < 2 ,
/// Read, Group
ReadGroup = 1 < < 3 ,
/// Write, Group
WriteGroup = 1 < < 4 ,
/// Execute, Group
ExecuteGroup = 1 < < 5 ,
/// Read, Owner
ReadOwner = 1 < < 6 ,
/// Write, Owner
WriteOwner = 1 < < 7 ,
/// Execute, Owner
ExecuteOwner = 1 < < 8 ,
/// Sticky bit
Sticky = 1 < < 9 ,
/// Set GID
SetGID = 1 < < 10 ,
/// Set UID
SetUID = 1 < < 11 ,
}
/// # Filetype
/// Represents a file's type in the last 4 bits of the mode field of an inode.
#[ repr(u16) ]
pub enum Filetype {
/// Named FIFO pipe
FIFO = 0b0001 < < 12 ,
/// Character device
CharDevice = 0b0010 < < 12 ,
/// Directory
Directory = 0b0011 < < 12 ,
/// Block device
BlockDevice = 0b0100 < < 12 ,
/// Regular file
RegularFile = 0b0101 < < 12 ,
/// Symbolic link
SymbolicLink = 0b0110 < < 12 ,
/// Socket
Socket = 0b0111 < < 12 ,
}
/// # Inode
/// Usually represents a file or directory, used to store metadata and locations of data blocks.
#[ repr(C) ]
pub struct Inode {
/// UNIX permissions / mode and filetype
pub mode : u16 ,
/// Number of links to this inode
pub link_count : u16 ,
/// User ID of owner
pub uid : u32 ,
/// Group ID of owner
pub gid : u32 ,
/// Size in bytes
pub size : Index ,
/// Size in blocks
pub block_count : Index ,
/// Timestamp of creation
pub creation_time : Timestamp ,
/// Timestamp of last access
pub last_access_time : Timestamp ,
/// Timestamp of last modification
pub last_modification_time : Timestamp ,
/// Timestamp of last Inode modification
pub last_inode_modification_time : Timestamp ,
/// Timestamp of deletion
pub deletion_time : Timestamp ,
/// Flags field, see `InodeFlags`
pub flags : u32 ,
2023-09-10 00:02:26 -07:00
/// listblock for storing data block addresses
pub listblock : ListBlock ,
2023-07-25 07:03:06 -07:00
/// CRC32 checksum of this inode
pub checksum : u32 ,
2023-07-27 09:28:06 -07:00
}
impl Inode {
/// in-place conversion from the storage representation (big endian) to the native representation
pub fn convert_big_endian_to_native ( & mut self ) {
#[ cfg(target_endian = " little " ) ]
{
self . mode = u16 ::from_be ( self . mode ) ;
self . link_count = u16 ::from_be ( self . link_count ) ;
self . uid = u32 ::from_be ( self . uid ) ;
self . gid = u32 ::from_be ( self . gid ) ;
self . size = u64 ::from_be ( self . size ) ;
self . block_count = u64 ::from_be ( self . block_count ) ;
self . creation_time = u64 ::from_be ( self . creation_time ) ;
self . last_access_time = u64 ::from_be ( self . last_access_time ) ;
self . last_modification_time = u64 ::from_be ( self . last_modification_time ) ;
self . last_inode_modification_time = u64 ::from_be ( self . last_inode_modification_time ) ;
self . deletion_time = u64 ::from_be ( self . deletion_time ) ;
self . flags = u32 ::from_be ( self . flags ) ;
2023-09-10 00:02:26 -07:00
self . listblock . convert_big_endian_to_native ( ) ;
2023-07-27 09:28:06 -07:00
self . checksum = u32 ::from_be ( self . checksum ) ;
}
}
/// in-place conversion from the native representation to the storage representation (big endian)
pub fn convert_native_to_big_endian ( & mut self ) {
#[ cfg(target_endian = " little " ) ]
{
self . mode = u16 ::to_be ( self . mode ) ;
self . link_count = u16 ::to_be ( self . link_count ) ;
self . uid = u32 ::to_be ( self . uid ) ;
self . gid = u32 ::to_be ( self . gid ) ;
self . size = u64 ::to_be ( self . size ) ;
self . block_count = u64 ::to_be ( self . block_count ) ;
self . creation_time = u64 ::to_be ( self . creation_time ) ;
self . last_access_time = u64 ::to_be ( self . last_access_time ) ;
self . last_modification_time = u64 ::to_be ( self . last_modification_time ) ;
self . last_inode_modification_time = u64 ::to_be ( self . last_inode_modification_time ) ;
self . deletion_time = u64 ::to_be ( self . deletion_time ) ;
self . flags = u32 ::to_be ( self . flags ) ;
2023-09-10 00:02:26 -07:00
self . listblock . convert_native_to_big_endian ( ) ;
2023-07-27 09:28:06 -07:00
self . checksum = u32 ::to_be ( self . checksum ) ;
}
}
/// returns true if the crc32 checksum is currently valid
/// returns false otherwise
pub fn is_checksum_valid ( & self ) -> bool {
let mut buf = [ 0 ; core ::mem ::size_of ::< Self > ( ) - 4 ] ; // don't hash the checksum
unsafe {
core ::ptr ::copy ( self as * const Self as * const u8 , buf . as_mut_ptr ( ) , buf . len ( ) ) ;
}
let checksum = crc32 ::crc32 ( & buf ) ;
checksum = = self . checksum
}
/// updates the crc32 checksum
pub fn recalculate_checksum ( & mut self ) {
let mut buf = [ 0 ; core ::mem ::size_of ::< Self > ( ) - 4 ] ; // don't hash the checksum
unsafe {
core ::ptr ::copy ( self as * const Self as * const u8 , buf . as_mut_ptr ( ) , buf . len ( ) ) ;
}
let checksum = crc32 ::crc32 ( & buf ) ;
self . checksum = checksum ;
}
2023-07-25 07:03:06 -07:00
}
/// # InodeFlags
/// Flags field of an inode
#[ repr(u32) ]
pub enum InodeFlags {
/// File is corrupted
CORRUPT = 1 < < 0 ,
2023-09-10 00:02:26 -07:00
/// File uses Single Indirect Block
INDIRECT1 = 1 < < 1 ,
/// File uses Double Indirect Block
INDIRECT2 = 1 < < 2 ,
/// File uses Triple Indirect Block
INDIRECT3 = 1 < < 3 ,
/// File uses Quadruple Indirect Block
INDIRECT4 = 1 < < 4 ,
/// File uses Quintuple Indirect Block
INDIRECT5 = 1 < < 5 ,
/// File uses Sextuple Indirect Block
INDIRECT6 = 1 < < 6 ,
2023-07-27 09:28:06 -07:00
}
/// # JournalEntry
/// A Journal Entry
#[ repr(C) ]
2023-08-07 15:15:39 -07:00
#[ derive(Copy, Clone) ]
2023-07-31 07:43:49 -07:00
pub struct JournalEntry {
/// JournalOperation
pub operation : u32 ,
2023-07-27 09:28:06 -07:00
/// crc32 hash of the content with flags set to zero, used to verify journal was fully written without verifying the stage
pub zeroed_content_crc32 : u32 ,
2023-07-31 07:43:49 -07:00
pub content : JournalEntryContents ,
}
impl JournalEntry {
/// in-place conversion from the storage representation (big endian) to the native representation
pub fn convert_big_endian_to_native ( & mut self ) {
#[ cfg(target_endian = " little " ) ]
{
self . operation = u32 ::from_be ( self . operation ) ;
self . zeroed_content_crc32 = u32 ::from_be ( self . zeroed_content_crc32 ) ;
match self . operation {
0 = > { // SingleBlockWrite
unsafe { self . content . block_write . convert_big_endian_to_native ( ) } ;
}
1 = > { // MultiblockWrite
unsafe { self . content . multiblock_write . convert_big_endian_to_native ( ) } ;
}
_ = > { }
}
}
}
/// in-place conversion from the native representation to the storage representation (big endian)
pub fn convert_native_to_big_endian ( & mut self ) {
#[ cfg(target_endian = " little " ) ]
{
self . operation = u32 ::to_be ( self . operation ) ;
self . zeroed_content_crc32 = u32 ::to_be ( self . zeroed_content_crc32 ) ;
match self . operation {
0 = > { // SingleBlockWrite
unsafe { self . content . block_write . convert_native_to_big_endian ( ) } ;
}
1 = > { // MultiblockWrite
unsafe { self . content . multiblock_write . convert_native_to_big_endian ( ) } ;
}
_ = > { }
}
}
}
2023-07-27 09:28:06 -07:00
}
/// # JournalOperation
/// Type of operation performed by a Journal Entry
#[ repr(u32) ]
pub enum JournalOperation {
/// A single block write, described by a `JournalBlockWrite`
SingleBlockWrite = 0 ,
/// A multi-block write, described by a `JournalMultiblockWrite`
MultiblockWrite = 1 ,
}
/// # JournalBlockWrite
/// writes are performed as follows:
/// 1. create and write the journal entry
/// 2. allocate a data block for the data to be written
/// 3. set the entry's allocated flag
/// 4. write the data to the allocated data block
/// 5. set the entry's stored flag
/// == the following steps will be performed upon a journal flush, i.e. when the driver has decided that it's time to finally "commit" the journal ==
/// 6. depending on the destination of the write, either:
/// - update inode metadata to point to the new data block
/// - copy the data from the old data block to the new data block
/// 7. set the entry's written flag
/// 8. deallocate the old data block
/// 9. set the entry's deallocated flag
/// == done! ==
/// ideally, with this schema the filesystem shall never become corrupt
/// all fields in the entry should be modified individually on the block device instead of rewriting the entire entry
#[ repr(C) ]
#[ derive(Copy, Clone) ]
pub struct JournalBlockWrite {
2023-07-31 07:43:49 -07:00
/// JBRFlags stating how far the write has progressed
pub flags : u32 ,
2023-08-12 16:38:37 -07:00
/// are we writing to an inode instead of a data block, or maybe even directly to the disk?
/// see JBRTargetType
pub target_type : u32 ,
2023-08-07 15:15:39 -07:00
/// target inode number
pub target_inode : Index ,
/// target block number (if target is a data block, this will be the index in the inode's direct block array;
2023-09-10 00:02:26 -07:00
/// if greater than 32, see the following:
/// let N = maximum number of pointers in an indirect block
/// (beginning...count)
/// 32..N: single indirect block
/// 32+N..N^2: double indirect block
/// 32+N^2..N^3: triple indirect block
/// 32+N^3..N^4: quadruple indirect block
/// 32+N^4..N^5: quintuple indirect block
/// 32+N^5..N^6: sextuple indirect block
2023-07-27 09:28:06 -07:00
pub target_block : Index ,
2023-08-11 15:04:54 -07:00
/// actual data block number, unused if target is an inode
pub real_target_block : Index ,
2023-07-27 09:28:06 -07:00
/// block number of source data block
pub source_block : Index ,
/// crc32 hash of the source data block
pub source_block_crc32 : u32 ,
}
2023-07-31 07:43:49 -07:00
impl JournalBlockWrite {
/// in-place conversion from the storage representation (big endian) to the native representation
pub fn convert_big_endian_to_native ( & mut self ) {
#[ cfg(target_endian = " little " ) ]
{
self . flags = u32 ::from_be ( self . flags ) ;
self . target_block = u64 ::from_be ( self . target_block ) ;
self . source_block = u64 ::from_be ( self . source_block ) ;
self . source_block_crc32 = u32 ::from_be ( self . source_block_crc32 ) ;
}
}
/// in-place conversion from the native representation to the storage representation (big endian)
pub fn convert_native_to_big_endian ( & mut self ) {
#[ cfg(target_endian = " little " ) ]
{
self . flags = u32 ::to_be ( self . flags ) ;
self . target_block = u64 ::to_be ( self . target_block ) ;
self . source_block = u64 ::to_be ( self . source_block ) ;
self . source_block_crc32 = u32 ::to_be ( self . source_block_crc32 ) ;
}
}
}
2023-07-27 09:28:06 -07:00
/// # JBRFlags
/// Flags field of a JournalBlockWrite
#[ repr(u32) ]
#[ derive(Copy, Clone) ]
pub enum JBRFlags {
2023-08-07 15:15:39 -07:00
/// source data block has been chosen but not yet allocated
Chosen = 1 ,
2023-07-27 09:28:06 -07:00
/// source data block has been allocated
2023-08-07 15:15:39 -07:00
Allocated = 2 ,
2023-07-27 09:28:06 -07:00
/// data has been written to the source data block
2023-08-07 15:15:39 -07:00
Stored = 3 ,
2023-07-27 09:28:06 -07:00
/// source data block has either replaced an old data block or has been written to an inode
2023-08-07 15:15:39 -07:00
Written = 4 ,
2023-07-27 09:28:06 -07:00
/// source data block (in the case of a write to an inode) or old data block (in the case of a write to a data block) has been deallocated
/// (i.e. this journal entry has been fully committed)
2023-08-07 15:15:39 -07:00
CompleteAndDeallocated = 0 ,
2023-07-27 09:28:06 -07:00
}
2023-08-12 16:38:37 -07:00
/// # JBRTargetType
/// Type of target of a JournalBlockWrite
#[ repr(u32) ]
#[ derive(Copy, Clone) ]
pub enum JBRTargetType {
/// target is a data block
DataBlock = 0 ,
/// target is an inode
Inode = 1 ,
/// target is the disk itself
Disk = 2 ,
}
2023-07-27 09:28:06 -07:00
/// # JournalMultiblockWrite
/// a special entry for writing to multiple blocks at once,
/// used for circumstances where it is very important that all blocks are either
2023-08-21 22:04:10 -07:00
/// written successfully, or not written at all (i.e. directory blocks).
/// all data stored in an inode must be written at once using this operation,
/// so it may not be suitable for large files.
2023-07-27 09:28:06 -07:00
/// writes are performed as follows:
/// 1. create and write the journal entry
/// 2. allocate a data block to store a MultiblockWriteList
/// 3. set the entry's allocated_list flag
/// 4. allocate data blocks to store the data to be written
/// 5. set the entry's allocated_data flag
/// 6. write the data to the allocated data blocks and the list to the allocated list block
/// 7. set the entry's stored flag
/// == the following steps will be performed upon a journal flush ==
/// 8. update inode metadata to point to the new data blocks
/// 9. set the entry's written flag
/// 10. deallocate the old data blocks & list block
/// 11. set the entry's deallocated flag
/// == done! ==
#[ repr(C) ]
#[ derive(Copy, Clone) ]
pub struct JournalMultiblockWrite {
2023-07-31 07:43:49 -07:00
/// JMWFlags stating how far the write has progressed
pub flags : u32 ,
2023-08-07 15:15:39 -07:00
/// inode number of target inode
pub target_inode : Index ,
2023-07-27 09:28:06 -07:00
/// block number of first target block
pub target_block : Index ,
/// number of target blocks
pub target_block_count : Index ,
/// block number of list block structure
pub list_block : Index ,
2023-08-11 15:59:26 -07:00
/// block number of old list block structure
pub old_list_block : Index ,
2023-07-27 09:28:06 -07:00
/// crc32 hash of the list block
pub list_block_crc32 : u32 ,
}
2023-07-31 07:43:49 -07:00
impl JournalMultiblockWrite {
/// in-place conversion from the storage representation (big endian) to the native representation
pub fn convert_big_endian_to_native ( & mut self ) {
#[ cfg(target_endian = " little " ) ]
{
self . flags = u32 ::from_be ( self . flags ) ;
self . target_block = u64 ::from_be ( self . target_block ) ;
self . target_block_count = u64 ::from_be ( self . target_block_count ) ;
self . list_block = u64 ::from_be ( self . list_block ) ;
self . list_block_crc32 = u32 ::from_be ( self . list_block_crc32 ) ;
}
}
/// in-place conversion from the native representation to the storage representation (big endian)
pub fn convert_native_to_big_endian ( & mut self ) {
#[ cfg(target_endian = " little " ) ]
{
self . flags = u32 ::to_be ( self . flags ) ;
self . target_block = u64 ::to_be ( self . target_block ) ;
self . target_block_count = u64 ::to_be ( self . target_block_count ) ;
self . list_block = u64 ::to_be ( self . list_block ) ;
self . list_block_crc32 = u32 ::to_be ( self . list_block_crc32 ) ;
}
}
}
2023-07-27 09:28:06 -07:00
/// # JMWFlags
/// Flags field of a JournalMultiblockWrite
#[ repr(u32) ]
#[ derive(Copy, Clone) ]
pub enum JMWFlags {
2023-08-07 15:15:39 -07:00
/// list block has been chosen but not yet allocated
ChosenList = 1 ,
2023-07-27 09:28:06 -07:00
/// list block has been allocated
2023-08-07 15:15:39 -07:00
AllocatedList = 2 ,
/// data blocks have been chosen and stored in the list block but not yet allocated
ChosenData = 3 ,
2023-07-27 09:28:06 -07:00
/// data blocks have been allocated
2023-08-07 15:15:39 -07:00
AllocatedData = 4 ,
2023-07-27 09:28:06 -07:00
/// data has been written to the data blocks and the list block
2023-08-07 15:15:39 -07:00
Stored = 5 ,
2023-07-27 09:28:06 -07:00
/// data blocks have replaced old data blocks
2023-08-07 15:15:39 -07:00
Written = 6 ,
2023-07-27 09:28:06 -07:00
/// data blocks and list block have been deallocated
/// (i.e. this journal entry has been fully committed)
2023-08-07 15:15:39 -07:00
CompleteAndDeallocated = 0 ,
2023-07-27 09:28:06 -07:00
}
/// # ListBlock
/// a list of data blocks for a journaled multiblock write, similar in structure to an inode
#[ repr(C) ]
#[ derive(Copy, Clone) ]
pub struct ListBlock {
2023-09-10 00:02:26 -07:00
/// Count of blocks used
pub count : Index ,
/// Direct-Block-Addresses
pub direct_block_addresses : [ Index ; 32 ] ,
/// Single Indirect-Block-Address
/// Indirect blocks are Indexes to other blocks, their contents are N u64 data pointers
pub single_indirect_block_address : [ Index ; 32 ] ,
/// Double Indirect-Block-Address
/// Double indirect blocks are Indexes to other blocks, their contents are N u64 indirect block pointers (they point to single indirect blocks)
pub double_indirect_block_address : [ Index ; 32 ] ,
/// Triple Indirect-Block-Address
/// Triple indirect blocks are Indexes to other blocks, their contents are N u64 double indirect block pointers (they point to double indirect blocks)
pub triple_indirect_block_address : [ Index ; 32 ] ,
/// Quadruple Indirect-Block-Address
/// Quadruple indirect blocks are Indexes to other blocks, their contents are N u64 triple indirect block pointers (they point to triple indirect blocks)
pub quadruple_indirect_block_address : [ Index ; 32 ] ,
/// Quintuple Indirect-Block-Address
/// Quintuple indirect blocks are Indexes to other blocks, their contents are N u64 quadruple indirect block pointers (they point to quadruple indirect blocks)
pub quintuple_indirect_block_address : [ Index ; 32 ] ,
/// Sextuple Indirect-Block-Address
/// Sextuple indirect blocks are Indexes to other blocks, their contents are N u64 quintuple indirect block pointers (they point to quintuple indirect blocks)
pub sextuple_indirect_block_address : [ Index ; 32 ] ,
2023-07-27 09:28:06 -07:00
}
2023-07-31 07:43:49 -07:00
impl ListBlock {
/// in-place conversion from the storage representation (big endian) to the native representation
pub fn convert_big_endian_to_native ( & mut self ) {
#[ cfg(target_endian = " little " ) ]
{
2023-09-10 00:02:26 -07:00
for i in 0 .. 32 {
2023-07-31 07:43:49 -07:00
self . direct_block_addresses [ i ] = u64 ::from_be ( self . direct_block_addresses [ i ] ) ;
2023-09-10 00:02:26 -07:00
self . single_indirect_block_address [ i ] = u64 ::from_be ( self . single_indirect_block_address [ i ] ) ;
self . double_indirect_block_address [ i ] = u64 ::from_be ( self . double_indirect_block_address [ i ] ) ;
self . triple_indirect_block_address [ i ] = u64 ::from_be ( self . triple_indirect_block_address [ i ] ) ;
self . quadruple_indirect_block_address [ i ] = u64 ::from_be ( self . quadruple_indirect_block_address [ i ] ) ;
self . quintuple_indirect_block_address [ i ] = u64 ::from_be ( self . quintuple_indirect_block_address [ i ] ) ;
self . sextuple_indirect_block_address [ i ] = u64 ::from_be ( self . sextuple_indirect_block_address [ i ] ) ;
2023-07-31 07:43:49 -07:00
}
}
}
/// in-place conversion from the native representation to the storage representation (big endian)
pub fn convert_native_to_big_endian ( & mut self ) {
#[ cfg(target_endian = " little " ) ]
{
2023-09-10 00:02:26 -07:00
for i in 0 .. 32 {
2023-07-31 07:43:49 -07:00
self . direct_block_addresses [ i ] = u64 ::to_be ( self . direct_block_addresses [ i ] ) ;
2023-09-10 00:02:26 -07:00
self . single_indirect_block_address [ i ] = u64 ::to_be ( self . single_indirect_block_address [ i ] ) ;
self . double_indirect_block_address [ i ] = u64 ::to_be ( self . double_indirect_block_address [ i ] ) ;
self . triple_indirect_block_address [ i ] = u64 ::to_be ( self . triple_indirect_block_address [ i ] ) ;
self . quadruple_indirect_block_address [ i ] = u64 ::to_be ( self . quadruple_indirect_block_address [ i ] ) ;
self . quintuple_indirect_block_address [ i ] = u64 ::to_be ( self . quintuple_indirect_block_address [ i ] ) ;
self . sextuple_indirect_block_address [ i ] = u64 ::to_be ( self . sextuple_indirect_block_address [ i ] ) ;
2023-07-31 07:43:49 -07:00
}
}
}
}
/// # JournalEntryContents
2023-07-27 09:28:06 -07:00
/// union of all possible journal entries
#[ repr(C) ]
2023-08-07 15:15:39 -07:00
#[ derive(Copy, Clone) ]
2023-07-31 07:43:49 -07:00
pub union JournalEntryContents {
2023-07-27 09:28:06 -07:00
pub block_write : JournalBlockWrite ,
pub multiblock_write : JournalMultiblockWrite ,
2023-07-25 07:03:06 -07:00
}