BTRFS: Solving issues with copy-on-write

5 April 2016

I really like BTRFS, that’s why I write so much about it. But there are some issues with it. BTRFS is based on the copy-on-write principle but this can create some real troubles with virtualisation or databases. Therefore I will explain in this article how to disable cow.

Problems with copy-on-write

I experienced some strange problems with my VirtualBox-Machines. If I start a virtual machine, it just freezes. I didn’t find anything in the logfiles and I could only fix the problem by disabling copy-on-write on that machine AND revert to a previous snapshot(lucky me that I had one).

Mounting without copy-on-write

It is possible to disable copy-on-write using the mount-option “nodatacow”. This option has no effect on existing files and copy-on-write will only be disabled for new files. It’s also good to know that this option disables all compression. A subvolume could be mounted using the following fstab-line:

LABEL=RAIDBUTTER	/vms btrfs	subvol=VMS,nodatacow,defaults,auto	0	0

Disabling cow for specific files

It is also possible to disable copy-on-write for specific files only using chattr. Again this only works for new and empty files. So lets create a file and check it’s attributes:

touch somefile
lsattr somefile 
---------------- somefile

Now let’s disable copy-on-write on this file:

chattr +C somefile

To check the attributes of a file we can use lsattr:

lsattr somefile
---------------C somefile

It is also possible to disable cow on directories. Then all new files will automatically be created with the no-data-cow-flag enabled. Also on directory it is important to know that this only works on empty directories!

In the following example I will create a new directory, set the no-data-cow-flag and then create a new file:

mkdir somedir   
lsattr -d somedir 
---------------- somedir
chattr +C somedir 
lsattr -d somedir 
---------------C somedir
touch somedir/somefile
lsattr somedir 
---------------C somedir/somefile

But what about existing files?

All changes from above just work on empty files. If we want to convert an existing file, we really have to recreate the file and change the attributes before filling the content of the file. can do this for us:


if [$# != 2]
echo "Usage: $0 "
exit 0


if ! [-e $FILE]
echo "$FILE doesn't exist"
exit 0

if [-d $FILE]
echo "directories are not supported yet."
exit 0

echo "Converting $FILE(via $TMP).."

touch $TMP
chattr +C $TMP
dd if=$FILE of=$TMP bs=1M
rm $FILE

exit 0
[ Linux  Sysadmin  Btrfs  Virtualization  ]
Except where otherwise noted, content on this site is licensed under a Creative Commons Attribution 3.0 Unported License.

Copyright 2015-present Hoti