Implement clone threshold to work around Redox problems

This commit is contained in:
Jeremy Soller
2025-09-26 11:25:22 -06:00
parent 5e044e88c0
commit eea5c96137
3 changed files with 28 additions and 20 deletions
+4 -2
View File
@@ -116,7 +116,7 @@ fn main() {
let free_old = fs_old.allocator().free() * redoxfs::BLOCK_SIZE;
let used_old = size_old - free_old;
let mut last_percent = 0;
match clone(&mut fs_old, &mut fs, move |used| {
let clone_res = clone(&mut fs_old, &mut fs, move |used| {
let percent = (used * 100) / used_old;
if percent != last_percent {
eprint!(
@@ -127,7 +127,9 @@ fn main() {
);
last_percent = percent;
}
}) {
});
eprintln!();
match clone_res {
Ok(()) => (),
Err(err) => {
println!(
+22 -16
View File
@@ -9,11 +9,17 @@ fn syscall_err(err: syscall::Error) -> io::Error {
io::Error::from_raw_os_error(err.errno)
}
fn tx_progress<D: Disk, F: FnMut(u64)>(tx: &mut Transaction<D>, progress: &mut F) {
let size = tx.header.size();
let free = tx.allocator.free() * BLOCK_SIZE;
progress(size - free);
}
//TODO: handle hard links
fn clone_at<D: Disk, E: Disk, F: FnMut(u64)>(
tx_old: &mut Transaction<D>,
parent_ptr_old: TreePtr<Node>,
fs: &mut FileSystem<E>,
tx: &mut Transaction<E>,
parent_ptr: TreePtr<Node>,
buf: &mut [u8],
progress: &mut F,
@@ -28,8 +34,12 @@ fn clone_at<D: Disk, E: Disk, F: FnMut(u64)>(
let node_ptr_old = entry.node_ptr();
let node_old = tx_old.read_tree(node_ptr_old)?;
//TODO: doing the whole clone_at inside a single transaction works on Linux but not Redox
let node_ptr = fs.tx(|tx| {
//TODO: this slows down the clone, but Redox has issues without this (Linux is fine)
if tx.write_cache.len() > 64 {
tx.sync(false)?;
}
let node_ptr = {
let mode = node_old.data().mode();
let (ctime, ctime_nsec) = node_old.data().ctime();
let (mtime, mtime_nsec) = node_old.data().mtime();
@@ -51,15 +61,13 @@ fn clone_at<D: Disk, E: Disk, F: FnMut(u64)>(
let node_ptr = node.ptr();
tx.sync_tree(node)?;
Ok(node_ptr)
})?;
node_ptr
};
let size = fs.header.size();
let free = fs.allocator().free() * BLOCK_SIZE;
progress(size - free);
tx_progress(tx, progress);
if node_old.data().is_dir() {
clone_at(tx_old, node_ptr_old, fs, node_ptr, buf, progress)?;
clone_at(tx_old, node_ptr_old, tx, node_ptr, buf, progress)?;
}
}
@@ -72,22 +80,20 @@ pub fn clone<D: Disk, E: Disk, F: FnMut(u64)>(
mut progress: F,
) -> syscall::Result<()> {
fs_old.tx(|tx_old| {
let mut tx = Transaction::new(fs);
// Clone at root node
let mut buf = vec![0; 4 * 1024 * 1024];
clone_at(
tx_old,
TreePtr::root(),
fs,
&mut tx,
TreePtr::root(),
&mut buf,
&mut progress,
)?;
fs.tx(|tx| {
// Squash alloc log
tx.sync(true)?;
Ok(())
})
// Commit and squash alloc log
tx.commit(true)
})
}
+2 -2
View File
@@ -53,10 +53,10 @@ pub struct Transaction<'a, D: Disk> {
pub header: Header,
//TODO: make private
pub header_changed: bool,
allocator: Allocator,
pub(crate) allocator: Allocator,
allocator_log: VecDeque<AllocEntry>,
deallocate: Vec<BlockAddr>,
write_cache: BTreeMap<BlockAddr, Box<[u8]>>,
pub(crate) write_cache: BTreeMap<BlockAddr, Box<[u8]>>,
}
impl<'a, D: Disk> Transaction<'a, D> {