Reverting LVM snapshots

One thing that would be nice to have in linux LVM is the ability to take a snapshot of a logical volume, make some changes then ‘roll back’ to the state preserved in the snapshot. If you look at the current set of lv commands on most linux distros there is no such option to ‘revert to snapshot’. Now, that I’m using KVM more, the ability to ‘rollback’ a virtual machine installed on a logical volume would be particularly handy.

Well it turns out you can ‘revert to snapshot’, but you just have to use a non-standard tool and some dmsetup commands. The tool is called dm-merge. Go to the dm-merge git repository or download the latest dm-merge snapshot . dm-merge just looks at the ‘changed blocks’ and pushes the old copies of them back into the original logical volume. You’ll need to compile the dm-merge program (just do a ‘make’). dm-merge comes with some doco. It explains two possible methods; reverting with an active logical volume OR reverting with an inactive one. In the former case you’re attempting to revert to a snapshot when the filesystem you’re trying to change is already mounted. I imagine that to be a very dangerous activity (but I guess it works well enough if there is little filesystem activity). I chose the latter (safer) method.

Here are my notes on the procedure. If this were a document for work, I would a) tell people they were crazy to even attempt this and b) if you’re still crazy make sure you make a backup. At least try this procedure out on a test machine first. The possibility of screwing your disk by virtue of a small typing mistake is quite high.

In the example below, I had a logical volume /dev/vgz/lvubuntu910full32bit that I was using as my hda drive in a KVM guest machine, and I had created a snapshot ‘snap1’ beforehand;

   lvcreate --size 1G --snapshot --name snap1 /dev/vgz/lvubuntu910full32bit

One important thing I realised recently is that the amount of space you allocate to a snapshot (eg. 1GB in the example above) can actually be resized without killing the snapshot (eg. lvresize -L 20G /dev/vgz/snap1)

Most of the following is a rehash of what is in the README that comes with dm-merge. I’m only referring to the method involving an inactive logical volume

# Firstly, shut down access to your logical volume (ie. /dev/vgz/vgzlvubuntu910full32bit).
   Since this is a KVM guest, all I did was shut down the guest. If you're doing this on a
   mounted logical volume then you should umount it.
 
# Duplicate the tables of the logical volumes and snapshot storage (note the use of the 
   special -real and -cow suffixes)

dmsetup table vgz-lvubuntu910full32bit-real |dmsetup create tmplv
dmsetup table vgz-snap1-cow |dmsetup create tmpcow

# Deactivate the main lv

lvchange -a n /dev/vgz/lvubuntu910full32bit

# flush buffers

blockdev --flushbufs /dev/mapper/{tmplv,tmpcow}

# Do a dm-merge test run. You see lots of lines that start with 'dd' and a summary at the bottom.

dm-merge -i /dev/mapper/tmpcow -o /dev/mapper/tmplv -vd
...
dd of="/dev/mapper/tmplv" seek=2135444 if='/dev/mapper/tmpcow' iflag=direct skip=8275 count=1 bs=8b
dd of="/dev/mapper/tmplv" seek=2135445 if='/dev/mapper/tmpcow' iflag=direct skip=8276 count=1 bs=8b
dd of="/dev/mapper/tmplv" seek=2135446 if='/dev/mapper/tmpcow' iflag=direct skip=8277 count=1 bs=8b
dd of="/dev/mapper/tmplv" seek=5056466 if='/dev/mapper/tmpcow' iflag=direct skip=8278 count=1 bs=8b
dd of="/dev/mapper/tmplv" seek=5056467 if='/dev/mapper/tmpcow' iflag=direct skip=8279 count=1 bs=8b
Found 8246 exceptions of chunksize 4096, total size 33775616 bytes (32984 KiB, 32.211 MiB, 0.031 GiB).

# Do it for real. You get a couple of lines of output plus the same summary line.

 dm-merge -i /dev/mapper/tmpcow -o /dev/mapper/tmplv -f

Artificial sleep (1 second)
Found a proper MAGIC header: 0x70416e53
valid = 1
version = 1
chunk_size = 8 (4096 bytes)
Found 8246 exceptions of chunksize 4096, total size 33775616 bytes (32984 KiB, 32.211 MiB, 0.031 GiB).

# Flush buffers again

blockdev --flushbufs /dev/mapper/{tmplv,tmpcow}

# Remove the tmp lv's. These are just references to data, so it won't delete your real data.

dmsetup remove tmplv
dmsetup remove tmpcow

# Activate it

lvchange -a y /dev/vgz/lvubuntu910full32bit

Now try to start your KVM guest again … or remount it to check it out and confirm that it’s reverted to the original state. If you snapshotted a live KVM guest or a mounted filesystem, then you may find that your KVM guest will do a filesystem check on boot (fair enough), or you may need to run fsck on your filesystem before you can mount it.

Don’t forget to remove the snapshot you initially made (eg. lvremove /dev/vgz/snap1)

One thing to note is the ‘revert to snapshot’ capability has been ‘coming’ for a while in mainstream LVM. There’s a recent mention on LWN about it