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. nocow.sh can do this for us:
#!/bin/bash if [$# != 2] then echo "Usage: $0 " exit 0 fi FILE=$1 TMP=$2 if ! [-e $FILE] then echo "$FILE doesn't exist" exit 0 fi if [-d $FILE] then echo "directories are not supported yet." exit 0 fi echo "Converting $FILE(via $TMP).." touch $TMP chattr +C $TMP dd if=$FILE of=$TMP bs=1M rm $FILE mv $TMP $FILE exit 0