xref: /qemu/block/dirty-bitmap.c (revision ca759622)
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 "qemu-common.h"
27ebab2259SFam Zheng #include "trace.h"
28ebab2259SFam Zheng #include "block/block_int.h"
29ebab2259SFam Zheng #include "block/blockjob.h"
30ebab2259SFam Zheng 
31ebab2259SFam Zheng /**
32ebab2259SFam Zheng  * A BdrvDirtyBitmap can be in three possible states:
33ebab2259SFam Zheng  * (1) successor is NULL and disabled is false: full r/w mode
34ebab2259SFam Zheng  * (2) successor is NULL and disabled is true: read only mode ("disabled")
35ebab2259SFam Zheng  * (3) successor is set: frozen mode.
36ebab2259SFam Zheng  *     A frozen bitmap cannot be renamed, deleted, anonymized, cleared, set,
37ebab2259SFam Zheng  *     or enabled. A frozen bitmap can only abdicate() or reclaim().
38ebab2259SFam Zheng  */
39ebab2259SFam Zheng struct BdrvDirtyBitmap {
40b64bd51eSPaolo Bonzini     QemuMutex *mutex;
41*ca759622SEric Blake     HBitmap *bitmap;            /* Dirty bitmap implementation */
42fb933437SFam Zheng     HBitmap *meta;              /* Meta dirty bitmap */
43ebab2259SFam Zheng     BdrvDirtyBitmap *successor; /* Anonymous child; implies frozen status */
44ebab2259SFam Zheng     char *name;                 /* Optional non-empty unique ID */
45993e6525SEric Blake     int64_t size;               /* Size of the bitmap, in bytes */
468bfc932eSVladimir Sementsov-Ogievskiy     bool disabled;              /* Bitmap is disabled. It ignores all writes to
478bfc932eSVladimir Sementsov-Ogievskiy                                    the device */
48dc162c8eSFam Zheng     int active_iterators;       /* How many iterators are active */
49d6883bc9SVladimir Sementsov-Ogievskiy     bool readonly;              /* Bitmap is read-only. This field also
50d6883bc9SVladimir Sementsov-Ogievskiy                                    prevents the respective image from being
51d6883bc9SVladimir Sementsov-Ogievskiy                                    modified (i.e. blocks writes and discards).
52d6883bc9SVladimir Sementsov-Ogievskiy                                    Such operations must fail and both the image
53d6883bc9SVladimir Sementsov-Ogievskiy                                    and this bitmap must remain unchanged while
54d6883bc9SVladimir Sementsov-Ogievskiy                                    this flag is set. */
55a0319aacSVladimir Sementsov-Ogievskiy     bool autoload;              /* For persistent bitmaps: bitmap must be
56a0319aacSVladimir Sementsov-Ogievskiy                                    autoloaded on image opening */
57a88b179fSVladimir Sementsov-Ogievskiy     bool persistent;            /* bitmap must be saved to owner disk image */
58ebab2259SFam Zheng     QLIST_ENTRY(BdrvDirtyBitmap) list;
59ebab2259SFam Zheng };
60ebab2259SFam Zheng 
61dc162c8eSFam Zheng struct BdrvDirtyBitmapIter {
62dc162c8eSFam Zheng     HBitmapIter hbi;
63dc162c8eSFam Zheng     BdrvDirtyBitmap *bitmap;
64dc162c8eSFam Zheng };
65dc162c8eSFam Zheng 
662119882cSPaolo Bonzini static inline void bdrv_dirty_bitmaps_lock(BlockDriverState *bs)
672119882cSPaolo Bonzini {
682119882cSPaolo Bonzini     qemu_mutex_lock(&bs->dirty_bitmap_mutex);
692119882cSPaolo Bonzini }
702119882cSPaolo Bonzini 
712119882cSPaolo Bonzini static inline void bdrv_dirty_bitmaps_unlock(BlockDriverState *bs)
722119882cSPaolo Bonzini {
732119882cSPaolo Bonzini     qemu_mutex_unlock(&bs->dirty_bitmap_mutex);
742119882cSPaolo Bonzini }
752119882cSPaolo Bonzini 
76b64bd51eSPaolo Bonzini void bdrv_dirty_bitmap_lock(BdrvDirtyBitmap *bitmap)
77b64bd51eSPaolo Bonzini {
78b64bd51eSPaolo Bonzini     qemu_mutex_lock(bitmap->mutex);
79b64bd51eSPaolo Bonzini }
80b64bd51eSPaolo Bonzini 
81b64bd51eSPaolo Bonzini void bdrv_dirty_bitmap_unlock(BdrvDirtyBitmap *bitmap)
82b64bd51eSPaolo Bonzini {
83b64bd51eSPaolo Bonzini     qemu_mutex_unlock(bitmap->mutex);
84b64bd51eSPaolo Bonzini }
85b64bd51eSPaolo Bonzini 
862119882cSPaolo Bonzini /* Called with BQL or dirty_bitmap lock taken.  */
87ebab2259SFam Zheng BdrvDirtyBitmap *bdrv_find_dirty_bitmap(BlockDriverState *bs, const char *name)
88ebab2259SFam Zheng {
89ebab2259SFam Zheng     BdrvDirtyBitmap *bm;
90ebab2259SFam Zheng 
91ebab2259SFam Zheng     assert(name);
92ebab2259SFam Zheng     QLIST_FOREACH(bm, &bs->dirty_bitmaps, list) {
93ebab2259SFam Zheng         if (bm->name && !strcmp(name, bm->name)) {
94ebab2259SFam Zheng             return bm;
95ebab2259SFam Zheng         }
96ebab2259SFam Zheng     }
97ebab2259SFam Zheng     return NULL;
98ebab2259SFam Zheng }
99ebab2259SFam Zheng 
1002119882cSPaolo Bonzini /* Called with BQL taken.  */
101ebab2259SFam Zheng void bdrv_dirty_bitmap_make_anon(BdrvDirtyBitmap *bitmap)
102ebab2259SFam Zheng {
103ebab2259SFam Zheng     assert(!bdrv_dirty_bitmap_frozen(bitmap));
104ebab2259SFam Zheng     g_free(bitmap->name);
105ebab2259SFam Zheng     bitmap->name = NULL;
106a88b179fSVladimir Sementsov-Ogievskiy     bitmap->persistent = false;
107a0319aacSVladimir Sementsov-Ogievskiy     bitmap->autoload = false;
108ebab2259SFam Zheng }
109ebab2259SFam Zheng 
1102119882cSPaolo Bonzini /* Called with BQL taken.  */
111ebab2259SFam Zheng BdrvDirtyBitmap *bdrv_create_dirty_bitmap(BlockDriverState *bs,
112ebab2259SFam Zheng                                           uint32_t granularity,
113ebab2259SFam Zheng                                           const char *name,
114ebab2259SFam Zheng                                           Error **errp)
115ebab2259SFam Zheng {
116ebab2259SFam Zheng     int64_t bitmap_size;
117ebab2259SFam Zheng     BdrvDirtyBitmap *bitmap;
118ebab2259SFam Zheng 
119993e6525SEric Blake     assert(is_power_of_2(granularity) && granularity >= BDRV_SECTOR_SIZE);
120ebab2259SFam Zheng 
121ebab2259SFam Zheng     if (name && bdrv_find_dirty_bitmap(bs, name)) {
122ebab2259SFam Zheng         error_setg(errp, "Bitmap already exists: %s", name);
123ebab2259SFam Zheng         return NULL;
124ebab2259SFam Zheng     }
125993e6525SEric Blake     bitmap_size = bdrv_getlength(bs);
126ebab2259SFam Zheng     if (bitmap_size < 0) {
127ebab2259SFam Zheng         error_setg_errno(errp, -bitmap_size, "could not get length of device");
128ebab2259SFam Zheng         errno = -bitmap_size;
129ebab2259SFam Zheng         return NULL;
130ebab2259SFam Zheng     }
131ebab2259SFam Zheng     bitmap = g_new0(BdrvDirtyBitmap, 1);
132b64bd51eSPaolo Bonzini     bitmap->mutex = &bs->dirty_bitmap_mutex;
133*ca759622SEric Blake     bitmap->bitmap = hbitmap_alloc(bitmap_size, ctz32(granularity));
134ebab2259SFam Zheng     bitmap->size = bitmap_size;
135ebab2259SFam Zheng     bitmap->name = g_strdup(name);
136ebab2259SFam Zheng     bitmap->disabled = false;
1372119882cSPaolo Bonzini     bdrv_dirty_bitmaps_lock(bs);
138ebab2259SFam Zheng     QLIST_INSERT_HEAD(&bs->dirty_bitmaps, bitmap, list);
1392119882cSPaolo Bonzini     bdrv_dirty_bitmaps_unlock(bs);
140ebab2259SFam Zheng     return bitmap;
141ebab2259SFam Zheng }
142ebab2259SFam Zheng 
143fb933437SFam Zheng /* bdrv_create_meta_dirty_bitmap
144fb933437SFam Zheng  *
145fb933437SFam Zheng  * Create a meta dirty bitmap that tracks the changes of bits in @bitmap. I.e.
146fb933437SFam Zheng  * when a dirty status bit in @bitmap is changed (either from reset to set or
147fb933437SFam Zheng  * the other way around), its respective meta dirty bitmap bit will be marked
148fb933437SFam Zheng  * dirty as well.
149fb933437SFam Zheng  *
150fb933437SFam Zheng  * @bitmap: the block dirty bitmap for which to create a meta dirty bitmap.
151fb933437SFam Zheng  * @chunk_size: how many bytes of bitmap data does each bit in the meta bitmap
152fb933437SFam Zheng  * track.
153fb933437SFam Zheng  */
154fb933437SFam Zheng void bdrv_create_meta_dirty_bitmap(BdrvDirtyBitmap *bitmap,
155fb933437SFam Zheng                                    int chunk_size)
156fb933437SFam Zheng {
157fb933437SFam Zheng     assert(!bitmap->meta);
158b64bd51eSPaolo Bonzini     qemu_mutex_lock(bitmap->mutex);
159fb933437SFam Zheng     bitmap->meta = hbitmap_create_meta(bitmap->bitmap,
160fb933437SFam Zheng                                        chunk_size * BITS_PER_BYTE);
161b64bd51eSPaolo Bonzini     qemu_mutex_unlock(bitmap->mutex);
162fb933437SFam Zheng }
163fb933437SFam Zheng 
164fb933437SFam Zheng void bdrv_release_meta_dirty_bitmap(BdrvDirtyBitmap *bitmap)
165fb933437SFam Zheng {
166fb933437SFam Zheng     assert(bitmap->meta);
167b64bd51eSPaolo Bonzini     qemu_mutex_lock(bitmap->mutex);
168fb933437SFam Zheng     hbitmap_free_meta(bitmap->bitmap);
169fb933437SFam Zheng     bitmap->meta = NULL;
170b64bd51eSPaolo Bonzini     qemu_mutex_unlock(bitmap->mutex);
171fb933437SFam Zheng }
172fb933437SFam Zheng 
17315891facSFam Zheng int64_t bdrv_dirty_bitmap_size(const BdrvDirtyBitmap *bitmap)
17415891facSFam Zheng {
175993e6525SEric Blake     return bitmap->size;
17615891facSFam Zheng }
17715891facSFam Zheng 
17815891facSFam Zheng const char *bdrv_dirty_bitmap_name(const BdrvDirtyBitmap *bitmap)
17915891facSFam Zheng {
18015891facSFam Zheng     return bitmap->name;
18115891facSFam Zheng }
18215891facSFam Zheng 
1832119882cSPaolo Bonzini /* Called with BQL taken.  */
184ebab2259SFam Zheng bool bdrv_dirty_bitmap_frozen(BdrvDirtyBitmap *bitmap)
185ebab2259SFam Zheng {
186ebab2259SFam Zheng     return bitmap->successor;
187ebab2259SFam Zheng }
188ebab2259SFam Zheng 
1892119882cSPaolo Bonzini /* Called with BQL taken.  */
190ebab2259SFam Zheng bool bdrv_dirty_bitmap_enabled(BdrvDirtyBitmap *bitmap)
191ebab2259SFam Zheng {
192ebab2259SFam Zheng     return !(bitmap->disabled || bitmap->successor);
193ebab2259SFam Zheng }
194ebab2259SFam Zheng 
1952119882cSPaolo Bonzini /* Called with BQL taken.  */
196ebab2259SFam Zheng DirtyBitmapStatus bdrv_dirty_bitmap_status(BdrvDirtyBitmap *bitmap)
197ebab2259SFam Zheng {
198ebab2259SFam Zheng     if (bdrv_dirty_bitmap_frozen(bitmap)) {
199ebab2259SFam Zheng         return DIRTY_BITMAP_STATUS_FROZEN;
200ebab2259SFam Zheng     } else if (!bdrv_dirty_bitmap_enabled(bitmap)) {
201ebab2259SFam Zheng         return DIRTY_BITMAP_STATUS_DISABLED;
202ebab2259SFam Zheng     } else {
203ebab2259SFam Zheng         return DIRTY_BITMAP_STATUS_ACTIVE;
204ebab2259SFam Zheng     }
205ebab2259SFam Zheng }
206ebab2259SFam Zheng 
207ebab2259SFam Zheng /**
208ebab2259SFam Zheng  * Create a successor bitmap destined to replace this bitmap after an operation.
209ebab2259SFam Zheng  * Requires that the bitmap is not frozen and has no successor.
2102119882cSPaolo Bonzini  * Called with BQL taken.
211ebab2259SFam Zheng  */
212ebab2259SFam Zheng int bdrv_dirty_bitmap_create_successor(BlockDriverState *bs,
213ebab2259SFam Zheng                                        BdrvDirtyBitmap *bitmap, Error **errp)
214ebab2259SFam Zheng {
215ebab2259SFam Zheng     uint64_t granularity;
216ebab2259SFam Zheng     BdrvDirtyBitmap *child;
217ebab2259SFam Zheng 
218ebab2259SFam Zheng     if (bdrv_dirty_bitmap_frozen(bitmap)) {
219ebab2259SFam Zheng         error_setg(errp, "Cannot create a successor for a bitmap that is "
220ebab2259SFam Zheng                    "currently frozen");
221ebab2259SFam Zheng         return -1;
222ebab2259SFam Zheng     }
223ebab2259SFam Zheng     assert(!bitmap->successor);
224ebab2259SFam Zheng 
225ebab2259SFam Zheng     /* Create an anonymous successor */
226ebab2259SFam Zheng     granularity = bdrv_dirty_bitmap_granularity(bitmap);
227ebab2259SFam Zheng     child = bdrv_create_dirty_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;
234ebab2259SFam Zheng 
235ebab2259SFam Zheng     /* Install the successor and freeze the parent */
236ebab2259SFam Zheng     bitmap->successor = child;
237ebab2259SFam Zheng     return 0;
238ebab2259SFam Zheng }
239ebab2259SFam Zheng 
240ebab2259SFam Zheng /**
241ebab2259SFam Zheng  * For a bitmap with a successor, yield our name to the successor,
242ebab2259SFam Zheng  * delete the old bitmap, and return a handle to the new bitmap.
2432119882cSPaolo Bonzini  * Called with BQL taken.
244ebab2259SFam Zheng  */
245ebab2259SFam Zheng BdrvDirtyBitmap *bdrv_dirty_bitmap_abdicate(BlockDriverState *bs,
246ebab2259SFam Zheng                                             BdrvDirtyBitmap *bitmap,
247ebab2259SFam Zheng                                             Error **errp)
248ebab2259SFam Zheng {
249ebab2259SFam Zheng     char *name;
250ebab2259SFam Zheng     BdrvDirtyBitmap *successor = bitmap->successor;
251ebab2259SFam Zheng 
252ebab2259SFam Zheng     if (successor == NULL) {
253ebab2259SFam Zheng         error_setg(errp, "Cannot relinquish control if "
254ebab2259SFam Zheng                    "there's no successor present");
255ebab2259SFam Zheng         return NULL;
256ebab2259SFam Zheng     }
257ebab2259SFam Zheng 
258ebab2259SFam Zheng     name = bitmap->name;
259ebab2259SFam Zheng     bitmap->name = NULL;
260ebab2259SFam Zheng     successor->name = name;
261ebab2259SFam Zheng     bitmap->successor = NULL;
262a88b179fSVladimir Sementsov-Ogievskiy     successor->persistent = bitmap->persistent;
263a88b179fSVladimir Sementsov-Ogievskiy     bitmap->persistent = false;
264a0319aacSVladimir Sementsov-Ogievskiy     successor->autoload = bitmap->autoload;
265a0319aacSVladimir Sementsov-Ogievskiy     bitmap->autoload = false;
266ebab2259SFam Zheng     bdrv_release_dirty_bitmap(bs, bitmap);
267ebab2259SFam Zheng 
268ebab2259SFam Zheng     return successor;
269ebab2259SFam Zheng }
270ebab2259SFam Zheng 
271ebab2259SFam Zheng /**
272ebab2259SFam Zheng  * In cases of failure where we can no longer safely delete the parent,
273ebab2259SFam Zheng  * we may wish to re-join the parent and child/successor.
274ebab2259SFam Zheng  * The merged parent will be un-frozen, but not explicitly re-enabled.
2752119882cSPaolo Bonzini  * Called with BQL taken.
276ebab2259SFam Zheng  */
277ebab2259SFam Zheng BdrvDirtyBitmap *bdrv_reclaim_dirty_bitmap(BlockDriverState *bs,
278ebab2259SFam Zheng                                            BdrvDirtyBitmap *parent,
279ebab2259SFam Zheng                                            Error **errp)
280ebab2259SFam Zheng {
281ebab2259SFam Zheng     BdrvDirtyBitmap *successor = parent->successor;
282ebab2259SFam Zheng 
283ebab2259SFam Zheng     if (!successor) {
284ebab2259SFam Zheng         error_setg(errp, "Cannot reclaim a successor when none is present");
285ebab2259SFam Zheng         return NULL;
286ebab2259SFam Zheng     }
287ebab2259SFam Zheng 
288ebab2259SFam Zheng     if (!hbitmap_merge(parent->bitmap, successor->bitmap)) {
289ebab2259SFam Zheng         error_setg(errp, "Merging of parent and successor bitmap failed");
290ebab2259SFam Zheng         return NULL;
291ebab2259SFam Zheng     }
292ebab2259SFam Zheng     bdrv_release_dirty_bitmap(bs, successor);
293ebab2259SFam Zheng     parent->successor = NULL;
294ebab2259SFam Zheng 
295ebab2259SFam Zheng     return parent;
296ebab2259SFam Zheng }
297ebab2259SFam Zheng 
298ebab2259SFam Zheng /**
299ebab2259SFam Zheng  * Truncates _all_ bitmaps attached to a BDS.
3002119882cSPaolo Bonzini  * Called with BQL taken.
301ebab2259SFam Zheng  */
3021b6cc579SEric Blake void bdrv_dirty_bitmap_truncate(BlockDriverState *bs, int64_t bytes)
303ebab2259SFam Zheng {
304ebab2259SFam Zheng     BdrvDirtyBitmap *bitmap;
305ebab2259SFam Zheng 
3062119882cSPaolo Bonzini     bdrv_dirty_bitmaps_lock(bs);
307ebab2259SFam Zheng     QLIST_FOREACH(bitmap, &bs->dirty_bitmaps, list) {
308ebab2259SFam Zheng         assert(!bdrv_dirty_bitmap_frozen(bitmap));
309dc162c8eSFam Zheng         assert(!bitmap->active_iterators);
310*ca759622SEric Blake         hbitmap_truncate(bitmap->bitmap, bytes);
311993e6525SEric Blake         bitmap->size = bytes;
312ebab2259SFam Zheng     }
3132119882cSPaolo Bonzini     bdrv_dirty_bitmaps_unlock(bs);
314ebab2259SFam Zheng }
315ebab2259SFam Zheng 
316615b5dcfSVladimir Sementsov-Ogievskiy static bool bdrv_dirty_bitmap_has_name(BdrvDirtyBitmap *bitmap)
317615b5dcfSVladimir Sementsov-Ogievskiy {
318615b5dcfSVladimir Sementsov-Ogievskiy     return !!bdrv_dirty_bitmap_name(bitmap);
319615b5dcfSVladimir Sementsov-Ogievskiy }
320615b5dcfSVladimir Sementsov-Ogievskiy 
3212119882cSPaolo Bonzini /* Called with BQL taken.  */
322615b5dcfSVladimir Sementsov-Ogievskiy static void bdrv_do_release_matching_dirty_bitmap(
323615b5dcfSVladimir Sementsov-Ogievskiy     BlockDriverState *bs, BdrvDirtyBitmap *bitmap,
324615b5dcfSVladimir Sementsov-Ogievskiy     bool (*cond)(BdrvDirtyBitmap *bitmap))
325ebab2259SFam Zheng {
326ebab2259SFam Zheng     BdrvDirtyBitmap *bm, *next;
3272119882cSPaolo Bonzini     bdrv_dirty_bitmaps_lock(bs);
328ebab2259SFam Zheng     QLIST_FOREACH_SAFE(bm, &bs->dirty_bitmaps, list, next) {
329615b5dcfSVladimir Sementsov-Ogievskiy         if ((!bitmap || bm == bitmap) && (!cond || cond(bm))) {
330dc162c8eSFam Zheng             assert(!bm->active_iterators);
331ebab2259SFam Zheng             assert(!bdrv_dirty_bitmap_frozen(bm));
332fb933437SFam Zheng             assert(!bm->meta);
333ebab2259SFam Zheng             QLIST_REMOVE(bm, list);
334ebab2259SFam Zheng             hbitmap_free(bm->bitmap);
335ebab2259SFam Zheng             g_free(bm->name);
336ebab2259SFam Zheng             g_free(bm);
337ebab2259SFam Zheng 
338ebab2259SFam Zheng             if (bitmap) {
3392119882cSPaolo Bonzini                 goto out;
340ebab2259SFam Zheng             }
341ebab2259SFam Zheng         }
342ebab2259SFam Zheng     }
3437105007aSFam Zheng     if (bitmap) {
3447105007aSFam Zheng         abort();
3457105007aSFam Zheng     }
3462119882cSPaolo Bonzini 
3472119882cSPaolo Bonzini out:
3482119882cSPaolo Bonzini     bdrv_dirty_bitmaps_unlock(bs);
349ebab2259SFam Zheng }
350ebab2259SFam Zheng 
3512119882cSPaolo Bonzini /* Called with BQL taken.  */
352ebab2259SFam Zheng void bdrv_release_dirty_bitmap(BlockDriverState *bs, BdrvDirtyBitmap *bitmap)
353ebab2259SFam Zheng {
354615b5dcfSVladimir Sementsov-Ogievskiy     bdrv_do_release_matching_dirty_bitmap(bs, bitmap, NULL);
355ebab2259SFam Zheng }
356ebab2259SFam Zheng 
357ebab2259SFam Zheng /**
358ebab2259SFam Zheng  * Release all named dirty bitmaps attached to a BDS (for use in bdrv_close()).
359ebab2259SFam Zheng  * There must not be any frozen bitmaps attached.
36056f364e6SVladimir Sementsov-Ogievskiy  * This function does not remove persistent bitmaps from the storage.
3612119882cSPaolo Bonzini  * Called with BQL taken.
362ebab2259SFam Zheng  */
363ebab2259SFam Zheng void bdrv_release_named_dirty_bitmaps(BlockDriverState *bs)
364ebab2259SFam Zheng {
365615b5dcfSVladimir Sementsov-Ogievskiy     bdrv_do_release_matching_dirty_bitmap(bs, NULL, bdrv_dirty_bitmap_has_name);
366615b5dcfSVladimir Sementsov-Ogievskiy }
367615b5dcfSVladimir Sementsov-Ogievskiy 
368615b5dcfSVladimir Sementsov-Ogievskiy /**
369615b5dcfSVladimir Sementsov-Ogievskiy  * Release all persistent dirty bitmaps attached to a BDS (for use in
370615b5dcfSVladimir Sementsov-Ogievskiy  * bdrv_inactivate_recurse()).
371615b5dcfSVladimir Sementsov-Ogievskiy  * There must not be any frozen bitmaps attached.
372615b5dcfSVladimir Sementsov-Ogievskiy  * This function does not remove persistent bitmaps from the storage.
373615b5dcfSVladimir Sementsov-Ogievskiy  */
374615b5dcfSVladimir Sementsov-Ogievskiy void bdrv_release_persistent_dirty_bitmaps(BlockDriverState *bs)
375615b5dcfSVladimir Sementsov-Ogievskiy {
376615b5dcfSVladimir Sementsov-Ogievskiy     bdrv_do_release_matching_dirty_bitmap(bs, NULL,
377615b5dcfSVladimir Sementsov-Ogievskiy                                           bdrv_dirty_bitmap_get_persistance);
378ebab2259SFam Zheng }
379ebab2259SFam Zheng 
38056f364e6SVladimir Sementsov-Ogievskiy /**
38156f364e6SVladimir Sementsov-Ogievskiy  * Remove persistent dirty bitmap from the storage if it exists.
38256f364e6SVladimir Sementsov-Ogievskiy  * Absence of bitmap is not an error, because we have the following scenario:
38356f364e6SVladimir Sementsov-Ogievskiy  * BdrvDirtyBitmap can have .persistent = true but not yet saved and have no
38456f364e6SVladimir Sementsov-Ogievskiy  * stored version. For such bitmap bdrv_remove_persistent_dirty_bitmap() should
38556f364e6SVladimir Sementsov-Ogievskiy  * not fail.
38656f364e6SVladimir Sementsov-Ogievskiy  * This function doesn't release corresponding BdrvDirtyBitmap.
38756f364e6SVladimir Sementsov-Ogievskiy  */
38856f364e6SVladimir Sementsov-Ogievskiy void bdrv_remove_persistent_dirty_bitmap(BlockDriverState *bs,
38956f364e6SVladimir Sementsov-Ogievskiy                                          const char *name,
39056f364e6SVladimir Sementsov-Ogievskiy                                          Error **errp)
39156f364e6SVladimir Sementsov-Ogievskiy {
39256f364e6SVladimir Sementsov-Ogievskiy     if (bs->drv && bs->drv->bdrv_remove_persistent_dirty_bitmap) {
39356f364e6SVladimir Sementsov-Ogievskiy         bs->drv->bdrv_remove_persistent_dirty_bitmap(bs, name, errp);
39456f364e6SVladimir Sementsov-Ogievskiy     }
39556f364e6SVladimir Sementsov-Ogievskiy }
39656f364e6SVladimir Sementsov-Ogievskiy 
3972119882cSPaolo Bonzini /* Called with BQL taken.  */
398ebab2259SFam Zheng void bdrv_disable_dirty_bitmap(BdrvDirtyBitmap *bitmap)
399ebab2259SFam Zheng {
400ebab2259SFam Zheng     assert(!bdrv_dirty_bitmap_frozen(bitmap));
401ebab2259SFam Zheng     bitmap->disabled = true;
402ebab2259SFam Zheng }
403ebab2259SFam Zheng 
4042119882cSPaolo Bonzini /* Called with BQL taken.  */
405ebab2259SFam Zheng void bdrv_enable_dirty_bitmap(BdrvDirtyBitmap *bitmap)
406ebab2259SFam Zheng {
407ebab2259SFam Zheng     assert(!bdrv_dirty_bitmap_frozen(bitmap));
408ebab2259SFam Zheng     bitmap->disabled = false;
409ebab2259SFam Zheng }
410ebab2259SFam Zheng 
411ebab2259SFam Zheng BlockDirtyInfoList *bdrv_query_dirty_bitmaps(BlockDriverState *bs)
412ebab2259SFam Zheng {
413ebab2259SFam Zheng     BdrvDirtyBitmap *bm;
414ebab2259SFam Zheng     BlockDirtyInfoList *list = NULL;
415ebab2259SFam Zheng     BlockDirtyInfoList **plist = &list;
416ebab2259SFam Zheng 
4172119882cSPaolo Bonzini     bdrv_dirty_bitmaps_lock(bs);
418ebab2259SFam Zheng     QLIST_FOREACH(bm, &bs->dirty_bitmaps, list) {
419ebab2259SFam Zheng         BlockDirtyInfo *info = g_new0(BlockDirtyInfo, 1);
420ebab2259SFam Zheng         BlockDirtyInfoList *entry = g_new0(BlockDirtyInfoList, 1);
4219a46dba7SEric Blake         info->count = bdrv_get_dirty_count(bm);
422ebab2259SFam Zheng         info->granularity = bdrv_dirty_bitmap_granularity(bm);
423ebab2259SFam Zheng         info->has_name = !!bm->name;
424ebab2259SFam Zheng         info->name = g_strdup(bm->name);
425ebab2259SFam Zheng         info->status = bdrv_dirty_bitmap_status(bm);
426ebab2259SFam Zheng         entry->value = info;
427ebab2259SFam Zheng         *plist = entry;
428ebab2259SFam Zheng         plist = &entry->next;
429ebab2259SFam Zheng     }
4302119882cSPaolo Bonzini     bdrv_dirty_bitmaps_unlock(bs);
431ebab2259SFam Zheng 
432ebab2259SFam Zheng     return list;
433ebab2259SFam Zheng }
434ebab2259SFam Zheng 
435b64bd51eSPaolo Bonzini /* Called within bdrv_dirty_bitmap_lock..unlock */
4363b5d4df0SEric Blake bool bdrv_get_dirty_locked(BlockDriverState *bs, BdrvDirtyBitmap *bitmap,
4373b5d4df0SEric Blake                            int64_t offset)
438ebab2259SFam Zheng {
439ebab2259SFam Zheng     if (bitmap) {
440*ca759622SEric Blake         return hbitmap_get(bitmap->bitmap, offset);
441ebab2259SFam Zheng     } else {
4423b5d4df0SEric Blake         return false;
443ebab2259SFam Zheng     }
444ebab2259SFam Zheng }
445ebab2259SFam Zheng 
446ebab2259SFam Zheng /**
447ebab2259SFam Zheng  * Chooses a default granularity based on the existing cluster size,
448ebab2259SFam Zheng  * but clamped between [4K, 64K]. Defaults to 64K in the case that there
449ebab2259SFam Zheng  * is no cluster size information available.
450ebab2259SFam Zheng  */
451ebab2259SFam Zheng uint32_t bdrv_get_default_bitmap_granularity(BlockDriverState *bs)
452ebab2259SFam Zheng {
453ebab2259SFam Zheng     BlockDriverInfo bdi;
454ebab2259SFam Zheng     uint32_t granularity;
455ebab2259SFam Zheng 
456ebab2259SFam Zheng     if (bdrv_get_info(bs, &bdi) >= 0 && bdi.cluster_size > 0) {
457ebab2259SFam Zheng         granularity = MAX(4096, bdi.cluster_size);
458ebab2259SFam Zheng         granularity = MIN(65536, granularity);
459ebab2259SFam Zheng     } else {
460ebab2259SFam Zheng         granularity = 65536;
461ebab2259SFam Zheng     }
462ebab2259SFam Zheng 
463ebab2259SFam Zheng     return granularity;
464ebab2259SFam Zheng }
465ebab2259SFam Zheng 
466ba06ff1aSVladimir Sementsov-Ogievskiy uint32_t bdrv_dirty_bitmap_granularity(const BdrvDirtyBitmap *bitmap)
467ebab2259SFam Zheng {
468*ca759622SEric Blake     return 1U << hbitmap_granularity(bitmap->bitmap);
469ebab2259SFam Zheng }
470ebab2259SFam Zheng 
471715a74d8SEric Blake BdrvDirtyBitmapIter *bdrv_dirty_iter_new(BdrvDirtyBitmap *bitmap)
472ebab2259SFam Zheng {
473dc162c8eSFam Zheng     BdrvDirtyBitmapIter *iter = g_new(BdrvDirtyBitmapIter, 1);
474715a74d8SEric Blake     hbitmap_iter_init(&iter->hbi, bitmap->bitmap, 0);
475dc162c8eSFam Zheng     iter->bitmap = bitmap;
476dc162c8eSFam Zheng     bitmap->active_iterators++;
477dc162c8eSFam Zheng     return iter;
478dc162c8eSFam Zheng }
479dc162c8eSFam Zheng 
4806d3f4049SFam Zheng BdrvDirtyBitmapIter *bdrv_dirty_meta_iter_new(BdrvDirtyBitmap *bitmap)
4816d3f4049SFam Zheng {
4826d3f4049SFam Zheng     BdrvDirtyBitmapIter *iter = g_new(BdrvDirtyBitmapIter, 1);
4836d3f4049SFam Zheng     hbitmap_iter_init(&iter->hbi, bitmap->meta, 0);
4846d3f4049SFam Zheng     iter->bitmap = bitmap;
4856d3f4049SFam Zheng     bitmap->active_iterators++;
4866d3f4049SFam Zheng     return iter;
4876d3f4049SFam Zheng }
4886d3f4049SFam Zheng 
489dc162c8eSFam Zheng void bdrv_dirty_iter_free(BdrvDirtyBitmapIter *iter)
490dc162c8eSFam Zheng {
491dc162c8eSFam Zheng     if (!iter) {
492dc162c8eSFam Zheng         return;
493dc162c8eSFam Zheng     }
494dc162c8eSFam Zheng     assert(iter->bitmap->active_iterators > 0);
495dc162c8eSFam Zheng     iter->bitmap->active_iterators--;
496dc162c8eSFam Zheng     g_free(iter);
497dc162c8eSFam Zheng }
498dc162c8eSFam Zheng 
499dc162c8eSFam Zheng int64_t bdrv_dirty_iter_next(BdrvDirtyBitmapIter *iter)
500dc162c8eSFam Zheng {
501*ca759622SEric Blake     return hbitmap_iter_next(&iter->hbi);
502ebab2259SFam Zheng }
503ebab2259SFam Zheng 
504b64bd51eSPaolo Bonzini /* Called within bdrv_dirty_bitmap_lock..unlock */
505b64bd51eSPaolo Bonzini void bdrv_set_dirty_bitmap_locked(BdrvDirtyBitmap *bitmap,
506e0d7f73eSEric Blake                                   int64_t offset, int64_t bytes)
507ebab2259SFam Zheng {
508ebab2259SFam Zheng     assert(bdrv_dirty_bitmap_enabled(bitmap));
509d6883bc9SVladimir Sementsov-Ogievskiy     assert(!bdrv_dirty_bitmap_readonly(bitmap));
510*ca759622SEric Blake     hbitmap_set(bitmap->bitmap, offset, bytes);
511ebab2259SFam Zheng }
512ebab2259SFam Zheng 
513b64bd51eSPaolo Bonzini void bdrv_set_dirty_bitmap(BdrvDirtyBitmap *bitmap,
514e0d7f73eSEric Blake                            int64_t offset, int64_t bytes)
515b64bd51eSPaolo Bonzini {
516b64bd51eSPaolo Bonzini     bdrv_dirty_bitmap_lock(bitmap);
517e0d7f73eSEric Blake     bdrv_set_dirty_bitmap_locked(bitmap, offset, bytes);
518b64bd51eSPaolo Bonzini     bdrv_dirty_bitmap_unlock(bitmap);
519b64bd51eSPaolo Bonzini }
520b64bd51eSPaolo Bonzini 
521b64bd51eSPaolo Bonzini /* Called within bdrv_dirty_bitmap_lock..unlock */
522b64bd51eSPaolo Bonzini void bdrv_reset_dirty_bitmap_locked(BdrvDirtyBitmap *bitmap,
523e0d7f73eSEric Blake                                     int64_t offset, int64_t bytes)
524ebab2259SFam Zheng {
525ebab2259SFam Zheng     assert(bdrv_dirty_bitmap_enabled(bitmap));
526d6883bc9SVladimir Sementsov-Ogievskiy     assert(!bdrv_dirty_bitmap_readonly(bitmap));
527*ca759622SEric Blake     hbitmap_reset(bitmap->bitmap, offset, bytes);
528ebab2259SFam Zheng }
529ebab2259SFam Zheng 
530b64bd51eSPaolo Bonzini void bdrv_reset_dirty_bitmap(BdrvDirtyBitmap *bitmap,
531e0d7f73eSEric Blake                              int64_t offset, int64_t bytes)
532b64bd51eSPaolo Bonzini {
533b64bd51eSPaolo Bonzini     bdrv_dirty_bitmap_lock(bitmap);
534e0d7f73eSEric Blake     bdrv_reset_dirty_bitmap_locked(bitmap, offset, bytes);
535b64bd51eSPaolo Bonzini     bdrv_dirty_bitmap_unlock(bitmap);
536b64bd51eSPaolo Bonzini }
537b64bd51eSPaolo Bonzini 
538ebab2259SFam Zheng void bdrv_clear_dirty_bitmap(BdrvDirtyBitmap *bitmap, HBitmap **out)
539ebab2259SFam Zheng {
540ebab2259SFam Zheng     assert(bdrv_dirty_bitmap_enabled(bitmap));
541d6883bc9SVladimir Sementsov-Ogievskiy     assert(!bdrv_dirty_bitmap_readonly(bitmap));
542b64bd51eSPaolo Bonzini     bdrv_dirty_bitmap_lock(bitmap);
543ebab2259SFam Zheng     if (!out) {
544ebab2259SFam Zheng         hbitmap_reset_all(bitmap->bitmap);
545ebab2259SFam Zheng     } else {
546ebab2259SFam Zheng         HBitmap *backup = bitmap->bitmap;
547*ca759622SEric Blake         bitmap->bitmap = hbitmap_alloc(bitmap->size,
548ebab2259SFam Zheng                                        hbitmap_granularity(backup));
549ebab2259SFam Zheng         *out = backup;
550ebab2259SFam Zheng     }
551b64bd51eSPaolo Bonzini     bdrv_dirty_bitmap_unlock(bitmap);
552ebab2259SFam Zheng }
553ebab2259SFam Zheng 
554ebab2259SFam Zheng void bdrv_undo_clear_dirty_bitmap(BdrvDirtyBitmap *bitmap, HBitmap *in)
555ebab2259SFam Zheng {
556ebab2259SFam Zheng     HBitmap *tmp = bitmap->bitmap;
557ebab2259SFam Zheng     assert(bdrv_dirty_bitmap_enabled(bitmap));
558d6883bc9SVladimir Sementsov-Ogievskiy     assert(!bdrv_dirty_bitmap_readonly(bitmap));
559ebab2259SFam Zheng     bitmap->bitmap = in;
560ebab2259SFam Zheng     hbitmap_free(tmp);
561ebab2259SFam Zheng }
562ebab2259SFam Zheng 
563882c36f5SVladimir Sementsov-Ogievskiy uint64_t bdrv_dirty_bitmap_serialization_size(const BdrvDirtyBitmap *bitmap,
56486f6ae67SEric Blake                                               uint64_t offset, uint64_t bytes)
565882c36f5SVladimir Sementsov-Ogievskiy {
566*ca759622SEric Blake     return hbitmap_serialization_size(bitmap->bitmap, offset, bytes);
567882c36f5SVladimir Sementsov-Ogievskiy }
568882c36f5SVladimir Sementsov-Ogievskiy 
569882c36f5SVladimir Sementsov-Ogievskiy uint64_t bdrv_dirty_bitmap_serialization_align(const BdrvDirtyBitmap *bitmap)
570882c36f5SVladimir Sementsov-Ogievskiy {
571*ca759622SEric Blake     return hbitmap_serialization_align(bitmap->bitmap);
572882c36f5SVladimir Sementsov-Ogievskiy }
573882c36f5SVladimir Sementsov-Ogievskiy 
574882c36f5SVladimir Sementsov-Ogievskiy void bdrv_dirty_bitmap_serialize_part(const BdrvDirtyBitmap *bitmap,
57586f6ae67SEric Blake                                       uint8_t *buf, uint64_t offset,
57686f6ae67SEric Blake                                       uint64_t bytes)
577882c36f5SVladimir Sementsov-Ogievskiy {
578*ca759622SEric Blake     hbitmap_serialize_part(bitmap->bitmap, buf, offset, bytes);
579882c36f5SVladimir Sementsov-Ogievskiy }
580882c36f5SVladimir Sementsov-Ogievskiy 
581882c36f5SVladimir Sementsov-Ogievskiy void bdrv_dirty_bitmap_deserialize_part(BdrvDirtyBitmap *bitmap,
58286f6ae67SEric Blake                                         uint8_t *buf, uint64_t offset,
58386f6ae67SEric Blake                                         uint64_t bytes, bool finish)
584882c36f5SVladimir Sementsov-Ogievskiy {
585*ca759622SEric Blake     hbitmap_deserialize_part(bitmap->bitmap, buf, offset, bytes, finish);
586882c36f5SVladimir Sementsov-Ogievskiy }
587882c36f5SVladimir Sementsov-Ogievskiy 
588882c36f5SVladimir Sementsov-Ogievskiy void bdrv_dirty_bitmap_deserialize_zeroes(BdrvDirtyBitmap *bitmap,
58986f6ae67SEric Blake                                           uint64_t offset, uint64_t bytes,
590882c36f5SVladimir Sementsov-Ogievskiy                                           bool finish)
591882c36f5SVladimir Sementsov-Ogievskiy {
592*ca759622SEric Blake     hbitmap_deserialize_zeroes(bitmap->bitmap, offset, bytes, finish);
593882c36f5SVladimir Sementsov-Ogievskiy }
594882c36f5SVladimir Sementsov-Ogievskiy 
5956bdc8b71SVladimir Sementsov-Ogievskiy void bdrv_dirty_bitmap_deserialize_ones(BdrvDirtyBitmap *bitmap,
59686f6ae67SEric Blake                                         uint64_t offset, uint64_t bytes,
5976bdc8b71SVladimir Sementsov-Ogievskiy                                         bool finish)
5986bdc8b71SVladimir Sementsov-Ogievskiy {
599*ca759622SEric Blake     hbitmap_deserialize_ones(bitmap->bitmap, offset, bytes, finish);
6006bdc8b71SVladimir Sementsov-Ogievskiy }
6016bdc8b71SVladimir Sementsov-Ogievskiy 
602882c36f5SVladimir Sementsov-Ogievskiy void bdrv_dirty_bitmap_deserialize_finish(BdrvDirtyBitmap *bitmap)
603882c36f5SVladimir Sementsov-Ogievskiy {
604882c36f5SVladimir Sementsov-Ogievskiy     hbitmap_deserialize_finish(bitmap->bitmap);
605882c36f5SVladimir Sementsov-Ogievskiy }
606882c36f5SVladimir Sementsov-Ogievskiy 
6070fdf1a4fSEric Blake void bdrv_set_dirty(BlockDriverState *bs, int64_t offset, int64_t bytes)
608ebab2259SFam Zheng {
609ebab2259SFam Zheng     BdrvDirtyBitmap *bitmap;
6102119882cSPaolo Bonzini 
6112119882cSPaolo Bonzini     if (QLIST_EMPTY(&bs->dirty_bitmaps)) {
6122119882cSPaolo Bonzini         return;
6132119882cSPaolo Bonzini     }
6142119882cSPaolo Bonzini 
6152119882cSPaolo Bonzini     bdrv_dirty_bitmaps_lock(bs);
616ebab2259SFam Zheng     QLIST_FOREACH(bitmap, &bs->dirty_bitmaps, list) {
617ebab2259SFam Zheng         if (!bdrv_dirty_bitmap_enabled(bitmap)) {
618ebab2259SFam Zheng             continue;
619ebab2259SFam Zheng         }
620d6883bc9SVladimir Sementsov-Ogievskiy         assert(!bdrv_dirty_bitmap_readonly(bitmap));
621*ca759622SEric Blake         hbitmap_set(bitmap->bitmap, offset, bytes);
622ebab2259SFam Zheng     }
6232119882cSPaolo Bonzini     bdrv_dirty_bitmaps_unlock(bs);
624ebab2259SFam Zheng }
625ebab2259SFam Zheng 
626ebab2259SFam Zheng /**
627dc162c8eSFam Zheng  * Advance a BdrvDirtyBitmapIter to an arbitrary offset.
628ebab2259SFam Zheng  */
629715a74d8SEric Blake void bdrv_set_dirty_iter(BdrvDirtyBitmapIter *iter, int64_t offset)
630ebab2259SFam Zheng {
631*ca759622SEric Blake     hbitmap_iter_init(&iter->hbi, iter->hbi.hb, offset);
632ebab2259SFam Zheng }
633ebab2259SFam Zheng 
634ebab2259SFam Zheng int64_t bdrv_get_dirty_count(BdrvDirtyBitmap *bitmap)
635ebab2259SFam Zheng {
636*ca759622SEric Blake     return hbitmap_count(bitmap->bitmap);
637ebab2259SFam Zheng }
6386d3f4049SFam Zheng 
6396d3f4049SFam Zheng int64_t bdrv_get_meta_dirty_count(BdrvDirtyBitmap *bitmap)
6406d3f4049SFam Zheng {
6416d3f4049SFam Zheng     return hbitmap_count(bitmap->meta);
6426d3f4049SFam Zheng }
643d6883bc9SVladimir Sementsov-Ogievskiy 
644d6883bc9SVladimir Sementsov-Ogievskiy bool bdrv_dirty_bitmap_readonly(const BdrvDirtyBitmap *bitmap)
645d6883bc9SVladimir Sementsov-Ogievskiy {
646d6883bc9SVladimir Sementsov-Ogievskiy     return bitmap->readonly;
647d6883bc9SVladimir Sementsov-Ogievskiy }
648d6883bc9SVladimir Sementsov-Ogievskiy 
649d6883bc9SVladimir Sementsov-Ogievskiy /* Called with BQL taken. */
650d6883bc9SVladimir Sementsov-Ogievskiy void bdrv_dirty_bitmap_set_readonly(BdrvDirtyBitmap *bitmap, bool value)
651d6883bc9SVladimir Sementsov-Ogievskiy {
652d6883bc9SVladimir Sementsov-Ogievskiy     qemu_mutex_lock(bitmap->mutex);
653d6883bc9SVladimir Sementsov-Ogievskiy     bitmap->readonly = value;
654d6883bc9SVladimir Sementsov-Ogievskiy     qemu_mutex_unlock(bitmap->mutex);
655d6883bc9SVladimir Sementsov-Ogievskiy }
656d6883bc9SVladimir Sementsov-Ogievskiy 
657d6883bc9SVladimir Sementsov-Ogievskiy bool bdrv_has_readonly_bitmaps(BlockDriverState *bs)
658d6883bc9SVladimir Sementsov-Ogievskiy {
659d6883bc9SVladimir Sementsov-Ogievskiy     BdrvDirtyBitmap *bm;
660d6883bc9SVladimir Sementsov-Ogievskiy     QLIST_FOREACH(bm, &bs->dirty_bitmaps, list) {
661d6883bc9SVladimir Sementsov-Ogievskiy         if (bm->readonly) {
662d6883bc9SVladimir Sementsov-Ogievskiy             return true;
663d6883bc9SVladimir Sementsov-Ogievskiy         }
664d6883bc9SVladimir Sementsov-Ogievskiy     }
665d6883bc9SVladimir Sementsov-Ogievskiy 
666d6883bc9SVladimir Sementsov-Ogievskiy     return false;
667d6883bc9SVladimir Sementsov-Ogievskiy }
668a0319aacSVladimir Sementsov-Ogievskiy 
669a0319aacSVladimir Sementsov-Ogievskiy /* Called with BQL taken. */
670a0319aacSVladimir Sementsov-Ogievskiy void bdrv_dirty_bitmap_set_autoload(BdrvDirtyBitmap *bitmap, bool autoload)
671a0319aacSVladimir Sementsov-Ogievskiy {
672a0319aacSVladimir Sementsov-Ogievskiy     qemu_mutex_lock(bitmap->mutex);
673a0319aacSVladimir Sementsov-Ogievskiy     bitmap->autoload = autoload;
674a0319aacSVladimir Sementsov-Ogievskiy     qemu_mutex_unlock(bitmap->mutex);
675a0319aacSVladimir Sementsov-Ogievskiy }
676a0319aacSVladimir Sementsov-Ogievskiy 
677a0319aacSVladimir Sementsov-Ogievskiy bool bdrv_dirty_bitmap_get_autoload(const BdrvDirtyBitmap *bitmap)
678a0319aacSVladimir Sementsov-Ogievskiy {
679a0319aacSVladimir Sementsov-Ogievskiy     return bitmap->autoload;
680a0319aacSVladimir Sementsov-Ogievskiy }
681a88b179fSVladimir Sementsov-Ogievskiy 
682a88b179fSVladimir Sementsov-Ogievskiy /* Called with BQL taken. */
683a88b179fSVladimir Sementsov-Ogievskiy void bdrv_dirty_bitmap_set_persistance(BdrvDirtyBitmap *bitmap, bool persistent)
684a88b179fSVladimir Sementsov-Ogievskiy {
685a88b179fSVladimir Sementsov-Ogievskiy     qemu_mutex_lock(bitmap->mutex);
686a88b179fSVladimir Sementsov-Ogievskiy     bitmap->persistent = persistent;
687a88b179fSVladimir Sementsov-Ogievskiy     qemu_mutex_unlock(bitmap->mutex);
688a88b179fSVladimir Sementsov-Ogievskiy }
689a88b179fSVladimir Sementsov-Ogievskiy 
690a88b179fSVladimir Sementsov-Ogievskiy bool bdrv_dirty_bitmap_get_persistance(BdrvDirtyBitmap *bitmap)
691a88b179fSVladimir Sementsov-Ogievskiy {
692a88b179fSVladimir Sementsov-Ogievskiy     return bitmap->persistent;
693a88b179fSVladimir Sementsov-Ogievskiy }
694a88b179fSVladimir Sementsov-Ogievskiy 
695a88b179fSVladimir Sementsov-Ogievskiy bool bdrv_has_changed_persistent_bitmaps(BlockDriverState *bs)
696a88b179fSVladimir Sementsov-Ogievskiy {
697a88b179fSVladimir Sementsov-Ogievskiy     BdrvDirtyBitmap *bm;
698a88b179fSVladimir Sementsov-Ogievskiy     QLIST_FOREACH(bm, &bs->dirty_bitmaps, list) {
699a88b179fSVladimir Sementsov-Ogievskiy         if (bm->persistent && !bm->readonly) {
700a88b179fSVladimir Sementsov-Ogievskiy             return true;
701a88b179fSVladimir Sementsov-Ogievskiy         }
702a88b179fSVladimir Sementsov-Ogievskiy     }
703a88b179fSVladimir Sementsov-Ogievskiy 
704a88b179fSVladimir Sementsov-Ogievskiy     return false;
705a88b179fSVladimir Sementsov-Ogievskiy }
7063dd10a06SVladimir Sementsov-Ogievskiy 
7073dd10a06SVladimir Sementsov-Ogievskiy BdrvDirtyBitmap *bdrv_dirty_bitmap_next(BlockDriverState *bs,
7083dd10a06SVladimir Sementsov-Ogievskiy                                         BdrvDirtyBitmap *bitmap)
7093dd10a06SVladimir Sementsov-Ogievskiy {
7103dd10a06SVladimir Sementsov-Ogievskiy     return bitmap == NULL ? QLIST_FIRST(&bs->dirty_bitmaps) :
7113dd10a06SVladimir Sementsov-Ogievskiy                             QLIST_NEXT(bitmap, list);
7123dd10a06SVladimir Sementsov-Ogievskiy }
713a3b52535SVladimir Sementsov-Ogievskiy 
714a3b52535SVladimir Sementsov-Ogievskiy char *bdrv_dirty_bitmap_sha256(const BdrvDirtyBitmap *bitmap, Error **errp)
715a3b52535SVladimir Sementsov-Ogievskiy {
716a3b52535SVladimir Sementsov-Ogievskiy     return hbitmap_sha256(bitmap->bitmap, errp);
717a3b52535SVladimir Sementsov-Ogievskiy }
718