Skip to content

Commit

Permalink
Workaround for copy_file_range spuriously returning EOPNOTSUPP when a…
Browse files Browse the repository at this point in the history
…ttemted on a NFS mount under RHEL/CentOS 7.

The syscall is supposed to return ENOSYS in most cases but when calling it on NFS it may leak through
EOPNOTSUPP even though that's supposed to be handled by the kernel and not returned to userspace.
Since it returns ENOSYS in some cases anyway this will trip the  HAS_COPY_FILE_RANGE
detection anyway, so treat EOPNOTSUPP as if it were a ENOSYS.

https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/7/html/7.8_release_notes/deprecated_functionality#the_literal_copy_file_range_literal_call_has_been_disabled_on_local_file_systems_and_in_nfs
https://bugzilla.redhat.com/show_bug.cgi?id=1783554
  • Loading branch information
the8472 committed Aug 11, 2020
1 parent e5e33eb commit 1316c78
Showing 1 changed file with 4 additions and 2 deletions.
6 changes: 4 additions & 2 deletions library/std/src/sys/unix/fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1162,7 +1162,7 @@ pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
};
if let Err(ref copy_err) = copy_result {
match copy_err.raw_os_error() {
Some(libc::ENOSYS) | Some(libc::EPERM) => {
Some(libc::ENOSYS) | Some(libc::EPERM) | Some(libc::EOPNOTSUPP) => {
HAS_COPY_FILE_RANGE.store(false, Ordering::Relaxed);
}
_ => {}
Expand All @@ -1180,11 +1180,13 @@ pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
if os_err == libc::ENOSYS
|| os_err == libc::EXDEV
|| os_err == libc::EINVAL
|| os_err == libc::EPERM =>
|| os_err == libc::EPERM
|| os_err == libc::EOPNOTSUPP =>
{
// Try fallback io::copy if either:
// - Kernel version is < 4.5 (ENOSYS)
// - Files are mounted on different fs (EXDEV)
// - copy_file_range is broken in various ways on RHEL/CentOS 7 (EOPNOTSUPP)
// - copy_file_range is disallowed, for example by seccomp (EPERM)
// - copy_file_range cannot be used with pipes or device nodes (EINVAL)
assert_eq!(written, 0);
Expand Down

0 comments on commit 1316c78

Please sign in to comment.