As touched on in my previous post about btrfs, the copy on write (COW) capabilities are very handy. However, as COW shouldn't be used for large files with small random writes (e.g. databases and VMs), I wanted to turn it off for these things.

Turning COW off for a single directory (e.g. where my VMs are stored) was as simple as chattr +C, but what if we want to turn off COW for a whole subvolume? As of today, the nodatacow option applies to the whole filesystem and only the options for the first mounted subvolume are taken into account.

Here is the solution I came up with -- I'd be keen to receive feedback.

Create a directory just for noCOW files

This can be anywhere, but I chose /var/lib as this is where my large databases are kept.

cd /var/lib
sudo mkdir noCOW
# optional, to remind when this dir is not mounted
sudo touch noCOW/UNMOUNTED

Create filesystem

Mount broot

If it's not already mounted on your system, mount the btrfs root filesystem

mkdir /broot
mount -o autodefrag,compress=lzo,noatime,space_cache /dev/mapper/btree /broot

Create subvolume

sudo btrfs subvolume create /broot/active/noCOW

Mount the filesystem

sudo vim /etc/fstab
  /dev/mapper/btree     /var/lib/nocow  btrfs       rw,noatime,compress=lzo,space_cache,autodefrag,subvol=active/nocow  0 0
sudo mount -a

Set attribute

As we're doing this on directories within the subvolume, we don't have the issue of not being able to use attributes on the subvolume itself.

sudo mkdir noCOW/mysql
sudo chattr +C noCOW/mysql
# check nocow attribute is set
lsattr noCOW

Symlink to "real" location

sudo ln -s noCOW/mysql .