4 dm-merge is a simple tool to apply changes recorded in a copy-on-write
5 exception table. It can be effectively used to either "commit" the changes into
6 the source (as made with simple snapshot target) or "rollback" (reverting to a
7 state the snapshot was created; as made with snapshot linked to snapshot-origin
8 target). And while LVM snapshots are simply (maybe not so simply, actually) the
9 latter case, it can revert a logical volume to the exact state it was when the
12 dm-merge simply reads an exception table and applies the changes back to the
15 It can be thought of as a C port of Lars Ellenberg's 'list_exception_chunks'
16 perl script [1]. I liked the idea very much.
20 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
22 Disclaimer: be warned: the tool was only tested on X86 and X86_64 little endian
23 machines! It is still experimental. Use at _your_ _own_ risk! Before using it,
24 you should understand how device-mapper, LVM and snapshots work.
26 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
33 dm-merge [options] -i <snapshot_device> [ -o <output_device> ]
36 -f REALLY do it (no dry run)
37 -x Relaxed mode; allow some things (namely ioctl) to fail
38 -d Print dd lines as list_exception_chunks.pl would
39 -D Try to use O_DIRECT
40 -v Be verbose (more '-v's increase verbosity)
41 -i <file> Input (snapshot) COW (copy-on-write) filename
42 -o <file> Output (the device being snapshoted) filename
49 2.1 Reverting (LVM) snapshot
50 ----------------------------
52 Suppose you have a logical volume ${lv} in a virtual group ${vg} and a snapshot
53 ${sn} of ${lv} made by something like:
55 lvcreate -L ${some_size} -n ${sn} ${vg}/${lv}
57 As long as ${sn} isn't full it will behave like ${lv} at the time the snapshot
60 Now you make some changes to ${lv} and realize you'd like to revert to the
61 state of ${sn}. This is when dm-merge comes into play.
63 With dm-merge you have basically two options:
65 1) make the changes while ${lv} is "inactive" (recommended)
67 2) keep ${lv} "active" and attempt the changes (for the adventurous)
70 2.1.1 dm-merge and inactive ${lv}
71 ---------------------------------
74 1) Duplicate the tables of ${lv} and snapshot storage:
76 dmsetup ${vg}-${lv}-real | dmsetup create tmp_lv
77 dmsetup ${vg}-${sn}-cow | dmsetup create tmp_cow
79 2) Deactivate the LV (the mappings will disappear, that's why we duplicate the
82 lvchange -a n ${vg}/${lv}
84 3) Flush buffers (better safe than sorry):
86 blockdev --flushbufs /dev/mapper/{tmp_lv,tmp_cow}
88 4) Make sure nothing else touches the data (it should _not_ be mounted!):
92 5) First (purely informative; non-destructive) dm-merge run. See if the numbers
95 dm-merge -i /dev/mapper/tmp_cow -o /dev/mapper/tmp_lv -vd
97 6) If everything seems OK, do it:
99 dm-merge -i /dev/mapper/tmp_cow -o /dev/mapper/tmp_lv -f
101 7) Flush buffers (better safe than sorry):
103 blockdev --flushbufs /dev/mapper/{tmp_lv,tmp_cow}
105 8) Now it should be done. You may remove the temporary mapping then:
107 dmsetup remove tmp_lv
108 dmsetup remove tmp_cow
110 9) The original snapshot may not be necessary anymore (it will show the same
111 data as the ${lv} now), so you can remove it:
115 10) Activate the LV again:
117 lvchange -a y ${vg}/${lv}
121 2.1.2 dm-merge and active ${lv}
122 -------------------------------
124 1) Make sure nothing else touches the data (it should _not_ be mounted!);
125 perhaps "dmsetup suspend" could help a little...:
129 2) Flush buffers (better safe than sorry):
131 blockdev --flushbufs /dev/mapper/${vg}-${sn}* /dev/mapper/${vg}-${lv}*
133 3) First (purely informative; non-destructive) dm-merge run. See if the numbers
136 dm-merge -i /dev/mapper/${vg}-${sn}-cow -o /dev/mapper/${vg}-${lv}-real -vd
138 4) If everything seems OK, do it:
140 dm-merge -i /dev/mapper/${vg}-${sn}-cow -o /dev/mapper/${vg}-${lv}-real -f
142 5) Flush buffers (better safe than sorry):
144 blockdev --flushbufs /dev/mapper/${vg}-${sn}* /dev/mapper/${vg}-${lv}*
146 6) The original snapshot may not be necessary anymore (it will show the same
147 data as the LV now, so you can remove it):
153 2.2 Applying a copy-on-write back to the source ("commit")
154 ----------------------------------------------------------
156 With device mapper and the "snapshot" target (dm-snapshot != LVM snapshot [2]),
157 you can simply create a mapping that "redirects" all writes to a different
158 device so the source stays intact. So when not changed, data is read from the
159 source device; when changed, it is read from a special device (exception
162 So you have some data mapping ${data}, a COW storage ${cow_s} and a dm-snapshot
163 mapping ${sn} [3] created with something like:
165 echo "0 $(blockdev --getsize /path/to/${data}) snapshot /path/to/${data} /path/to/${cow_s} P 8" | dmsetup create ${sn}
167 Now all writes made to /dev/mapper/${sn} go to /path/to/${cow_s}.
169 Imagine you are testing a program inside ${sn}. After testing you'd like to
170 apply the changes made in ${sn} back into ${data}.
174 1) Make sure nothing else touches the data (it should _not_ be mounted!) ...
178 2) Flush buffers (better safe than sorry):
180 blockdev --flushbufs /path/to/${data} /path/to/${cow_s} /dev/mapper/${sn}
182 3) First (purely informative; non-destructive) dm-merge run. See if the numbers
185 dm-merge -i /path/to/${cow_s} -o /path/to/${data} -vd
187 4) If everything seems OK, do it:
189 dm-merge -i /path/to/${cow_s} -o /path/to/${data} -f
191 5) Flush buffers (better safe than sorry):
193 blockdev --flushbufs /path/to/${data} /path/to/${cow_s} /dev/mapper/${sn}
200 [1] http://article.gmane.org/gmane.linux.lvm.general/9899
202 [2] LVM snapshots need "snapshot" and "snapshot-origin" dm targets to
205 [3] Neither ${data} nor ${cow_s} has to be a device-mapper device (for the
206 simplest case). But if you want to do some clever tricks (such as table
207 changing so ${sn} takes place of ${data}; as shown at
208 http://linuxgazette.net/114/kapil.html), you'd need them to be.