I try to create a snapshot copy of a directory recursively, but it returns errors for every single file if the filesystem (custom shfs) does not support reflink copies:

# cp -a --reflink=always /mnt/user/libvirt /mnt/user/libvirt_copy
cp: failed to clone '/mnt/user/libvirt_copy/libvirt/libvirt.img' from '/mnt/user/libvirt/libvirt.img': Operation not supported
cp: failed to clone '/mnt/user/libvirt_copy/libvirt/test.txt' from '/mnt/user/libvirt/test.txt': Operation not supported

As it seems to be impossible to stop cp on the first error (?), which means useless looping through probably thousands of files, I instead like to pre-check if the filesystem supports reflinks.

One idea is to search for a single file and do a testcopy:

if ! find /mnt/user/libvirt -type f -print -quit | xargs -I {} sh -c 'dst_path=$(dirname $(echo {} | sed "s#^/mnt/user/libvirt#/mnt/user/libvirt_copy#")); mkdir -vp $dst_path && cp -a --reflink=always {} "$dst_path"'; then
    echo "Error: Filesystem does not support reflink"

But this leaves the dir and an empty file which needs to be cleaned up afterwards:

# find /mnt/user/libvirt_copy/
# ls -lah /mnt/user/libvirt_copy/libvirt.img
-rw------- 1 root root 0 Nov  1 08:58 /mnt/user/libvirt_copy/libvirt.img

Isn't there an better way? Or maybe there is a solution to stop cp on the first error?

2 Answers 2


I'm not sure about the "custom shfs" filesystem you mention you are using, but for a normal filesystem on disk, there should be a filesystem-specific command you can run to get information about it. For example, for the XFS filesystem, a sh script could test whether it supports reflink functionality like this:

if xfs_info /yourXfsMount | grep reflink=1; then
   echo "Filesystem supports reflink"
   echo>&2 "ERROR: Filesystem does not support reflink"
   exit 1
  • I'm searching for a general solution or this would be huge list and won't cover for example ZFS after it supports reflinks, too. PS The custom SHFS filesystem I'm talking about is unRAIDs Array + Cache structure.
    – mgutt
    Jul 7 at 12:04

If you need a generic answer that isn't dependent on the specific filesystem, I think simply attempting to do a test copy is likely your best bet. You don't need to use your existing data for this test, you just need to know what filesystem you are attempting to do the relinking on. Rather than involving any of your real data in the test, I think it is simplest to just create an empty file with a unique name, attempt to copy it, and then clean it up. Maybe something like this:

touch ${filename}
cp --reflink=always ${filename} ${filename2}
rm -f ${filename} ${filename2}
if [ ${result} -ne 0 ]; then
  echo "ERROR: Filesystem ${filesystem} does not support reflink."
  exit 1
echo "Reflink supported"
# Proceed with your reflink copying...
  • touch ${filename} or the more correct touch -- "$filename" would create an empty file (unless the file already existed in which case it would just update the mtime and atime). To know whether you can reflink, you'd need at least some data. I'd say more than a 4KiB block and uncompressible (like the output of head -c 5K /dev/urandom) as smaller sizes might be treated specially by some filesystems. Jul 8 at 8:24
  • I only tested on xfs versus ext4. While an empty file worked fine to detect reflink support on XFS, you might have a point as I could imagine there being some filesystems that might treat empty/tiny files specially. Or it might not matter at all regardless of filesystem, depending on how cp implemented its check and how the Linux kernel works (I didn't dig into this). I'm leaving it up to the reader to confirm it works for their use case. Jul 8 at 12:22
  • As you can see in my question this is not the way I wanted to check it. And the reason is: You are only verifying that cp is working. And I hoped there is a better method of course.
    – mgutt
    Jul 9 at 5:51

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .