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 vapfs::{BlockDevice, Index};
|
||||
use crate::structs::{Inode, Superblock};
|
||||
use crate::structs::{Inode, JournalEntry, Superblock};
|
||||
|
||||
pub mod btree;
|
||||
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);
|
||||
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
|
||||
/// 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,
|
||||
}
|
Loading…
Add table
Reference in a new issue