Linux – How to delete a file in all snapshots on a btrfs system

btrfslinuxsnapshot

I've set up a sophisticated backup scheme with hourly, daily, weekly, monthly backups that take up (thanks to the glory of the btrfs cow-filesystem) almost no extra space on the device.

But unfortunately I ran out of space the old-fashioned way (by copying to much stuff to it).

Now deleting something is of no use, as it persists in all the snapshots. To free the disk space, I would have to delete all the snapshots since the file was first copied to the device. I don't want to do that because

  • it's hard to find out when exactly this was (especially if the files was changed since)
  • I don't want to loose the history of all the other files in those snapshots
  • accessing the snapshots can only be done by mounting them, with is a bit more complicated for a root-fs then just doing rm -f

So how do I tell btrfs to delete a single file throughout all snapshots? Effectively this means setting some internal reference counter to zero so the space can be freed.

If this isn't possible with the btrfs tools itself (which would be a bit short-sighted), I'm also happy with any third-party tool that could ease the task of searching, mounting and deleting a file in all the snapshots.

Best Answer

One workaround is to temporarily set the snapshots writable and delete the files on every snapshot in which they appear.

To set a snapshot writable (from How to make a btrfs snapshot writable?):

btrfs property set -ts <snapshot> ro false

Delete the files to free up space, then set it back to readonly with

btrfs property set -ts <snapshot> ro true

As soon as all references to the files are gone, btrfs will detect that there is more free space.

Unfortunately this method doesn't help very much if you have lost track of what the files used to be named. But you can still use Baobab or K4DirStat or du -h | sort -h to find where big files are in the snapshots.

Also, you don't have to individually mount every snapshot, if you can just mount the directory that contains them.

Related Question