WIP: delete after close instead of unlink
This commit is contained in:
+72
-1
@@ -2,10 +2,13 @@ use alloc::{collections::BTreeSet, vec::Vec};
|
||||
use core::{fmt, mem, ops, slice};
|
||||
use endian_num::Le;
|
||||
|
||||
use crate::{BlockAddr, BlockLevel, BlockMeta, BlockPtr, BlockTrait, BLOCK_SIZE};
|
||||
use crate::{BlockAddr, BlockLevel, BlockMeta, BlockPtr, BlockTrait, Node, TreePtr, BLOCK_SIZE};
|
||||
|
||||
pub const ALLOC_LIST_ENTRIES: usize =
|
||||
(BLOCK_SIZE as usize - mem::size_of::<BlockPtr<AllocList>>()) / mem::size_of::<AllocEntry>();
|
||||
pub const RELEASE_LIST_ENTRIES: usize = (BLOCK_SIZE as usize
|
||||
- mem::size_of::<BlockPtr<ReleaseList>>())
|
||||
/ mem::size_of::<TreePtr<Node>>();
|
||||
|
||||
/// The RedoxFS block allocator. This struct manages all "data" blocks in RedoxFS
|
||||
/// (i.e, all blocks that aren't reserved or part of the header chain).
|
||||
@@ -275,11 +278,79 @@ impl ops::DerefMut for AllocList {
|
||||
}
|
||||
}
|
||||
|
||||
/// A list of nodes pending release.
|
||||
#[repr(C, packed)]
|
||||
pub struct ReleaseList {
|
||||
/// A pointer to the previous ReleaseList.
|
||||
/// If this is the null pointer, this is the first element of the chain.
|
||||
pub prev: BlockPtr<ReleaseList>,
|
||||
|
||||
/// Allocation entries.
|
||||
pub entries: [TreePtr<Node>; RELEASE_LIST_ENTRIES],
|
||||
}
|
||||
|
||||
unsafe impl BlockTrait for ReleaseList {
|
||||
fn empty(level: BlockLevel) -> Option<Self> {
|
||||
if level.0 == 0 {
|
||||
Some(Self {
|
||||
prev: BlockPtr::default(),
|
||||
entries: [TreePtr::<Node>::default(); RELEASE_LIST_ENTRIES],
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for ReleaseList {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
let prev = self.prev;
|
||||
let entries: Vec<_> = self
|
||||
.entries
|
||||
.iter()
|
||||
.filter(|entry| !entry.is_null())
|
||||
.map(|entry| entry.id())
|
||||
.collect();
|
||||
f.debug_struct("ReleaseList")
|
||||
.field("prev", &prev)
|
||||
.field("entries", &entries)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl ops::Deref for ReleaseList {
|
||||
type Target = [u8];
|
||||
fn deref(&self) -> &[u8] {
|
||||
unsafe {
|
||||
slice::from_raw_parts(
|
||||
self as *const ReleaseList as *const u8,
|
||||
mem::size_of::<ReleaseList>(),
|
||||
) as &[u8]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ops::DerefMut for ReleaseList {
|
||||
fn deref_mut(&mut self) -> &mut [u8] {
|
||||
unsafe {
|
||||
slice::from_raw_parts_mut(
|
||||
self as *mut ReleaseList as *mut u8,
|
||||
mem::size_of::<ReleaseList>(),
|
||||
) as &mut [u8]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn alloc_node_size_test() {
|
||||
assert_eq!(mem::size_of::<AllocList>(), crate::BLOCK_SIZE as usize);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn release_node_size_test() {
|
||||
assert_eq!(mem::size_of::<ReleaseList>(), crate::BLOCK_SIZE as usize);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn allocator_test() {
|
||||
let mut alloc = Allocator::default();
|
||||
|
||||
+8
-3
@@ -5,7 +5,7 @@ use endian_num::Le;
|
||||
use aes::Aes128;
|
||||
use xts_mode::{get_tweak_default, Xts128};
|
||||
|
||||
use crate::{AllocList, BlockPtr, KeySlot, Tree, BLOCK_SIZE, SIGNATURE, VERSION};
|
||||
use crate::{AllocList, BlockPtr, KeySlot, ReleaseList, Tree, BLOCK_SIZE, SIGNATURE, VERSION};
|
||||
|
||||
pub const HEADER_RING: u64 = 256;
|
||||
|
||||
@@ -29,8 +29,10 @@ pub struct Header {
|
||||
pub alloc: BlockPtr<AllocList>,
|
||||
/// Key slots
|
||||
pub key_slots: [KeySlot; 64],
|
||||
/// Nodes pending release, may be null
|
||||
pub release: BlockPtr<ReleaseList>,
|
||||
/// Padding
|
||||
pub padding: [u8; BLOCK_SIZE as usize - 3176],
|
||||
pub padding: [u8; BLOCK_SIZE as usize - 3192],
|
||||
/// encrypted hash of header data without hash, set to hash and padded if disk is not encrypted
|
||||
pub encrypted_hash: [u8; 16],
|
||||
/// hash of header data without hash
|
||||
@@ -159,7 +161,8 @@ impl Default for Header {
|
||||
tree: BlockPtr::<Tree>::default(),
|
||||
alloc: BlockPtr::<AllocList>::default(),
|
||||
key_slots: [KeySlot::default(); 64],
|
||||
padding: [0; BLOCK_SIZE as usize - 3176],
|
||||
release: BlockPtr::<ReleaseList>::default(),
|
||||
padding: [0; BLOCK_SIZE as usize - 3192],
|
||||
encrypted_hash: [0; 16],
|
||||
hash: 0.into(),
|
||||
}
|
||||
@@ -175,6 +178,7 @@ impl fmt::Debug for Header {
|
||||
let generation = self.generation;
|
||||
let tree = self.tree;
|
||||
let alloc = self.alloc;
|
||||
let release = self.release;
|
||||
let hash = self.hash;
|
||||
f.debug_struct("Header")
|
||||
.field("signature", &signature)
|
||||
@@ -184,6 +188,7 @@ impl fmt::Debug for Header {
|
||||
.field("generation", &generation)
|
||||
.field("tree", &tree)
|
||||
.field("alloc", &alloc)
|
||||
.field("release", &release)
|
||||
.field("hash", &hash)
|
||||
.finish()
|
||||
}
|
||||
|
||||
+1
-1
@@ -21,7 +21,7 @@ pub const DIR_ENTRY_MAX_LENGTH: usize = 252;
|
||||
|
||||
pub static IS_UMT: AtomicUsize = AtomicUsize::new(0);
|
||||
|
||||
pub use self::allocator::{AllocEntry, AllocList, Allocator, ALLOC_LIST_ENTRIES};
|
||||
pub use self::allocator::{AllocEntry, AllocList, Allocator, ReleaseList, ALLOC_LIST_ENTRIES};
|
||||
#[cfg(feature = "std")]
|
||||
pub use self::archive::{archive, archive_at};
|
||||
pub use self::block::{
|
||||
|
||||
+1
-1
@@ -1151,7 +1151,6 @@ impl<'a, D: Disk> Transaction<'a, D> {
|
||||
false
|
||||
} else {
|
||||
node.data_mut().set_links(0);
|
||||
self.truncate_node_inner(&mut node, 0)?;
|
||||
true
|
||||
};
|
||||
|
||||
@@ -1191,6 +1190,7 @@ impl<'a, D: Disk> Transaction<'a, D> {
|
||||
}
|
||||
|
||||
if remove_node {
|
||||
self.truncate_node_inner(&mut node, 0)?;
|
||||
self.sync_tree(parent)?;
|
||||
self.remove_tree(node.ptr())?;
|
||||
unsafe {
|
||||
|
||||
Reference in New Issue
Block a user