xref: /qemu/block/dirty-bitmap.c (revision 167f748d)
1ebab2259SFam Zheng /*
2ebab2259SFam Zheng  * Block Dirty Bitmap
3ebab2259SFam Zheng  *
41b6cc579SEric Blake  * Copyright (c) 2016-2017 Red Hat. Inc
5ebab2259SFam Zheng  *
6ebab2259SFam Zheng  * Permission is hereby granted, free of charge, to any person obtaining a copy
7ebab2259SFam Zheng  * of this software and associated documentation files (the "Software"), to deal
8ebab2259SFam Zheng  * in the Software without restriction, including without limitation the rights
9ebab2259SFam Zheng  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10ebab2259SFam Zheng  * copies of the Software, and to permit persons to whom the Software is
11ebab2259SFam Zheng  * furnished to do so, subject to the following conditions:
12ebab2259SFam Zheng  *
13ebab2259SFam Zheng  * The above copyright notice and this permission notice shall be included in
14ebab2259SFam Zheng  * all copies or substantial portions of the Software.
15ebab2259SFam Zheng  *
16ebab2259SFam Zheng  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17ebab2259SFam Zheng  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18ebab2259SFam Zheng  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19ebab2259SFam Zheng  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20ebab2259SFam Zheng  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21ebab2259SFam Zheng  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22ebab2259SFam Zheng  * THE SOFTWARE.
23ebab2259SFam Zheng  */
24ebab2259SFam Zheng #include "qemu/osdep.h"
25da34e65cSMarkus Armbruster #include "qapi/error.h"
26ebab2259SFam Zheng #include "trace.h"
27e2c1c34fSMarkus Armbruster #include "block/block-io.h"
28ebab2259SFam Zheng #include "block/block_int.h"
29ebab2259SFam Zheng #include "block/blockjob.h"
30e2c1c34fSMarkus Armbruster #include "block/dirty-bitmap.h"
31d2c3080eSVladimir Sementsov-Ogievskiy #include "qemu/main-loop.h"
32ebab2259SFam Zheng 
33ebab2259SFam Zheng struct BdrvDirtyBitmap {
345deb6cbdSVladimir Sementsov-Ogievskiy     BlockDriverState *bs;
35ca759622SEric Blake     HBitmap *bitmap;            /* Dirty bitmap implementation */
3627a1b301SJohn Snow     bool busy;                  /* Bitmap is busy, it can't be used via QMP */
3721d2376fSJohn Snow     BdrvDirtyBitmap *successor; /* Anonymous child, if any. */
38ebab2259SFam Zheng     char *name;                 /* Optional non-empty unique ID */
39993e6525SEric Blake     int64_t size;               /* Size of the bitmap, in bytes */
408bfc932eSVladimir Sementsov-Ogievskiy     bool disabled;              /* Bitmap is disabled. It ignores all writes to
418bfc932eSVladimir Sementsov-Ogievskiy                                    the device */
42dc162c8eSFam Zheng     int active_iterators;       /* How many iterators are active */
43d6883bc9SVladimir Sementsov-Ogievskiy     bool readonly;              /* Bitmap is read-only. This field also
44d6883bc9SVladimir Sementsov-Ogievskiy                                    prevents the respective image from being
45d6883bc9SVladimir Sementsov-Ogievskiy                                    modified (i.e. blocks writes and discards).
46d6883bc9SVladimir Sementsov-Ogievskiy                                    Such operations must fail and both the image
47d6883bc9SVladimir Sementsov-Ogievskiy                                    and this bitmap must remain unchanged while
48d6883bc9SVladimir Sementsov-Ogievskiy                                    this flag is set. */
49a88b179fSVladimir Sementsov-Ogievskiy     bool persistent;            /* bitmap must be saved to owner disk image */
50b0f45559SJohn Snow     bool inconsistent;          /* bitmap is persistent, but inconsistent.
51b0f45559SJohn Snow                                    It cannot be used at all in any way, except
52b0f45559SJohn Snow                                    a QMP user can remove it. */
53c4e4b0faSJohn Snow     bool skip_store;            /* We are either migrating or deleting this
54c4e4b0faSJohn Snow                                  * bitmap; it should not be stored on the next
55c4e4b0faSJohn Snow                                  * inactivation. */
56ebab2259SFam Zheng     QLIST_ENTRY(BdrvDirtyBitmap) list;
57ebab2259SFam Zheng };
58ebab2259SFam Zheng 
59dc162c8eSFam Zheng struct BdrvDirtyBitmapIter {
60dc162c8eSFam Zheng     HBitmapIter hbi;
61dc162c8eSFam Zheng     BdrvDirtyBitmap *bitmap;
62dc162c8eSFam Zheng };
63dc162c8eSFam Zheng 
bdrv_dirty_bitmaps_lock(BlockDriverState * bs)642119882cSPaolo Bonzini static inline void bdrv_dirty_bitmaps_lock(BlockDriverState *bs)
652119882cSPaolo Bonzini {
662119882cSPaolo Bonzini     qemu_mutex_lock(&bs->dirty_bitmap_mutex);
672119882cSPaolo Bonzini }
682119882cSPaolo Bonzini 
bdrv_dirty_bitmaps_unlock(BlockDriverState * bs)692119882cSPaolo Bonzini static inline void bdrv_dirty_bitmaps_unlock(BlockDriverState *bs)
702119882cSPaolo Bonzini {
712119882cSPaolo Bonzini     qemu_mutex_unlock(&bs->dirty_bitmap_mutex);
722119882cSPaolo Bonzini }
732119882cSPaolo Bonzini 
bdrv_dirty_bitmap_lock(BdrvDirtyBitmap * bitmap)74b64bd51eSPaolo Bonzini void bdrv_dirty_bitmap_lock(BdrvDirtyBitmap *bitmap)
75b64bd51eSPaolo Bonzini {
761e638301SVladimir Sementsov-Ogievskiy     bdrv_dirty_bitmaps_lock(bitmap->bs);
77b64bd51eSPaolo Bonzini }
78b64bd51eSPaolo Bonzini 
bdrv_dirty_bitmap_unlock(BdrvDirtyBitmap * bitmap)79b64bd51eSPaolo Bonzini void bdrv_dirty_bitmap_unlock(BdrvDirtyBitmap *bitmap)
80b64bd51eSPaolo Bonzini {
811e638301SVladimir Sementsov-Ogievskiy     bdrv_dirty_bitmaps_unlock(bitmap->bs);
82b64bd51eSPaolo Bonzini }
83b64bd51eSPaolo Bonzini 
842119882cSPaolo Bonzini /* Called with BQL or dirty_bitmap lock taken.  */
bdrv_find_dirty_bitmap(BlockDriverState * bs,const char * name)85ebab2259SFam Zheng BdrvDirtyBitmap *bdrv_find_dirty_bitmap(BlockDriverState *bs, const char *name)
86ebab2259SFam Zheng {
87ebab2259SFam Zheng     BdrvDirtyBitmap *bm;
88ebab2259SFam Zheng 
89ebab2259SFam Zheng     assert(name);
90ebab2259SFam Zheng     QLIST_FOREACH(bm, &bs->dirty_bitmaps, list) {
91ebab2259SFam Zheng         if (bm->name && !strcmp(name, bm->name)) {
92ebab2259SFam Zheng             return bm;
93ebab2259SFam Zheng         }
94ebab2259SFam Zheng     }
95ebab2259SFam Zheng     return NULL;
96ebab2259SFam Zheng }
97ebab2259SFam Zheng 
982119882cSPaolo Bonzini /* Called with BQL taken.  */
bdrv_create_dirty_bitmap(BlockDriverState * bs,uint32_t granularity,const char * name,Error ** errp)99ebab2259SFam Zheng BdrvDirtyBitmap *bdrv_create_dirty_bitmap(BlockDriverState *bs,
100ebab2259SFam Zheng                                           uint32_t granularity,
101ebab2259SFam Zheng                                           const char *name,
102ebab2259SFam Zheng                                           Error **errp)
103ebab2259SFam Zheng {
104ebab2259SFam Zheng     int64_t bitmap_size;
105ebab2259SFam Zheng     BdrvDirtyBitmap *bitmap;
106ebab2259SFam Zheng 
107993e6525SEric Blake     assert(is_power_of_2(granularity) && granularity >= BDRV_SECTOR_SIZE);
108ebab2259SFam Zheng 
109cf7c49cfSEric Blake     if (name) {
110cf7c49cfSEric Blake         if (bdrv_find_dirty_bitmap(bs, name)) {
111ebab2259SFam Zheng             error_setg(errp, "Bitmap already exists: %s", name);
112ebab2259SFam Zheng             return NULL;
113ebab2259SFam Zheng         }
114cf7c49cfSEric Blake         if (strlen(name) > BDRV_BITMAP_MAX_NAME_SIZE) {
115cf7c49cfSEric Blake             error_setg(errp, "Bitmap name too long: %s", name);
116cf7c49cfSEric Blake             return NULL;
117cf7c49cfSEric Blake         }
118cf7c49cfSEric Blake     }
119993e6525SEric Blake     bitmap_size = bdrv_getlength(bs);
120ebab2259SFam Zheng     if (bitmap_size < 0) {
121ebab2259SFam Zheng         error_setg_errno(errp, -bitmap_size, "could not get length of device");
122ebab2259SFam Zheng         errno = -bitmap_size;
123ebab2259SFam Zheng         return NULL;
124ebab2259SFam Zheng     }
125ebab2259SFam Zheng     bitmap = g_new0(BdrvDirtyBitmap, 1);
1265deb6cbdSVladimir Sementsov-Ogievskiy     bitmap->bs = bs;
127ca759622SEric Blake     bitmap->bitmap = hbitmap_alloc(bitmap_size, ctz32(granularity));
128ebab2259SFam Zheng     bitmap->size = bitmap_size;
129ebab2259SFam Zheng     bitmap->name = g_strdup(name);
130ebab2259SFam Zheng     bitmap->disabled = false;
1312119882cSPaolo Bonzini     bdrv_dirty_bitmaps_lock(bs);
132ebab2259SFam Zheng     QLIST_INSERT_HEAD(&bs->dirty_bitmaps, bitmap, list);
1332119882cSPaolo Bonzini     bdrv_dirty_bitmaps_unlock(bs);
134ebab2259SFam Zheng     return bitmap;
135ebab2259SFam Zheng }
136ebab2259SFam Zheng 
bdrv_dirty_bitmap_size(const BdrvDirtyBitmap * bitmap)13715891facSFam Zheng int64_t bdrv_dirty_bitmap_size(const BdrvDirtyBitmap *bitmap)
13815891facSFam Zheng {
139993e6525SEric Blake     return bitmap->size;
14015891facSFam Zheng }
14115891facSFam Zheng 
bdrv_dirty_bitmap_name(const BdrvDirtyBitmap * bitmap)14215891facSFam Zheng const char *bdrv_dirty_bitmap_name(const BdrvDirtyBitmap *bitmap)
14315891facSFam Zheng {
14415891facSFam Zheng     return bitmap->name;
14515891facSFam Zheng }
14615891facSFam Zheng 
1472119882cSPaolo Bonzini /* Called with BQL taken.  */
bdrv_dirty_bitmap_has_successor(BdrvDirtyBitmap * bitmap)14850a47257SJohn Snow bool bdrv_dirty_bitmap_has_successor(BdrvDirtyBitmap *bitmap)
149ebab2259SFam Zheng {
150ebab2259SFam Zheng     return bitmap->successor;
151ebab2259SFam Zheng }
152ebab2259SFam Zheng 
bdrv_dirty_bitmap_busy(const BdrvDirtyBitmap * bitmap)1533ae96d66SJohn Snow static bool bdrv_dirty_bitmap_busy(const BdrvDirtyBitmap *bitmap)
15427a1b301SJohn Snow {
15527a1b301SJohn Snow     return bitmap->busy;
156993edc0cSJohn Snow }
157993edc0cSJohn Snow 
bdrv_dirty_bitmap_set_busy(BdrvDirtyBitmap * bitmap,bool busy)15827a1b301SJohn Snow void bdrv_dirty_bitmap_set_busy(BdrvDirtyBitmap *bitmap, bool busy)
1594f43e953SVladimir Sementsov-Ogievskiy {
1601e638301SVladimir Sementsov-Ogievskiy     bdrv_dirty_bitmaps_lock(bitmap->bs);
16127a1b301SJohn Snow     bitmap->busy = busy;
1621e638301SVladimir Sementsov-Ogievskiy     bdrv_dirty_bitmaps_unlock(bitmap->bs);
1634f43e953SVladimir Sementsov-Ogievskiy }
1644f43e953SVladimir Sementsov-Ogievskiy 
1652119882cSPaolo Bonzini /* Called with BQL taken.  */
bdrv_dirty_bitmap_enabled(BdrvDirtyBitmap * bitmap)166ebab2259SFam Zheng bool bdrv_dirty_bitmap_enabled(BdrvDirtyBitmap *bitmap)
167ebab2259SFam Zheng {
1688b2e20f6SJohn Snow     return !bitmap->disabled;
169ebab2259SFam Zheng }
170ebab2259SFam Zheng 
1714db6ceb0SJohn Snow /* Called with BQL taken.  */
bdrv_dirty_bitmap_recording(BdrvDirtyBitmap * bitmap)1724db6ceb0SJohn Snow static bool bdrv_dirty_bitmap_recording(BdrvDirtyBitmap *bitmap)
1734db6ceb0SJohn Snow {
1744db6ceb0SJohn Snow     return !bitmap->disabled || (bitmap->successor &&
1754db6ceb0SJohn Snow                                  !bitmap->successor->disabled);
1764db6ceb0SJohn Snow }
1774db6ceb0SJohn Snow 
bdrv_dirty_bitmap_check(const BdrvDirtyBitmap * bitmap,uint32_t flags,Error ** errp)1783ae96d66SJohn Snow int bdrv_dirty_bitmap_check(const BdrvDirtyBitmap *bitmap, uint32_t flags,
1793ae96d66SJohn Snow                             Error **errp)
1803ae96d66SJohn Snow {
1813ae96d66SJohn Snow     if ((flags & BDRV_BITMAP_BUSY) && bdrv_dirty_bitmap_busy(bitmap)) {
1823ae96d66SJohn Snow         error_setg(errp, "Bitmap '%s' is currently in use by another"
1833ae96d66SJohn Snow                    " operation and cannot be used", bitmap->name);
1843ae96d66SJohn Snow         return -1;
1853ae96d66SJohn Snow     }
1863ae96d66SJohn Snow 
1873ae96d66SJohn Snow     if ((flags & BDRV_BITMAP_RO) && bdrv_dirty_bitmap_readonly(bitmap)) {
1883ae96d66SJohn Snow         error_setg(errp, "Bitmap '%s' is readonly and cannot be modified",
1893ae96d66SJohn Snow                    bitmap->name);
1903ae96d66SJohn Snow         return -1;
1913ae96d66SJohn Snow     }
1923ae96d66SJohn Snow 
1933ae96d66SJohn Snow     if ((flags & BDRV_BITMAP_INCONSISTENT) &&
1943ae96d66SJohn Snow         bdrv_dirty_bitmap_inconsistent(bitmap)) {
1953ae96d66SJohn Snow         error_setg(errp, "Bitmap '%s' is inconsistent and cannot be used",
1963ae96d66SJohn Snow                    bitmap->name);
1973ae96d66SJohn Snow         error_append_hint(errp, "Try block-dirty-bitmap-remove to delete"
19894075c28SEric Blake                           " this bitmap from disk\n");
1993ae96d66SJohn Snow         return -1;
2003ae96d66SJohn Snow     }
2013ae96d66SJohn Snow 
2023ae96d66SJohn Snow     return 0;
2033ae96d66SJohn Snow }
2043ae96d66SJohn Snow 
205ebab2259SFam Zheng /**
206ebab2259SFam Zheng  * Create a successor bitmap destined to replace this bitmap after an operation.
20727a1b301SJohn Snow  * Requires that the bitmap is not marked busy and has no successor.
2088b2e20f6SJohn Snow  * The successor will be enabled if the parent bitmap was.
2092119882cSPaolo Bonzini  * Called with BQL taken.
210ebab2259SFam Zheng  */
bdrv_dirty_bitmap_create_successor(BdrvDirtyBitmap * bitmap,Error ** errp)2115deb6cbdSVladimir Sementsov-Ogievskiy int bdrv_dirty_bitmap_create_successor(BdrvDirtyBitmap *bitmap, Error **errp)
212ebab2259SFam Zheng {
213ebab2259SFam Zheng     uint64_t granularity;
214ebab2259SFam Zheng     BdrvDirtyBitmap *child;
215ebab2259SFam Zheng 
2163ae96d66SJohn Snow     if (bdrv_dirty_bitmap_check(bitmap, BDRV_BITMAP_BUSY, errp)) {
217ebab2259SFam Zheng         return -1;
218ebab2259SFam Zheng     }
21950a47257SJohn Snow     if (bdrv_dirty_bitmap_has_successor(bitmap)) {
22050a47257SJohn Snow         error_setg(errp, "Cannot create a successor for a bitmap that already "
22150a47257SJohn Snow                    "has one");
22250a47257SJohn Snow         return -1;
22350a47257SJohn Snow     }
224ebab2259SFam Zheng 
225ebab2259SFam Zheng     /* Create an anonymous successor */
226ebab2259SFam Zheng     granularity = bdrv_dirty_bitmap_granularity(bitmap);
2275deb6cbdSVladimir Sementsov-Ogievskiy     child = bdrv_create_dirty_bitmap(bitmap->bs, granularity, NULL, errp);
228ebab2259SFam Zheng     if (!child) {
229ebab2259SFam Zheng         return -1;
230ebab2259SFam Zheng     }
231ebab2259SFam Zheng 
232ebab2259SFam Zheng     /* Successor will be on or off based on our current state. */
233ebab2259SFam Zheng     child->disabled = bitmap->disabled;
2348b2e20f6SJohn Snow     bitmap->disabled = true;
235ebab2259SFam Zheng 
23627a1b301SJohn Snow     /* Install the successor and mark the parent as busy */
237ebab2259SFam Zheng     bitmap->successor = child;
23827a1b301SJohn Snow     bitmap->busy = true;
239ebab2259SFam Zheng     return 0;
240ebab2259SFam Zheng }
241ebab2259SFam Zheng 
bdrv_enable_dirty_bitmap_locked(BdrvDirtyBitmap * bitmap)24292bcea40SVladimir Sementsov-Ogievskiy void bdrv_enable_dirty_bitmap_locked(BdrvDirtyBitmap *bitmap)
24392bcea40SVladimir Sementsov-Ogievskiy {
24492bcea40SVladimir Sementsov-Ogievskiy     bitmap->disabled = false;
24592bcea40SVladimir Sementsov-Ogievskiy }
24692bcea40SVladimir Sementsov-Ogievskiy 
247e73a265eSVladimir Sementsov-Ogievskiy /* Called with BQL taken. */
bdrv_dirty_bitmap_enable_successor(BdrvDirtyBitmap * bitmap)248e73a265eSVladimir Sementsov-Ogievskiy void bdrv_dirty_bitmap_enable_successor(BdrvDirtyBitmap *bitmap)
249e73a265eSVladimir Sementsov-Ogievskiy {
2501e638301SVladimir Sementsov-Ogievskiy     assert(bitmap->bs == bitmap->successor->bs);
2511e638301SVladimir Sementsov-Ogievskiy     bdrv_dirty_bitmaps_lock(bitmap->bs);
25258f72b96SVladimir Sementsov-Ogievskiy     bdrv_enable_dirty_bitmap_locked(bitmap->successor);
2531e638301SVladimir Sementsov-Ogievskiy     bdrv_dirty_bitmaps_unlock(bitmap->bs);
254e73a265eSVladimir Sementsov-Ogievskiy }
255e73a265eSVladimir Sementsov-Ogievskiy 
256b133c27fSPaolo Bonzini /* Called within bdrv_dirty_bitmap_lock..unlock and with BQL taken.  */
bdrv_release_dirty_bitmap_locked(BdrvDirtyBitmap * bitmap)257b133c27fSPaolo Bonzini static void bdrv_release_dirty_bitmap_locked(BdrvDirtyBitmap *bitmap)
258604ab74bSVladimir Sementsov-Ogievskiy {
259b133c27fSPaolo Bonzini     assert(!bitmap->active_iterators);
26027a1b301SJohn Snow     assert(!bdrv_dirty_bitmap_busy(bitmap));
26150a47257SJohn Snow     assert(!bdrv_dirty_bitmap_has_successor(bitmap));
262b133c27fSPaolo Bonzini     QLIST_REMOVE(bitmap, list);
263b133c27fSPaolo Bonzini     hbitmap_free(bitmap->bitmap);
264b133c27fSPaolo Bonzini     g_free(bitmap->name);
265b133c27fSPaolo Bonzini     g_free(bitmap);
266604ab74bSVladimir Sementsov-Ogievskiy }
267604ab74bSVladimir Sementsov-Ogievskiy 
268ebab2259SFam Zheng /**
269ebab2259SFam Zheng  * For a bitmap with a successor, yield our name to the successor,
270ebab2259SFam Zheng  * delete the old bitmap, and return a handle to the new bitmap.
2712119882cSPaolo Bonzini  * Called with BQL taken.
272ebab2259SFam Zheng  */
bdrv_dirty_bitmap_abdicate(BdrvDirtyBitmap * bitmap,Error ** errp)2735deb6cbdSVladimir Sementsov-Ogievskiy BdrvDirtyBitmap *bdrv_dirty_bitmap_abdicate(BdrvDirtyBitmap *bitmap,
274ebab2259SFam Zheng                                             Error **errp)
275ebab2259SFam Zheng {
276ebab2259SFam Zheng     char *name;
277ebab2259SFam Zheng     BdrvDirtyBitmap *successor = bitmap->successor;
278ebab2259SFam Zheng 
279ebab2259SFam Zheng     if (successor == NULL) {
280ebab2259SFam Zheng         error_setg(errp, "Cannot relinquish control if "
281ebab2259SFam Zheng                    "there's no successor present");
282ebab2259SFam Zheng         return NULL;
283ebab2259SFam Zheng     }
284ebab2259SFam Zheng 
285ebab2259SFam Zheng     name = bitmap->name;
286ebab2259SFam Zheng     bitmap->name = NULL;
287ebab2259SFam Zheng     successor->name = name;
288ebab2259SFam Zheng     bitmap->successor = NULL;
289a88b179fSVladimir Sementsov-Ogievskiy     successor->persistent = bitmap->persistent;
290a88b179fSVladimir Sementsov-Ogievskiy     bitmap->persistent = false;
29127a1b301SJohn Snow     bitmap->busy = false;
2925deb6cbdSVladimir Sementsov-Ogievskiy     bdrv_release_dirty_bitmap(bitmap);
293ebab2259SFam Zheng 
294ebab2259SFam Zheng     return successor;
295ebab2259SFam Zheng }
296ebab2259SFam Zheng 
297ebab2259SFam Zheng /**
298ebab2259SFam Zheng  * In cases of failure where we can no longer safely delete the parent,
299ebab2259SFam Zheng  * we may wish to re-join the parent and child/successor.
30027a1b301SJohn Snow  * The merged parent will be marked as not busy.
3018b2e20f6SJohn Snow  * The marged parent will be enabled if and only if the successor was enabled.
302044ee8e1SVladimir Sementsov-Ogievskiy  * Called within bdrv_dirty_bitmap_lock..unlock and with BQL taken.
303ebab2259SFam Zheng  */
bdrv_reclaim_dirty_bitmap_locked(BdrvDirtyBitmap * parent,Error ** errp)3045deb6cbdSVladimir Sementsov-Ogievskiy BdrvDirtyBitmap *bdrv_reclaim_dirty_bitmap_locked(BdrvDirtyBitmap *parent,
305ebab2259SFam Zheng                                                   Error **errp)
306ebab2259SFam Zheng {
307044ee8e1SVladimir Sementsov-Ogievskiy     BdrvDirtyBitmap *successor = parent->successor;
308ebab2259SFam Zheng 
309ebab2259SFam Zheng     if (!successor) {
310ebab2259SFam Zheng         error_setg(errp, "Cannot reclaim a successor when none is present");
311ebab2259SFam Zheng         return NULL;
312ebab2259SFam Zheng     }
313ebab2259SFam Zheng 
314618af89eSVladimir Sementsov-Ogievskiy     hbitmap_merge(parent->bitmap, successor->bitmap, parent->bitmap);
3158b2e20f6SJohn Snow 
3168b2e20f6SJohn Snow     parent->disabled = successor->disabled;
31727a1b301SJohn Snow     parent->busy = false;
318b133c27fSPaolo Bonzini     bdrv_release_dirty_bitmap_locked(successor);
319ebab2259SFam Zheng     parent->successor = NULL;
320ebab2259SFam Zheng 
321044ee8e1SVladimir Sementsov-Ogievskiy     return parent;
322044ee8e1SVladimir Sementsov-Ogievskiy }
323044ee8e1SVladimir Sementsov-Ogievskiy 
324044ee8e1SVladimir Sementsov-Ogievskiy /* Called with BQL taken. */
bdrv_reclaim_dirty_bitmap(BdrvDirtyBitmap * parent,Error ** errp)3255deb6cbdSVladimir Sementsov-Ogievskiy BdrvDirtyBitmap *bdrv_reclaim_dirty_bitmap(BdrvDirtyBitmap *parent,
326044ee8e1SVladimir Sementsov-Ogievskiy                                            Error **errp)
327044ee8e1SVladimir Sementsov-Ogievskiy {
328044ee8e1SVladimir Sementsov-Ogievskiy     BdrvDirtyBitmap *ret;
329044ee8e1SVladimir Sementsov-Ogievskiy 
3301e638301SVladimir Sementsov-Ogievskiy     bdrv_dirty_bitmaps_lock(parent->bs);
3315deb6cbdSVladimir Sementsov-Ogievskiy     ret = bdrv_reclaim_dirty_bitmap_locked(parent, errp);
3321e638301SVladimir Sementsov-Ogievskiy     bdrv_dirty_bitmaps_unlock(parent->bs);
333604ab74bSVladimir Sementsov-Ogievskiy 
334044ee8e1SVladimir Sementsov-Ogievskiy     return ret;
335ebab2259SFam Zheng }
336ebab2259SFam Zheng 
337ebab2259SFam Zheng /**
338ebab2259SFam Zheng  * Truncates _all_ bitmaps attached to a BDS.
3392119882cSPaolo Bonzini  * Called with BQL taken.
340ebab2259SFam Zheng  */
bdrv_dirty_bitmap_truncate(BlockDriverState * bs,int64_t bytes)3411b6cc579SEric Blake void bdrv_dirty_bitmap_truncate(BlockDriverState *bs, int64_t bytes)
342ebab2259SFam Zheng {
343ebab2259SFam Zheng     BdrvDirtyBitmap *bitmap;
344ebab2259SFam Zheng 
3452119882cSPaolo Bonzini     bdrv_dirty_bitmaps_lock(bs);
346ebab2259SFam Zheng     QLIST_FOREACH(bitmap, &bs->dirty_bitmaps, list) {
34727a1b301SJohn Snow         assert(!bdrv_dirty_bitmap_busy(bitmap));
34850a47257SJohn Snow         assert(!bdrv_dirty_bitmap_has_successor(bitmap));
349dc162c8eSFam Zheng         assert(!bitmap->active_iterators);
350ca759622SEric Blake         hbitmap_truncate(bitmap->bitmap, bytes);
351993e6525SEric Blake         bitmap->size = bytes;
352ebab2259SFam Zheng     }
3532119882cSPaolo Bonzini     bdrv_dirty_bitmaps_unlock(bs);
354ebab2259SFam Zheng }
355ebab2259SFam Zheng 
3562119882cSPaolo Bonzini /* Called with BQL taken.  */
bdrv_release_dirty_bitmap(BdrvDirtyBitmap * bitmap)3575deb6cbdSVladimir Sementsov-Ogievskiy void bdrv_release_dirty_bitmap(BdrvDirtyBitmap *bitmap)
358ebab2259SFam Zheng {
3595deb6cbdSVladimir Sementsov-Ogievskiy     BlockDriverState *bs = bitmap->bs;
3605deb6cbdSVladimir Sementsov-Ogievskiy 
361b133c27fSPaolo Bonzini     bdrv_dirty_bitmaps_lock(bs);
362b133c27fSPaolo Bonzini     bdrv_release_dirty_bitmap_locked(bitmap);
363b133c27fSPaolo Bonzini     bdrv_dirty_bitmaps_unlock(bs);
364ebab2259SFam Zheng }
365ebab2259SFam Zheng 
366ebab2259SFam Zheng /**
367ebab2259SFam Zheng  * Release all named dirty bitmaps attached to a BDS (for use in bdrv_close()).
36827a1b301SJohn Snow  * There must not be any busy bitmaps attached.
36956f364e6SVladimir Sementsov-Ogievskiy  * This function does not remove persistent bitmaps from the storage.
3702119882cSPaolo Bonzini  * Called with BQL taken.
371ebab2259SFam Zheng  */
bdrv_release_named_dirty_bitmaps(BlockDriverState * bs)372ebab2259SFam Zheng void bdrv_release_named_dirty_bitmaps(BlockDriverState *bs)
373ebab2259SFam Zheng {
374b133c27fSPaolo Bonzini     BdrvDirtyBitmap *bm, *next;
375b133c27fSPaolo Bonzini 
376b133c27fSPaolo Bonzini     bdrv_dirty_bitmaps_lock(bs);
377b133c27fSPaolo Bonzini     QLIST_FOREACH_SAFE(bm, &bs->dirty_bitmaps, list, next) {
378b133c27fSPaolo Bonzini         if (bdrv_dirty_bitmap_name(bm)) {
379b133c27fSPaolo Bonzini             bdrv_release_dirty_bitmap_locked(bm);
380b133c27fSPaolo Bonzini         }
381b133c27fSPaolo Bonzini     }
382b133c27fSPaolo Bonzini     bdrv_dirty_bitmaps_unlock(bs);
383615b5dcfSVladimir Sementsov-Ogievskiy }
384615b5dcfSVladimir Sementsov-Ogievskiy 
385615b5dcfSVladimir Sementsov-Ogievskiy /**
38656f364e6SVladimir Sementsov-Ogievskiy  * Remove persistent dirty bitmap from the storage if it exists.
38756f364e6SVladimir Sementsov-Ogievskiy  * Absence of bitmap is not an error, because we have the following scenario:
38856f364e6SVladimir Sementsov-Ogievskiy  * BdrvDirtyBitmap can have .persistent = true but not yet saved and have no
38956f364e6SVladimir Sementsov-Ogievskiy  * stored version. For such bitmap bdrv_remove_persistent_dirty_bitmap() should
39056f364e6SVladimir Sementsov-Ogievskiy  * not fail.
39156f364e6SVladimir Sementsov-Ogievskiy  * This function doesn't release corresponding BdrvDirtyBitmap.
39256f364e6SVladimir Sementsov-Ogievskiy  */
3930508d0beSEmanuele Giuseppe Esposito int coroutine_fn
bdrv_co_remove_persistent_dirty_bitmap(BlockDriverState * bs,const char * name,Error ** errp)394d2c3080eSVladimir Sementsov-Ogievskiy bdrv_co_remove_persistent_dirty_bitmap(BlockDriverState *bs, const char *name,
39556f364e6SVladimir Sementsov-Ogievskiy                                        Error **errp)
39656f364e6SVladimir Sementsov-Ogievskiy {
397167f748dSKevin Wolf     assert_bdrv_graph_readable();
398d2c3080eSVladimir Sementsov-Ogievskiy     if (bs->drv && bs->drv->bdrv_co_remove_persistent_dirty_bitmap) {
399d2c3080eSVladimir Sementsov-Ogievskiy         return bs->drv->bdrv_co_remove_persistent_dirty_bitmap(bs, name, errp);
40056f364e6SVladimir Sementsov-Ogievskiy     }
401b56a1e31SVladimir Sementsov-Ogievskiy 
402b56a1e31SVladimir Sementsov-Ogievskiy     return 0;
40356f364e6SVladimir Sementsov-Ogievskiy }
40456f364e6SVladimir Sementsov-Ogievskiy 
405ef893b5cSEric Blake bool
bdrv_supports_persistent_dirty_bitmap(BlockDriverState * bs)406ef893b5cSEric Blake bdrv_supports_persistent_dirty_bitmap(BlockDriverState *bs)
407ef893b5cSEric Blake {
408ef893b5cSEric Blake     if (bs->drv && bs->drv->bdrv_supports_persistent_dirty_bitmap) {
409ef893b5cSEric Blake         return bs->drv->bdrv_supports_persistent_dirty_bitmap(bs);
410ef893b5cSEric Blake     }
411ef893b5cSEric Blake     return false;
412ef893b5cSEric Blake }
413ef893b5cSEric Blake 
4140508d0beSEmanuele Giuseppe Esposito bool coroutine_fn
bdrv_co_can_store_new_dirty_bitmap(BlockDriverState * bs,const char * name,uint32_t granularity,Error ** errp)415d2c3080eSVladimir Sementsov-Ogievskiy bdrv_co_can_store_new_dirty_bitmap(BlockDriverState *bs, const char *name,
41685cc8a4fSVladimir Sementsov-Ogievskiy                                    uint32_t granularity, Error **errp)
41785cc8a4fSVladimir Sementsov-Ogievskiy {
41885cc8a4fSVladimir Sementsov-Ogievskiy     BlockDriver *drv = bs->drv;
419167f748dSKevin Wolf     assert_bdrv_graph_readable();
42085cc8a4fSVladimir Sementsov-Ogievskiy 
42185cc8a4fSVladimir Sementsov-Ogievskiy     if (!drv) {
42285cc8a4fSVladimir Sementsov-Ogievskiy         error_setg_errno(errp, ENOMEDIUM,
42385cc8a4fSVladimir Sementsov-Ogievskiy                          "Can't store persistent bitmaps to %s",
42485cc8a4fSVladimir Sementsov-Ogievskiy                          bdrv_get_device_or_node_name(bs));
42585cc8a4fSVladimir Sementsov-Ogievskiy         return false;
42685cc8a4fSVladimir Sementsov-Ogievskiy     }
42785cc8a4fSVladimir Sementsov-Ogievskiy 
428d2c3080eSVladimir Sementsov-Ogievskiy     if (!drv->bdrv_co_can_store_new_dirty_bitmap) {
42985cc8a4fSVladimir Sementsov-Ogievskiy         error_setg_errno(errp, ENOTSUP,
43085cc8a4fSVladimir Sementsov-Ogievskiy                          "Can't store persistent bitmaps to %s",
43185cc8a4fSVladimir Sementsov-Ogievskiy                          bdrv_get_device_or_node_name(bs));
43285cc8a4fSVladimir Sementsov-Ogievskiy         return false;
43385cc8a4fSVladimir Sementsov-Ogievskiy     }
43485cc8a4fSVladimir Sementsov-Ogievskiy 
435d2c3080eSVladimir Sementsov-Ogievskiy     return drv->bdrv_co_can_store_new_dirty_bitmap(bs, name, granularity, errp);
436d2c3080eSVladimir Sementsov-Ogievskiy }
437d2c3080eSVladimir Sementsov-Ogievskiy 
bdrv_disable_dirty_bitmap(BdrvDirtyBitmap * bitmap)438ebab2259SFam Zheng void bdrv_disable_dirty_bitmap(BdrvDirtyBitmap *bitmap)
439ebab2259SFam Zheng {
4401e638301SVladimir Sementsov-Ogievskiy     bdrv_dirty_bitmaps_lock(bitmap->bs);
441ebab2259SFam Zheng     bitmap->disabled = true;
4421e638301SVladimir Sementsov-Ogievskiy     bdrv_dirty_bitmaps_unlock(bitmap->bs);
443ebab2259SFam Zheng }
444ebab2259SFam Zheng 
bdrv_enable_dirty_bitmap(BdrvDirtyBitmap * bitmap)445ebab2259SFam Zheng void bdrv_enable_dirty_bitmap(BdrvDirtyBitmap *bitmap)
446ebab2259SFam Zheng {
4471e638301SVladimir Sementsov-Ogievskiy     bdrv_dirty_bitmaps_lock(bitmap->bs);
44892bcea40SVladimir Sementsov-Ogievskiy     bdrv_enable_dirty_bitmap_locked(bitmap);
4491e638301SVladimir Sementsov-Ogievskiy     bdrv_dirty_bitmaps_unlock(bitmap->bs);
450ebab2259SFam Zheng }
451ebab2259SFam Zheng 
bdrv_query_dirty_bitmaps(BlockDriverState * bs)452ebab2259SFam Zheng BlockDirtyInfoList *bdrv_query_dirty_bitmaps(BlockDriverState *bs)
453ebab2259SFam Zheng {
454ebab2259SFam Zheng     BdrvDirtyBitmap *bm;
455ebab2259SFam Zheng     BlockDirtyInfoList *list = NULL;
456c3033fd3SEric Blake     BlockDirtyInfoList **tail = &list;
457ebab2259SFam Zheng 
4582119882cSPaolo Bonzini     bdrv_dirty_bitmaps_lock(bs);
459ebab2259SFam Zheng     QLIST_FOREACH(bm, &bs->dirty_bitmaps, list) {
460ebab2259SFam Zheng         BlockDirtyInfo *info = g_new0(BlockDirtyInfo, 1);
461c3033fd3SEric Blake 
4629a46dba7SEric Blake         info->count = bdrv_get_dirty_count(bm);
463ebab2259SFam Zheng         info->granularity = bdrv_dirty_bitmap_granularity(bm);
464ebab2259SFam Zheng         info->name = g_strdup(bm->name);
4654db6ceb0SJohn Snow         info->recording = bdrv_dirty_bitmap_recording(bm);
46627a1b301SJohn Snow         info->busy = bdrv_dirty_bitmap_busy(bm);
467f67cf661SEric Blake         info->persistent = bm->persistent;
468b0f45559SJohn Snow         info->has_inconsistent = bm->inconsistent;
469b0f45559SJohn Snow         info->inconsistent = bm->inconsistent;
470c3033fd3SEric Blake         QAPI_LIST_APPEND(tail, info);
471ebab2259SFam Zheng     }
4722119882cSPaolo Bonzini     bdrv_dirty_bitmaps_unlock(bs);
473ebab2259SFam Zheng 
474ebab2259SFam Zheng     return list;
475ebab2259SFam Zheng }
476ebab2259SFam Zheng 
477b64bd51eSPaolo Bonzini /* Called within bdrv_dirty_bitmap_lock..unlock */
bdrv_dirty_bitmap_get_locked(BdrvDirtyBitmap * bitmap,int64_t offset)47828636b82SJohn Snow bool bdrv_dirty_bitmap_get_locked(BdrvDirtyBitmap *bitmap, int64_t offset)
479ebab2259SFam Zheng {
480ca759622SEric Blake     return hbitmap_get(bitmap->bitmap, offset);
481ebab2259SFam Zheng }
48228636b82SJohn Snow 
bdrv_dirty_bitmap_get(BdrvDirtyBitmap * bitmap,int64_t offset)48328636b82SJohn Snow bool bdrv_dirty_bitmap_get(BdrvDirtyBitmap *bitmap, int64_t offset)
48428636b82SJohn Snow {
48528636b82SJohn Snow     bool ret;
4861e638301SVladimir Sementsov-Ogievskiy     bdrv_dirty_bitmaps_lock(bitmap->bs);
48728636b82SJohn Snow     ret = bdrv_dirty_bitmap_get_locked(bitmap, offset);
4881e638301SVladimir Sementsov-Ogievskiy     bdrv_dirty_bitmaps_unlock(bitmap->bs);
48928636b82SJohn Snow 
49028636b82SJohn Snow     return ret;
491ebab2259SFam Zheng }
492ebab2259SFam Zheng 
493ebab2259SFam Zheng /**
494ebab2259SFam Zheng  * Chooses a default granularity based on the existing cluster size,
495ebab2259SFam Zheng  * but clamped between [4K, 64K]. Defaults to 64K in the case that there
496ebab2259SFam Zheng  * is no cluster size information available.
497ebab2259SFam Zheng  */
bdrv_get_default_bitmap_granularity(BlockDriverState * bs)498ebab2259SFam Zheng uint32_t bdrv_get_default_bitmap_granularity(BlockDriverState *bs)
499ebab2259SFam Zheng {
500ebab2259SFam Zheng     BlockDriverInfo bdi;
501ebab2259SFam Zheng     uint32_t granularity;
502ebab2259SFam Zheng 
503ebab2259SFam Zheng     if (bdrv_get_info(bs, &bdi) >= 0 && bdi.cluster_size > 0) {
504ebab2259SFam Zheng         granularity = MAX(4096, bdi.cluster_size);
505ebab2259SFam Zheng         granularity = MIN(65536, granularity);
506ebab2259SFam Zheng     } else {
507ebab2259SFam Zheng         granularity = 65536;
508ebab2259SFam Zheng     }
509ebab2259SFam Zheng 
510ebab2259SFam Zheng     return granularity;
511ebab2259SFam Zheng }
512ebab2259SFam Zheng 
bdrv_dirty_bitmap_granularity(const BdrvDirtyBitmap * bitmap)513ba06ff1aSVladimir Sementsov-Ogievskiy uint32_t bdrv_dirty_bitmap_granularity(const BdrvDirtyBitmap *bitmap)
514ebab2259SFam Zheng {
515ca759622SEric Blake     return 1U << hbitmap_granularity(bitmap->bitmap);
516ebab2259SFam Zheng }
517ebab2259SFam Zheng 
bdrv_dirty_iter_new(BdrvDirtyBitmap * bitmap)518715a74d8SEric Blake BdrvDirtyBitmapIter *bdrv_dirty_iter_new(BdrvDirtyBitmap *bitmap)
519ebab2259SFam Zheng {
520dc162c8eSFam Zheng     BdrvDirtyBitmapIter *iter = g_new(BdrvDirtyBitmapIter, 1);
521715a74d8SEric Blake     hbitmap_iter_init(&iter->hbi, bitmap->bitmap, 0);
522dc162c8eSFam Zheng     iter->bitmap = bitmap;
523dc162c8eSFam Zheng     bitmap->active_iterators++;
524dc162c8eSFam Zheng     return iter;
525dc162c8eSFam Zheng }
526dc162c8eSFam Zheng 
bdrv_dirty_iter_free(BdrvDirtyBitmapIter * iter)527dc162c8eSFam Zheng void bdrv_dirty_iter_free(BdrvDirtyBitmapIter *iter)
528dc162c8eSFam Zheng {
529dc162c8eSFam Zheng     if (!iter) {
530dc162c8eSFam Zheng         return;
531dc162c8eSFam Zheng     }
532dc162c8eSFam Zheng     assert(iter->bitmap->active_iterators > 0);
533dc162c8eSFam Zheng     iter->bitmap->active_iterators--;
534dc162c8eSFam Zheng     g_free(iter);
535dc162c8eSFam Zheng }
536dc162c8eSFam Zheng 
bdrv_dirty_iter_next(BdrvDirtyBitmapIter * iter)537dc162c8eSFam Zheng int64_t bdrv_dirty_iter_next(BdrvDirtyBitmapIter *iter)
538dc162c8eSFam Zheng {
53919c021e1SVladimir Sementsov-Ogievskiy     return hbitmap_iter_next(&iter->hbi);
540ebab2259SFam Zheng }
541ebab2259SFam Zheng 
542b64bd51eSPaolo Bonzini /* Called within bdrv_dirty_bitmap_lock..unlock */
bdrv_set_dirty_bitmap_locked(BdrvDirtyBitmap * bitmap,int64_t offset,int64_t bytes)543b64bd51eSPaolo Bonzini void bdrv_set_dirty_bitmap_locked(BdrvDirtyBitmap *bitmap,
544e0d7f73eSEric Blake                                   int64_t offset, int64_t bytes)
545ebab2259SFam Zheng {
546d6883bc9SVladimir Sementsov-Ogievskiy     assert(!bdrv_dirty_bitmap_readonly(bitmap));
547ca759622SEric Blake     hbitmap_set(bitmap->bitmap, offset, bytes);
548ebab2259SFam Zheng }
549ebab2259SFam Zheng 
bdrv_set_dirty_bitmap(BdrvDirtyBitmap * bitmap,int64_t offset,int64_t bytes)550b64bd51eSPaolo Bonzini void bdrv_set_dirty_bitmap(BdrvDirtyBitmap *bitmap,
551e0d7f73eSEric Blake                            int64_t offset, int64_t bytes)
552b64bd51eSPaolo Bonzini {
5531e638301SVladimir Sementsov-Ogievskiy     bdrv_dirty_bitmaps_lock(bitmap->bs);
554e0d7f73eSEric Blake     bdrv_set_dirty_bitmap_locked(bitmap, offset, bytes);
5551e638301SVladimir Sementsov-Ogievskiy     bdrv_dirty_bitmaps_unlock(bitmap->bs);
556b64bd51eSPaolo Bonzini }
557b64bd51eSPaolo Bonzini 
558b64bd51eSPaolo Bonzini /* Called within bdrv_dirty_bitmap_lock..unlock */
bdrv_reset_dirty_bitmap_locked(BdrvDirtyBitmap * bitmap,int64_t offset,int64_t bytes)559b64bd51eSPaolo Bonzini void bdrv_reset_dirty_bitmap_locked(BdrvDirtyBitmap *bitmap,
560e0d7f73eSEric Blake                                     int64_t offset, int64_t bytes)
561ebab2259SFam Zheng {
562d6883bc9SVladimir Sementsov-Ogievskiy     assert(!bdrv_dirty_bitmap_readonly(bitmap));
563ca759622SEric Blake     hbitmap_reset(bitmap->bitmap, offset, bytes);
564ebab2259SFam Zheng }
565ebab2259SFam Zheng 
bdrv_reset_dirty_bitmap(BdrvDirtyBitmap * bitmap,int64_t offset,int64_t bytes)566b64bd51eSPaolo Bonzini void bdrv_reset_dirty_bitmap(BdrvDirtyBitmap *bitmap,
567e0d7f73eSEric Blake                              int64_t offset, int64_t bytes)
568b64bd51eSPaolo Bonzini {
5691e638301SVladimir Sementsov-Ogievskiy     bdrv_dirty_bitmaps_lock(bitmap->bs);
570e0d7f73eSEric Blake     bdrv_reset_dirty_bitmap_locked(bitmap, offset, bytes);
5711e638301SVladimir Sementsov-Ogievskiy     bdrv_dirty_bitmaps_unlock(bitmap->bs);
572b64bd51eSPaolo Bonzini }
573b64bd51eSPaolo Bonzini 
bdrv_clear_dirty_bitmap(BdrvDirtyBitmap * bitmap,HBitmap ** out)574ebab2259SFam Zheng void bdrv_clear_dirty_bitmap(BdrvDirtyBitmap *bitmap, HBitmap **out)
575ebab2259SFam Zheng {
576967d7905SEmanuele Giuseppe Esposito     IO_CODE();
577d6883bc9SVladimir Sementsov-Ogievskiy     assert(!bdrv_dirty_bitmap_readonly(bitmap));
5781e638301SVladimir Sementsov-Ogievskiy     bdrv_dirty_bitmaps_lock(bitmap->bs);
579ebab2259SFam Zheng     if (!out) {
580ebab2259SFam Zheng         hbitmap_reset_all(bitmap->bitmap);
581ebab2259SFam Zheng     } else {
582ebab2259SFam Zheng         HBitmap *backup = bitmap->bitmap;
583ca759622SEric Blake         bitmap->bitmap = hbitmap_alloc(bitmap->size,
584ebab2259SFam Zheng                                        hbitmap_granularity(backup));
585ebab2259SFam Zheng         *out = backup;
586ebab2259SFam Zheng     }
5871e638301SVladimir Sementsov-Ogievskiy     bdrv_dirty_bitmaps_unlock(bitmap->bs);
588ebab2259SFam Zheng }
589ebab2259SFam Zheng 
bdrv_restore_dirty_bitmap(BdrvDirtyBitmap * bitmap,HBitmap * backup)59056bd6624SVladimir Sementsov-Ogievskiy void bdrv_restore_dirty_bitmap(BdrvDirtyBitmap *bitmap, HBitmap *backup)
591ebab2259SFam Zheng {
592ebab2259SFam Zheng     HBitmap *tmp = bitmap->bitmap;
593d6883bc9SVladimir Sementsov-Ogievskiy     assert(!bdrv_dirty_bitmap_readonly(bitmap));
594b4ad82aaSEmanuele Giuseppe Esposito     GLOBAL_STATE_CODE();
59556bd6624SVladimir Sementsov-Ogievskiy     bitmap->bitmap = backup;
596ebab2259SFam Zheng     hbitmap_free(tmp);
597ebab2259SFam Zheng }
598ebab2259SFam Zheng 
bdrv_dirty_bitmap_serialization_size(const BdrvDirtyBitmap * bitmap,uint64_t offset,uint64_t bytes)599882c36f5SVladimir Sementsov-Ogievskiy uint64_t bdrv_dirty_bitmap_serialization_size(const BdrvDirtyBitmap *bitmap,
60086f6ae67SEric Blake                                               uint64_t offset, uint64_t bytes)
601882c36f5SVladimir Sementsov-Ogievskiy {
602ca759622SEric Blake     return hbitmap_serialization_size(bitmap->bitmap, offset, bytes);
603882c36f5SVladimir Sementsov-Ogievskiy }
604882c36f5SVladimir Sementsov-Ogievskiy 
bdrv_dirty_bitmap_serialization_align(const BdrvDirtyBitmap * bitmap)605882c36f5SVladimir Sementsov-Ogievskiy uint64_t bdrv_dirty_bitmap_serialization_align(const BdrvDirtyBitmap *bitmap)
606882c36f5SVladimir Sementsov-Ogievskiy {
607ca759622SEric Blake     return hbitmap_serialization_align(bitmap->bitmap);
608882c36f5SVladimir Sementsov-Ogievskiy }
609882c36f5SVladimir Sementsov-Ogievskiy 
61035f428baSVladimir Sementsov-Ogievskiy /* Return the disk size covered by a chunk of serialized bitmap data. */
bdrv_dirty_bitmap_serialization_coverage(int serialized_chunk_size,const BdrvDirtyBitmap * bitmap)61135f428baSVladimir Sementsov-Ogievskiy uint64_t bdrv_dirty_bitmap_serialization_coverage(int serialized_chunk_size,
61235f428baSVladimir Sementsov-Ogievskiy                                                   const BdrvDirtyBitmap *bitmap)
61335f428baSVladimir Sementsov-Ogievskiy {
61435f428baSVladimir Sementsov-Ogievskiy     uint64_t granularity = bdrv_dirty_bitmap_granularity(bitmap);
61535f428baSVladimir Sementsov-Ogievskiy     uint64_t limit = granularity * (serialized_chunk_size << 3);
61635f428baSVladimir Sementsov-Ogievskiy 
61735f428baSVladimir Sementsov-Ogievskiy     assert(QEMU_IS_ALIGNED(limit,
61835f428baSVladimir Sementsov-Ogievskiy                            bdrv_dirty_bitmap_serialization_align(bitmap)));
61935f428baSVladimir Sementsov-Ogievskiy     return limit;
62035f428baSVladimir Sementsov-Ogievskiy }
62135f428baSVladimir Sementsov-Ogievskiy 
62235f428baSVladimir Sementsov-Ogievskiy 
bdrv_dirty_bitmap_serialize_part(const BdrvDirtyBitmap * bitmap,uint8_t * buf,uint64_t offset,uint64_t bytes)623882c36f5SVladimir Sementsov-Ogievskiy void bdrv_dirty_bitmap_serialize_part(const BdrvDirtyBitmap *bitmap,
62486f6ae67SEric Blake                                       uint8_t *buf, uint64_t offset,
62586f6ae67SEric Blake                                       uint64_t bytes)
626882c36f5SVladimir Sementsov-Ogievskiy {
627ca759622SEric Blake     hbitmap_serialize_part(bitmap->bitmap, buf, offset, bytes);
628882c36f5SVladimir Sementsov-Ogievskiy }
629882c36f5SVladimir Sementsov-Ogievskiy 
bdrv_dirty_bitmap_deserialize_part(BdrvDirtyBitmap * bitmap,uint8_t * buf,uint64_t offset,uint64_t bytes,bool finish)630882c36f5SVladimir Sementsov-Ogievskiy void bdrv_dirty_bitmap_deserialize_part(BdrvDirtyBitmap *bitmap,
63186f6ae67SEric Blake                                         uint8_t *buf, uint64_t offset,
63286f6ae67SEric Blake                                         uint64_t bytes, bool finish)
633882c36f5SVladimir Sementsov-Ogievskiy {
634ca759622SEric Blake     hbitmap_deserialize_part(bitmap->bitmap, buf, offset, bytes, finish);
635882c36f5SVladimir Sementsov-Ogievskiy }
636882c36f5SVladimir Sementsov-Ogievskiy 
bdrv_dirty_bitmap_deserialize_zeroes(BdrvDirtyBitmap * bitmap,uint64_t offset,uint64_t bytes,bool finish)637882c36f5SVladimir Sementsov-Ogievskiy void bdrv_dirty_bitmap_deserialize_zeroes(BdrvDirtyBitmap *bitmap,
63886f6ae67SEric Blake                                           uint64_t offset, uint64_t bytes,
639882c36f5SVladimir Sementsov-Ogievskiy                                           bool finish)
640882c36f5SVladimir Sementsov-Ogievskiy {
641ca759622SEric Blake     hbitmap_deserialize_zeroes(bitmap->bitmap, offset, bytes, finish);
642882c36f5SVladimir Sementsov-Ogievskiy }
643882c36f5SVladimir Sementsov-Ogievskiy 
bdrv_dirty_bitmap_deserialize_ones(BdrvDirtyBitmap * bitmap,uint64_t offset,uint64_t bytes,bool finish)6446bdc8b71SVladimir Sementsov-Ogievskiy void bdrv_dirty_bitmap_deserialize_ones(BdrvDirtyBitmap *bitmap,
64586f6ae67SEric Blake                                         uint64_t offset, uint64_t bytes,
6466bdc8b71SVladimir Sementsov-Ogievskiy                                         bool finish)
6476bdc8b71SVladimir Sementsov-Ogievskiy {
648ca759622SEric Blake     hbitmap_deserialize_ones(bitmap->bitmap, offset, bytes, finish);
6496bdc8b71SVladimir Sementsov-Ogievskiy }
6506bdc8b71SVladimir Sementsov-Ogievskiy 
bdrv_dirty_bitmap_deserialize_finish(BdrvDirtyBitmap * bitmap)651882c36f5SVladimir Sementsov-Ogievskiy void bdrv_dirty_bitmap_deserialize_finish(BdrvDirtyBitmap *bitmap)
652882c36f5SVladimir Sementsov-Ogievskiy {
653882c36f5SVladimir Sementsov-Ogievskiy     hbitmap_deserialize_finish(bitmap->bitmap);
654882c36f5SVladimir Sementsov-Ogievskiy }
655882c36f5SVladimir Sementsov-Ogievskiy 
bdrv_set_dirty(BlockDriverState * bs,int64_t offset,int64_t bytes)6560fdf1a4fSEric Blake void bdrv_set_dirty(BlockDriverState *bs, int64_t offset, int64_t bytes)
657ebab2259SFam Zheng {
658ebab2259SFam Zheng     BdrvDirtyBitmap *bitmap;
659967d7905SEmanuele Giuseppe Esposito     IO_CODE();
6602119882cSPaolo Bonzini 
6612119882cSPaolo Bonzini     if (QLIST_EMPTY(&bs->dirty_bitmaps)) {
6622119882cSPaolo Bonzini         return;
6632119882cSPaolo Bonzini     }
6642119882cSPaolo Bonzini 
6652119882cSPaolo Bonzini     bdrv_dirty_bitmaps_lock(bs);
666ebab2259SFam Zheng     QLIST_FOREACH(bitmap, &bs->dirty_bitmaps, list) {
667ebab2259SFam Zheng         if (!bdrv_dirty_bitmap_enabled(bitmap)) {
668ebab2259SFam Zheng             continue;
669ebab2259SFam Zheng         }
670d6883bc9SVladimir Sementsov-Ogievskiy         assert(!bdrv_dirty_bitmap_readonly(bitmap));
671ca759622SEric Blake         hbitmap_set(bitmap->bitmap, offset, bytes);
672ebab2259SFam Zheng     }
6732119882cSPaolo Bonzini     bdrv_dirty_bitmaps_unlock(bs);
674ebab2259SFam Zheng }
675ebab2259SFam Zheng 
676ebab2259SFam Zheng /**
677dc162c8eSFam Zheng  * Advance a BdrvDirtyBitmapIter to an arbitrary offset.
678ebab2259SFam Zheng  */
bdrv_set_dirty_iter(BdrvDirtyBitmapIter * iter,int64_t offset)679715a74d8SEric Blake void bdrv_set_dirty_iter(BdrvDirtyBitmapIter *iter, int64_t offset)
680ebab2259SFam Zheng {
681ca759622SEric Blake     hbitmap_iter_init(&iter->hbi, iter->hbi.hb, offset);
682ebab2259SFam Zheng }
683ebab2259SFam Zheng 
bdrv_get_dirty_count(BdrvDirtyBitmap * bitmap)684ebab2259SFam Zheng int64_t bdrv_get_dirty_count(BdrvDirtyBitmap *bitmap)
685ebab2259SFam Zheng {
686ca759622SEric Blake     return hbitmap_count(bitmap->bitmap);
687ebab2259SFam Zheng }
6886d3f4049SFam Zheng 
bdrv_dirty_bitmap_readonly(const BdrvDirtyBitmap * bitmap)689d6883bc9SVladimir Sementsov-Ogievskiy bool bdrv_dirty_bitmap_readonly(const BdrvDirtyBitmap *bitmap)
690d6883bc9SVladimir Sementsov-Ogievskiy {
691d6883bc9SVladimir Sementsov-Ogievskiy     return bitmap->readonly;
692d6883bc9SVladimir Sementsov-Ogievskiy }
693d6883bc9SVladimir Sementsov-Ogievskiy 
694d6883bc9SVladimir Sementsov-Ogievskiy /* Called with BQL taken. */
bdrv_dirty_bitmap_set_readonly(BdrvDirtyBitmap * bitmap,bool value)695d6883bc9SVladimir Sementsov-Ogievskiy void bdrv_dirty_bitmap_set_readonly(BdrvDirtyBitmap *bitmap, bool value)
696d6883bc9SVladimir Sementsov-Ogievskiy {
6971e638301SVladimir Sementsov-Ogievskiy     bdrv_dirty_bitmaps_lock(bitmap->bs);
698d6883bc9SVladimir Sementsov-Ogievskiy     bitmap->readonly = value;
6991e638301SVladimir Sementsov-Ogievskiy     bdrv_dirty_bitmaps_unlock(bitmap->bs);
700d6883bc9SVladimir Sementsov-Ogievskiy }
701d6883bc9SVladimir Sementsov-Ogievskiy 
bdrv_has_readonly_bitmaps(BlockDriverState * bs)702d6883bc9SVladimir Sementsov-Ogievskiy bool bdrv_has_readonly_bitmaps(BlockDriverState *bs)
703d6883bc9SVladimir Sementsov-Ogievskiy {
704d6883bc9SVladimir Sementsov-Ogievskiy     BdrvDirtyBitmap *bm;
705d6883bc9SVladimir Sementsov-Ogievskiy     QLIST_FOREACH(bm, &bs->dirty_bitmaps, list) {
706d6883bc9SVladimir Sementsov-Ogievskiy         if (bm->readonly) {
707d6883bc9SVladimir Sementsov-Ogievskiy             return true;
708d6883bc9SVladimir Sementsov-Ogievskiy         }
709d6883bc9SVladimir Sementsov-Ogievskiy     }
710d6883bc9SVladimir Sementsov-Ogievskiy 
711d6883bc9SVladimir Sementsov-Ogievskiy     return false;
712d6883bc9SVladimir Sementsov-Ogievskiy }
713a0319aacSVladimir Sementsov-Ogievskiy 
bdrv_has_named_bitmaps(BlockDriverState * bs)7147ae89a0dSVladimir Sementsov-Ogievskiy bool bdrv_has_named_bitmaps(BlockDriverState *bs)
7157ae89a0dSVladimir Sementsov-Ogievskiy {
7167ae89a0dSVladimir Sementsov-Ogievskiy     BdrvDirtyBitmap *bm;
7177ae89a0dSVladimir Sementsov-Ogievskiy 
7187ae89a0dSVladimir Sementsov-Ogievskiy     QLIST_FOREACH(bm, &bs->dirty_bitmaps, list) {
7197ae89a0dSVladimir Sementsov-Ogievskiy         if (bdrv_dirty_bitmap_name(bm)) {
7207ae89a0dSVladimir Sementsov-Ogievskiy             return true;
7217ae89a0dSVladimir Sementsov-Ogievskiy         }
7227ae89a0dSVladimir Sementsov-Ogievskiy     }
7237ae89a0dSVladimir Sementsov-Ogievskiy 
7247ae89a0dSVladimir Sementsov-Ogievskiy     return false;
7257ae89a0dSVladimir Sementsov-Ogievskiy }
7267ae89a0dSVladimir Sementsov-Ogievskiy 
727a0319aacSVladimir Sementsov-Ogievskiy /* Called with BQL taken. */
bdrv_dirty_bitmap_set_persistence(BdrvDirtyBitmap * bitmap,bool persistent)728796a3798SEric Blake void bdrv_dirty_bitmap_set_persistence(BdrvDirtyBitmap *bitmap, bool persistent)
729a88b179fSVladimir Sementsov-Ogievskiy {
7301e638301SVladimir Sementsov-Ogievskiy     bdrv_dirty_bitmaps_lock(bitmap->bs);
731a88b179fSVladimir Sementsov-Ogievskiy     bitmap->persistent = persistent;
7321e638301SVladimir Sementsov-Ogievskiy     bdrv_dirty_bitmaps_unlock(bitmap->bs);
733a88b179fSVladimir Sementsov-Ogievskiy }
734a88b179fSVladimir Sementsov-Ogievskiy 
7359c98f145SVladimir Sementsov-Ogievskiy /* Called with BQL taken. */
bdrv_dirty_bitmap_set_inconsistent(BdrvDirtyBitmap * bitmap)736b0f45559SJohn Snow void bdrv_dirty_bitmap_set_inconsistent(BdrvDirtyBitmap *bitmap)
737b0f45559SJohn Snow {
7381e638301SVladimir Sementsov-Ogievskiy     bdrv_dirty_bitmaps_lock(bitmap->bs);
739b0f45559SJohn Snow     assert(bitmap->persistent == true);
740b0f45559SJohn Snow     bitmap->inconsistent = true;
741b0f45559SJohn Snow     bitmap->disabled = true;
7421e638301SVladimir Sementsov-Ogievskiy     bdrv_dirty_bitmaps_unlock(bitmap->bs);
743b0f45559SJohn Snow }
744b0f45559SJohn Snow 
745b0f45559SJohn Snow /* Called with BQL taken. */
bdrv_dirty_bitmap_skip_store(BdrvDirtyBitmap * bitmap,bool skip)746c4e4b0faSJohn Snow void bdrv_dirty_bitmap_skip_store(BdrvDirtyBitmap *bitmap, bool skip)
7479c98f145SVladimir Sementsov-Ogievskiy {
7481e638301SVladimir Sementsov-Ogievskiy     bdrv_dirty_bitmaps_lock(bitmap->bs);
749c4e4b0faSJohn Snow     bitmap->skip_store = skip;
7501e638301SVladimir Sementsov-Ogievskiy     bdrv_dirty_bitmaps_unlock(bitmap->bs);
7519c98f145SVladimir Sementsov-Ogievskiy }
7529c98f145SVladimir Sementsov-Ogievskiy 
bdrv_dirty_bitmap_get_persistence(BdrvDirtyBitmap * bitmap)753796a3798SEric Blake bool bdrv_dirty_bitmap_get_persistence(BdrvDirtyBitmap *bitmap)
754a88b179fSVladimir Sementsov-Ogievskiy {
755c4e4b0faSJohn Snow     return bitmap->persistent && !bitmap->skip_store;
756a88b179fSVladimir Sementsov-Ogievskiy }
757a88b179fSVladimir Sementsov-Ogievskiy 
bdrv_dirty_bitmap_inconsistent(const BdrvDirtyBitmap * bitmap)758b0f45559SJohn Snow bool bdrv_dirty_bitmap_inconsistent(const BdrvDirtyBitmap *bitmap)
759b0f45559SJohn Snow {
760b0f45559SJohn Snow     return bitmap->inconsistent;
761b0f45559SJohn Snow }
762b0f45559SJohn Snow 
bdrv_dirty_bitmap_first(BlockDriverState * bs)763ef9041a7SVladimir Sementsov-Ogievskiy BdrvDirtyBitmap *bdrv_dirty_bitmap_first(BlockDriverState *bs)
7643dd10a06SVladimir Sementsov-Ogievskiy {
765ef9041a7SVladimir Sementsov-Ogievskiy     return QLIST_FIRST(&bs->dirty_bitmaps);
766ef9041a7SVladimir Sementsov-Ogievskiy }
767ef9041a7SVladimir Sementsov-Ogievskiy 
bdrv_dirty_bitmap_next(BdrvDirtyBitmap * bitmap)768ef9041a7SVladimir Sementsov-Ogievskiy BdrvDirtyBitmap *bdrv_dirty_bitmap_next(BdrvDirtyBitmap *bitmap)
769ef9041a7SVladimir Sementsov-Ogievskiy {
770ef9041a7SVladimir Sementsov-Ogievskiy     return QLIST_NEXT(bitmap, list);
7713dd10a06SVladimir Sementsov-Ogievskiy }
772a3b52535SVladimir Sementsov-Ogievskiy 
bdrv_dirty_bitmap_sha256(const BdrvDirtyBitmap * bitmap,Error ** errp)773a3b52535SVladimir Sementsov-Ogievskiy char *bdrv_dirty_bitmap_sha256(const BdrvDirtyBitmap *bitmap, Error **errp)
774a3b52535SVladimir Sementsov-Ogievskiy {
775a3b52535SVladimir Sementsov-Ogievskiy     return hbitmap_sha256(bitmap->bitmap, errp);
776a3b52535SVladimir Sementsov-Ogievskiy }
77756207df5SVladimir Sementsov-Ogievskiy 
bdrv_dirty_bitmap_next_dirty(BdrvDirtyBitmap * bitmap,int64_t offset,int64_t bytes)7789399c54bSVladimir Sementsov-Ogievskiy int64_t bdrv_dirty_bitmap_next_dirty(BdrvDirtyBitmap *bitmap, int64_t offset,
7799399c54bSVladimir Sementsov-Ogievskiy                                      int64_t bytes)
7809399c54bSVladimir Sementsov-Ogievskiy {
7819399c54bSVladimir Sementsov-Ogievskiy     return hbitmap_next_dirty(bitmap->bitmap, offset, bytes);
7829399c54bSVladimir Sementsov-Ogievskiy }
7839399c54bSVladimir Sementsov-Ogievskiy 
bdrv_dirty_bitmap_next_zero(BdrvDirtyBitmap * bitmap,int64_t offset,int64_t bytes)784642700fdSVladimir Sementsov-Ogievskiy int64_t bdrv_dirty_bitmap_next_zero(BdrvDirtyBitmap *bitmap, int64_t offset,
785642700fdSVladimir Sementsov-Ogievskiy                                     int64_t bytes)
78656207df5SVladimir Sementsov-Ogievskiy {
78776d570dcSVladimir Sementsov-Ogievskiy     return hbitmap_next_zero(bitmap->bitmap, offset, bytes);
78856207df5SVladimir Sementsov-Ogievskiy }
789b598e531SVladimir Sementsov-Ogievskiy 
bdrv_dirty_bitmap_next_dirty_area(BdrvDirtyBitmap * bitmap,int64_t start,int64_t end,int64_t max_dirty_count,int64_t * dirty_start,int64_t * dirty_count)790a78a1a48SVladimir Sementsov-Ogievskiy bool bdrv_dirty_bitmap_next_dirty_area(BdrvDirtyBitmap *bitmap,
791299ea9ffSVladimir Sementsov-Ogievskiy         int64_t start, int64_t end, int64_t max_dirty_count,
792299ea9ffSVladimir Sementsov-Ogievskiy         int64_t *dirty_start, int64_t *dirty_count)
793a78a1a48SVladimir Sementsov-Ogievskiy {
794299ea9ffSVladimir Sementsov-Ogievskiy     return hbitmap_next_dirty_area(bitmap->bitmap, start, end, max_dirty_count,
795299ea9ffSVladimir Sementsov-Ogievskiy                                    dirty_start, dirty_count);
796a78a1a48SVladimir Sementsov-Ogievskiy }
797a78a1a48SVladimir Sementsov-Ogievskiy 
bdrv_dirty_bitmap_status(BdrvDirtyBitmap * bitmap,int64_t offset,int64_t bytes,int64_t * count)798a6426475SVladimir Sementsov-Ogievskiy bool bdrv_dirty_bitmap_status(BdrvDirtyBitmap *bitmap, int64_t offset,
799a6426475SVladimir Sementsov-Ogievskiy                               int64_t bytes, int64_t *count)
800a6426475SVladimir Sementsov-Ogievskiy {
801a6426475SVladimir Sementsov-Ogievskiy     return hbitmap_status(bitmap->bitmap, offset, bytes, count);
802a6426475SVladimir Sementsov-Ogievskiy }
803a6426475SVladimir Sementsov-Ogievskiy 
804b7661ca5SJohn Snow /**
805b7661ca5SJohn Snow  * bdrv_merge_dirty_bitmap: merge src into dest.
806b7661ca5SJohn Snow  * Ensures permissions on bitmaps are reasonable; use for public API.
807b7661ca5SJohn Snow  *
808b7661ca5SJohn Snow  * @backup: If provided, make a copy of dest here prior to merge.
80934ffacb7SVladimir Sementsov-Ogievskiy  *
81034ffacb7SVladimir Sementsov-Ogievskiy  * Returns true on success, false on failure. In case of failure bitmaps are
81134ffacb7SVladimir Sementsov-Ogievskiy  * untouched.
812b7661ca5SJohn Snow  */
bdrv_merge_dirty_bitmap(BdrvDirtyBitmap * dest,const BdrvDirtyBitmap * src,HBitmap ** backup,Error ** errp)81334ffacb7SVladimir Sementsov-Ogievskiy bool bdrv_merge_dirty_bitmap(BdrvDirtyBitmap *dest, const BdrvDirtyBitmap *src,
814fa000f2fSVladimir Sementsov-Ogievskiy                              HBitmap **backup, Error **errp)
815b598e531SVladimir Sementsov-Ogievskiy {
81634ffacb7SVladimir Sementsov-Ogievskiy     bool ret = false;
817fa000f2fSVladimir Sementsov-Ogievskiy 
8181e638301SVladimir Sementsov-Ogievskiy     bdrv_dirty_bitmaps_lock(dest->bs);
8191e638301SVladimir Sementsov-Ogievskiy     if (src->bs != dest->bs) {
8201e638301SVladimir Sementsov-Ogievskiy         bdrv_dirty_bitmaps_lock(src->bs);
821eff0829bSVladimir Sementsov-Ogievskiy     }
822b598e531SVladimir Sementsov-Ogievskiy 
8233ae96d66SJohn Snow     if (bdrv_dirty_bitmap_check(dest, BDRV_BITMAP_DEFAULT, errp)) {
82406bf5006SVladimir Sementsov-Ogievskiy         goto out;
82506bf5006SVladimir Sementsov-Ogievskiy     }
82606bf5006SVladimir Sementsov-Ogievskiy 
827cb8e58e3SJohn Snow     if (bdrv_dirty_bitmap_check(src, BDRV_BITMAP_ALLOW_RO, errp)) {
828cb8e58e3SJohn Snow         goto out;
829cb8e58e3SJohn Snow     }
830b598e531SVladimir Sementsov-Ogievskiy 
831618af89eSVladimir Sementsov-Ogievskiy     if (bdrv_dirty_bitmap_size(src) != bdrv_dirty_bitmap_size(dest)) {
832618af89eSVladimir Sementsov-Ogievskiy         error_setg(errp, "Bitmaps are of different sizes (destination size is %"
833618af89eSVladimir Sementsov-Ogievskiy                    PRId64 ", source size is %" PRId64 ") and can't be merged",
834618af89eSVladimir Sementsov-Ogievskiy                    bdrv_dirty_bitmap_size(dest), bdrv_dirty_bitmap_size(src));
83506bf5006SVladimir Sementsov-Ogievskiy         goto out;
836b598e531SVladimir Sementsov-Ogievskiy     }
837b598e531SVladimir Sementsov-Ogievskiy 
838618af89eSVladimir Sementsov-Ogievskiy     bdrv_dirty_bitmap_merge_internal(dest, src, backup, false);
839618af89eSVladimir Sementsov-Ogievskiy     ret = true;
840fa000f2fSVladimir Sementsov-Ogievskiy 
84106bf5006SVladimir Sementsov-Ogievskiy out:
8421e638301SVladimir Sementsov-Ogievskiy     bdrv_dirty_bitmaps_unlock(dest->bs);
8431e638301SVladimir Sementsov-Ogievskiy     if (src->bs != dest->bs) {
8441e638301SVladimir Sementsov-Ogievskiy         bdrv_dirty_bitmaps_unlock(src->bs);
845eff0829bSVladimir Sementsov-Ogievskiy     }
84634ffacb7SVladimir Sementsov-Ogievskiy 
84734ffacb7SVladimir Sementsov-Ogievskiy     return ret;
848b598e531SVladimir Sementsov-Ogievskiy }
849b7661ca5SJohn Snow 
850b7661ca5SJohn Snow /**
851b7661ca5SJohn Snow  * bdrv_dirty_bitmap_merge_internal: merge src into dest.
852b7661ca5SJohn Snow  * Does NOT check bitmap permissions; not suitable for use as public API.
853618af89eSVladimir Sementsov-Ogievskiy  * @dest, @src and @backup (if not NULL) must have same size.
854b7661ca5SJohn Snow  *
855b7661ca5SJohn Snow  * @backup: If provided, make a copy of dest here prior to merge.
856b7661ca5SJohn Snow  * @lock: If true, lock and unlock bitmaps on the way in/out.
857b7661ca5SJohn Snow  */
bdrv_dirty_bitmap_merge_internal(BdrvDirtyBitmap * dest,const BdrvDirtyBitmap * src,HBitmap ** backup,bool lock)858618af89eSVladimir Sementsov-Ogievskiy void bdrv_dirty_bitmap_merge_internal(BdrvDirtyBitmap *dest,
859b7661ca5SJohn Snow                                       const BdrvDirtyBitmap *src,
860b7661ca5SJohn Snow                                       HBitmap **backup,
861b7661ca5SJohn Snow                                       bool lock)
862b7661ca5SJohn Snow {
863967d7905SEmanuele Giuseppe Esposito     IO_CODE();
864b7661ca5SJohn Snow 
865b7661ca5SJohn Snow     assert(!bdrv_dirty_bitmap_readonly(dest));
866b7661ca5SJohn Snow     assert(!bdrv_dirty_bitmap_inconsistent(dest));
867b7661ca5SJohn Snow     assert(!bdrv_dirty_bitmap_inconsistent(src));
868b7661ca5SJohn Snow 
869b7661ca5SJohn Snow     if (lock) {
8701e638301SVladimir Sementsov-Ogievskiy         bdrv_dirty_bitmaps_lock(dest->bs);
8711e638301SVladimir Sementsov-Ogievskiy         if (src->bs != dest->bs) {
8721e638301SVladimir Sementsov-Ogievskiy             bdrv_dirty_bitmaps_lock(src->bs);
873b7661ca5SJohn Snow         }
874b7661ca5SJohn Snow     }
875b7661ca5SJohn Snow 
876b7661ca5SJohn Snow     if (backup) {
877b7661ca5SJohn Snow         *backup = dest->bitmap;
878b7661ca5SJohn Snow         dest->bitmap = hbitmap_alloc(dest->size, hbitmap_granularity(*backup));
879618af89eSVladimir Sementsov-Ogievskiy         hbitmap_merge(*backup, src->bitmap, dest->bitmap);
880b7661ca5SJohn Snow     } else {
881618af89eSVladimir Sementsov-Ogievskiy         hbitmap_merge(dest->bitmap, src->bitmap, dest->bitmap);
882b7661ca5SJohn Snow     }
883b7661ca5SJohn Snow 
884b7661ca5SJohn Snow     if (lock) {
8851e638301SVladimir Sementsov-Ogievskiy         bdrv_dirty_bitmaps_unlock(dest->bs);
8861e638301SVladimir Sementsov-Ogievskiy         if (src->bs != dest->bs) {
8871e638301SVladimir Sementsov-Ogievskiy             bdrv_dirty_bitmaps_unlock(src->bs);
888b7661ca5SJohn Snow         }
889b7661ca5SJohn Snow     }
890b7661ca5SJohn Snow }
891