Workaround for copy_file_range spuriously returning EOPNOTSUPP when attemted 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
This commit is contained in:
parent
e5e33ebd2b
commit
1316c786a0
1 changed files with 4 additions and 2 deletions
|
@ -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);
|
||||
}
|
||||
_ => {}
|
||||
|
@ -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);
|
||||
|
|
Loading…
Add table
Reference in a new issue