xref: /qemu/block/monitor/bitmap-qmp-cmds.c (revision 2abf0da2)
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 
99     if (!name || name[0] == '\0') {
100         error_setg(errp, "Bitmap name cannot be empty");
101         return;
102     }
103 
104     bs = bdrv_lookup_bs(node, node, errp);
105     if (!bs) {
106         return;
107     }
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             return;
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         return;
132     }
133 
134     bitmap = bdrv_create_dirty_bitmap(bs, granularity, name, errp);
135     if (bitmap == NULL) {
136         return;
137     }
138 
139     if (disabled) {
140         bdrv_disable_dirty_bitmap(bitmap);
141     }
142 
143     bdrv_dirty_bitmap_set_persistence(bitmap, persistent);
144 }
145 
146 BdrvDirtyBitmap *block_dirty_bitmap_remove(const char *node, const char *name,
147                                            bool release,
148                                            BlockDriverState **bitmap_bs,
149                                            Error **errp)
150 {
151     BlockDriverState *bs;
152     BdrvDirtyBitmap *bitmap;
153 
154     GLOBAL_STATE_CODE();
155 
156     bitmap = block_dirty_bitmap_lookup(node, name, &bs, errp);
157     if (!bitmap || !bs) {
158         return NULL;
159     }
160 
161     if (bdrv_dirty_bitmap_check(bitmap, BDRV_BITMAP_BUSY | BDRV_BITMAP_RO,
162                                 errp)) {
163         return NULL;
164     }
165 
166     if (bdrv_dirty_bitmap_get_persistence(bitmap) &&
167         bdrv_remove_persistent_dirty_bitmap(bs, name, errp) < 0)
168     {
169         return NULL;
170     }
171 
172     if (release) {
173         bdrv_release_dirty_bitmap(bitmap);
174     }
175 
176     if (bitmap_bs) {
177         *bitmap_bs = bs;
178     }
179 
180     return release ? NULL : bitmap;
181 }
182 
183 void qmp_block_dirty_bitmap_remove(const char *node, const char *name,
184                                    Error **errp)
185 {
186     block_dirty_bitmap_remove(node, name, true, NULL, errp);
187 }
188 
189 /**
190  * Completely clear a bitmap, for the purposes of synchronizing a bitmap
191  * immediately after a full backup operation.
192  */
193 void qmp_block_dirty_bitmap_clear(const char *node, const char *name,
194                                   Error **errp)
195 {
196     BdrvDirtyBitmap *bitmap;
197     BlockDriverState *bs;
198 
199     bitmap = block_dirty_bitmap_lookup(node, name, &bs, errp);
200     if (!bitmap || !bs) {
201         return;
202     }
203 
204     if (bdrv_dirty_bitmap_check(bitmap, BDRV_BITMAP_DEFAULT, errp)) {
205         return;
206     }
207 
208     bdrv_clear_dirty_bitmap(bitmap, NULL);
209 }
210 
211 void qmp_block_dirty_bitmap_enable(const char *node, const char *name,
212                                    Error **errp)
213 {
214     BlockDriverState *bs;
215     BdrvDirtyBitmap *bitmap;
216 
217     bitmap = block_dirty_bitmap_lookup(node, name, &bs, errp);
218     if (!bitmap) {
219         return;
220     }
221 
222     if (bdrv_dirty_bitmap_check(bitmap, BDRV_BITMAP_ALLOW_RO, errp)) {
223         return;
224     }
225 
226     bdrv_enable_dirty_bitmap(bitmap);
227 }
228 
229 void qmp_block_dirty_bitmap_disable(const char *node, const char *name,
230                                     Error **errp)
231 {
232     BlockDriverState *bs;
233     BdrvDirtyBitmap *bitmap;
234 
235     bitmap = block_dirty_bitmap_lookup(node, name, &bs, errp);
236     if (!bitmap) {
237         return;
238     }
239 
240     if (bdrv_dirty_bitmap_check(bitmap, BDRV_BITMAP_ALLOW_RO, errp)) {
241         return;
242     }
243 
244     bdrv_disable_dirty_bitmap(bitmap);
245 }
246 
247 BdrvDirtyBitmap *block_dirty_bitmap_merge(const char *dst_node,
248                                           const char *dst_bitmap,
249                                           BlockDirtyBitmapOrStrList *bms,
250                                           HBitmap **backup, Error **errp)
251 {
252     BlockDriverState *bs;
253     BdrvDirtyBitmap *dst, *src;
254     BlockDirtyBitmapOrStrList *lst;
255     const char *src_node, *src_bitmap;
256     HBitmap *local_backup = NULL;
257 
258     GLOBAL_STATE_CODE();
259 
260     dst = block_dirty_bitmap_lookup(dst_node, dst_bitmap, &bs, errp);
261     if (!dst) {
262         return NULL;
263     }
264 
265     for (lst = bms; lst; lst = lst->next) {
266         switch (lst->value->type) {
267         case QTYPE_QSTRING:
268             src_bitmap = lst->value->u.local;
269             src = bdrv_find_dirty_bitmap(bs, src_bitmap);
270             if (!src) {
271                 error_setg(errp, "Dirty bitmap '%s' not found", src_bitmap);
272                 goto fail;
273             }
274             break;
275         case QTYPE_QDICT:
276             src_node = lst->value->u.external.node;
277             src_bitmap = lst->value->u.external.name;
278             src = block_dirty_bitmap_lookup(src_node, src_bitmap, NULL, errp);
279             if (!src) {
280                 goto fail;
281             }
282             break;
283         default:
284             abort();
285         }
286 
287         /* We do backup only for first merge operation */
288         if (!bdrv_merge_dirty_bitmap(dst, src,
289                                      local_backup ? NULL : &local_backup,
290                                      errp))
291         {
292             goto fail;
293         }
294     }
295 
296     if (backup) {
297         *backup = local_backup;
298     } else {
299         hbitmap_free(local_backup);
300     }
301 
302     return dst;
303 
304 fail:
305     if (local_backup) {
306         bdrv_restore_dirty_bitmap(dst, local_backup);
307     }
308 
309     return NULL;
310 }
311 
312 void qmp_block_dirty_bitmap_merge(const char *node, const char *target,
313                                   BlockDirtyBitmapOrStrList *bitmaps,
314                                   Error **errp)
315 {
316     block_dirty_bitmap_merge(node, target, bitmaps, NULL, errp);
317 }
318