]>
Commit | Line | Data |
---|---|---|
efcfa278 JS |
1 | <!-- |
2 | Copyright 2015 John Snow <[email protected]> and Red Hat, Inc. | |
3 | All rights reserved. | |
4 | ||
5 | This file is licensed via The FreeBSD Documentation License, the full text of | |
6 | which is included at the end of this document. | |
7 | --> | |
8 | ||
9 | # Dirty Bitmaps and Incremental Backup | |
10 | ||
11 | * Dirty Bitmaps are objects that track which data needs to be backed up for the | |
12 | next incremental backup. | |
13 | ||
14 | * Dirty bitmaps can be created at any time and attached to any node | |
15 | (not just complete drives.) | |
16 | ||
17 | ## Dirty Bitmap Names | |
18 | ||
19 | * A dirty bitmap's name is unique to the node, but bitmaps attached to different | |
20 | nodes can share the same name. | |
21 | ||
22 | ## Bitmap Modes | |
23 | ||
24 | * A Bitmap can be "frozen," which means that it is currently in-use by a backup | |
25 | operation and cannot be deleted, renamed, written to, reset, | |
26 | etc. | |
27 | ||
28 | ## Basic QMP Usage | |
29 | ||
30 | ### Supported Commands ### | |
31 | ||
32 | * block-dirty-bitmap-add | |
33 | * block-dirty-bitmap-remove | |
34 | * block-dirty-bitmap-clear | |
35 | ||
36 | ### Creation | |
37 | ||
38 | * To create a new bitmap, enabled, on the drive with id=drive0: | |
39 | ||
40 | ```json | |
41 | { "execute": "block-dirty-bitmap-add", | |
42 | "arguments": { | |
43 | "node": "drive0", | |
44 | "name": "bitmap0" | |
45 | } | |
46 | } | |
47 | ``` | |
48 | ||
49 | * This bitmap will have a default granularity that matches the cluster size of | |
50 | its associated drive, if available, clamped to between [4KiB, 64KiB]. | |
51 | The current default for qcow2 is 64KiB. | |
52 | ||
53 | * To create a new bitmap that tracks changes in 32KiB segments: | |
54 | ||
55 | ```json | |
56 | { "execute": "block-dirty-bitmap-add", | |
57 | "arguments": { | |
58 | "node": "drive0", | |
59 | "name": "bitmap0", | |
60 | "granularity": 32768 | |
61 | } | |
62 | } | |
63 | ``` | |
64 | ||
65 | ### Deletion | |
66 | ||
67 | * Bitmaps that are frozen cannot be deleted. | |
68 | ||
69 | * Deleting the bitmap does not impact any other bitmaps attached to the same | |
70 | node, nor does it affect any backups already created from this node. | |
71 | ||
72 | * Because bitmaps are only unique to the node to which they are attached, | |
73 | you must specify the node/drive name here, too. | |
74 | ||
75 | ```json | |
76 | { "execute": "block-dirty-bitmap-remove", | |
77 | "arguments": { | |
78 | "node": "drive0", | |
79 | "name": "bitmap0" | |
80 | } | |
81 | } | |
82 | ``` | |
83 | ||
84 | ### Resetting | |
85 | ||
86 | * Resetting a bitmap will clear all information it holds. | |
87 | ||
88 | * An incremental backup created from an empty bitmap will copy no data, | |
89 | as if nothing has changed. | |
90 | ||
91 | ```json | |
92 | { "execute": "block-dirty-bitmap-clear", | |
93 | "arguments": { | |
94 | "node": "drive0", | |
95 | "name": "bitmap0" | |
96 | } | |
97 | } | |
98 | ``` | |
99 | ||
100 | ## Transactions (Not yet implemented) | |
101 | ||
102 | * Transactional commands are forthcoming in a future version, | |
103 | and are not yet available for use. This section serves as | |
104 | documentation of intent for their design and usage. | |
105 | ||
106 | ### Justification | |
107 | ||
108 | Bitmaps can be safely modified when the VM is paused or halted by using | |
109 | the basic QMP commands. For instance, you might perform the following actions: | |
110 | ||
111 | 1. Boot the VM in a paused state. | |
112 | 2. Create a full drive backup of drive0. | |
113 | 3. Create a new bitmap attached to drive0. | |
114 | 4. Resume execution of the VM. | |
115 | 5. Incremental backups are ready to be created. | |
116 | ||
117 | At this point, the bitmap and drive backup would be correctly in sync, | |
118 | and incremental backups made from this point forward would be correctly aligned | |
119 | to the full drive backup. | |
120 | ||
121 | This is not particularly useful if we decide we want to start incremental | |
122 | backups after the VM has been running for a while, for which we will need to | |
123 | perform actions such as the following: | |
124 | ||
125 | 1. Boot the VM and begin execution. | |
126 | 2. Using a single transaction, perform the following operations: | |
127 | * Create bitmap0. | |
128 | * Create a full drive backup of drive0. | |
129 | 3. Incremental backups are now ready to be created. | |
130 | ||
131 | ### Supported Bitmap Transactions | |
132 | ||
133 | * block-dirty-bitmap-add | |
134 | * block-dirty-bitmap-clear | |
135 | ||
136 | The usages are identical to their respective QMP commands, but see below | |
137 | for examples. | |
138 | ||
139 | ### Example: New Incremental Backup | |
140 | ||
141 | As outlined in the justification, perhaps we want to create a new incremental | |
142 | backup chain attached to a drive. | |
143 | ||
144 | ```json | |
145 | { "execute": "transaction", | |
146 | "arguments": { | |
147 | "actions": [ | |
148 | {"type": "block-dirty-bitmap-add", | |
149 | "data": {"node": "drive0", "name": "bitmap0"} }, | |
150 | {"type": "drive-backup", | |
151 | "data": {"device": "drive0", "target": "/path/to/full_backup.img", | |
152 | "sync": "full", "format": "qcow2"} } | |
153 | ] | |
154 | } | |
155 | } | |
156 | ``` | |
157 | ||
158 | ### Example: New Incremental Backup Anchor Point | |
159 | ||
160 | Maybe we just want to create a new full backup with an existing bitmap and | |
161 | want to reset the bitmap to track the new chain. | |
162 | ||
163 | ```json | |
164 | { "execute": "transaction", | |
165 | "arguments": { | |
166 | "actions": [ | |
167 | {"type": "block-dirty-bitmap-clear", | |
168 | "data": {"node": "drive0", "name": "bitmap0"} }, | |
169 | {"type": "drive-backup", | |
170 | "data": {"device": "drive0", "target": "/path/to/new_full_backup.img", | |
171 | "sync": "full", "format": "qcow2"} } | |
172 | ] | |
173 | } | |
174 | } | |
175 | ``` | |
176 | ||
177 | ## Incremental Backups | |
178 | ||
179 | The star of the show. | |
180 | ||
181 | **Nota Bene!** Only incremental backups of entire drives are supported for now. | |
182 | So despite the fact that you can attach a bitmap to any arbitrary node, they are | |
183 | only currently useful when attached to the root node. This is because | |
184 | drive-backup only supports drives/devices instead of arbitrary nodes. | |
185 | ||
186 | ### Example: First Incremental Backup | |
187 | ||
188 | 1. Create a full backup and sync it to the dirty bitmap, as in the transactional | |
189 | examples above; or with the VM offline, manually create a full copy and then | |
190 | create a new bitmap before the VM begins execution. | |
191 | ||
192 | * Let's assume the full backup is named 'full_backup.img'. | |
193 | * Let's assume the bitmap you created is 'bitmap0' attached to 'drive0'. | |
194 | ||
195 | 2. Create a destination image for the incremental backup that utilizes the | |
196 | full backup as a backing image. | |
197 | ||
198 | * Let's assume it is named 'incremental.0.img'. | |
199 | ||
200 | ```sh | |
201 | # qemu-img create -f qcow2 incremental.0.img -b full_backup.img -F qcow2 | |
202 | ``` | |
203 | ||
204 | 3. Issue the incremental backup command: | |
205 | ||
206 | ```json | |
207 | { "execute": "drive-backup", | |
208 | "arguments": { | |
209 | "device": "drive0", | |
210 | "bitmap": "bitmap0", | |
211 | "target": "incremental.0.img", | |
212 | "format": "qcow2", | |
4b80ab2b | 213 | "sync": "incremental", |
efcfa278 JS |
214 | "mode": "existing" |
215 | } | |
216 | } | |
217 | ``` | |
218 | ||
219 | ### Example: Second Incremental Backup | |
220 | ||
221 | 1. Create a new destination image for the incremental backup that points to the | |
222 | previous one, e.g.: 'incremental.1.img' | |
223 | ||
224 | ```sh | |
225 | # qemu-img create -f qcow2 incremental.1.img -b incremental.0.img -F qcow2 | |
226 | ``` | |
227 | ||
228 | 2. Issue a new incremental backup command. The only difference here is that we | |
229 | have changed the target image below. | |
230 | ||
231 | ```json | |
232 | { "execute": "drive-backup", | |
233 | "arguments": { | |
234 | "device": "drive0", | |
235 | "bitmap": "bitmap0", | |
236 | "target": "incremental.1.img", | |
237 | "format": "qcow2", | |
4b80ab2b | 238 | "sync": "incremental", |
efcfa278 JS |
239 | "mode": "existing" |
240 | } | |
241 | } | |
242 | ``` | |
243 | ||
244 | ## Errors | |
245 | ||
246 | * In the event of an error that occurs after a backup job is successfully | |
247 | launched, either by a direct QMP command or a QMP transaction, the user | |
248 | will receive a BLOCK_JOB_COMPLETE event with a failure message, accompanied | |
249 | by a BLOCK_JOB_ERROR event. | |
250 | ||
251 | * In the case of an event being cancelled, the user will receive a | |
252 | BLOCK_JOB_CANCELLED event instead of a pair of COMPLETE and ERROR events. | |
253 | ||
254 | * In either case, the incremental backup data contained within the bitmap is | |
255 | safely rolled back, and the data within the bitmap is not lost. The image | |
256 | file created for the failed attempt can be safely deleted. | |
257 | ||
258 | * Once the underlying problem is fixed (e.g. more storage space is freed up), | |
259 | you can simply retry the incremental backup command with the same bitmap. | |
260 | ||
261 | ### Example | |
262 | ||
263 | 1. Create a target image: | |
264 | ||
265 | ```sh | |
266 | # qemu-img create -f qcow2 incremental.0.img -b full_backup.img -F qcow2 | |
267 | ``` | |
268 | ||
269 | 2. Attempt to create an incremental backup via QMP: | |
270 | ||
271 | ```json | |
272 | { "execute": "drive-backup", | |
273 | "arguments": { | |
274 | "device": "drive0", | |
275 | "bitmap": "bitmap0", | |
276 | "target": "incremental.0.img", | |
277 | "format": "qcow2", | |
4b80ab2b | 278 | "sync": "incremental", |
efcfa278 JS |
279 | "mode": "existing" |
280 | } | |
281 | } | |
282 | ``` | |
283 | ||
284 | 3. Receive an event notifying us of failure: | |
285 | ||
286 | ```json | |
287 | { "timestamp": { "seconds": 1424709442, "microseconds": 844524 }, | |
288 | "data": { "speed": 0, "offset": 0, "len": 67108864, | |
289 | "error": "No space left on device", | |
290 | "device": "drive1", "type": "backup" }, | |
291 | "event": "BLOCK_JOB_COMPLETED" } | |
292 | ``` | |
293 | ||
294 | 4. Delete the failed incremental, and re-create the image. | |
295 | ||
296 | ```sh | |
297 | # rm incremental.0.img | |
298 | # qemu-img create -f qcow2 incremental.0.img -b full_backup.img -F qcow2 | |
299 | ``` | |
300 | ||
301 | 5. Retry the command after fixing the underlying problem, | |
302 | such as freeing up space on the backup volume: | |
303 | ||
304 | ```json | |
305 | { "execute": "drive-backup", | |
306 | "arguments": { | |
307 | "device": "drive0", | |
308 | "bitmap": "bitmap0", | |
309 | "target": "incremental.0.img", | |
310 | "format": "qcow2", | |
4b80ab2b | 311 | "sync": "incremental", |
efcfa278 JS |
312 | "mode": "existing" |
313 | } | |
314 | } | |
315 | ``` | |
316 | ||
317 | 6. Receive confirmation that the job completed successfully: | |
318 | ||
319 | ```json | |
320 | { "timestamp": { "seconds": 1424709668, "microseconds": 526525 }, | |
321 | "data": { "device": "drive1", "type": "backup", | |
322 | "speed": 0, "len": 67108864, "offset": 67108864}, | |
323 | "event": "BLOCK_JOB_COMPLETED" } | |
324 | ``` | |
325 | ||
326 | <!-- | |
327 | The FreeBSD Documentation License | |
328 | ||
329 | Redistribution and use in source (Markdown) and 'compiled' forms (SGML, HTML, | |
330 | PDF, PostScript, RTF and so forth) with or without modification, are permitted | |
331 | provided that the following conditions are met: | |
332 | ||
333 | Redistributions of source code (Markdown) must retain the above copyright | |
334 | notice, this list of conditions and the following disclaimer of this file | |
335 | unmodified. | |
336 | ||
337 | Redistributions in compiled form (transformed to other DTDs, converted to PDF, | |
338 | PostScript, RTF and other formats) must reproduce the above copyright notice, | |
339 | this list of conditions and the following disclaimer in the documentation and/or | |
340 | other materials provided with the distribution. | |
341 | ||
342 | THIS DOCUMENTATION IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | |
343 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
344 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |
345 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE | |
346 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
347 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | |
348 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER | |
349 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | |
350 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | |
351 | THIS DOCUMENTATION, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
352 | --> |