I'm playing with btrfs, which allows cp --reflink
to copy-on-write. Other programs, such as lxc-clone
, may use this feature as well. My question is, how to tell if a file is a CoW of another? Like for hardlink, I can tell from the inode number.

- 555
4 Answers
Good question. Looks like there aren't currently any easy high-level ways to tell.
One problem is that a file may only share part of the data via Copy-on-Write. This is called a physical extent, and some or all of the physical extents may be shared between CoW files.
There is nothing analogous to an (Edit: see my other answer).inode
which, when compared between files, would tell you that the files share the same physical extents.
The low level answer is that you can ask the kernel which physical extents are used for the file using the FS_IOC_FIEMAP
ioctl
, which is documented in Documentation/filesystems/fiemap.txt
. In principle, if all of the physical extents are the same, then the file must be sharing the same underlying storage.
Few things implement a way to look at this information at a higher level. I found some go code here. Apparently the filefrag
utility is supposed to show the extents with -v. In addition, btrfs-debug-tree
shows this information.
I would exercise caution however, since these things may have had little use in the wild for this purpose, you could find bugs giving you wrong answers, so beware relying on this data for deciding on operations which could cause data corruption.
Some related questions:
-
Great answer! How would you use
btrfs-debug-tree
to list the extents on a given filename? – Tom Hale Feb 16 '18 at 14:38 -
btrfs-debug-tree
is now obsolete; usebtrfs inspect-internal dump-tree
– bitinerant Sep 04 '20 at 22:48 -
See https://unix.stackexchange.com/a/679796/42620 for another (similar) approach. – jrw32982 Dec 01 '21 at 18:28
Further to my previous answer, I have just released fienode
which computes a SHA1 hash of the physical extents of the file and can be used to find some (identical) reflink copies. Beware though, there are caveats (see the documentation). BTRFS decided to change some, but not all, of the physical extents of a refink copy I made without provocation or warning, causing the value to change.
Easiest solution for this is using btrfs filesystem du .
Exclusive will be 0.00B if it is CoW.
Found here: https://unix.stackexchange.com/a/655813/525352

- 51
- 1
- 1
-
3Thank you for linking to the source of your information. Please copy enough information into your answer so that it can be understood and used by itself, without reference to the other answer. – G-Man Says 'Reinstate Monica' May 10 '22 at 17:38
-
1The confusing is that as soon as any snapshot is taken all files on the drive will have 0.00B as they are now shared with the snapshot – Patrick Wolf Apr 10 '23 at 22:35
This does not add much to the accepted answer but someone has summarised the problems and several methods here - https://www.ctrl.blog/entry/distinguish-file-link-clone.html
Problems:
- distinguish symbolic links and hard links from ref links
- identify partial clones (files that share some but not all data)
Solutions:
- Use filefrag
- Use
stat
to identify the device as clones must reside on the same filesystem.
Quote:
Hard links share the same inode number as their destination, whereas clones have their own inodes. This distinction (plus a copy-on-write file system) is what enables clones to act independently of their originals even when modified by non-cloning aware programs."
- Run the command filefrag -v file1 file2 (part of e2fsprogs). Compare the files’ physical_offset ranges within the extent rows that have the shared flag set.
The two files share deduplicated/cloned data on the storage drive if they share any identical or overlapping ranges.
As to determining which is the original and which is the clone … . That is almost impossible to determine without a time machine.

- 652
rmlint
on the files, it will sayLeaving as-is (already reflinked to original):
– endolith Jan 16 '21 at 23:17