BTRFS - Snapshot rollback
I was trying to clean up my user directory backup - which I currently rsync and then do periodic snapshots of. I realised that I wasn't deleting old files in my destination and I had a bunch of temp files that I didn't need to include. In my bid to sort out the links I managed to wipe out a lot of data on my backup.
When I ran rsync again it started trying to move gigs of photos over - not something I fancied doing and also lead me to wonder, if I:
- Create a file
- Snapshot the file
- Delete the original file
- Re-create the original file with an identical copy
Would the 'btrfs' snapshot store the file twice? Unless it was very clever, I suspected it would. A quick drop in on #btrfs on Freenode confirmed my thoughts. By re-running my backups from scratch would make my next snapshot a complete duplication of all the data that was there before. So in addition to taking a long time, I would lose a lot of space. Lucky for me, I have period snapshots that I can roll back to.
Everybody knows that they should keep backups of their data and have disaster recovery and rollback options when it comes to IT. Many people and organisations get the backups but a fewer number test the recovery of that data. If you cannot revert your data then what's the point in the backup? This was my first real-world attempt to rollback a 'btrfs' subvolume.
My first port-of-call was the program that manages my backups - "Snapper". This creates hourly backups and has a built-in undochanges command - which I ran. Everything back to how it was, I kicked of my 'rsync' job again but was confused to see all my files being re-copied. After a bit of investigation it turns out that Snapper does not retain timestamps when it does a rollback (WHY!?!?). A manual rollback is therefore required. I began to brain-freeze when I realised that the snapshots were in a subdirectory of the directory I wanted to rollback. Still, I crossed my fingers and started running commands:
mv mydirectory mydirectory.old btrfs subvolume snapshot mydirectory.old/.snapshots/20/snapshot mydirectory mv mydirectory.old/.snapshots mydirectory/ rm -rf mydirectory.old
What this does is:
- Moves the old subvolume out of the way - this should be instant as no data is moved, just the reference
- Takes a snapshot of the snapshot that I want to recover and puts it in place of the original subvolume
- Move all my other snapshots into the new subvolume
- Delete the old subvolume
This all works because snapshots are subvolumes. By moving directories I appear to be essentially creating links to different subvolumes. As each snapshot is exactly that, a snapshot of the entire directory, we can delete the originals without issue.
Useful to know!