Skip to content

Rustup fails to install on RHEL 7 if /home is mapped to an NFS filesystem #2452

Closed
@Tavi-Kohn

Description

@Tavi-Kohn

Problem
Rustup fails partway when installing on my university's shared Red Hat 7.8 server, with OS error EOPNOTSUPP (95). I believe this is a bug in std::sys::unix::fs::copy. This previously wasn't an issue (a few months ago), but I don't know what configuration/software changed on the server. I'm filing a report here to see if anyone else can verify the issue, to see if my analysis is sane, and to make it more visible for those searching for rustup-specific issues.

Steps
Here's the output of curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh with default options:

info: profile set to 'default'
info: default host triple is x86_64-unknown-linux-gnu
info: syncing channel updates for 'stable-x86_64-unknown-linux-gnu'
info: latest update on 2020-08-03, rust version 1.45.2 (d3fb005a3 2020-07-31)
info: downloading component 'cargo'
info: downloading component 'clippy'
info: downloading component 'rust-docs'
info: downloading component 'rust-std'
info: downloading component 'rustc'
info: downloading component 'rustfmt'
info: installing component 'cargo'
info: Defaulting to 500.0 MiB unpack ram
info: installing component 'clippy'
info: rolling back changes
error: could not copy file from '/home/TAVIKOHN/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/components' to '/home/TAVIKOHN/.rustup/tmp/nzqk3x5j5klr1bwu_file'
error: caused by: Operation not supported (os error 95)

I haven't been able to reproduce the bug on another system (or VM).

Possible Cause
I suspect the cause is an upstream issue with std::sys::unix::fs::copy, but I've jumped to a few conclusions and could be completely wrong.
std::sys::unix::fs::copy uses the copy_file_range system call to efficiently copy files on Linux kernel v4.5 and later.
RHEL 7 comes with Linux kernel v3.10 and glibc v2.17. The kernel does not support the copy_file_range system call, and glibc does not provide a wrapper.

This is normally fine, as std::sys::unix::fs::copy tries the system call and gracefully falls back to use std::io::copy if the kernel returns one of a few specific errors (ENOSYS, EXDEV, EINVAL, or EPERM). The problem is that from what I can tell, attempting to call copy_file_range for a file on a NFS filesystem mount reports EOPNOTSUPP instead of ENOSYS, causing std::sys::unix::fs::copy to break.

Since the university server maps /home to an NFS volume, rustup fails when it tries to copy a temporary file to the toolchain directory. I think the only reason rustup gets as far as it does is because /tmp is mapped to an XFS volume, which doesn't seem to have this odd behavior.

Here's the code I'm referring to in rust-lang/rust

Possible Solution(s)
I think the ideal solution is implement a fix in std, maybe just falling back to std::io::copy if EOPNOTSUPP is encountered (in addition to the other errors already covered).
While a workaround could be created for rustup specifically, that doesn't really fix the problem of not being able to copy files using the Rust standard library.

Notes
I've taken a trace of each shell command and system call, but I've opted not to include it for now.

Output of rustup --version:

rustup 1.22.1 (b01adbbc3 2020-07-08)

Output of rustup show:

Default host: x86_64-unknown-linux-gnu
rustup home:  /home/TAVIKOHN/.rustup

no active toolchain

Output of uname -r

3.10.0-1127.8.2.el7.x86_64

Output of ldd --version

ldd (GNU libc) 2.17
Copyright (C) 2012 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Written by Roland McGrath and Ulrich Drepper.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions