From 3b9b8a6c479673ee8ba0ddc0df3284a7bcec5a76 Mon Sep 17 00:00:00 2001 From: husky Date: Mon, 31 Jul 2023 07:43:49 -0700 Subject: [PATCH] direct access for journal entries --- src/lib.rs | 27 +++++++++- src/structs.rs | 133 +++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 150 insertions(+), 10 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index a2949bd..235dc79 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -4,7 +4,7 @@ extern crate alloc; use alloc::vec::Vec; use vapfs::{BlockDevice, Index}; -use crate::structs::{Inode, Superblock}; +use crate::structs::{Inode, JournalEntry, Superblock}; pub mod btree; pub mod structs; @@ -203,4 +203,29 @@ pub unsafe fn set_inode_allocation_status(index: Index, sb: &Superblock, bd: &mu bd.seek(bitmap_offset); let write_count = bd.write_blocks(&bitmap_buf); write_count == bitmap_length as usize +} + +/// Reads a journal entry by index +pub fn read_journal_entry(index: Index, sb: &Superblock, bd: &mut dyn BlockDevice) -> Option { + let mut buf: [u8; core::mem::size_of::()] = [0; core::mem::size_of::()]; + bd.seek((sb.first_journal_block * sb.block_size as u64) + (index * core::mem::size_of::() as u64)); + let read_count = bd.read_blocks(&mut buf); + if read_count < core::mem::size_of::() { + return None; + } + let mut entry = unsafe { core::ptr::read(buf.as_ptr() as *const JournalEntry) }; + entry.convert_big_endian_to_native(); + Some(entry) +} + +/// Performs a direct write of a journal entry to the block device. +/// # Safety +/// unsafe because it assumes that the entry is correctly formatted and that everything has been performed correctly +pub unsafe fn write_journal_entry(index: Index, sb: &Superblock, bd: &mut dyn BlockDevice, mut entry: JournalEntry) -> bool { + entry.convert_native_to_big_endian(); + let mut buf: [u8; core::mem::size_of::()] = [0; core::mem::size_of::()]; + core::ptr::write(buf.as_mut_ptr() as *mut JournalEntry, entry); + bd.seek((sb.first_journal_block * sb.block_size as u64) + (index * core::mem::size_of::() as u64)); + let write_count = bd.write_blocks(&buf); + write_count == core::mem::size_of::() } \ No newline at end of file diff --git a/src/structs.rs b/src/structs.rs index f39200a..cb4cf44 100644 --- a/src/structs.rs +++ b/src/structs.rs @@ -288,12 +288,55 @@ pub enum InodeFlags { /// # JournalEntry /// A Journal Entry #[repr(C)] -pub struct JournalHeader { +pub struct JournalEntry { pub flags: u32, - pub operation: JournalOperation, + /// JournalOperation + pub operation: u32, /// 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, - pub content: JournalEntry, + 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.flags = u32::from_be(self.flags); + 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.flags = u32::to_be(self.flags); + 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() }; + } + + _ => {} + } + } + } } /// # JournalOperation @@ -326,8 +369,8 @@ pub enum JournalOperation { #[repr(C)] #[derive(Copy, Clone)] pub struct JournalBlockWrite { - /// flags stating how far the write has progressed - pub flags: JBRFlags, + /// JBRFlags stating how far the write has progressed + pub flags: u32, /// are we writing to an inode instead of a data block? pub target_is_inode: bool, /// block number of target @@ -338,6 +381,30 @@ pub struct JournalBlockWrite { pub source_block_crc32: u32, } +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); + } + } +} + /// # JBRFlags /// Flags field of a JournalBlockWrite #[repr(u32)] @@ -375,8 +442,8 @@ pub enum JBRFlags { #[repr(C)] #[derive(Copy, Clone)] pub struct JournalMultiblockWrite { - /// flags stating how far the write has progressed - pub flags: JMWFlags, + /// JMWFlags stating how far the write has progressed + pub flags: u32, /// block number of first target block pub target_block: Index, /// number of target blocks @@ -387,6 +454,32 @@ pub struct JournalMultiblockWrite { pub list_block_crc32: u32, } +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); + } + } +} + /// # JMWFlags /// Flags field of a JournalMultiblockWrite #[repr(u32)] @@ -417,10 +510,32 @@ pub struct ListBlock { pub direct_block_addresses: [Index; 12], } -/// # JournalEntry +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")] + { + for i in 0..12 { + self.direct_block_addresses[i] = u64::from_be(self.direct_block_addresses[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")] + { + for i in 0..12 { + self.direct_block_addresses[i] = u64::to_be(self.direct_block_addresses[i]); + } + } + } +} + +/// # JournalEntryContents /// union of all possible journal entries #[repr(C)] -pub union JournalEntry { +pub union JournalEntryContents { pub block_write: JournalBlockWrite, pub multiblock_write: JournalMultiblockWrite, } \ No newline at end of file