10

Let's say I have a large file (8GB) called example.log on ZFS. I do cp example.log example.bak to make a copy. Then I add or modify a few bytes in original file. What will happen?

Will ZFS copy the entire 8GB file or only the blocks that changed (and all the chain of inodes pointing from the file descriptor to that block)?

2 Answers 2

4

As far as I could tell, FreeBSD ZFS does not support copy-on-write using cp; the native cp does not seem to have an option for such lightweight copies, and trying GNU cp with --reflink errors out on the ZFS system I tried with error message "cp: failed to clone 'example.bak' from 'example.log': Operation not supported".

(Updates: A 2020 comment mentions that Solaris cp has a -z switch to do such copies. Additionally, a 2024 comment mentions that GNU cp with --reflink works on Linux OpenZFS; I was not able to test that: FreeBSD's cp still does not appear to support copy-on-write, and using GNU cp with --reflink from a contemporary Linux NFS mount still failed.)

However, and I hope this answers your underlying question, copy-on-write is used for filesystem snapshots: let's say you have 900GB used out of 1000GB available, nothing prevents you from making a snapshot of that filesystem, the snapshot will not occupy 900GB; in fact, it will initially not occupy any new data blocks at all.

After creating a snapshot of your original filesystem containing example.log, you end up with two "copies": the read-only version in the snapshot, and you live version in its original location. What happens when the copy is modified, be it by appending or by being altered in-place? That is where the magic happens: only those blocks that are altered get copied and start using up space. It is not the case that the entire file gets copied as soon as it gets altered.

3
  • 1
    As far as I could tell, ZFS does not support copy-on-writes using cp ZFS on Solaris 11.4 does, via cp -z .... For Linux, XFS w/ kernel 4.8 or later and BTRFS do support reflinks. Commented Jan 22, 2020 at 11:07
  • cp --reflink source dest works for OpenZFS in Linux 6.6.32 (TrueNAS SCALE Dragonfish-24.04.2). It may work in earlier releases too. Commented Aug 13, 2024 at 5:55
  • 1
    To enable support for cp --reflink on Ubuntu 24.04 LTS and some other current linux distros, you may need to perform echo 1 | sudo tee /sys/module/zfs/parameters/zfs_bclone_enabled, first. To enable this feature across reboots, put options zfs zfs_bclone_enabled=1 into /etc/modprobe.d/zfs.conf. Further verify, that block-cloning is enabled on the particular ZFS pool, that you are using: zpool get feature@block_cloning. If not, use: zpool set feature@block_cloning=enabled POOL to activate it. Note, that block-cloning is still considered somewhat experimental. Commented Jul 4 at 16:38
1

The cp command will create a new file, so there will be a duplicate of every block. Once you modify a few bytes in the original file, ZFS will first copy the block of data which contains those bytes from disk into RAM, apply the new bytes to it, and then write that block out to a new location on disk. The original block will be freed (simplifying here, but that's essentially what happens). The rest of the blocks of the file are left alone.

Regarding the inode part of your question: ZFS does not have inodes. Instead, it maintains "indirect blocks". These are blocks of metadata on disk which point to the data of the file. There can be layers of indirect blocks, depending on the file size and the file's block size. The indirect block(s) which point to the modified block will need to be updated, but the rest are left alone.

3
  • 1
    Do I need to use any special parameters or simple cp <source> <target> is fine? dhag mentioned that I need to use cp --reflink and Andrew Henle suggested using cp -z Commented Jan 22, 2020 at 13:45
  • 2
    If you're using Solaris, then cp -z will create a new name for the same blocks of data. It differs from ln in that writing to one file will use copy-on-write to allow the two files to diverge, whereas with ln there is only ever one file. Note that -z is restricted to directories in the same ZFS pool. I don't know about how linux behaves, sorry Commented Jan 22, 2020 at 16:49
  • On linux, you need to use cp --reflink to create a logical copy-on-write copy instead of a physical copy. See my long comment to the other answer on which further steps may be necessary to enable cp --reflink for your particular ZFS. You should have at least ZFS version 2.2.2. Check with zfs --version. Commented Jul 4 at 16:40

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.