xref: /qemu/block/dirty-bitmap.c (revision a6426475)
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"
27ebab2259SFam Zheng #include "block/block_int.h"
28ebab2259SFam Zheng #include "block/blockjob.h"
29d2c3080eSVladimir Sementsov-Ogievskiy #include "qemu/main-loop.h"
30ebab2259SFam Zheng 
31ebab2259SFam Zheng struct BdrvDirtyBitmap {
325deb6cbdSVladimir Sementsov-Ogievskiy     BlockDriverState *bs;
33ca759622SEric Blake     HBitmap *bitmap;            /* Dirty bitmap implementation */
3427a1b301SJohn Snow     bool busy;                  /* Bitmap is busy, it can't be used via QMP */
3521d2376fSJohn Snow     BdrvDirtyBitmap *successor; /* Anonymous child, if any. */
36ebab2259SFam Zheng     char *name;                 /* Optional non-empty unique ID */
37993e6525SEric Blake     int64_t size;               /* Size of the bitmap, in bytes */
388bfc932eSVladimir Sementsov-Ogievskiy     bool disabled;              /* Bitmap is disabled. It ignores all writes to
398bfc932eSVladimir Sementsov-Ogievskiy                                    the device */
40dc162c8eSFam Zheng     int active_iterators;       /* How many iterators are active */
41d6883bc9SVladimir Sementsov-Ogievskiy     bool readonly;              /* Bitmap is read-only. This field also
42d6883bc9SVladimir Sementsov-Ogievskiy                                    prevents the respective image from being
43d6883bc9SVladimir Sementsov-Ogievskiy                                    modified (i.e. blocks writes and discards).
44d6883bc9SVladimir Sementsov-Ogievskiy                                    Such operations must fail and both the image
45d6883bc9SVladimir Sementsov-Ogievskiy                                    and this bitmap must remain unchanged while
46d6883bc9SVladimir Sementsov-Ogievskiy                                    this flag is set. */
47a88b179fSVladimir Sementsov-Ogievskiy     bool persistent;            /* bitmap must be saved to owner disk image */
48b0f45559SJohn Snow     bool inconsistent;          /* bitmap is persistent, but inconsistent.
49b0f45559SJohn Snow                                    It cannot be used at all in any way, except
50b0f45559SJohn Snow                                    a QMP user can remove it. */
51c4e4b0faSJohn Snow     bool skip_store;            /* We are either migrating or deleting this
52c4e4b0faSJohn Snow                                  * bitmap; it should not be stored on the next
53c4e4b0faSJohn Snow                                  * inactivation. */
54ebab2259SFam Zheng     QLIST_ENTRY(BdrvDirtyBitmap) list;
55ebab2259SFam Zheng };
56ebab2259SFam Zheng 
57dc162c8eSFam Zheng struct BdrvDirtyBitmapIter {
58dc162c8eSFam Zheng     HBitmapIter hbi;
59dc162c8eSFam Zheng     BdrvDirtyBitmap *bitmap;
60dc162c8eSFam Zheng };
61dc162c8eSFam Zheng 
622119882cSPaolo Bonzini static inline void bdrv_dirty_bitmaps_lock(BlockDriverState *bs)
632119882cSPaolo Bonzini {
642119882cSPaolo Bonzini     qemu_mutex_lock(&bs->dirty_bitmap_mutex);
652119882cSPaolo Bonzini }
662119882cSPaolo Bonzini 
672119882cSPaolo Bonzini static inline void bdrv_dirty_bitmaps_unlock(BlockDriverState *bs)
682119882cSPaolo Bonzini {
692119882cSPaolo Bonzini     qemu_mutex_unlock(&bs->dirty_bitmap_mutex);
702119882cSPaolo Bonzini }
712119882cSPaolo Bonzini 
72b64bd51eSPaolo Bonzini void bdrv_dirty_bitmap_lock(BdrvDirtyBitmap *bitmap)
73b64bd51eSPaolo Bonzini {
741e638301SVladimir Sementsov-Ogievskiy     bdrv_dirty_bitmaps_lock(bitmap->bs);
75b64bd51eSPaolo Bonzini }
76b64bd51eSPaolo Bonzini 
77b64bd51eSPaolo Bonzini void bdrv_dirty_bitmap_unlock(BdrvDirtyBitmap *bitmap)
78b64bd51eSPaolo Bonzini {
791e638301SVladimir Sementsov-Ogievskiy     bdrv_dirty_bitmaps_unlock(bitmap->bs);
80b64bd51eSPaolo Bonzini }
81b64bd51eSPaolo Bonzini 
822119882cSPaolo Bonzini /* Called with BQL or dirty_bitmap lock taken.  */
83ebab2259SFam Zheng BdrvDirtyBitmap *bdrv_find_dirty_bitmap(BlockDriverState *bs, const char *name)
84ebab2259SFam Zheng {
85ebab2259SFam Zheng     BdrvDirtyBitmap *bm;
86ebab2259SFam Zheng 
87ebab2259SFam Zheng     assert(name);
88ebab2259SFam Zheng     QLIST_FOREACH(bm, &bs->dirty_bitmaps, list) {
89ebab2259SFam Zheng         if (bm->name && !strcmp(name, bm->name)) {
90ebab2259SFam Zheng             return bm;
91ebab2259SFam Zheng         }
92ebab2259SFam Zheng     }
93ebab2259SFam Zheng     return NULL;
94ebab2259SFam Zheng }
95ebab2259SFam Zheng 
962119882cSPaolo Bonzini /* Called with BQL taken.  */
97ebab2259SFam Zheng BdrvDirtyBitmap *bdrv_create_dirty_bitmap(BlockDriverState *bs,
98ebab2259SFam Zheng                                           uint32_t granularity,
99ebab2259SFam Zheng                                           const char *name,
100ebab2259SFam Zheng                                           Error **errp)
101ebab2259SFam Zheng {
102ebab2259SFam Zheng     int64_t bitmap_size;
103ebab2259SFam Zheng     BdrvDirtyBitmap *bitmap;
104ebab2259SFam Zheng 
105993e6525SEric Blake     assert(is_power_of_2(granularity) && granularity >= BDRV_SECTOR_SIZE);
106ebab2259SFam Zheng 
107cf7c49cfSEric Blake     if (name) {
108cf7c49cfSEric Blake         if (bdrv_find_dirty_bitmap(bs, name)) {
109ebab2259SFam Zheng             error_setg(errp, "Bitmap already exists: %s", name);
110ebab2259SFam Zheng             return NULL;
111ebab2259SFam Zheng         }
112cf7c49cfSEric Blake         if (strlen(name) > BDRV_BITMAP_MAX_NAME_SIZE) {
113cf7c49cfSEric Blake             error_setg(errp, "Bitmap name too long: %s", name);
114cf7c49cfSEric Blake             return NULL;
115cf7c49cfSEric Blake         }
116cf7c49cfSEric Blake     }
117993e6525SEric Blake     bitmap_size = bdrv_getlength(bs);
118ebab2259SFam Zheng     if (bitmap_size < 0) {
119ebab2259SFam Zheng         error_setg_errno(errp, -bitmap_size, "could not get length of device");
120ebab2259SFam Zheng         errno = -bitmap_size;
121ebab2259SFam Zheng         return NULL;
122ebab2259SFam Zheng     }
123ebab2259SFam Zheng     bitmap = g_new0(BdrvDirtyBitmap, 1);
1245deb6cbdSVladimir Sementsov-Ogievskiy     bitmap->bs = bs;
125ca759622SEric Blake     bitmap->bitmap = hbitmap_alloc(bitmap_size, ctz32(granularity));
126ebab2259SFam Zheng     bitmap->size = bitmap_size;
127ebab2259SFam Zheng     bitmap->name = g_strdup(name);
128ebab2259SFam Zheng     bitmap->disabled = false;
1292119882cSPaolo Bonzini     bdrv_dirty_bitmaps_lock(bs);
130ebab2259SFam Zheng     QLIST_INSERT_HEAD(&bs->dirty_bitmaps, bitmap, list);
1312119882cSPaolo Bonzini     bdrv_dirty_bitmaps_unlock(bs);
132ebab2259SFam Zheng     return bitmap;
133ebab2259SFam Zheng }
134ebab2259SFam Zheng 
13515891facSFam Zheng int64_t bdrv_dirty_bitmap_size(const BdrvDirtyBitmap *bitmap)
13615891facSFam Zheng {
137993e6525SEric Blake     return bitmap->size;
13815891facSFam Zheng }
13915891facSFam Zheng 
14015891facSFam Zheng const char *bdrv_dirty_bitmap_name(const BdrvDirtyBitmap *bitmap)
14115891facSFam Zheng {
14215891facSFam Zheng     return bitmap->name;
14315891facSFam Zheng }
14415891facSFam Zheng 
1452119882cSPaolo Bonzini /* Called with BQL taken.  */
14650a47257SJohn Snow bool bdrv_dirty_bitmap_has_successor(BdrvDirtyBitmap *bitmap)
147ebab2259SFam Zheng {
148ebab2259SFam Zheng     return bitmap->successor;
149ebab2259SFam Zheng }
150ebab2259SFam Zheng 
1513ae96d66SJohn Snow static bool bdrv_dirty_bitmap_busy(const BdrvDirtyBitmap *bitmap)
15227a1b301SJohn Snow {
15327a1b301SJohn Snow     return bitmap->busy;
154993edc0cSJohn Snow }
155993edc0cSJohn Snow 
15627a1b301SJohn Snow void bdrv_dirty_bitmap_set_busy(BdrvDirtyBitmap *bitmap, bool busy)
1574f43e953SVladimir Sementsov-Ogievskiy {
1581e638301SVladimir Sementsov-Ogievskiy     bdrv_dirty_bitmaps_lock(bitmap->bs);
15927a1b301SJohn Snow     bitmap->busy = busy;
1601e638301SVladimir Sementsov-Ogievskiy     bdrv_dirty_bitmaps_unlock(bitmap->bs);
1614f43e953SVladimir Sementsov-Ogievskiy }
1624f43e953SVladimir Sementsov-Ogievskiy 
1632119882cSPaolo Bonzini /* Called with BQL taken.  */
164ebab2259SFam Zheng bool bdrv_dirty_bitmap_enabled(BdrvDirtyBitmap *bitmap)
165ebab2259SFam Zheng {
1668b2e20f6SJohn Snow     return !bitmap->disabled;
167ebab2259SFam Zheng }
168ebab2259SFam Zheng 
1694db6ceb0SJohn Snow /* Called with BQL taken.  */
1704db6ceb0SJohn Snow static bool bdrv_dirty_bitmap_recording(BdrvDirtyBitmap *bitmap)
1714db6ceb0SJohn Snow {
1724db6ceb0SJohn Snow     return !bitmap->disabled || (bitmap->successor &&
1734db6ceb0SJohn Snow                                  !bitmap->successor->disabled);
1744db6ceb0SJohn Snow }
1754db6ceb0SJohn Snow 
1763ae96d66SJohn Snow int bdrv_dirty_bitmap_check(const BdrvDirtyBitmap *bitmap, uint32_t flags,
1773ae96d66SJohn Snow                             Error **errp)
1783ae96d66SJohn Snow {
1793ae96d66SJohn Snow     if ((flags & BDRV_BITMAP_BUSY) && bdrv_dirty_bitmap_busy(bitmap)) {
1803ae96d66SJohn Snow         error_setg(errp, "Bitmap '%s' is currently in use by another"
1813ae96d66SJohn Snow                    " operation and cannot be used", bitmap->name);
1823ae96d66SJohn Snow         return -1;
1833ae96d66SJohn Snow     }
1843ae96d66SJohn Snow 
1853ae96d66SJohn Snow     if ((flags & BDRV_BITMAP_RO) && bdrv_dirty_bitmap_readonly(bitmap)) {
1863ae96d66SJohn Snow         error_setg(errp, "Bitmap '%s' is readonly and cannot be modified",
1873ae96d66SJohn Snow                    bitmap->name);
1883ae96d66SJohn Snow         return -1;
1893ae96d66SJohn Snow     }
1903ae96d66SJohn Snow 
1913ae96d66SJohn Snow     if ((flags & BDRV_BITMAP_INCONSISTENT) &&
1923ae96d66SJohn Snow         bdrv_dirty_bitmap_inconsistent(bitmap)) {
1933ae96d66SJohn Snow         error_setg(errp, "Bitmap '%s' is inconsistent and cannot be used",
1943ae96d66SJohn Snow                    bitmap->name);
1953ae96d66SJohn Snow         error_append_hint(errp, "Try block-dirty-bitmap-remove to delete"
19694075c28SEric Blake                           " this bitmap from disk\n");
1973ae96d66SJohn Snow         return -1;
1983ae96d66SJohn Snow     }
1993ae96d66SJohn Snow 
2003ae96d66SJohn Snow     return 0;
2013ae96d66SJohn Snow }
2023ae96d66SJohn Snow 
203ebab2259SFam Zheng /**
204ebab2259SFam Zheng  * Create a successor bitmap destined to replace this bitmap after an operation.
20527a1b301SJohn Snow  * Requires that the bitmap is not marked busy and has no successor.
2068b2e20f6SJohn Snow  * The successor will be enabled if the parent bitmap was.
2072119882cSPaolo Bonzini  * Called with BQL taken.
208ebab2259SFam Zheng  */
2095deb6cbdSVladimir Sementsov-Ogievskiy int bdrv_dirty_bitmap_create_successor(BdrvDirtyBitmap *bitmap, Error **errp)
210ebab2259SFam Zheng {
211ebab2259SFam Zheng     uint64_t granularity;
212ebab2259SFam Zheng     BdrvDirtyBitmap *child;
213ebab2259SFam Zheng 
2143ae96d66SJohn Snow     if (bdrv_dirty_bitmap_check(bitmap, BDRV_BITMAP_BUSY, errp)) {
215ebab2259SFam Zheng         return -1;
216ebab2259SFam Zheng     }
21750a47257SJohn Snow     if (bdrv_dirty_bitmap_has_successor(bitmap)) {
21850a47257SJohn Snow         error_setg(errp, "Cannot create a successor for a bitmap that already "
21950a47257SJohn Snow                    "has one");
22050a47257SJohn Snow         return -1;
22150a47257SJohn Snow     }
222ebab2259SFam Zheng 
223ebab2259SFam Zheng     /* Create an anonymous successor */
224ebab2259SFam Zheng     granularity = bdrv_dirty_bitmap_granularity(bitmap);
2255deb6cbdSVladimir Sementsov-Ogievskiy     child = bdrv_create_dirty_bitmap(bitmap->bs, granularity, NULL, errp);
226ebab2259SFam Zheng     if (!child) {
227ebab2259SFam Zheng         return -1;
228ebab2259SFam Zheng     }
229ebab2259SFam Zheng 
230ebab2259SFam Zheng     /* Successor will be on or off based on our current state. */
231ebab2259SFam Zheng     child->disabled = bitmap->disabled;
2328b2e20f6SJohn Snow     bitmap->disabled = true;
233ebab2259SFam Zheng 
23427a1b301SJohn Snow     /* Install the successor and mark the parent as busy */
235ebab2259SFam Zheng     bitmap->successor = child;
23627a1b301SJohn Snow     bitmap->busy = true;
237ebab2259SFam Zheng     return 0;
238ebab2259SFam Zheng }
239ebab2259SFam Zheng 
24092bcea40SVladimir Sementsov-Ogievskiy void bdrv_enable_dirty_bitmap_locked(BdrvDirtyBitmap *bitmap)
24192bcea40SVladimir Sementsov-Ogievskiy {
24292bcea40SVladimir Sementsov-Ogievskiy     bitmap->disabled = false;
24392bcea40SVladimir Sementsov-Ogievskiy }
24492bcea40SVladimir Sementsov-Ogievskiy 
245e73a265eSVladimir Sementsov-Ogievskiy /* Called with BQL taken. */
246e73a265eSVladimir Sementsov-Ogievskiy void bdrv_dirty_bitmap_enable_successor(BdrvDirtyBitmap *bitmap)
247e73a265eSVladimir Sementsov-Ogievskiy {
2481e638301SVladimir Sementsov-Ogievskiy     assert(bitmap->bs == bitmap->successor->bs);
2491e638301SVladimir Sementsov-Ogievskiy     bdrv_dirty_bitmaps_lock(bitmap->bs);
25058f72b96SVladimir Sementsov-Ogievskiy     bdrv_enable_dirty_bitmap_locked(bitmap->successor);
2511e638301SVladimir Sementsov-Ogievskiy     bdrv_dirty_bitmaps_unlock(bitmap->bs);
252e73a265eSVladimir Sementsov-Ogievskiy }
253e73a265eSVladimir Sementsov-Ogievskiy 
254b133c27fSPaolo Bonzini /* Called within bdrv_dirty_bitmap_lock..unlock and with BQL taken.  */
255b133c27fSPaolo Bonzini static void bdrv_release_dirty_bitmap_locked(BdrvDirtyBitmap *bitmap)
256604ab74bSVladimir Sementsov-Ogievskiy {
257b133c27fSPaolo Bonzini     assert(!bitmap->active_iterators);
25827a1b301SJohn Snow     assert(!bdrv_dirty_bitmap_busy(bitmap));
25950a47257SJohn Snow     assert(!bdrv_dirty_bitmap_has_successor(bitmap));
260b133c27fSPaolo Bonzini     QLIST_REMOVE(bitmap, list);
261b133c27fSPaolo Bonzini     hbitmap_free(bitmap->bitmap);
262b133c27fSPaolo Bonzini     g_free(bitmap->name);
263b133c27fSPaolo Bonzini     g_free(bitmap);
264604ab74bSVladimir Sementsov-Ogievskiy }
265604ab74bSVladimir Sementsov-Ogievskiy 
266ebab2259SFam Zheng /**
267ebab2259SFam Zheng  * For a bitmap with a successor, yield our name to the successor,
268ebab2259SFam Zheng  * delete the old bitmap, and return a handle to the new bitmap.
2692119882cSPaolo Bonzini  * Called with BQL taken.
270ebab2259SFam Zheng  */
2715deb6cbdSVladimir Sementsov-Ogievskiy BdrvDirtyBitmap *bdrv_dirty_bitmap_abdicate(BdrvDirtyBitmap *bitmap,
272ebab2259SFam Zheng                                             Error **errp)
273ebab2259SFam Zheng {
274ebab2259SFam Zheng     char *name;
275ebab2259SFam Zheng     BdrvDirtyBitmap *successor = bitmap->successor;
276ebab2259SFam Zheng 
277ebab2259SFam Zheng     if (successor == NULL) {
278ebab2259SFam Zheng         error_setg(errp, "Cannot relinquish control if "
279ebab2259SFam Zheng                    "there's no successor present");
280ebab2259SFam Zheng         return NULL;
281ebab2259SFam Zheng     }
282ebab2259SFam Zheng 
283ebab2259SFam Zheng     name = bitmap->name;
284ebab2259SFam Zheng     bitmap->name = NULL;
285ebab2259SFam Zheng     successor->name = name;
286ebab2259SFam Zheng     bitmap->successor = NULL;
287a88b179fSVladimir Sementsov-Ogievskiy     successor->persistent = bitmap->persistent;
288a88b179fSVladimir Sementsov-Ogievskiy     bitmap->persistent = false;
28927a1b301SJohn Snow     bitmap->busy = false;
2905deb6cbdSVladimir Sementsov-Ogievskiy     bdrv_release_dirty_bitmap(bitmap);
291ebab2259SFam Zheng 
292ebab2259SFam Zheng     return successor;
293ebab2259SFam Zheng }
294ebab2259SFam Zheng 
295ebab2259SFam Zheng /**
296ebab2259SFam Zheng  * In cases of failure where we can no longer safely delete the parent,
297ebab2259SFam Zheng  * we may wish to re-join the parent and child/successor.
29827a1b301SJohn Snow  * The merged parent will be marked as not busy.
2998b2e20f6SJohn Snow  * The marged parent will be enabled if and only if the successor was enabled.
300044ee8e1SVladimir Sementsov-Ogievskiy  * Called within bdrv_dirty_bitmap_lock..unlock and with BQL taken.
301ebab2259SFam Zheng  */
3025deb6cbdSVladimir Sementsov-Ogievskiy BdrvDirtyBitmap *bdrv_reclaim_dirty_bitmap_locked(BdrvDirtyBitmap *parent,
303ebab2259SFam Zheng                                                   Error **errp)
304ebab2259SFam Zheng {
305044ee8e1SVladimir Sementsov-Ogievskiy     BdrvDirtyBitmap *successor = parent->successor;
306ebab2259SFam Zheng 
307ebab2259SFam Zheng     if (!successor) {
308ebab2259SFam Zheng         error_setg(errp, "Cannot reclaim a successor when none is present");
309ebab2259SFam Zheng         return NULL;
310ebab2259SFam Zheng     }
311ebab2259SFam Zheng 
312fa000f2fSVladimir Sementsov-Ogievskiy     if (!hbitmap_merge(parent->bitmap, successor->bitmap, parent->bitmap)) {
313ebab2259SFam Zheng         error_setg(errp, "Merging of parent and successor bitmap failed");
314ebab2259SFam Zheng         return NULL;
315ebab2259SFam Zheng     }
3168b2e20f6SJohn Snow 
3178b2e20f6SJohn Snow     parent->disabled = successor->disabled;
31827a1b301SJohn Snow     parent->busy = false;
319b133c27fSPaolo Bonzini     bdrv_release_dirty_bitmap_locked(successor);
320ebab2259SFam Zheng     parent->successor = NULL;
321ebab2259SFam Zheng 
322044ee8e1SVladimir Sementsov-Ogievskiy     return parent;
323044ee8e1SVladimir Sementsov-Ogievskiy }
324044ee8e1SVladimir Sementsov-Ogievskiy 
325044ee8e1SVladimir Sementsov-Ogievskiy /* Called with BQL taken. */
3265deb6cbdSVladimir Sementsov-Ogievskiy BdrvDirtyBitmap *bdrv_reclaim_dirty_bitmap(BdrvDirtyBitmap *parent,
327044ee8e1SVladimir Sementsov-Ogievskiy                                            Error **errp)
328044ee8e1SVladimir Sementsov-Ogievskiy {
329044ee8e1SVladimir Sementsov-Ogievskiy     BdrvDirtyBitmap *ret;
330044ee8e1SVladimir Sementsov-Ogievskiy 
3311e638301SVladimir Sementsov-Ogievskiy     bdrv_dirty_bitmaps_lock(parent->bs);
3325deb6cbdSVladimir Sementsov-Ogievskiy     ret = bdrv_reclaim_dirty_bitmap_locked(parent, errp);
3331e638301SVladimir Sementsov-Ogievskiy     bdrv_dirty_bitmaps_unlock(parent->bs);
334604ab74bSVladimir Sementsov-Ogievskiy 
335044ee8e1SVladimir Sementsov-Ogievskiy     return ret;
336ebab2259SFam Zheng }
337ebab2259SFam Zheng 
338ebab2259SFam Zheng /**
339ebab2259SFam Zheng  * Truncates _all_ bitmaps attached to a BDS.
3402119882cSPaolo Bonzini  * Called with BQL taken.
341ebab2259SFam Zheng  */
3421b6cc579SEric Blake void bdrv_dirty_bitmap_truncate(BlockDriverState *bs, int64_t bytes)
343ebab2259SFam Zheng {
344ebab2259SFam Zheng     BdrvDirtyBitmap *bitmap;
345ebab2259SFam Zheng 
3462119882cSPaolo Bonzini     bdrv_dirty_bitmaps_lock(bs);
347ebab2259SFam Zheng     QLIST_FOREACH(bitmap, &bs->dirty_bitmaps, list) {
34827a1b301SJohn Snow         assert(!bdrv_dirty_bitmap_busy(bitmap));
34950a47257SJohn Snow         assert(!bdrv_dirty_bitmap_has_successor(bitmap));
350dc162c8eSFam Zheng         assert(!bitmap->active_iterators);
351ca759622SEric Blake         hbitmap_truncate(bitmap->bitmap, bytes);
352993e6525SEric Blake         bitmap->size = bytes;
353ebab2259SFam Zheng     }
3542119882cSPaolo Bonzini     bdrv_dirty_bitmaps_unlock(bs);
355ebab2259SFam Zheng }
356ebab2259SFam Zheng 
3572119882cSPaolo Bonzini /* Called with BQL taken.  */
3585deb6cbdSVladimir Sementsov-Ogievskiy void bdrv_release_dirty_bitmap(BdrvDirtyBitmap *bitmap)
359ebab2259SFam Zheng {
3605deb6cbdSVladimir Sementsov-Ogievskiy     BlockDriverState *bs = bitmap->bs;
3615deb6cbdSVladimir Sementsov-Ogievskiy 
362b133c27fSPaolo Bonzini     bdrv_dirty_bitmaps_lock(bs);
363b133c27fSPaolo Bonzini     bdrv_release_dirty_bitmap_locked(bitmap);
364b133c27fSPaolo Bonzini     bdrv_dirty_bitmaps_unlock(bs);
365ebab2259SFam Zheng }
366ebab2259SFam Zheng 
367ebab2259SFam Zheng /**
368ebab2259SFam Zheng  * Release all named dirty bitmaps attached to a BDS (for use in bdrv_close()).
36927a1b301SJohn Snow  * There must not be any busy bitmaps attached.
37056f364e6SVladimir Sementsov-Ogievskiy  * This function does not remove persistent bitmaps from the storage.
3712119882cSPaolo Bonzini  * Called with BQL taken.
372ebab2259SFam Zheng  */
373ebab2259SFam Zheng void bdrv_release_named_dirty_bitmaps(BlockDriverState *bs)
374ebab2259SFam Zheng {
375b133c27fSPaolo Bonzini     BdrvDirtyBitmap *bm, *next;
376b133c27fSPaolo Bonzini 
377b133c27fSPaolo Bonzini     bdrv_dirty_bitmaps_lock(bs);
378b133c27fSPaolo Bonzini     QLIST_FOREACH_SAFE(bm, &bs->dirty_bitmaps, list, next) {
379b133c27fSPaolo Bonzini         if (bdrv_dirty_bitmap_name(bm)) {
380b133c27fSPaolo Bonzini             bdrv_release_dirty_bitmap_locked(bm);
381b133c27fSPaolo Bonzini         }
382b133c27fSPaolo Bonzini     }
383b133c27fSPaolo Bonzini     bdrv_dirty_bitmaps_unlock(bs);
384615b5dcfSVladimir Sementsov-Ogievskiy }
385615b5dcfSVladimir Sementsov-Ogievskiy 
386615b5dcfSVladimir Sementsov-Ogievskiy /**
38756f364e6SVladimir Sementsov-Ogievskiy  * Remove persistent dirty bitmap from the storage if it exists.
38856f364e6SVladimir Sementsov-Ogievskiy  * Absence of bitmap is not an error, because we have the following scenario:
38956f364e6SVladimir Sementsov-Ogievskiy  * BdrvDirtyBitmap can have .persistent = true but not yet saved and have no
39056f364e6SVladimir Sementsov-Ogievskiy  * stored version. For such bitmap bdrv_remove_persistent_dirty_bitmap() should
39156f364e6SVladimir Sementsov-Ogievskiy  * not fail.
39256f364e6SVladimir Sementsov-Ogievskiy  * This function doesn't release corresponding BdrvDirtyBitmap.
39356f364e6SVladimir Sementsov-Ogievskiy  */
394d2c3080eSVladimir Sementsov-Ogievskiy static int coroutine_fn
395d2c3080eSVladimir Sementsov-Ogievskiy bdrv_co_remove_persistent_dirty_bitmap(BlockDriverState *bs, const char *name,
39656f364e6SVladimir Sementsov-Ogievskiy                                        Error **errp)
39756f364e6SVladimir Sementsov-Ogievskiy {
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 
405d2c3080eSVladimir Sementsov-Ogievskiy typedef struct BdrvRemovePersistentDirtyBitmapCo {
406d2c3080eSVladimir Sementsov-Ogievskiy     BlockDriverState *bs;
407d2c3080eSVladimir Sementsov-Ogievskiy     const char *name;
408d2c3080eSVladimir Sementsov-Ogievskiy     Error **errp;
409d2c3080eSVladimir Sementsov-Ogievskiy     int ret;
410d2c3080eSVladimir Sementsov-Ogievskiy } BdrvRemovePersistentDirtyBitmapCo;
411d2c3080eSVladimir Sementsov-Ogievskiy 
412d2c3080eSVladimir Sementsov-Ogievskiy static void coroutine_fn
413d2c3080eSVladimir Sementsov-Ogievskiy bdrv_co_remove_persistent_dirty_bitmap_entry(void *opaque)
414d2c3080eSVladimir Sementsov-Ogievskiy {
415d2c3080eSVladimir Sementsov-Ogievskiy     BdrvRemovePersistentDirtyBitmapCo *s = opaque;
416d2c3080eSVladimir Sementsov-Ogievskiy 
417d2c3080eSVladimir Sementsov-Ogievskiy     s->ret = bdrv_co_remove_persistent_dirty_bitmap(s->bs, s->name, s->errp);
418d2c3080eSVladimir Sementsov-Ogievskiy     aio_wait_kick();
419d2c3080eSVladimir Sementsov-Ogievskiy }
420d2c3080eSVladimir Sementsov-Ogievskiy 
421d2c3080eSVladimir Sementsov-Ogievskiy int bdrv_remove_persistent_dirty_bitmap(BlockDriverState *bs, const char *name,
422d2c3080eSVladimir Sementsov-Ogievskiy                                         Error **errp)
423d2c3080eSVladimir Sementsov-Ogievskiy {
424d2c3080eSVladimir Sementsov-Ogievskiy     if (qemu_in_coroutine()) {
425d2c3080eSVladimir Sementsov-Ogievskiy         return bdrv_co_remove_persistent_dirty_bitmap(bs, name, errp);
426d2c3080eSVladimir Sementsov-Ogievskiy     } else {
427d2c3080eSVladimir Sementsov-Ogievskiy         Coroutine *co;
428d2c3080eSVladimir Sementsov-Ogievskiy         BdrvRemovePersistentDirtyBitmapCo s = {
429d2c3080eSVladimir Sementsov-Ogievskiy             .bs = bs,
430d2c3080eSVladimir Sementsov-Ogievskiy             .name = name,
431d2c3080eSVladimir Sementsov-Ogievskiy             .errp = errp,
432d2c3080eSVladimir Sementsov-Ogievskiy             .ret = -EINPROGRESS,
433d2c3080eSVladimir Sementsov-Ogievskiy         };
434d2c3080eSVladimir Sementsov-Ogievskiy 
435d2c3080eSVladimir Sementsov-Ogievskiy         co = qemu_coroutine_create(bdrv_co_remove_persistent_dirty_bitmap_entry,
436d2c3080eSVladimir Sementsov-Ogievskiy                                    &s);
437d2c3080eSVladimir Sementsov-Ogievskiy         bdrv_coroutine_enter(bs, co);
438d2c3080eSVladimir Sementsov-Ogievskiy         BDRV_POLL_WHILE(bs, s.ret == -EINPROGRESS);
439d2c3080eSVladimir Sementsov-Ogievskiy 
440d2c3080eSVladimir Sementsov-Ogievskiy         return s.ret;
441d2c3080eSVladimir Sementsov-Ogievskiy     }
442d2c3080eSVladimir Sementsov-Ogievskiy }
443d2c3080eSVladimir Sementsov-Ogievskiy 
444ef893b5cSEric Blake bool
445ef893b5cSEric Blake bdrv_supports_persistent_dirty_bitmap(BlockDriverState *bs)
446ef893b5cSEric Blake {
447ef893b5cSEric Blake     if (bs->drv && bs->drv->bdrv_supports_persistent_dirty_bitmap) {
448ef893b5cSEric Blake         return bs->drv->bdrv_supports_persistent_dirty_bitmap(bs);
449ef893b5cSEric Blake     }
450ef893b5cSEric Blake     return false;
451ef893b5cSEric Blake }
452ef893b5cSEric Blake 
453d2c3080eSVladimir Sementsov-Ogievskiy static bool coroutine_fn
454d2c3080eSVladimir Sementsov-Ogievskiy bdrv_co_can_store_new_dirty_bitmap(BlockDriverState *bs, const char *name,
45585cc8a4fSVladimir Sementsov-Ogievskiy                                    uint32_t granularity, Error **errp)
45685cc8a4fSVladimir Sementsov-Ogievskiy {
45785cc8a4fSVladimir Sementsov-Ogievskiy     BlockDriver *drv = bs->drv;
45885cc8a4fSVladimir Sementsov-Ogievskiy 
45985cc8a4fSVladimir Sementsov-Ogievskiy     if (!drv) {
46085cc8a4fSVladimir Sementsov-Ogievskiy         error_setg_errno(errp, ENOMEDIUM,
46185cc8a4fSVladimir Sementsov-Ogievskiy                          "Can't store persistent bitmaps to %s",
46285cc8a4fSVladimir Sementsov-Ogievskiy                          bdrv_get_device_or_node_name(bs));
46385cc8a4fSVladimir Sementsov-Ogievskiy         return false;
46485cc8a4fSVladimir Sementsov-Ogievskiy     }
46585cc8a4fSVladimir Sementsov-Ogievskiy 
466d2c3080eSVladimir Sementsov-Ogievskiy     if (!drv->bdrv_co_can_store_new_dirty_bitmap) {
46785cc8a4fSVladimir Sementsov-Ogievskiy         error_setg_errno(errp, ENOTSUP,
46885cc8a4fSVladimir Sementsov-Ogievskiy                          "Can't store persistent bitmaps to %s",
46985cc8a4fSVladimir Sementsov-Ogievskiy                          bdrv_get_device_or_node_name(bs));
47085cc8a4fSVladimir Sementsov-Ogievskiy         return false;
47185cc8a4fSVladimir Sementsov-Ogievskiy     }
47285cc8a4fSVladimir Sementsov-Ogievskiy 
473d2c3080eSVladimir Sementsov-Ogievskiy     return drv->bdrv_co_can_store_new_dirty_bitmap(bs, name, granularity, errp);
474d2c3080eSVladimir Sementsov-Ogievskiy }
475d2c3080eSVladimir Sementsov-Ogievskiy 
476d2c3080eSVladimir Sementsov-Ogievskiy typedef struct BdrvCanStoreNewDirtyBitmapCo {
477d2c3080eSVladimir Sementsov-Ogievskiy     BlockDriverState *bs;
478d2c3080eSVladimir Sementsov-Ogievskiy     const char *name;
479d2c3080eSVladimir Sementsov-Ogievskiy     uint32_t granularity;
480d2c3080eSVladimir Sementsov-Ogievskiy     Error **errp;
481d2c3080eSVladimir Sementsov-Ogievskiy     bool ret;
482d2c3080eSVladimir Sementsov-Ogievskiy 
483d2c3080eSVladimir Sementsov-Ogievskiy     bool in_progress;
484d2c3080eSVladimir Sementsov-Ogievskiy } BdrvCanStoreNewDirtyBitmapCo;
485d2c3080eSVladimir Sementsov-Ogievskiy 
486d2c3080eSVladimir Sementsov-Ogievskiy static void coroutine_fn bdrv_co_can_store_new_dirty_bitmap_entry(void *opaque)
487d2c3080eSVladimir Sementsov-Ogievskiy {
488d2c3080eSVladimir Sementsov-Ogievskiy     BdrvCanStoreNewDirtyBitmapCo *s = opaque;
489d2c3080eSVladimir Sementsov-Ogievskiy 
490d2c3080eSVladimir Sementsov-Ogievskiy     s->ret = bdrv_co_can_store_new_dirty_bitmap(s->bs, s->name, s->granularity,
491d2c3080eSVladimir Sementsov-Ogievskiy                                                 s->errp);
492d2c3080eSVladimir Sementsov-Ogievskiy     s->in_progress = false;
493d2c3080eSVladimir Sementsov-Ogievskiy     aio_wait_kick();
494d2c3080eSVladimir Sementsov-Ogievskiy }
495d2c3080eSVladimir Sementsov-Ogievskiy 
496d2c3080eSVladimir Sementsov-Ogievskiy bool bdrv_can_store_new_dirty_bitmap(BlockDriverState *bs, const char *name,
497d2c3080eSVladimir Sementsov-Ogievskiy                                      uint32_t granularity, Error **errp)
498d2c3080eSVladimir Sementsov-Ogievskiy {
499384a48fbSEmanuele Giuseppe Esposito     IO_CODE();
500d2c3080eSVladimir Sementsov-Ogievskiy     if (qemu_in_coroutine()) {
501d2c3080eSVladimir Sementsov-Ogievskiy         return bdrv_co_can_store_new_dirty_bitmap(bs, name, granularity, errp);
502d2c3080eSVladimir Sementsov-Ogievskiy     } else {
503d2c3080eSVladimir Sementsov-Ogievskiy         Coroutine *co;
504d2c3080eSVladimir Sementsov-Ogievskiy         BdrvCanStoreNewDirtyBitmapCo s = {
505d2c3080eSVladimir Sementsov-Ogievskiy             .bs = bs,
506d2c3080eSVladimir Sementsov-Ogievskiy             .name = name,
507d2c3080eSVladimir Sementsov-Ogievskiy             .granularity = granularity,
508d2c3080eSVladimir Sementsov-Ogievskiy             .errp = errp,
509d2c3080eSVladimir Sementsov-Ogievskiy             .in_progress = true,
510d2c3080eSVladimir Sementsov-Ogievskiy         };
511d2c3080eSVladimir Sementsov-Ogievskiy 
512d2c3080eSVladimir Sementsov-Ogievskiy         co = qemu_coroutine_create(bdrv_co_can_store_new_dirty_bitmap_entry,
513d2c3080eSVladimir Sementsov-Ogievskiy                                    &s);
514d2c3080eSVladimir Sementsov-Ogievskiy         bdrv_coroutine_enter(bs, co);
515d2c3080eSVladimir Sementsov-Ogievskiy         BDRV_POLL_WHILE(bs, s.in_progress);
516d2c3080eSVladimir Sementsov-Ogievskiy 
517d2c3080eSVladimir Sementsov-Ogievskiy         return s.ret;
518d2c3080eSVladimir Sementsov-Ogievskiy     }
51985cc8a4fSVladimir Sementsov-Ogievskiy }
52085cc8a4fSVladimir Sementsov-Ogievskiy 
521ebab2259SFam Zheng void bdrv_disable_dirty_bitmap(BdrvDirtyBitmap *bitmap)
522ebab2259SFam Zheng {
5231e638301SVladimir Sementsov-Ogievskiy     bdrv_dirty_bitmaps_lock(bitmap->bs);
524ebab2259SFam Zheng     bitmap->disabled = true;
5251e638301SVladimir Sementsov-Ogievskiy     bdrv_dirty_bitmaps_unlock(bitmap->bs);
526ebab2259SFam Zheng }
527ebab2259SFam Zheng 
528ebab2259SFam Zheng void bdrv_enable_dirty_bitmap(BdrvDirtyBitmap *bitmap)
529ebab2259SFam Zheng {
5301e638301SVladimir Sementsov-Ogievskiy     bdrv_dirty_bitmaps_lock(bitmap->bs);
53192bcea40SVladimir Sementsov-Ogievskiy     bdrv_enable_dirty_bitmap_locked(bitmap);
5321e638301SVladimir Sementsov-Ogievskiy     bdrv_dirty_bitmaps_unlock(bitmap->bs);
533ebab2259SFam Zheng }
534ebab2259SFam Zheng 
535ebab2259SFam Zheng BlockDirtyInfoList *bdrv_query_dirty_bitmaps(BlockDriverState *bs)
536ebab2259SFam Zheng {
537ebab2259SFam Zheng     BdrvDirtyBitmap *bm;
538ebab2259SFam Zheng     BlockDirtyInfoList *list = NULL;
539c3033fd3SEric Blake     BlockDirtyInfoList **tail = &list;
540ebab2259SFam Zheng 
5412119882cSPaolo Bonzini     bdrv_dirty_bitmaps_lock(bs);
542ebab2259SFam Zheng     QLIST_FOREACH(bm, &bs->dirty_bitmaps, list) {
543ebab2259SFam Zheng         BlockDirtyInfo *info = g_new0(BlockDirtyInfo, 1);
544c3033fd3SEric Blake 
5459a46dba7SEric Blake         info->count = bdrv_get_dirty_count(bm);
546ebab2259SFam Zheng         info->granularity = bdrv_dirty_bitmap_granularity(bm);
547ebab2259SFam Zheng         info->has_name = !!bm->name;
548ebab2259SFam Zheng         info->name = g_strdup(bm->name);
5494db6ceb0SJohn Snow         info->recording = bdrv_dirty_bitmap_recording(bm);
55027a1b301SJohn Snow         info->busy = bdrv_dirty_bitmap_busy(bm);
551f67cf661SEric Blake         info->persistent = bm->persistent;
552b0f45559SJohn Snow         info->has_inconsistent = bm->inconsistent;
553b0f45559SJohn Snow         info->inconsistent = bm->inconsistent;
554c3033fd3SEric Blake         QAPI_LIST_APPEND(tail, info);
555ebab2259SFam Zheng     }
5562119882cSPaolo Bonzini     bdrv_dirty_bitmaps_unlock(bs);
557ebab2259SFam Zheng 
558ebab2259SFam Zheng     return list;
559ebab2259SFam Zheng }
560ebab2259SFam Zheng 
561b64bd51eSPaolo Bonzini /* Called within bdrv_dirty_bitmap_lock..unlock */
56228636b82SJohn Snow bool bdrv_dirty_bitmap_get_locked(BdrvDirtyBitmap *bitmap, int64_t offset)
563ebab2259SFam Zheng {
564ca759622SEric Blake     return hbitmap_get(bitmap->bitmap, offset);
565ebab2259SFam Zheng }
56628636b82SJohn Snow 
56728636b82SJohn Snow bool bdrv_dirty_bitmap_get(BdrvDirtyBitmap *bitmap, int64_t offset)
56828636b82SJohn Snow {
56928636b82SJohn Snow     bool ret;
5701e638301SVladimir Sementsov-Ogievskiy     bdrv_dirty_bitmaps_lock(bitmap->bs);
57128636b82SJohn Snow     ret = bdrv_dirty_bitmap_get_locked(bitmap, offset);
5721e638301SVladimir Sementsov-Ogievskiy     bdrv_dirty_bitmaps_unlock(bitmap->bs);
57328636b82SJohn Snow 
57428636b82SJohn Snow     return ret;
575ebab2259SFam Zheng }
576ebab2259SFam Zheng 
577ebab2259SFam Zheng /**
578ebab2259SFam Zheng  * Chooses a default granularity based on the existing cluster size,
579ebab2259SFam Zheng  * but clamped between [4K, 64K]. Defaults to 64K in the case that there
580ebab2259SFam Zheng  * is no cluster size information available.
581ebab2259SFam Zheng  */
582ebab2259SFam Zheng uint32_t bdrv_get_default_bitmap_granularity(BlockDriverState *bs)
583ebab2259SFam Zheng {
584ebab2259SFam Zheng     BlockDriverInfo bdi;
585ebab2259SFam Zheng     uint32_t granularity;
586ebab2259SFam Zheng 
587ebab2259SFam Zheng     if (bdrv_get_info(bs, &bdi) >= 0 && bdi.cluster_size > 0) {
588ebab2259SFam Zheng         granularity = MAX(4096, bdi.cluster_size);
589ebab2259SFam Zheng         granularity = MIN(65536, granularity);
590ebab2259SFam Zheng     } else {
591ebab2259SFam Zheng         granularity = 65536;
592ebab2259SFam Zheng     }
593ebab2259SFam Zheng 
594ebab2259SFam Zheng     return granularity;
595ebab2259SFam Zheng }
596ebab2259SFam Zheng 
597ba06ff1aSVladimir Sementsov-Ogievskiy uint32_t bdrv_dirty_bitmap_granularity(const BdrvDirtyBitmap *bitmap)
598ebab2259SFam Zheng {
599ca759622SEric Blake     return 1U << hbitmap_granularity(bitmap->bitmap);
600ebab2259SFam Zheng }
601ebab2259SFam Zheng 
602715a74d8SEric Blake BdrvDirtyBitmapIter *bdrv_dirty_iter_new(BdrvDirtyBitmap *bitmap)
603ebab2259SFam Zheng {
604dc162c8eSFam Zheng     BdrvDirtyBitmapIter *iter = g_new(BdrvDirtyBitmapIter, 1);
605715a74d8SEric Blake     hbitmap_iter_init(&iter->hbi, bitmap->bitmap, 0);
606dc162c8eSFam Zheng     iter->bitmap = bitmap;
607dc162c8eSFam Zheng     bitmap->active_iterators++;
608dc162c8eSFam Zheng     return iter;
609dc162c8eSFam Zheng }
610dc162c8eSFam Zheng 
611dc162c8eSFam Zheng void bdrv_dirty_iter_free(BdrvDirtyBitmapIter *iter)
612dc162c8eSFam Zheng {
613dc162c8eSFam Zheng     if (!iter) {
614dc162c8eSFam Zheng         return;
615dc162c8eSFam Zheng     }
616dc162c8eSFam Zheng     assert(iter->bitmap->active_iterators > 0);
617dc162c8eSFam Zheng     iter->bitmap->active_iterators--;
618dc162c8eSFam Zheng     g_free(iter);
619dc162c8eSFam Zheng }
620dc162c8eSFam Zheng 
621dc162c8eSFam Zheng int64_t bdrv_dirty_iter_next(BdrvDirtyBitmapIter *iter)
622dc162c8eSFam Zheng {
62319c021e1SVladimir Sementsov-Ogievskiy     return hbitmap_iter_next(&iter->hbi);
624ebab2259SFam Zheng }
625ebab2259SFam Zheng 
626b64bd51eSPaolo Bonzini /* Called within bdrv_dirty_bitmap_lock..unlock */
627b64bd51eSPaolo Bonzini void bdrv_set_dirty_bitmap_locked(BdrvDirtyBitmap *bitmap,
628e0d7f73eSEric Blake                                   int64_t offset, int64_t bytes)
629ebab2259SFam Zheng {
630d6883bc9SVladimir Sementsov-Ogievskiy     assert(!bdrv_dirty_bitmap_readonly(bitmap));
631ca759622SEric Blake     hbitmap_set(bitmap->bitmap, offset, bytes);
632ebab2259SFam Zheng }
633ebab2259SFam Zheng 
634b64bd51eSPaolo Bonzini void bdrv_set_dirty_bitmap(BdrvDirtyBitmap *bitmap,
635e0d7f73eSEric Blake                            int64_t offset, int64_t bytes)
636b64bd51eSPaolo Bonzini {
6371e638301SVladimir Sementsov-Ogievskiy     bdrv_dirty_bitmaps_lock(bitmap->bs);
638e0d7f73eSEric Blake     bdrv_set_dirty_bitmap_locked(bitmap, offset, bytes);
6391e638301SVladimir Sementsov-Ogievskiy     bdrv_dirty_bitmaps_unlock(bitmap->bs);
640b64bd51eSPaolo Bonzini }
641b64bd51eSPaolo Bonzini 
642b64bd51eSPaolo Bonzini /* Called within bdrv_dirty_bitmap_lock..unlock */
643b64bd51eSPaolo Bonzini void bdrv_reset_dirty_bitmap_locked(BdrvDirtyBitmap *bitmap,
644e0d7f73eSEric Blake                                     int64_t offset, int64_t bytes)
645ebab2259SFam Zheng {
646d6883bc9SVladimir Sementsov-Ogievskiy     assert(!bdrv_dirty_bitmap_readonly(bitmap));
647ca759622SEric Blake     hbitmap_reset(bitmap->bitmap, offset, bytes);
648ebab2259SFam Zheng }
649ebab2259SFam Zheng 
650b64bd51eSPaolo Bonzini void bdrv_reset_dirty_bitmap(BdrvDirtyBitmap *bitmap,
651e0d7f73eSEric Blake                              int64_t offset, int64_t bytes)
652b64bd51eSPaolo Bonzini {
6531e638301SVladimir Sementsov-Ogievskiy     bdrv_dirty_bitmaps_lock(bitmap->bs);
654e0d7f73eSEric Blake     bdrv_reset_dirty_bitmap_locked(bitmap, offset, bytes);
6551e638301SVladimir Sementsov-Ogievskiy     bdrv_dirty_bitmaps_unlock(bitmap->bs);
656b64bd51eSPaolo Bonzini }
657b64bd51eSPaolo Bonzini 
658ebab2259SFam Zheng void bdrv_clear_dirty_bitmap(BdrvDirtyBitmap *bitmap, HBitmap **out)
659ebab2259SFam Zheng {
660967d7905SEmanuele Giuseppe Esposito     IO_CODE();
661d6883bc9SVladimir Sementsov-Ogievskiy     assert(!bdrv_dirty_bitmap_readonly(bitmap));
6621e638301SVladimir Sementsov-Ogievskiy     bdrv_dirty_bitmaps_lock(bitmap->bs);
663ebab2259SFam Zheng     if (!out) {
664ebab2259SFam Zheng         hbitmap_reset_all(bitmap->bitmap);
665ebab2259SFam Zheng     } else {
666ebab2259SFam Zheng         HBitmap *backup = bitmap->bitmap;
667ca759622SEric Blake         bitmap->bitmap = hbitmap_alloc(bitmap->size,
668ebab2259SFam Zheng                                        hbitmap_granularity(backup));
669ebab2259SFam Zheng         *out = backup;
670ebab2259SFam Zheng     }
6711e638301SVladimir Sementsov-Ogievskiy     bdrv_dirty_bitmaps_unlock(bitmap->bs);
672ebab2259SFam Zheng }
673ebab2259SFam Zheng 
67456bd6624SVladimir Sementsov-Ogievskiy void bdrv_restore_dirty_bitmap(BdrvDirtyBitmap *bitmap, HBitmap *backup)
675ebab2259SFam Zheng {
676ebab2259SFam Zheng     HBitmap *tmp = bitmap->bitmap;
677d6883bc9SVladimir Sementsov-Ogievskiy     assert(!bdrv_dirty_bitmap_readonly(bitmap));
678b4ad82aaSEmanuele Giuseppe Esposito     GLOBAL_STATE_CODE();
67956bd6624SVladimir Sementsov-Ogievskiy     bitmap->bitmap = backup;
680ebab2259SFam Zheng     hbitmap_free(tmp);
681ebab2259SFam Zheng }
682ebab2259SFam Zheng 
683882c36f5SVladimir Sementsov-Ogievskiy uint64_t bdrv_dirty_bitmap_serialization_size(const BdrvDirtyBitmap *bitmap,
68486f6ae67SEric Blake                                               uint64_t offset, uint64_t bytes)
685882c36f5SVladimir Sementsov-Ogievskiy {
686ca759622SEric Blake     return hbitmap_serialization_size(bitmap->bitmap, offset, bytes);
687882c36f5SVladimir Sementsov-Ogievskiy }
688882c36f5SVladimir Sementsov-Ogievskiy 
689882c36f5SVladimir Sementsov-Ogievskiy uint64_t bdrv_dirty_bitmap_serialization_align(const BdrvDirtyBitmap *bitmap)
690882c36f5SVladimir Sementsov-Ogievskiy {
691ca759622SEric Blake     return hbitmap_serialization_align(bitmap->bitmap);
692882c36f5SVladimir Sementsov-Ogievskiy }
693882c36f5SVladimir Sementsov-Ogievskiy 
69435f428baSVladimir Sementsov-Ogievskiy /* Return the disk size covered by a chunk of serialized bitmap data. */
69535f428baSVladimir Sementsov-Ogievskiy uint64_t bdrv_dirty_bitmap_serialization_coverage(int serialized_chunk_size,
69635f428baSVladimir Sementsov-Ogievskiy                                                   const BdrvDirtyBitmap *bitmap)
69735f428baSVladimir Sementsov-Ogievskiy {
69835f428baSVladimir Sementsov-Ogievskiy     uint64_t granularity = bdrv_dirty_bitmap_granularity(bitmap);
69935f428baSVladimir Sementsov-Ogievskiy     uint64_t limit = granularity * (serialized_chunk_size << 3);
70035f428baSVladimir Sementsov-Ogievskiy 
70135f428baSVladimir Sementsov-Ogievskiy     assert(QEMU_IS_ALIGNED(limit,
70235f428baSVladimir Sementsov-Ogievskiy                            bdrv_dirty_bitmap_serialization_align(bitmap)));
70335f428baSVladimir Sementsov-Ogievskiy     return limit;
70435f428baSVladimir Sementsov-Ogievskiy }
70535f428baSVladimir Sementsov-Ogievskiy 
70635f428baSVladimir Sementsov-Ogievskiy 
707882c36f5SVladimir Sementsov-Ogievskiy void bdrv_dirty_bitmap_serialize_part(const BdrvDirtyBitmap *bitmap,
70886f6ae67SEric Blake                                       uint8_t *buf, uint64_t offset,
70986f6ae67SEric Blake                                       uint64_t bytes)
710882c36f5SVladimir Sementsov-Ogievskiy {
711ca759622SEric Blake     hbitmap_serialize_part(bitmap->bitmap, buf, offset, bytes);
712882c36f5SVladimir Sementsov-Ogievskiy }
713882c36f5SVladimir Sementsov-Ogievskiy 
714882c36f5SVladimir Sementsov-Ogievskiy void bdrv_dirty_bitmap_deserialize_part(BdrvDirtyBitmap *bitmap,
71586f6ae67SEric Blake                                         uint8_t *buf, uint64_t offset,
71686f6ae67SEric Blake                                         uint64_t bytes, bool finish)
717882c36f5SVladimir Sementsov-Ogievskiy {
718ca759622SEric Blake     hbitmap_deserialize_part(bitmap->bitmap, buf, offset, bytes, finish);
719882c36f5SVladimir Sementsov-Ogievskiy }
720882c36f5SVladimir Sementsov-Ogievskiy 
721882c36f5SVladimir Sementsov-Ogievskiy void bdrv_dirty_bitmap_deserialize_zeroes(BdrvDirtyBitmap *bitmap,
72286f6ae67SEric Blake                                           uint64_t offset, uint64_t bytes,
723882c36f5SVladimir Sementsov-Ogievskiy                                           bool finish)
724882c36f5SVladimir Sementsov-Ogievskiy {
725ca759622SEric Blake     hbitmap_deserialize_zeroes(bitmap->bitmap, offset, bytes, finish);
726882c36f5SVladimir Sementsov-Ogievskiy }
727882c36f5SVladimir Sementsov-Ogievskiy 
7286bdc8b71SVladimir Sementsov-Ogievskiy void bdrv_dirty_bitmap_deserialize_ones(BdrvDirtyBitmap *bitmap,
72986f6ae67SEric Blake                                         uint64_t offset, uint64_t bytes,
7306bdc8b71SVladimir Sementsov-Ogievskiy                                         bool finish)
7316bdc8b71SVladimir Sementsov-Ogievskiy {
732ca759622SEric Blake     hbitmap_deserialize_ones(bitmap->bitmap, offset, bytes, finish);
7336bdc8b71SVladimir Sementsov-Ogievskiy }
7346bdc8b71SVladimir Sementsov-Ogievskiy 
735882c36f5SVladimir Sementsov-Ogievskiy void bdrv_dirty_bitmap_deserialize_finish(BdrvDirtyBitmap *bitmap)
736882c36f5SVladimir Sementsov-Ogievskiy {
737882c36f5SVladimir Sementsov-Ogievskiy     hbitmap_deserialize_finish(bitmap->bitmap);
738882c36f5SVladimir Sementsov-Ogievskiy }
739882c36f5SVladimir Sementsov-Ogievskiy 
7400fdf1a4fSEric Blake void bdrv_set_dirty(BlockDriverState *bs, int64_t offset, int64_t bytes)
741ebab2259SFam Zheng {
742ebab2259SFam Zheng     BdrvDirtyBitmap *bitmap;
743967d7905SEmanuele Giuseppe Esposito     IO_CODE();
7442119882cSPaolo Bonzini 
7452119882cSPaolo Bonzini     if (QLIST_EMPTY(&bs->dirty_bitmaps)) {
7462119882cSPaolo Bonzini         return;
7472119882cSPaolo Bonzini     }
7482119882cSPaolo Bonzini 
7492119882cSPaolo Bonzini     bdrv_dirty_bitmaps_lock(bs);
750ebab2259SFam Zheng     QLIST_FOREACH(bitmap, &bs->dirty_bitmaps, list) {
751ebab2259SFam Zheng         if (!bdrv_dirty_bitmap_enabled(bitmap)) {
752ebab2259SFam Zheng             continue;
753ebab2259SFam Zheng         }
754d6883bc9SVladimir Sementsov-Ogievskiy         assert(!bdrv_dirty_bitmap_readonly(bitmap));
755ca759622SEric Blake         hbitmap_set(bitmap->bitmap, offset, bytes);
756ebab2259SFam Zheng     }
7572119882cSPaolo Bonzini     bdrv_dirty_bitmaps_unlock(bs);
758ebab2259SFam Zheng }
759ebab2259SFam Zheng 
760ebab2259SFam Zheng /**
761dc162c8eSFam Zheng  * Advance a BdrvDirtyBitmapIter to an arbitrary offset.
762ebab2259SFam Zheng  */
763715a74d8SEric Blake void bdrv_set_dirty_iter(BdrvDirtyBitmapIter *iter, int64_t offset)
764ebab2259SFam Zheng {
765ca759622SEric Blake     hbitmap_iter_init(&iter->hbi, iter->hbi.hb, offset);
766ebab2259SFam Zheng }
767ebab2259SFam Zheng 
768ebab2259SFam Zheng int64_t bdrv_get_dirty_count(BdrvDirtyBitmap *bitmap)
769ebab2259SFam Zheng {
770ca759622SEric Blake     return hbitmap_count(bitmap->bitmap);
771ebab2259SFam Zheng }
7726d3f4049SFam Zheng 
773d6883bc9SVladimir Sementsov-Ogievskiy bool bdrv_dirty_bitmap_readonly(const BdrvDirtyBitmap *bitmap)
774d6883bc9SVladimir Sementsov-Ogievskiy {
775d6883bc9SVladimir Sementsov-Ogievskiy     return bitmap->readonly;
776d6883bc9SVladimir Sementsov-Ogievskiy }
777d6883bc9SVladimir Sementsov-Ogievskiy 
778d6883bc9SVladimir Sementsov-Ogievskiy /* Called with BQL taken. */
779d6883bc9SVladimir Sementsov-Ogievskiy void bdrv_dirty_bitmap_set_readonly(BdrvDirtyBitmap *bitmap, bool value)
780d6883bc9SVladimir Sementsov-Ogievskiy {
7811e638301SVladimir Sementsov-Ogievskiy     bdrv_dirty_bitmaps_lock(bitmap->bs);
782d6883bc9SVladimir Sementsov-Ogievskiy     bitmap->readonly = value;
7831e638301SVladimir Sementsov-Ogievskiy     bdrv_dirty_bitmaps_unlock(bitmap->bs);
784d6883bc9SVladimir Sementsov-Ogievskiy }
785d6883bc9SVladimir Sementsov-Ogievskiy 
786d6883bc9SVladimir Sementsov-Ogievskiy bool bdrv_has_readonly_bitmaps(BlockDriverState *bs)
787d6883bc9SVladimir Sementsov-Ogievskiy {
788d6883bc9SVladimir Sementsov-Ogievskiy     BdrvDirtyBitmap *bm;
789d6883bc9SVladimir Sementsov-Ogievskiy     QLIST_FOREACH(bm, &bs->dirty_bitmaps, list) {
790d6883bc9SVladimir Sementsov-Ogievskiy         if (bm->readonly) {
791d6883bc9SVladimir Sementsov-Ogievskiy             return true;
792d6883bc9SVladimir Sementsov-Ogievskiy         }
793d6883bc9SVladimir Sementsov-Ogievskiy     }
794d6883bc9SVladimir Sementsov-Ogievskiy 
795d6883bc9SVladimir Sementsov-Ogievskiy     return false;
796d6883bc9SVladimir Sementsov-Ogievskiy }
797a0319aacSVladimir Sementsov-Ogievskiy 
7987ae89a0dSVladimir Sementsov-Ogievskiy bool bdrv_has_named_bitmaps(BlockDriverState *bs)
7997ae89a0dSVladimir Sementsov-Ogievskiy {
8007ae89a0dSVladimir Sementsov-Ogievskiy     BdrvDirtyBitmap *bm;
8017ae89a0dSVladimir Sementsov-Ogievskiy 
8027ae89a0dSVladimir Sementsov-Ogievskiy     QLIST_FOREACH(bm, &bs->dirty_bitmaps, list) {
8037ae89a0dSVladimir Sementsov-Ogievskiy         if (bdrv_dirty_bitmap_name(bm)) {
8047ae89a0dSVladimir Sementsov-Ogievskiy             return true;
8057ae89a0dSVladimir Sementsov-Ogievskiy         }
8067ae89a0dSVladimir Sementsov-Ogievskiy     }
8077ae89a0dSVladimir Sementsov-Ogievskiy 
8087ae89a0dSVladimir Sementsov-Ogievskiy     return false;
8097ae89a0dSVladimir Sementsov-Ogievskiy }
8107ae89a0dSVladimir Sementsov-Ogievskiy 
811a0319aacSVladimir Sementsov-Ogievskiy /* Called with BQL taken. */
812796a3798SEric Blake void bdrv_dirty_bitmap_set_persistence(BdrvDirtyBitmap *bitmap, bool persistent)
813a88b179fSVladimir Sementsov-Ogievskiy {
8141e638301SVladimir Sementsov-Ogievskiy     bdrv_dirty_bitmaps_lock(bitmap->bs);
815a88b179fSVladimir Sementsov-Ogievskiy     bitmap->persistent = persistent;
8161e638301SVladimir Sementsov-Ogievskiy     bdrv_dirty_bitmaps_unlock(bitmap->bs);
817a88b179fSVladimir Sementsov-Ogievskiy }
818a88b179fSVladimir Sementsov-Ogievskiy 
8199c98f145SVladimir Sementsov-Ogievskiy /* Called with BQL taken. */
820b0f45559SJohn Snow void bdrv_dirty_bitmap_set_inconsistent(BdrvDirtyBitmap *bitmap)
821b0f45559SJohn Snow {
8221e638301SVladimir Sementsov-Ogievskiy     bdrv_dirty_bitmaps_lock(bitmap->bs);
823b0f45559SJohn Snow     assert(bitmap->persistent == true);
824b0f45559SJohn Snow     bitmap->inconsistent = true;
825b0f45559SJohn Snow     bitmap->disabled = true;
8261e638301SVladimir Sementsov-Ogievskiy     bdrv_dirty_bitmaps_unlock(bitmap->bs);
827b0f45559SJohn Snow }
828b0f45559SJohn Snow 
829b0f45559SJohn Snow /* Called with BQL taken. */
830c4e4b0faSJohn Snow void bdrv_dirty_bitmap_skip_store(BdrvDirtyBitmap *bitmap, bool skip)
8319c98f145SVladimir Sementsov-Ogievskiy {
8321e638301SVladimir Sementsov-Ogievskiy     bdrv_dirty_bitmaps_lock(bitmap->bs);
833c4e4b0faSJohn Snow     bitmap->skip_store = skip;
8341e638301SVladimir Sementsov-Ogievskiy     bdrv_dirty_bitmaps_unlock(bitmap->bs);
8359c98f145SVladimir Sementsov-Ogievskiy }
8369c98f145SVladimir Sementsov-Ogievskiy 
837796a3798SEric Blake bool bdrv_dirty_bitmap_get_persistence(BdrvDirtyBitmap *bitmap)
838a88b179fSVladimir Sementsov-Ogievskiy {
839c4e4b0faSJohn Snow     return bitmap->persistent && !bitmap->skip_store;
840a88b179fSVladimir Sementsov-Ogievskiy }
841a88b179fSVladimir Sementsov-Ogievskiy 
842b0f45559SJohn Snow bool bdrv_dirty_bitmap_inconsistent(const BdrvDirtyBitmap *bitmap)
843b0f45559SJohn Snow {
844b0f45559SJohn Snow     return bitmap->inconsistent;
845b0f45559SJohn Snow }
846b0f45559SJohn Snow 
847ef9041a7SVladimir Sementsov-Ogievskiy BdrvDirtyBitmap *bdrv_dirty_bitmap_first(BlockDriverState *bs)
8483dd10a06SVladimir Sementsov-Ogievskiy {
849ef9041a7SVladimir Sementsov-Ogievskiy     return QLIST_FIRST(&bs->dirty_bitmaps);
850ef9041a7SVladimir Sementsov-Ogievskiy }
851ef9041a7SVladimir Sementsov-Ogievskiy 
852ef9041a7SVladimir Sementsov-Ogievskiy BdrvDirtyBitmap *bdrv_dirty_bitmap_next(BdrvDirtyBitmap *bitmap)
853ef9041a7SVladimir Sementsov-Ogievskiy {
854ef9041a7SVladimir Sementsov-Ogievskiy     return QLIST_NEXT(bitmap, list);
8553dd10a06SVladimir Sementsov-Ogievskiy }
856a3b52535SVladimir Sementsov-Ogievskiy 
857a3b52535SVladimir Sementsov-Ogievskiy char *bdrv_dirty_bitmap_sha256(const BdrvDirtyBitmap *bitmap, Error **errp)
858a3b52535SVladimir Sementsov-Ogievskiy {
859a3b52535SVladimir Sementsov-Ogievskiy     return hbitmap_sha256(bitmap->bitmap, errp);
860a3b52535SVladimir Sementsov-Ogievskiy }
86156207df5SVladimir Sementsov-Ogievskiy 
8629399c54bSVladimir Sementsov-Ogievskiy int64_t bdrv_dirty_bitmap_next_dirty(BdrvDirtyBitmap *bitmap, int64_t offset,
8639399c54bSVladimir Sementsov-Ogievskiy                                      int64_t bytes)
8649399c54bSVladimir Sementsov-Ogievskiy {
8659399c54bSVladimir Sementsov-Ogievskiy     return hbitmap_next_dirty(bitmap->bitmap, offset, bytes);
8669399c54bSVladimir Sementsov-Ogievskiy }
8679399c54bSVladimir Sementsov-Ogievskiy 
868642700fdSVladimir Sementsov-Ogievskiy int64_t bdrv_dirty_bitmap_next_zero(BdrvDirtyBitmap *bitmap, int64_t offset,
869642700fdSVladimir Sementsov-Ogievskiy                                     int64_t bytes)
87056207df5SVladimir Sementsov-Ogievskiy {
87176d570dcSVladimir Sementsov-Ogievskiy     return hbitmap_next_zero(bitmap->bitmap, offset, bytes);
87256207df5SVladimir Sementsov-Ogievskiy }
873b598e531SVladimir Sementsov-Ogievskiy 
874a78a1a48SVladimir Sementsov-Ogievskiy bool bdrv_dirty_bitmap_next_dirty_area(BdrvDirtyBitmap *bitmap,
875299ea9ffSVladimir Sementsov-Ogievskiy         int64_t start, int64_t end, int64_t max_dirty_count,
876299ea9ffSVladimir Sementsov-Ogievskiy         int64_t *dirty_start, int64_t *dirty_count)
877a78a1a48SVladimir Sementsov-Ogievskiy {
878299ea9ffSVladimir Sementsov-Ogievskiy     return hbitmap_next_dirty_area(bitmap->bitmap, start, end, max_dirty_count,
879299ea9ffSVladimir Sementsov-Ogievskiy                                    dirty_start, dirty_count);
880a78a1a48SVladimir Sementsov-Ogievskiy }
881a78a1a48SVladimir Sementsov-Ogievskiy 
882*a6426475SVladimir Sementsov-Ogievskiy bool bdrv_dirty_bitmap_status(BdrvDirtyBitmap *bitmap, int64_t offset,
883*a6426475SVladimir Sementsov-Ogievskiy                               int64_t bytes, int64_t *count)
884*a6426475SVladimir Sementsov-Ogievskiy {
885*a6426475SVladimir Sementsov-Ogievskiy     return hbitmap_status(bitmap->bitmap, offset, bytes, count);
886*a6426475SVladimir Sementsov-Ogievskiy }
887*a6426475SVladimir Sementsov-Ogievskiy 
888b7661ca5SJohn Snow /**
889b7661ca5SJohn Snow  * bdrv_merge_dirty_bitmap: merge src into dest.
890b7661ca5SJohn Snow  * Ensures permissions on bitmaps are reasonable; use for public API.
891b7661ca5SJohn Snow  *
892b7661ca5SJohn Snow  * @backup: If provided, make a copy of dest here prior to merge.
89334ffacb7SVladimir Sementsov-Ogievskiy  *
89434ffacb7SVladimir Sementsov-Ogievskiy  * Returns true on success, false on failure. In case of failure bitmaps are
89534ffacb7SVladimir Sementsov-Ogievskiy  * untouched.
896b7661ca5SJohn Snow  */
89734ffacb7SVladimir Sementsov-Ogievskiy bool bdrv_merge_dirty_bitmap(BdrvDirtyBitmap *dest, const BdrvDirtyBitmap *src,
898fa000f2fSVladimir Sementsov-Ogievskiy                              HBitmap **backup, Error **errp)
899b598e531SVladimir Sementsov-Ogievskiy {
90034ffacb7SVladimir Sementsov-Ogievskiy     bool ret = false;
901fa000f2fSVladimir Sementsov-Ogievskiy 
9021e638301SVladimir Sementsov-Ogievskiy     bdrv_dirty_bitmaps_lock(dest->bs);
9031e638301SVladimir Sementsov-Ogievskiy     if (src->bs != dest->bs) {
9041e638301SVladimir Sementsov-Ogievskiy         bdrv_dirty_bitmaps_lock(src->bs);
905eff0829bSVladimir Sementsov-Ogievskiy     }
906b598e531SVladimir Sementsov-Ogievskiy 
9073ae96d66SJohn Snow     if (bdrv_dirty_bitmap_check(dest, BDRV_BITMAP_DEFAULT, errp)) {
90806bf5006SVladimir Sementsov-Ogievskiy         goto out;
90906bf5006SVladimir Sementsov-Ogievskiy     }
91006bf5006SVladimir Sementsov-Ogievskiy 
911cb8e58e3SJohn Snow     if (bdrv_dirty_bitmap_check(src, BDRV_BITMAP_ALLOW_RO, errp)) {
912cb8e58e3SJohn Snow         goto out;
913cb8e58e3SJohn Snow     }
914b598e531SVladimir Sementsov-Ogievskiy 
915fa000f2fSVladimir Sementsov-Ogievskiy     if (!hbitmap_can_merge(dest->bitmap, src->bitmap)) {
916b598e531SVladimir Sementsov-Ogievskiy         error_setg(errp, "Bitmaps are incompatible and can't be merged");
91706bf5006SVladimir Sementsov-Ogievskiy         goto out;
918b598e531SVladimir Sementsov-Ogievskiy     }
919b598e531SVladimir Sementsov-Ogievskiy 
920b7661ca5SJohn Snow     ret = bdrv_dirty_bitmap_merge_internal(dest, src, backup, false);
921fa000f2fSVladimir Sementsov-Ogievskiy     assert(ret);
922fa000f2fSVladimir Sementsov-Ogievskiy 
92306bf5006SVladimir Sementsov-Ogievskiy out:
9241e638301SVladimir Sementsov-Ogievskiy     bdrv_dirty_bitmaps_unlock(dest->bs);
9251e638301SVladimir Sementsov-Ogievskiy     if (src->bs != dest->bs) {
9261e638301SVladimir Sementsov-Ogievskiy         bdrv_dirty_bitmaps_unlock(src->bs);
927eff0829bSVladimir Sementsov-Ogievskiy     }
92834ffacb7SVladimir Sementsov-Ogievskiy 
92934ffacb7SVladimir Sementsov-Ogievskiy     return ret;
930b598e531SVladimir Sementsov-Ogievskiy }
931b7661ca5SJohn Snow 
932b7661ca5SJohn Snow /**
933b7661ca5SJohn Snow  * bdrv_dirty_bitmap_merge_internal: merge src into dest.
934b7661ca5SJohn Snow  * Does NOT check bitmap permissions; not suitable for use as public API.
935b7661ca5SJohn Snow  *
936b7661ca5SJohn Snow  * @backup: If provided, make a copy of dest here prior to merge.
937b7661ca5SJohn Snow  * @lock: If true, lock and unlock bitmaps on the way in/out.
938b7661ca5SJohn Snow  * returns true if the merge succeeded; false if unattempted.
939b7661ca5SJohn Snow  */
940b7661ca5SJohn Snow bool bdrv_dirty_bitmap_merge_internal(BdrvDirtyBitmap *dest,
941b7661ca5SJohn Snow                                       const BdrvDirtyBitmap *src,
942b7661ca5SJohn Snow                                       HBitmap **backup,
943b7661ca5SJohn Snow                                       bool lock)
944b7661ca5SJohn Snow {
945b7661ca5SJohn Snow     bool ret;
946967d7905SEmanuele Giuseppe Esposito     IO_CODE();
947b7661ca5SJohn Snow 
948b7661ca5SJohn Snow     assert(!bdrv_dirty_bitmap_readonly(dest));
949b7661ca5SJohn Snow     assert(!bdrv_dirty_bitmap_inconsistent(dest));
950b7661ca5SJohn Snow     assert(!bdrv_dirty_bitmap_inconsistent(src));
951b7661ca5SJohn Snow 
952b7661ca5SJohn Snow     if (lock) {
9531e638301SVladimir Sementsov-Ogievskiy         bdrv_dirty_bitmaps_lock(dest->bs);
9541e638301SVladimir Sementsov-Ogievskiy         if (src->bs != dest->bs) {
9551e638301SVladimir Sementsov-Ogievskiy             bdrv_dirty_bitmaps_lock(src->bs);
956b7661ca5SJohn Snow         }
957b7661ca5SJohn Snow     }
958b7661ca5SJohn Snow 
959b7661ca5SJohn Snow     if (backup) {
960b7661ca5SJohn Snow         *backup = dest->bitmap;
961b7661ca5SJohn Snow         dest->bitmap = hbitmap_alloc(dest->size, hbitmap_granularity(*backup));
962b7661ca5SJohn Snow         ret = hbitmap_merge(*backup, src->bitmap, dest->bitmap);
963b7661ca5SJohn Snow     } else {
964b7661ca5SJohn Snow         ret = hbitmap_merge(dest->bitmap, src->bitmap, dest->bitmap);
965b7661ca5SJohn Snow     }
966b7661ca5SJohn Snow 
967b7661ca5SJohn Snow     if (lock) {
9681e638301SVladimir Sementsov-Ogievskiy         bdrv_dirty_bitmaps_unlock(dest->bs);
9691e638301SVladimir Sementsov-Ogievskiy         if (src->bs != dest->bs) {
9701e638301SVladimir Sementsov-Ogievskiy             bdrv_dirty_bitmaps_unlock(src->bs);
971b7661ca5SJohn Snow         }
972b7661ca5SJohn Snow     }
973b7661ca5SJohn Snow 
974b7661ca5SJohn Snow     return ret;
975b7661ca5SJohn Snow }
976