direct access for journal entries

This commit is contained in:
husky 2023-07-31 07:43:49 -07:00
parent 999336ff9e
commit 3b9b8a6c47
No known key found for this signature in database
GPG key ID: 6B3D8CB511646891
2 changed files with 150 additions and 10 deletions

View file

@ -4,7 +4,7 @@ extern crate alloc;
use alloc::vec::Vec; use alloc::vec::Vec;
use vapfs::{BlockDevice, Index}; use vapfs::{BlockDevice, Index};
use crate::structs::{Inode, Superblock}; use crate::structs::{Inode, JournalEntry, Superblock};
pub mod btree; pub mod btree;
pub mod structs; pub mod structs;
@ -203,4 +203,29 @@ pub unsafe fn set_inode_allocation_status(index: Index, sb: &Superblock, bd: &mu
bd.seek(bitmap_offset); bd.seek(bitmap_offset);
let write_count = bd.write_blocks(&bitmap_buf); let write_count = bd.write_blocks(&bitmap_buf);
write_count == bitmap_length as usize 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<JournalEntry> {
let mut buf: [u8; core::mem::size_of::<JournalEntry>()] = [0; core::mem::size_of::<JournalEntry>()];
bd.seek((sb.first_journal_block * sb.block_size as u64) + (index * core::mem::size_of::<JournalEntry>() as u64));
let read_count = bd.read_blocks(&mut buf);
if read_count < core::mem::size_of::<JournalEntry>() {
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::<JournalEntry>()] = [0; core::mem::size_of::<JournalEntry>()];
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::<JournalEntry>() as u64));
let write_count = bd.write_blocks(&buf);
write_count == core::mem::size_of::<JournalEntry>()
} }

View file

@ -288,12 +288,55 @@ pub enum InodeFlags {
/// # JournalEntry /// # JournalEntry
/// A Journal Entry /// A Journal Entry
#[repr(C)] #[repr(C)]
pub struct JournalHeader { pub struct JournalEntry {
pub flags: u32, 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 /// 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 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 /// # JournalOperation
@ -326,8 +369,8 @@ pub enum JournalOperation {
#[repr(C)] #[repr(C)]
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
pub struct JournalBlockWrite { pub struct JournalBlockWrite {
/// flags stating how far the write has progressed /// JBRFlags stating how far the write has progressed
pub flags: JBRFlags, pub flags: u32,
/// are we writing to an inode instead of a data block? /// are we writing to an inode instead of a data block?
pub target_is_inode: bool, pub target_is_inode: bool,
/// block number of target /// block number of target
@ -338,6 +381,30 @@ pub struct JournalBlockWrite {
pub source_block_crc32: u32, 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 /// # JBRFlags
/// Flags field of a JournalBlockWrite /// Flags field of a JournalBlockWrite
#[repr(u32)] #[repr(u32)]
@ -375,8 +442,8 @@ pub enum JBRFlags {
#[repr(C)] #[repr(C)]
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
pub struct JournalMultiblockWrite { pub struct JournalMultiblockWrite {
/// flags stating how far the write has progressed /// JMWFlags stating how far the write has progressed
pub flags: JMWFlags, pub flags: u32,
/// block number of first target block /// block number of first target block
pub target_block: Index, pub target_block: Index,
/// number of target blocks /// number of target blocks
@ -387,6 +454,32 @@ pub struct JournalMultiblockWrite {
pub list_block_crc32: u32, 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 /// # JMWFlags
/// Flags field of a JournalMultiblockWrite /// Flags field of a JournalMultiblockWrite
#[repr(u32)] #[repr(u32)]
@ -417,10 +510,32 @@ pub struct ListBlock {
pub direct_block_addresses: [Index; 12], 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 /// union of all possible journal entries
#[repr(C)] #[repr(C)]
pub union JournalEntry { pub union JournalEntryContents {
pub block_write: JournalBlockWrite, pub block_write: JournalBlockWrite,
pub multiblock_write: JournalMultiblockWrite, pub multiblock_write: JournalMultiblockWrite,
} }