xref: /qemu/block/monitor/bitmap-qmp-cmds.c (revision 8f9abdf5)
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_int.h"
36 #include "qapi/qapi-commands-block.h"
37 #include "qapi/error.h"
38 
39 /**
40  * block_dirty_bitmap_lookup:
41  * Return a dirty bitmap (if present), after validating
42  * the node reference and bitmap names.
43  *
44  * @node: The name of the BDS node to search for bitmaps
45  * @name: The name of the bitmap to search for
46  * @pbs: Output pointer for BDS lookup, if desired. Can be NULL.
47  * @errp: Output pointer for error information. Can be NULL.
48  *
49  * @return: A bitmap object on success, or NULL on failure.
50  */
51 BdrvDirtyBitmap *block_dirty_bitmap_lookup(const char *node,
52                                            const char *name,
53                                            BlockDriverState **pbs,
54                                            Error **errp)
55 {
56     BlockDriverState *bs;
57     BdrvDirtyBitmap *bitmap;
58 
59     GLOBAL_STATE_CODE();
60 
61     if (!node) {
62         error_setg(errp, "Node cannot be NULL");
63         return NULL;
64     }
65     if (!name) {
66         error_setg(errp, "Bitmap name cannot be NULL");
67         return NULL;
68     }
69     bs = bdrv_lookup_bs(node, node, NULL);
70     if (!bs) {
71         error_setg(errp, "Node '%s' not found", node);
72         return NULL;
73     }
74 
75     bitmap = bdrv_find_dirty_bitmap(bs, name);
76     if (!bitmap) {
77         error_setg(errp, "Dirty bitmap '%s' not found", name);
78         return NULL;
79     }
80 
81     if (pbs) {
82         *pbs = bs;
83     }
84 
85     return bitmap;
86 }
87 
88 void qmp_block_dirty_bitmap_add(const char *node, const char *name,
89                                 bool has_granularity, uint32_t granularity,
90                                 bool has_persistent, bool persistent,
91                                 bool has_disabled, bool disabled,
92                                 Error **errp)
93 {
94     BlockDriverState *bs;
95     BdrvDirtyBitmap *bitmap;
96     AioContext *aio_context;
97 
98     if (!name || name[0] == '\0') {
99         error_setg(errp, "Bitmap name cannot be empty");
100         return;
101     }
102 
103     bs = bdrv_lookup_bs(node, node, errp);
104     if (!bs) {
105         return;
106     }
107 
108     aio_context = bdrv_get_aio_context(bs);
109     aio_context_acquire(aio_context);
110 
111     if (has_granularity) {
112         if (granularity < 512 || !is_power_of_2(granularity)) {
113             error_setg(errp, "Granularity must be power of 2 "
114                              "and at least 512");
115             goto out;
116         }
117     } else {
118         /* Default to cluster size, if available: */
119         granularity = bdrv_get_default_bitmap_granularity(bs);
120     }
121 
122     if (!has_persistent) {
123         persistent = false;
124     }
125 
126     if (!has_disabled) {
127         disabled = false;
128     }
129 
130     if (persistent &&
131         !bdrv_can_store_new_dirty_bitmap(bs, name, granularity, errp))
132     {
133         goto out;
134     }
135 
136     bitmap = bdrv_create_dirty_bitmap(bs, granularity, name, errp);
137     if (bitmap == NULL) {
138         goto out;
139     }
140 
141     if (disabled) {
142         bdrv_disable_dirty_bitmap(bitmap);
143     }
144 
145     bdrv_dirty_bitmap_set_persistence(bitmap, persistent);
146 
147 out:
148     aio_context_release(aio_context);
149 }
150 
151 BdrvDirtyBitmap *block_dirty_bitmap_remove(const char *node, const char *name,
152                                            bool release,
153                                            BlockDriverState **bitmap_bs,
154                                            Error **errp)
155 {
156     BlockDriverState *bs;
157     BdrvDirtyBitmap *bitmap;
158     AioContext *aio_context;
159 
160     GLOBAL_STATE_CODE();
161 
162     bitmap = block_dirty_bitmap_lookup(node, name, &bs, errp);
163     if (!bitmap || !bs) {
164         return NULL;
165     }
166 
167     aio_context = bdrv_get_aio_context(bs);
168     aio_context_acquire(aio_context);
169 
170     if (bdrv_dirty_bitmap_check(bitmap, BDRV_BITMAP_BUSY | BDRV_BITMAP_RO,
171                                 errp)) {
172         aio_context_release(aio_context);
173         return NULL;
174     }
175 
176     if (bdrv_dirty_bitmap_get_persistence(bitmap) &&
177         bdrv_remove_persistent_dirty_bitmap(bs, name, errp) < 0)
178     {
179         aio_context_release(aio_context);
180         return NULL;
181     }
182 
183     if (release) {
184         bdrv_release_dirty_bitmap(bitmap);
185     }
186 
187     if (bitmap_bs) {
188         *bitmap_bs = bs;
189     }
190 
191     aio_context_release(aio_context);
192     return release ? NULL : bitmap;
193 }
194 
195 void qmp_block_dirty_bitmap_remove(const char *node, const char *name,
196                                    Error **errp)
197 {
198     block_dirty_bitmap_remove(node, name, true, NULL, errp);
199 }
200 
201 /**
202  * Completely clear a bitmap, for the purposes of synchronizing a bitmap
203  * immediately after a full backup operation.
204  */
205 void qmp_block_dirty_bitmap_clear(const char *node, const char *name,
206                                   Error **errp)
207 {
208     BdrvDirtyBitmap *bitmap;
209     BlockDriverState *bs;
210 
211     bitmap = block_dirty_bitmap_lookup(node, name, &bs, errp);
212     if (!bitmap || !bs) {
213         return;
214     }
215 
216     if (bdrv_dirty_bitmap_check(bitmap, BDRV_BITMAP_DEFAULT, errp)) {
217         return;
218     }
219 
220     bdrv_clear_dirty_bitmap(bitmap, NULL);
221 }
222 
223 void qmp_block_dirty_bitmap_enable(const char *node, const char *name,
224                                    Error **errp)
225 {
226     BlockDriverState *bs;
227     BdrvDirtyBitmap *bitmap;
228 
229     bitmap = block_dirty_bitmap_lookup(node, name, &bs, errp);
230     if (!bitmap) {
231         return;
232     }
233 
234     if (bdrv_dirty_bitmap_check(bitmap, BDRV_BITMAP_ALLOW_RO, errp)) {
235         return;
236     }
237 
238     bdrv_enable_dirty_bitmap(bitmap);
239 }
240 
241 void qmp_block_dirty_bitmap_disable(const char *node, const char *name,
242                                     Error **errp)
243 {
244     BlockDriverState *bs;
245     BdrvDirtyBitmap *bitmap;
246 
247     bitmap = block_dirty_bitmap_lookup(node, name, &bs, errp);
248     if (!bitmap) {
249         return;
250     }
251 
252     if (bdrv_dirty_bitmap_check(bitmap, BDRV_BITMAP_ALLOW_RO, errp)) {
253         return;
254     }
255 
256     bdrv_disable_dirty_bitmap(bitmap);
257 }
258 
259 BdrvDirtyBitmap *block_dirty_bitmap_merge(const char *node, const char *target,
260                                           BlockDirtyBitmapOrStrList *bms,
261                                           HBitmap **backup, Error **errp)
262 {
263     BlockDriverState *bs;
264     BdrvDirtyBitmap *dst, *src;
265     BlockDirtyBitmapOrStrList *lst;
266     HBitmap *local_backup = NULL;
267 
268     GLOBAL_STATE_CODE();
269 
270     dst = block_dirty_bitmap_lookup(node, target, &bs, errp);
271     if (!dst) {
272         return NULL;
273     }
274 
275     for (lst = bms; lst; lst = lst->next) {
276         switch (lst->value->type) {
277             const char *name, *node;
278         case QTYPE_QSTRING:
279             name = lst->value->u.local;
280             src = bdrv_find_dirty_bitmap(bs, name);
281             if (!src) {
282                 error_setg(errp, "Dirty bitmap '%s' not found", name);
283                 goto fail;
284             }
285             break;
286         case QTYPE_QDICT:
287             node = lst->value->u.external.node;
288             name = lst->value->u.external.name;
289             src = block_dirty_bitmap_lookup(node, name, NULL, errp);
290             if (!src) {
291                 goto fail;
292             }
293             break;
294         default:
295             abort();
296         }
297 
298         /* We do backup only for first merge operation */
299         if (!bdrv_merge_dirty_bitmap(dst, src,
300                                      local_backup ? NULL : &local_backup,
301                                      errp))
302         {
303             goto fail;
304         }
305     }
306 
307     if (backup) {
308         *backup = local_backup;
309     } else {
310         hbitmap_free(local_backup);
311     }
312 
313     return dst;
314 
315 fail:
316     if (local_backup) {
317         bdrv_restore_dirty_bitmap(dst, local_backup);
318     }
319 
320     return NULL;
321 }
322 
323 void qmp_block_dirty_bitmap_merge(const char *node, const char *target,
324                                   BlockDirtyBitmapOrStrList *bitmaps,
325                                   Error **errp)
326 {
327     block_dirty_bitmap_merge(node, target, bitmaps, NULL, errp);
328 }
329