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