]> git.proxmox.com Git - mirror_qemu.git/blob - block/monitor/bitmap-qmp-cmds.c
include/block: Untangle inclusion loops
[mirror_qemu.git] / block / monitor / bitmap-qmp-cmds.c
1 /*
2 * QEMU block dirty bitmap QMP commands
3 *
4 * Copyright (c) 2003-2008 Fabrice Bellard
5 *
6 * This work is licensed under the terms of the GNU GPL, version 2 or
7 * later. See the COPYING file in the top-level directory.
8 *
9 * This file incorporates work covered by the following copyright and
10 * permission notice:
11 *
12 * Copyright (c) 2003-2008 Fabrice Bellard
13 *
14 * Permission is hereby granted, free of charge, to any person obtaining a copy
15 * of this software and associated documentation files (the "Software"), to deal
16 * in the Software without restriction, including without limitation the rights
17 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
18 * copies of the Software, and to permit persons to whom the Software is
19 * furnished to do so, subject to the following conditions:
20 *
21 * The above copyright notice and this permission notice shall be included in
22 * all copies or substantial portions of the Software.
23 *
24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
25 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
27 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
29 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
30 * THE SOFTWARE.
31 */
32
33 #include "qemu/osdep.h"
34
35 #include "block/block-io.h"
36 #include "block/block_int.h"
37 #include "block/dirty-bitmap.h"
38 #include "qapi/qapi-commands-block.h"
39 #include "qapi/error.h"
40
41 /**
42 * block_dirty_bitmap_lookup:
43 * Return a dirty bitmap (if present), after validating
44 * the node reference and bitmap names.
45 *
46 * @node: The name of the BDS node to search for bitmaps
47 * @name: The name of the bitmap to search for
48 * @pbs: Output pointer for BDS lookup, if desired. Can be NULL.
49 * @errp: Output pointer for error information. Can be NULL.
50 *
51 * @return: A bitmap object on success, or NULL on failure.
52 */
53 BdrvDirtyBitmap *block_dirty_bitmap_lookup(const char *node,
54 const char *name,
55 BlockDriverState **pbs,
56 Error **errp)
57 {
58 BlockDriverState *bs;
59 BdrvDirtyBitmap *bitmap;
60
61 GLOBAL_STATE_CODE();
62
63 if (!node) {
64 error_setg(errp, "Node cannot be NULL");
65 return NULL;
66 }
67 if (!name) {
68 error_setg(errp, "Bitmap name cannot be NULL");
69 return NULL;
70 }
71 bs = bdrv_lookup_bs(node, node, NULL);
72 if (!bs) {
73 error_setg(errp, "Node '%s' not found", node);
74 return NULL;
75 }
76
77 bitmap = bdrv_find_dirty_bitmap(bs, name);
78 if (!bitmap) {
79 error_setg(errp, "Dirty bitmap '%s' not found", name);
80 return NULL;
81 }
82
83 if (pbs) {
84 *pbs = bs;
85 }
86
87 return bitmap;
88 }
89
90 void qmp_block_dirty_bitmap_add(const char *node, const char *name,
91 bool has_granularity, uint32_t granularity,
92 bool has_persistent, bool persistent,
93 bool has_disabled, bool disabled,
94 Error **errp)
95 {
96 BlockDriverState *bs;
97 BdrvDirtyBitmap *bitmap;
98 AioContext *aio_context;
99
100 if (!name || name[0] == '\0') {
101 error_setg(errp, "Bitmap name cannot be empty");
102 return;
103 }
104
105 bs = bdrv_lookup_bs(node, node, errp);
106 if (!bs) {
107 return;
108 }
109
110 aio_context = bdrv_get_aio_context(bs);
111 aio_context_acquire(aio_context);
112
113 if (has_granularity) {
114 if (granularity < 512 || !is_power_of_2(granularity)) {
115 error_setg(errp, "Granularity must be power of 2 "
116 "and at least 512");
117 goto out;
118 }
119 } else {
120 /* Default to cluster size, if available: */
121 granularity = bdrv_get_default_bitmap_granularity(bs);
122 }
123
124 if (!has_persistent) {
125 persistent = false;
126 }
127
128 if (!has_disabled) {
129 disabled = false;
130 }
131
132 if (persistent &&
133 !bdrv_can_store_new_dirty_bitmap(bs, name, granularity, errp))
134 {
135 goto out;
136 }
137
138 bitmap = bdrv_create_dirty_bitmap(bs, granularity, name, errp);
139 if (bitmap == NULL) {
140 goto out;
141 }
142
143 if (disabled) {
144 bdrv_disable_dirty_bitmap(bitmap);
145 }
146
147 bdrv_dirty_bitmap_set_persistence(bitmap, persistent);
148
149 out:
150 aio_context_release(aio_context);
151 }
152
153 BdrvDirtyBitmap *block_dirty_bitmap_remove(const char *node, const char *name,
154 bool release,
155 BlockDriverState **bitmap_bs,
156 Error **errp)
157 {
158 BlockDriverState *bs;
159 BdrvDirtyBitmap *bitmap;
160 AioContext *aio_context;
161
162 GLOBAL_STATE_CODE();
163
164 bitmap = block_dirty_bitmap_lookup(node, name, &bs, errp);
165 if (!bitmap || !bs) {
166 return NULL;
167 }
168
169 aio_context = bdrv_get_aio_context(bs);
170 aio_context_acquire(aio_context);
171
172 if (bdrv_dirty_bitmap_check(bitmap, BDRV_BITMAP_BUSY | BDRV_BITMAP_RO,
173 errp)) {
174 aio_context_release(aio_context);
175 return NULL;
176 }
177
178 if (bdrv_dirty_bitmap_get_persistence(bitmap) &&
179 bdrv_remove_persistent_dirty_bitmap(bs, name, errp) < 0)
180 {
181 aio_context_release(aio_context);
182 return NULL;
183 }
184
185 if (release) {
186 bdrv_release_dirty_bitmap(bitmap);
187 }
188
189 if (bitmap_bs) {
190 *bitmap_bs = bs;
191 }
192
193 aio_context_release(aio_context);
194 return release ? NULL : bitmap;
195 }
196
197 void qmp_block_dirty_bitmap_remove(const char *node, const char *name,
198 Error **errp)
199 {
200 block_dirty_bitmap_remove(node, name, true, NULL, errp);
201 }
202
203 /**
204 * Completely clear a bitmap, for the purposes of synchronizing a bitmap
205 * immediately after a full backup operation.
206 */
207 void qmp_block_dirty_bitmap_clear(const char *node, const char *name,
208 Error **errp)
209 {
210 BdrvDirtyBitmap *bitmap;
211 BlockDriverState *bs;
212
213 bitmap = block_dirty_bitmap_lookup(node, name, &bs, errp);
214 if (!bitmap || !bs) {
215 return;
216 }
217
218 if (bdrv_dirty_bitmap_check(bitmap, BDRV_BITMAP_DEFAULT, errp)) {
219 return;
220 }
221
222 bdrv_clear_dirty_bitmap(bitmap, NULL);
223 }
224
225 void qmp_block_dirty_bitmap_enable(const char *node, const char *name,
226 Error **errp)
227 {
228 BlockDriverState *bs;
229 BdrvDirtyBitmap *bitmap;
230
231 bitmap = block_dirty_bitmap_lookup(node, name, &bs, errp);
232 if (!bitmap) {
233 return;
234 }
235
236 if (bdrv_dirty_bitmap_check(bitmap, BDRV_BITMAP_ALLOW_RO, errp)) {
237 return;
238 }
239
240 bdrv_enable_dirty_bitmap(bitmap);
241 }
242
243 void qmp_block_dirty_bitmap_disable(const char *node, const char *name,
244 Error **errp)
245 {
246 BlockDriverState *bs;
247 BdrvDirtyBitmap *bitmap;
248
249 bitmap = block_dirty_bitmap_lookup(node, name, &bs, errp);
250 if (!bitmap) {
251 return;
252 }
253
254 if (bdrv_dirty_bitmap_check(bitmap, BDRV_BITMAP_ALLOW_RO, errp)) {
255 return;
256 }
257
258 bdrv_disable_dirty_bitmap(bitmap);
259 }
260
261 BdrvDirtyBitmap *block_dirty_bitmap_merge(const char *node, const char *target,
262 BlockDirtyBitmapOrStrList *bms,
263 HBitmap **backup, Error **errp)
264 {
265 BlockDriverState *bs;
266 BdrvDirtyBitmap *dst, *src;
267 BlockDirtyBitmapOrStrList *lst;
268 HBitmap *local_backup = NULL;
269
270 GLOBAL_STATE_CODE();
271
272 dst = block_dirty_bitmap_lookup(node, target, &bs, errp);
273 if (!dst) {
274 return NULL;
275 }
276
277 for (lst = bms; lst; lst = lst->next) {
278 switch (lst->value->type) {
279 const char *name, *node;
280 case QTYPE_QSTRING:
281 name = lst->value->u.local;
282 src = bdrv_find_dirty_bitmap(bs, name);
283 if (!src) {
284 error_setg(errp, "Dirty bitmap '%s' not found", name);
285 goto fail;
286 }
287 break;
288 case QTYPE_QDICT:
289 node = lst->value->u.external.node;
290 name = lst->value->u.external.name;
291 src = block_dirty_bitmap_lookup(node, name, NULL, errp);
292 if (!src) {
293 goto fail;
294 }
295 break;
296 default:
297 abort();
298 }
299
300 /* We do backup only for first merge operation */
301 if (!bdrv_merge_dirty_bitmap(dst, src,
302 local_backup ? NULL : &local_backup,
303 errp))
304 {
305 goto fail;
306 }
307 }
308
309 if (backup) {
310 *backup = local_backup;
311 } else {
312 hbitmap_free(local_backup);
313 }
314
315 return dst;
316
317 fail:
318 if (local_backup) {
319 bdrv_restore_dirty_bitmap(dst, local_backup);
320 }
321
322 return NULL;
323 }
324
325 void qmp_block_dirty_bitmap_merge(const char *node, const char *target,
326 BlockDirtyBitmapOrStrList *bitmaps,
327 Error **errp)
328 {
329 block_dirty_bitmap_merge(node, target, bitmaps, NULL, errp);
330 }