xref: /openbmc/qemu/block/monitor/bitmap-qmp-cmds.c (revision 6370d13c62c300826f8eb80e4ed9d2e67bad3fa7)
1bb4e58c6SEric Blake /*
2bb4e58c6SEric Blake  * QEMU block dirty bitmap QMP commands
3bb4e58c6SEric Blake  *
4bb4e58c6SEric Blake  * Copyright (c) 2003-2008 Fabrice Bellard
5bb4e58c6SEric Blake  *
6bb4e58c6SEric Blake  * This work is licensed under the terms of the GNU GPL, version 2 or
7bb4e58c6SEric Blake  * later.  See the COPYING file in the top-level directory.
8bb4e58c6SEric Blake  *
9bb4e58c6SEric Blake  * This file incorporates work covered by the following copyright and
10bb4e58c6SEric Blake  * permission notice:
11bb4e58c6SEric Blake  *
12bb4e58c6SEric Blake  * Copyright (c) 2003-2008 Fabrice Bellard
13bb4e58c6SEric Blake  *
14bb4e58c6SEric Blake  * Permission is hereby granted, free of charge, to any person obtaining a copy
15bb4e58c6SEric Blake  * of this software and associated documentation files (the "Software"), to deal
16bb4e58c6SEric Blake  * in the Software without restriction, including without limitation the rights
17bb4e58c6SEric Blake  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
18bb4e58c6SEric Blake  * copies of the Software, and to permit persons to whom the Software is
19bb4e58c6SEric Blake  * furnished to do so, subject to the following conditions:
20bb4e58c6SEric Blake  *
21bb4e58c6SEric Blake  * The above copyright notice and this permission notice shall be included in
22bb4e58c6SEric Blake  * all copies or substantial portions of the Software.
23bb4e58c6SEric Blake  *
24bb4e58c6SEric Blake  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
25bb4e58c6SEric Blake  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26bb4e58c6SEric Blake  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
27bb4e58c6SEric Blake  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28bb4e58c6SEric Blake  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
29bb4e58c6SEric Blake  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
30bb4e58c6SEric Blake  * THE SOFTWARE.
31bb4e58c6SEric Blake  */
32bb4e58c6SEric Blake 
33bb4e58c6SEric Blake #include "qemu/osdep.h"
34bb4e58c6SEric Blake 
35e2c1c34fSMarkus Armbruster #include "block/block-io.h"
36bb4e58c6SEric Blake #include "block/block_int.h"
37e2c1c34fSMarkus Armbruster #include "block/dirty-bitmap.h"
38bb4e58c6SEric Blake #include "qapi/qapi-commands-block.h"
39bb4e58c6SEric Blake #include "qapi/error.h"
40bb4e58c6SEric Blake 
41bb4e58c6SEric Blake /**
42bb4e58c6SEric Blake  * block_dirty_bitmap_lookup:
43bb4e58c6SEric Blake  * Return a dirty bitmap (if present), after validating
44bb4e58c6SEric Blake  * the node reference and bitmap names.
45bb4e58c6SEric Blake  *
46bb4e58c6SEric Blake  * @node: The name of the BDS node to search for bitmaps
47bb4e58c6SEric Blake  * @name: The name of the bitmap to search for
48bb4e58c6SEric Blake  * @pbs: Output pointer for BDS lookup, if desired. Can be NULL.
49bb4e58c6SEric Blake  * @errp: Output pointer for error information. Can be NULL.
50bb4e58c6SEric Blake  *
51bb4e58c6SEric Blake  * @return: A bitmap object on success, or NULL on failure.
52bb4e58c6SEric Blake  */
block_dirty_bitmap_lookup(const char * node,const char * name,BlockDriverState ** pbs,Error ** errp)53bb4e58c6SEric Blake BdrvDirtyBitmap *block_dirty_bitmap_lookup(const char *node,
54bb4e58c6SEric Blake                                            const char *name,
55bb4e58c6SEric Blake                                            BlockDriverState **pbs,
56bb4e58c6SEric Blake                                            Error **errp)
57bb4e58c6SEric Blake {
58bb4e58c6SEric Blake     BlockDriverState *bs;
59bb4e58c6SEric Blake     BdrvDirtyBitmap *bitmap;
60bb4e58c6SEric Blake 
61b4ad82aaSEmanuele Giuseppe Esposito     GLOBAL_STATE_CODE();
62b4ad82aaSEmanuele Giuseppe Esposito 
63bb4e58c6SEric Blake     if (!node) {
64bb4e58c6SEric Blake         error_setg(errp, "Node cannot be NULL");
65bb4e58c6SEric Blake         return NULL;
66bb4e58c6SEric Blake     }
67bb4e58c6SEric Blake     if (!name) {
68bb4e58c6SEric Blake         error_setg(errp, "Bitmap name cannot be NULL");
69bb4e58c6SEric Blake         return NULL;
70bb4e58c6SEric Blake     }
71bb4e58c6SEric Blake     bs = bdrv_lookup_bs(node, node, NULL);
72bb4e58c6SEric Blake     if (!bs) {
73bb4e58c6SEric Blake         error_setg(errp, "Node '%s' not found", node);
74bb4e58c6SEric Blake         return NULL;
75bb4e58c6SEric Blake     }
76bb4e58c6SEric Blake 
77bb4e58c6SEric Blake     bitmap = bdrv_find_dirty_bitmap(bs, name);
78bb4e58c6SEric Blake     if (!bitmap) {
79bb4e58c6SEric Blake         error_setg(errp, "Dirty bitmap '%s' not found", name);
80bb4e58c6SEric Blake         return NULL;
81bb4e58c6SEric Blake     }
82bb4e58c6SEric Blake 
83bb4e58c6SEric Blake     if (pbs) {
84bb4e58c6SEric Blake         *pbs = bs;
85bb4e58c6SEric Blake     }
86bb4e58c6SEric Blake 
87bb4e58c6SEric Blake     return bitmap;
88bb4e58c6SEric Blake }
89bb4e58c6SEric Blake 
qmp_block_dirty_bitmap_add(const char * node,const char * name,bool has_granularity,uint32_t granularity,bool has_persistent,bool persistent,bool has_disabled,bool disabled,Error ** errp)90bb4e58c6SEric Blake void qmp_block_dirty_bitmap_add(const char *node, const char *name,
91bb4e58c6SEric Blake                                 bool has_granularity, uint32_t granularity,
92bb4e58c6SEric Blake                                 bool has_persistent, bool persistent,
93bb4e58c6SEric Blake                                 bool has_disabled, bool disabled,
94bb4e58c6SEric Blake                                 Error **errp)
95bb4e58c6SEric Blake {
96bb4e58c6SEric Blake     BlockDriverState *bs;
97bb4e58c6SEric Blake     BdrvDirtyBitmap *bitmap;
98bb4e58c6SEric Blake 
99bb4e58c6SEric Blake     if (!name || name[0] == '\0') {
100bb4e58c6SEric Blake         error_setg(errp, "Bitmap name cannot be empty");
101bb4e58c6SEric Blake         return;
102bb4e58c6SEric Blake     }
103bb4e58c6SEric Blake 
104bb4e58c6SEric Blake     bs = bdrv_lookup_bs(node, node, errp);
105bb4e58c6SEric Blake     if (!bs) {
106bb4e58c6SEric Blake         return;
107bb4e58c6SEric Blake     }
108bb4e58c6SEric Blake 
109bb4e58c6SEric Blake     if (has_granularity) {
110bb4e58c6SEric Blake         if (granularity < 512 || !is_power_of_2(granularity)) {
111bb4e58c6SEric Blake             error_setg(errp, "Granularity must be power of 2 "
112bb4e58c6SEric Blake                              "and at least 512");
113*b49f4755SStefan Hajnoczi             return;
114bb4e58c6SEric Blake         }
115bb4e58c6SEric Blake     } else {
116bb4e58c6SEric Blake         /* Default to cluster size, if available: */
117bb4e58c6SEric Blake         granularity = bdrv_get_default_bitmap_granularity(bs);
118bb4e58c6SEric Blake     }
119bb4e58c6SEric Blake 
120bb4e58c6SEric Blake     if (!has_persistent) {
121bb4e58c6SEric Blake         persistent = false;
122bb4e58c6SEric Blake     }
123bb4e58c6SEric Blake 
124bb4e58c6SEric Blake     if (!has_disabled) {
125bb4e58c6SEric Blake         disabled = false;
126bb4e58c6SEric Blake     }
127bb4e58c6SEric Blake 
128bb4e58c6SEric Blake     if (persistent &&
129bb4e58c6SEric Blake         !bdrv_can_store_new_dirty_bitmap(bs, name, granularity, errp))
130bb4e58c6SEric Blake     {
131*b49f4755SStefan Hajnoczi         return;
132bb4e58c6SEric Blake     }
133bb4e58c6SEric Blake 
134bb4e58c6SEric Blake     bitmap = bdrv_create_dirty_bitmap(bs, granularity, name, errp);
135bb4e58c6SEric Blake     if (bitmap == NULL) {
136*b49f4755SStefan Hajnoczi         return;
137bb4e58c6SEric Blake     }
138bb4e58c6SEric Blake 
139bb4e58c6SEric Blake     if (disabled) {
140bb4e58c6SEric Blake         bdrv_disable_dirty_bitmap(bitmap);
141bb4e58c6SEric Blake     }
142bb4e58c6SEric Blake 
143bb4e58c6SEric Blake     bdrv_dirty_bitmap_set_persistence(bitmap, persistent);
144bb4e58c6SEric Blake }
145bb4e58c6SEric Blake 
block_dirty_bitmap_remove(const char * node,const char * name,bool release,BlockDriverState ** bitmap_bs,Error ** errp)146bb4e58c6SEric Blake BdrvDirtyBitmap *block_dirty_bitmap_remove(const char *node, const char *name,
147bb4e58c6SEric Blake                                            bool release,
148bb4e58c6SEric Blake                                            BlockDriverState **bitmap_bs,
149bb4e58c6SEric Blake                                            Error **errp)
150bb4e58c6SEric Blake {
151bb4e58c6SEric Blake     BlockDriverState *bs;
152bb4e58c6SEric Blake     BdrvDirtyBitmap *bitmap;
153bb4e58c6SEric Blake 
154b4ad82aaSEmanuele Giuseppe Esposito     GLOBAL_STATE_CODE();
155b4ad82aaSEmanuele Giuseppe Esposito 
156bb4e58c6SEric Blake     bitmap = block_dirty_bitmap_lookup(node, name, &bs, errp);
157bb4e58c6SEric Blake     if (!bitmap || !bs) {
158bb4e58c6SEric Blake         return NULL;
159bb4e58c6SEric Blake     }
160bb4e58c6SEric Blake 
161bb4e58c6SEric Blake     if (bdrv_dirty_bitmap_check(bitmap, BDRV_BITMAP_BUSY | BDRV_BITMAP_RO,
162bb4e58c6SEric Blake                                 errp)) {
163bb4e58c6SEric Blake         return NULL;
164bb4e58c6SEric Blake     }
165bb4e58c6SEric Blake 
166bb4e58c6SEric Blake     if (bdrv_dirty_bitmap_get_persistence(bitmap) &&
167bb4e58c6SEric Blake         bdrv_remove_persistent_dirty_bitmap(bs, name, errp) < 0)
168bb4e58c6SEric Blake     {
169bb4e58c6SEric Blake         return NULL;
170bb4e58c6SEric Blake     }
171bb4e58c6SEric Blake 
172bb4e58c6SEric Blake     if (release) {
173bb4e58c6SEric Blake         bdrv_release_dirty_bitmap(bitmap);
174bb4e58c6SEric Blake     }
175bb4e58c6SEric Blake 
176bb4e58c6SEric Blake     if (bitmap_bs) {
177bb4e58c6SEric Blake         *bitmap_bs = bs;
178bb4e58c6SEric Blake     }
179bb4e58c6SEric Blake 
180bb4e58c6SEric Blake     return release ? NULL : bitmap;
181bb4e58c6SEric Blake }
182bb4e58c6SEric Blake 
qmp_block_dirty_bitmap_remove(const char * node,const char * name,Error ** errp)183bb4e58c6SEric Blake void qmp_block_dirty_bitmap_remove(const char *node, const char *name,
184bb4e58c6SEric Blake                                    Error **errp)
185bb4e58c6SEric Blake {
186bb4e58c6SEric Blake     block_dirty_bitmap_remove(node, name, true, NULL, errp);
187bb4e58c6SEric Blake }
188bb4e58c6SEric Blake 
189bb4e58c6SEric Blake /**
190bb4e58c6SEric Blake  * Completely clear a bitmap, for the purposes of synchronizing a bitmap
191bb4e58c6SEric Blake  * immediately after a full backup operation.
192bb4e58c6SEric Blake  */
qmp_block_dirty_bitmap_clear(const char * node,const char * name,Error ** errp)193bb4e58c6SEric Blake void qmp_block_dirty_bitmap_clear(const char *node, const char *name,
194bb4e58c6SEric Blake                                   Error **errp)
195bb4e58c6SEric Blake {
196bb4e58c6SEric Blake     BdrvDirtyBitmap *bitmap;
197bb4e58c6SEric Blake     BlockDriverState *bs;
198bb4e58c6SEric Blake 
199bb4e58c6SEric Blake     bitmap = block_dirty_bitmap_lookup(node, name, &bs, errp);
200bb4e58c6SEric Blake     if (!bitmap || !bs) {
201bb4e58c6SEric Blake         return;
202bb4e58c6SEric Blake     }
203bb4e58c6SEric Blake 
204bb4e58c6SEric Blake     if (bdrv_dirty_bitmap_check(bitmap, BDRV_BITMAP_DEFAULT, errp)) {
205bb4e58c6SEric Blake         return;
206bb4e58c6SEric Blake     }
207bb4e58c6SEric Blake 
208bb4e58c6SEric Blake     bdrv_clear_dirty_bitmap(bitmap, NULL);
209bb4e58c6SEric Blake }
210bb4e58c6SEric Blake 
qmp_block_dirty_bitmap_enable(const char * node,const char * name,Error ** errp)211bb4e58c6SEric Blake void qmp_block_dirty_bitmap_enable(const char *node, const char *name,
212bb4e58c6SEric Blake                                    Error **errp)
213bb4e58c6SEric Blake {
214bb4e58c6SEric Blake     BlockDriverState *bs;
215bb4e58c6SEric Blake     BdrvDirtyBitmap *bitmap;
216bb4e58c6SEric Blake 
217bb4e58c6SEric Blake     bitmap = block_dirty_bitmap_lookup(node, name, &bs, errp);
218bb4e58c6SEric Blake     if (!bitmap) {
219bb4e58c6SEric Blake         return;
220bb4e58c6SEric Blake     }
221bb4e58c6SEric Blake 
222bb4e58c6SEric Blake     if (bdrv_dirty_bitmap_check(bitmap, BDRV_BITMAP_ALLOW_RO, errp)) {
223bb4e58c6SEric Blake         return;
224bb4e58c6SEric Blake     }
225bb4e58c6SEric Blake 
226bb4e58c6SEric Blake     bdrv_enable_dirty_bitmap(bitmap);
227bb4e58c6SEric Blake }
228bb4e58c6SEric Blake 
qmp_block_dirty_bitmap_disable(const char * node,const char * name,Error ** errp)229bb4e58c6SEric Blake void qmp_block_dirty_bitmap_disable(const char *node, const char *name,
230bb4e58c6SEric Blake                                     Error **errp)
231bb4e58c6SEric Blake {
232bb4e58c6SEric Blake     BlockDriverState *bs;
233bb4e58c6SEric Blake     BdrvDirtyBitmap *bitmap;
234bb4e58c6SEric Blake 
235bb4e58c6SEric Blake     bitmap = block_dirty_bitmap_lookup(node, name, &bs, errp);
236bb4e58c6SEric Blake     if (!bitmap) {
237bb4e58c6SEric Blake         return;
238bb4e58c6SEric Blake     }
239bb4e58c6SEric Blake 
240bb4e58c6SEric Blake     if (bdrv_dirty_bitmap_check(bitmap, BDRV_BITMAP_ALLOW_RO, errp)) {
241bb4e58c6SEric Blake         return;
242bb4e58c6SEric Blake     }
243bb4e58c6SEric Blake 
244bb4e58c6SEric Blake     bdrv_disable_dirty_bitmap(bitmap);
245bb4e58c6SEric Blake }
246bb4e58c6SEric Blake 
block_dirty_bitmap_merge(const char * dst_node,const char * dst_bitmap,BlockDirtyBitmapOrStrList * bms,HBitmap ** backup,Error ** errp)2476a0f7ff7SMarkus Armbruster BdrvDirtyBitmap *block_dirty_bitmap_merge(const char *dst_node,
2486a0f7ff7SMarkus Armbruster                                           const char *dst_bitmap,
2491466ef6cSVladimir Sementsov-Ogievskiy                                           BlockDirtyBitmapOrStrList *bms,
250bb4e58c6SEric Blake                                           HBitmap **backup, Error **errp)
251bb4e58c6SEric Blake {
252bb4e58c6SEric Blake     BlockDriverState *bs;
25358cbfbdfSVladimir Sementsov-Ogievskiy     BdrvDirtyBitmap *dst, *src;
2541466ef6cSVladimir Sementsov-Ogievskiy     BlockDirtyBitmapOrStrList *lst;
2556a0f7ff7SMarkus Armbruster     const char *src_node, *src_bitmap;
25658cbfbdfSVladimir Sementsov-Ogievskiy     HBitmap *local_backup = NULL;
257bb4e58c6SEric Blake 
258b4ad82aaSEmanuele Giuseppe Esposito     GLOBAL_STATE_CODE();
259b4ad82aaSEmanuele Giuseppe Esposito 
2606a0f7ff7SMarkus Armbruster     dst = block_dirty_bitmap_lookup(dst_node, dst_bitmap, &bs, errp);
261bb4e58c6SEric Blake     if (!dst) {
262bb4e58c6SEric Blake         return NULL;
263bb4e58c6SEric Blake     }
264bb4e58c6SEric Blake 
265bb4e58c6SEric Blake     for (lst = bms; lst; lst = lst->next) {
266bb4e58c6SEric Blake         switch (lst->value->type) {
267bb4e58c6SEric Blake         case QTYPE_QSTRING:
2686a0f7ff7SMarkus Armbruster             src_bitmap = lst->value->u.local;
2696a0f7ff7SMarkus Armbruster             src = bdrv_find_dirty_bitmap(bs, src_bitmap);
270bb4e58c6SEric Blake             if (!src) {
2716a0f7ff7SMarkus Armbruster                 error_setg(errp, "Dirty bitmap '%s' not found", src_bitmap);
27258cbfbdfSVladimir Sementsov-Ogievskiy                 goto fail;
273bb4e58c6SEric Blake             }
274bb4e58c6SEric Blake             break;
275bb4e58c6SEric Blake         case QTYPE_QDICT:
2766a0f7ff7SMarkus Armbruster             src_node = lst->value->u.external.node;
2776a0f7ff7SMarkus Armbruster             src_bitmap = lst->value->u.external.name;
2786a0f7ff7SMarkus Armbruster             src = block_dirty_bitmap_lookup(src_node, src_bitmap, NULL, errp);
279bb4e58c6SEric Blake             if (!src) {
28058cbfbdfSVladimir Sementsov-Ogievskiy                 goto fail;
281bb4e58c6SEric Blake             }
282bb4e58c6SEric Blake             break;
283bb4e58c6SEric Blake         default:
284bb4e58c6SEric Blake             abort();
285bb4e58c6SEric Blake         }
286bb4e58c6SEric Blake 
28758cbfbdfSVladimir Sementsov-Ogievskiy         /* We do backup only for first merge operation */
28858cbfbdfSVladimir Sementsov-Ogievskiy         if (!bdrv_merge_dirty_bitmap(dst, src,
28958cbfbdfSVladimir Sementsov-Ogievskiy                                      local_backup ? NULL : &local_backup,
29058cbfbdfSVladimir Sementsov-Ogievskiy                                      errp))
29158cbfbdfSVladimir Sementsov-Ogievskiy         {
29258cbfbdfSVladimir Sementsov-Ogievskiy             goto fail;
293bb4e58c6SEric Blake         }
294bb4e58c6SEric Blake     }
295bb4e58c6SEric Blake 
29658cbfbdfSVladimir Sementsov-Ogievskiy     if (backup) {
29758cbfbdfSVladimir Sementsov-Ogievskiy         *backup = local_backup;
29858cbfbdfSVladimir Sementsov-Ogievskiy     } else {
29958cbfbdfSVladimir Sementsov-Ogievskiy         hbitmap_free(local_backup);
300775b30b3SVladimir Sementsov-Ogievskiy     }
301bb4e58c6SEric Blake 
302bb4e58c6SEric Blake     return dst;
30358cbfbdfSVladimir Sementsov-Ogievskiy 
30458cbfbdfSVladimir Sementsov-Ogievskiy fail:
30558cbfbdfSVladimir Sementsov-Ogievskiy     if (local_backup) {
30658cbfbdfSVladimir Sementsov-Ogievskiy         bdrv_restore_dirty_bitmap(dst, local_backup);
30758cbfbdfSVladimir Sementsov-Ogievskiy     }
30858cbfbdfSVladimir Sementsov-Ogievskiy 
30958cbfbdfSVladimir Sementsov-Ogievskiy     return NULL;
310bb4e58c6SEric Blake }
311bb4e58c6SEric Blake 
qmp_block_dirty_bitmap_merge(const char * node,const char * target,BlockDirtyBitmapOrStrList * bitmaps,Error ** errp)312bb4e58c6SEric Blake void qmp_block_dirty_bitmap_merge(const char *node, const char *target,
3131466ef6cSVladimir Sementsov-Ogievskiy                                   BlockDirtyBitmapOrStrList *bitmaps,
314bb4e58c6SEric Blake                                   Error **errp)
315bb4e58c6SEric Blake {
316bb4e58c6SEric Blake     block_dirty_bitmap_merge(node, target, bitmaps, NULL, errp);
317bb4e58c6SEric Blake }
318