xref: /qemu/block/monitor/bitmap-qmp-cmds.c (revision 940bb5fa)
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 *dst_node,
262                                           const char *dst_bitmap,
263                                           BlockDirtyBitmapOrStrList *bms,
264                                           HBitmap **backup, Error **errp)
265 {
266     BlockDriverState *bs;
267     BdrvDirtyBitmap *dst, *src;
268     BlockDirtyBitmapOrStrList *lst;
269     const char *src_node, *src_bitmap;
270     HBitmap *local_backup = NULL;
271 
272     GLOBAL_STATE_CODE();
273 
274     dst = block_dirty_bitmap_lookup(dst_node, dst_bitmap, &bs, errp);
275     if (!dst) {
276         return NULL;
277     }
278 
279     for (lst = bms; lst; lst = lst->next) {
280         switch (lst->value->type) {
281         case QTYPE_QSTRING:
282             src_bitmap = lst->value->u.local;
283             src = bdrv_find_dirty_bitmap(bs, src_bitmap);
284             if (!src) {
285                 error_setg(errp, "Dirty bitmap '%s' not found", src_bitmap);
286                 goto fail;
287             }
288             break;
289         case QTYPE_QDICT:
290             src_node = lst->value->u.external.node;
291             src_bitmap = lst->value->u.external.name;
292             src = block_dirty_bitmap_lookup(src_node, src_bitmap, NULL, errp);
293             if (!src) {
294                 goto fail;
295             }
296             break;
297         default:
298             abort();
299         }
300 
301         /* We do backup only for first merge operation */
302         if (!bdrv_merge_dirty_bitmap(dst, src,
303                                      local_backup ? NULL : &local_backup,
304                                      errp))
305         {
306             goto fail;
307         }
308     }
309 
310     if (backup) {
311         *backup = local_backup;
312     } else {
313         hbitmap_free(local_backup);
314     }
315 
316     return dst;
317 
318 fail:
319     if (local_backup) {
320         bdrv_restore_dirty_bitmap(dst, local_backup);
321     }
322 
323     return NULL;
324 }
325 
326 void qmp_block_dirty_bitmap_merge(const char *node, const char *target,
327                                   BlockDirtyBitmapOrStrList *bitmaps,
328                                   Error **errp)
329 {
330     block_dirty_bitmap_merge(node, target, bitmaps, NULL, errp);
331 }
332