Subject: Re: bug#55724: cp --reflink=always failing when --reflink=auto reflinks successfully on OpenZFS

From: Pádraig Brady <[email-masked]>
Date: Mon, 30 May 2022 16:04:07 +0100

On 30/05/2022 10:13, Rich wrote:
> Hi!
> 
> So, OpenZFS is adding reflink support Soon(tm), including across
> filesystems on a pool, which is nice.
> 
> Unfortunately, Linux's VFS returns EXDEV for trying FICLONE or
> FICLONERANGE (but not copy_file_range) cross-filesystem before you ever ask
> the filesystem-specific code, so currently, the following strange behavior
> occurs:
> 
> On coreutils 8.30 or 8.32, cp --reflink=always across filesystems will fail
> with EXDEV and --reflink=auto will not reflink (because they're not trying
> copy_file_range as a fallback).
> On coreutils git, as of b3331d59e, cp --reflink=always across filesystems
> will fail with EXDEV without ever getting out of Linux's VFS code, cp
> --reflink=auto will reflink silently (since it falls back to
> copy_file_range after getting EXDEV), cp --reflink=never will not reflink.
> 
> (On the same filesystem, in all of the above versions, cp --reflink=always
> and =auto do the same thing and reflink correctly.)
> 
> I'm not sure what the "correct" behavior here should be, but at least =auto
> working and =always failing seems like a surprising and incorrect outcome
> to me, though it's not readily obvious to me how the code "should" flow
> instead to avoid that - and since the failure cases happen before calling
> into OpenZFS, I don't see any way it could be handled better there.
> 
> Happy to point people at the WIP code being used to demonstrate this if it
> would be helpful, but this seems like it's only OpenZFS specific in that
> nobody else has this functionality but would hit this case (because IIUC
> btrfs avoids clone_file failing with EXDEV by pretending they're not
> distinct filesystems, and there's not many other FSes where reflink across
> filesystems would make sense).
> 
> Thanks for any insights,
> - Rich

Thanks for the clear info.
Yes this is an awkward one, which I'm not sure cp can do anything about.
`cp --reflink=always` => ensure we can reflink or otherwise fail.
Really the kernel has to behave appropriately there
and not do the blanket assumption with EXDEV.
cp can't determine from copy_file_range() whether a reflink
was performed or not, so wouldn't be appropriate to use with --reflink=always.

cheers,
Pádraig