xref: /qemu/block/monitor/bitmap-qmp-cmds.c (revision 49f95221)
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                                           BlockDirtyBitmapMergeSourceList *bms,
261                                           HBitmap **backup, Error **errp)
262 {
263     BlockDriverState *bs;
264     BdrvDirtyBitmap *dst, *src, *anon;
265     BlockDirtyBitmapMergeSourceList *lst;
266 
267     GLOBAL_STATE_CODE();
268 
269     dst = block_dirty_bitmap_lookup(node, target, &bs, errp);
270     if (!dst) {
271         return NULL;
272     }
273 
274     anon = bdrv_create_dirty_bitmap(bs, bdrv_dirty_bitmap_granularity(dst),
275                                     NULL, errp);
276     if (!anon) {
277         return NULL;
278     }
279 
280     for (lst = bms; lst; lst = lst->next) {
281         switch (lst->value->type) {
282             const char *name, *node;
283         case QTYPE_QSTRING:
284             name = lst->value->u.local;
285             src = bdrv_find_dirty_bitmap(bs, name);
286             if (!src) {
287                 error_setg(errp, "Dirty bitmap '%s' not found", name);
288                 dst = NULL;
289                 goto out;
290             }
291             break;
292         case QTYPE_QDICT:
293             node = lst->value->u.external.node;
294             name = lst->value->u.external.name;
295             src = block_dirty_bitmap_lookup(node, name, NULL, errp);
296             if (!src) {
297                 dst = NULL;
298                 goto out;
299             }
300             break;
301         default:
302             abort();
303         }
304 
305         if (!bdrv_merge_dirty_bitmap(anon, src, NULL, errp)) {
306             dst = NULL;
307             goto out;
308         }
309     }
310 
311     /* Merge into dst; dst is unchanged on failure. */
312     bdrv_merge_dirty_bitmap(dst, anon, backup, errp);
313 
314  out:
315     bdrv_release_dirty_bitmap(anon);
316     return dst;
317 }
318 
319 void qmp_block_dirty_bitmap_merge(const char *node, const char *target,
320                                   BlockDirtyBitmapMergeSourceList *bitmaps,
321                                   Error **errp)
322 {
323     block_dirty_bitmap_merge(node, target, bitmaps, NULL, errp);
324 }
325