Implement clone threshold to work around Redox problems
This commit is contained in:
+22
-16
@@ -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)
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user