direct access for journal entries
This commit is contained in:
parent
999336ff9e
commit
3b9b8a6c47
2 changed files with 150 additions and 10 deletions
27
src/lib.rs
27
src/lib.rs
|
@ -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;
|
||||||
|
@ -204,3 +204,28 @@ pub unsafe fn set_inode_allocation_status(index: Index, sb: &Superblock, bd: &mu
|
||||||
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>()
|
||||||
|
}
|
133
src/structs.rs
133
src/structs.rs
|
@ -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,
|
||||||
}
|
}
|
Loading…
Add table
Reference in a new issue