WIP: delete after close instead of unlink

This commit is contained in:
Jeremy Soller
2025-11-15 20:18:47 -07:00
parent 2e1bca19ac
commit a44303b4f6
4 changed files with 82 additions and 6 deletions
+72 -1
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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 {