diff --git a/src/bin/clone.rs b/src/bin/clone.rs index c3b1e8667a..c29f97220e 100644 --- a/src/bin/clone.rs +++ b/src/bin/clone.rs @@ -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!( diff --git a/src/clone.rs b/src/clone.rs index 3629db6916..62a89247f7 100644 --- a/src/clone.rs +++ b/src/clone.rs @@ -9,11 +9,17 @@ fn syscall_err(err: syscall::Error) -> io::Error { io::Error::from_raw_os_error(err.errno) } +fn tx_progress(tx: &mut Transaction, 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( tx_old: &mut Transaction, parent_ptr_old: TreePtr, - fs: &mut FileSystem, + tx: &mut Transaction, parent_ptr: TreePtr, buf: &mut [u8], progress: &mut F, @@ -28,8 +34,12 @@ fn clone_at( 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( 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( 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) }) } diff --git a/src/transaction.rs b/src/transaction.rs index 329bc5e7d5..cf89d95fe1 100644 --- a/src/transaction.rs +++ b/src/transaction.rs @@ -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, deallocate: Vec, - write_cache: BTreeMap>, + pub(crate) write_cache: BTreeMap>, } impl<'a, D: Disk> Transaction<'a, D> {