RedoxFS 0.5.0
Significant re-design to use copy-on-write and hashes for all data
This commit is contained in:
committed by
Jeremy Soller
parent
c98e63af87
commit
731b97262b
+207
@@ -0,0 +1,207 @@
|
||||
use core::{fmt, marker::PhantomData, mem, ops, slice};
|
||||
use simple_endian::*;
|
||||
|
||||
use crate::BLOCK_SIZE;
|
||||
|
||||
#[derive(Clone, Copy, Debug, Default)]
|
||||
pub struct BlockData<T> {
|
||||
addr: u64,
|
||||
data: T,
|
||||
}
|
||||
|
||||
impl<T> BlockData<T> {
|
||||
pub fn new(addr: u64, data: T) -> Self {
|
||||
Self { addr, data }
|
||||
}
|
||||
|
||||
pub fn addr(&self) -> u64 {
|
||||
self.addr
|
||||
}
|
||||
|
||||
#[must_use = "don't forget to de-allocate old block address"]
|
||||
pub fn swap_addr(&mut self, addr: u64) -> u64 {
|
||||
let old = self.addr;
|
||||
self.addr = addr;
|
||||
old
|
||||
}
|
||||
|
||||
pub fn data(&self) -> &T {
|
||||
&self.data
|
||||
}
|
||||
|
||||
pub fn data_mut(&mut self) -> &mut T {
|
||||
&mut self.data
|
||||
}
|
||||
|
||||
pub fn into_data(self) -> T {
|
||||
self.data
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ops::Deref<Target = [u8]>> BlockData<T> {
|
||||
pub fn create_ptr(&self) -> BlockPtr<T> {
|
||||
BlockPtr {
|
||||
addr: self.addr.into(),
|
||||
hash: seahash::hash(self.data.deref()).into(),
|
||||
phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(packed)]
|
||||
pub struct BlockList<T> {
|
||||
pub ptrs: [BlockPtr<T>; 256],
|
||||
}
|
||||
|
||||
impl<T> BlockList<T> {
|
||||
pub fn is_empty(&self) -> bool {
|
||||
for ptr in self.ptrs.iter() {
|
||||
if !ptr.is_null() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Default for BlockList<T> {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
ptrs: [BlockPtr::default(); 256],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> ops::Deref for BlockList<T> {
|
||||
type Target = [u8];
|
||||
fn deref(&self) -> &[u8] {
|
||||
unsafe {
|
||||
slice::from_raw_parts(
|
||||
self as *const BlockList<T> as *const u8,
|
||||
mem::size_of::<BlockList<T>>(),
|
||||
) as &[u8]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> ops::DerefMut for BlockList<T> {
|
||||
fn deref_mut(&mut self) -> &mut [u8] {
|
||||
unsafe {
|
||||
slice::from_raw_parts_mut(
|
||||
self as *mut BlockList<T> as *mut u8,
|
||||
mem::size_of::<BlockList<T>>(),
|
||||
) as &mut [u8]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(packed)]
|
||||
pub struct BlockPtr<T> {
|
||||
addr: u64le,
|
||||
hash: u64le,
|
||||
phantom: PhantomData<T>,
|
||||
}
|
||||
|
||||
impl<T> BlockPtr<T> {
|
||||
pub fn addr(&self) -> u64 {
|
||||
{ self.addr }.to_native()
|
||||
}
|
||||
|
||||
pub fn hash(&self) -> u64 {
|
||||
{ self.hash }.to_native()
|
||||
}
|
||||
|
||||
pub fn is_null(&self) -> bool {
|
||||
self.addr() == 0
|
||||
}
|
||||
|
||||
/// Cast BlockPtr to another type
|
||||
///
|
||||
/// # Safety
|
||||
/// Unsafe because it can be used to transmute types
|
||||
pub unsafe fn cast<U>(self) -> BlockPtr<U> {
|
||||
BlockPtr {
|
||||
addr: self.addr,
|
||||
hash: self.hash,
|
||||
phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use = "the returned pointer should usually be deallocated"]
|
||||
pub fn clear(&mut self) -> BlockPtr<T> {
|
||||
let mut ptr = Self::default();
|
||||
mem::swap(self, &mut ptr);
|
||||
ptr
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Clone for BlockPtr<T> {
|
||||
fn clone(&self) -> Self {
|
||||
Self {
|
||||
addr: self.addr,
|
||||
hash: self.hash,
|
||||
phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Copy for BlockPtr<T> {}
|
||||
|
||||
impl<T> Default for BlockPtr<T> {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
addr: 0.into(),
|
||||
hash: 0.into(),
|
||||
phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> fmt::Debug for BlockPtr<T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
let addr = self.addr();
|
||||
let hash = self.hash();
|
||||
f.debug_struct("BlockPtr")
|
||||
.field("addr", &addr)
|
||||
.field("hash", &hash)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(packed)]
|
||||
pub struct BlockRaw([u8; BLOCK_SIZE as usize]);
|
||||
|
||||
impl Clone for BlockRaw {
|
||||
fn clone(&self) -> Self {
|
||||
Self(self.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for BlockRaw {
|
||||
fn default() -> Self {
|
||||
Self([0; BLOCK_SIZE as usize])
|
||||
}
|
||||
}
|
||||
|
||||
impl ops::Deref for BlockRaw {
|
||||
type Target = [u8];
|
||||
fn deref(&self) -> &[u8] {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl ops::DerefMut for BlockRaw {
|
||||
fn deref_mut(&mut self) -> &mut [u8] {
|
||||
&mut self.0
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn block_list_size_test() {
|
||||
assert_eq!(mem::size_of::<BlockList<BlockRaw>>(), BLOCK_SIZE as usize);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn block_raw_size_test() {
|
||||
assert_eq!(mem::size_of::<BlockRaw>(), BLOCK_SIZE as usize);
|
||||
}
|
||||
Reference in New Issue
Block a user