From e078a7b8834ed8477a4ed7ab7160e22bf97dd355 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Abd=C3=B3=20Roig=20Maranges?= Date: Sat, 21 Sep 2024 19:47:15 +0200 Subject: [PATCH 1/2] Do not attempt to reflink directories on linux FICLONE would return EISDIR if the source is a directory. We resolve it by extending the cases in which we fall back to recursing into the directory. --- crates/install-wheel-rs/src/linker.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/install-wheel-rs/src/linker.rs b/crates/install-wheel-rs/src/linker.rs index 9226474f60a42..88b17c6b835e0 100644 --- a/crates/install-wheel-rs/src/linker.rs +++ b/crates/install-wheel-rs/src/linker.rs @@ -365,7 +365,7 @@ fn clone_recursive( debug!("Cloning {} to {}", from.display(), to.display()); - if cfg!(windows) && from.is_dir() { + if (cfg!(windows) || cfg!(target_os = "linux")) && from.is_dir() { // On Windows, reflinking directories is not supported, so we copy each file instead. fs::create_dir_all(&to)?; for entry in fs::read_dir(from)? { From 35a6e826de46df9a9bffbefb9b455d9ffeab4bf7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Abd=C3=B3=20Roig=20Maranges?= Date: Sun, 22 Sep 2024 19:27:30 +0200 Subject: [PATCH 2/2] Update comment --- crates/install-wheel-rs/src/linker.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/crates/install-wheel-rs/src/linker.rs b/crates/install-wheel-rs/src/linker.rs index 88b17c6b835e0..c4f3ee85f7672 100644 --- a/crates/install-wheel-rs/src/linker.rs +++ b/crates/install-wheel-rs/src/linker.rs @@ -296,10 +296,17 @@ fn clone_wheel_files( let mut count = 0usize; let mut attempt = Attempt::default(); - // On macOS, directly can be recursively copied with a single `clonefile` call. + // On macOS, directories can be recursively copied with a single `clonefile` call. // So we only need to iterate over the top-level of the directory, and copy each file or // subdirectory unless the subdirectory exists already in which case we'll need to recursively // merge its contents with the existing directory. + // + // On linux, we need to always reflink recursively, as `FICLONE` ioctl does not support directories. + // Also note, that reflink is only supported on certain filesystems (btrfs, xfs, ...), and only when + // it does not cross filesystem boundaries. + // + // On windows, we also always need to reflink recursively, as `FSCTL_DUPLICATE_EXTENTS_TO_FILE` ioctl + // is not supported on directories. Also, it is only supported on certain filesystems (ReFS, SMB, ...). for entry in fs::read_dir(wheel.as_ref())? { clone_recursive( site_packages.as_ref(),