xref: /qemu/block/dirty-bitmap.c (revision d6883bc9)
1ebab2259SFam Zheng /*
2ebab2259SFam Zheng  * Block Dirty Bitmap
3ebab2259SFam Zheng  *
4ebab2259SFam Zheng  * Copyright (c) 2016 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;
41ebab2259SFam Zheng     HBitmap *bitmap;            /* Dirty sector 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 */
45ebab2259SFam Zheng     int64_t size;               /* Size of the bitmap (Number of sectors) */
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 */
49*d6883bc9SVladimir Sementsov-Ogievskiy     bool readonly;              /* Bitmap is read-only. This field also
50*d6883bc9SVladimir Sementsov-Ogievskiy                                    prevents the respective image from being
51*d6883bc9SVladimir Sementsov-Ogievskiy                                    modified (i.e. blocks writes and discards).
52*d6883bc9SVladimir Sementsov-Ogievskiy                                    Such operations must fail and both the image
53*d6883bc9SVladimir Sementsov-Ogievskiy                                    and this bitmap must remain unchanged while
54*d6883bc9SVladimir Sementsov-Ogievskiy                                    this flag is set. */
55ebab2259SFam Zheng     QLIST_ENTRY(BdrvDirtyBitmap) list;
56ebab2259SFam Zheng };
57ebab2259SFam Zheng 
58dc162c8eSFam Zheng struct BdrvDirtyBitmapIter {
59dc162c8eSFam Zheng     HBitmapIter hbi;
60dc162c8eSFam Zheng     BdrvDirtyBitmap *bitmap;
61dc162c8eSFam Zheng };
62dc162c8eSFam Zheng 
632119882cSPaolo Bonzini static inline void bdrv_dirty_bitmaps_lock(BlockDriverState *bs)
642119882cSPaolo Bonzini {
652119882cSPaolo Bonzini     qemu_mutex_lock(&bs->dirty_bitmap_mutex);
662119882cSPaolo Bonzini }
672119882cSPaolo Bonzini 
682119882cSPaolo Bonzini static inline void bdrv_dirty_bitmaps_unlock(BlockDriverState *bs)
692119882cSPaolo Bonzini {
702119882cSPaolo Bonzini     qemu_mutex_unlock(&bs->dirty_bitmap_mutex);
712119882cSPaolo Bonzini }
722119882cSPaolo Bonzini 
73b64bd51eSPaolo Bonzini void bdrv_dirty_bitmap_lock(BdrvDirtyBitmap *bitmap)
74b64bd51eSPaolo Bonzini {
75b64bd51eSPaolo Bonzini     qemu_mutex_lock(bitmap->mutex);
76b64bd51eSPaolo Bonzini }
77b64bd51eSPaolo Bonzini 
78b64bd51eSPaolo Bonzini void bdrv_dirty_bitmap_unlock(BdrvDirtyBitmap *bitmap)
79b64bd51eSPaolo Bonzini {
80b64bd51eSPaolo Bonzini     qemu_mutex_unlock(bitmap->mutex);
81b64bd51eSPaolo Bonzini }
82b64bd51eSPaolo Bonzini 
832119882cSPaolo Bonzini /* Called with BQL or dirty_bitmap lock taken.  */
84ebab2259SFam Zheng BdrvDirtyBitmap *bdrv_find_dirty_bitmap(BlockDriverState *bs, const char *name)
85ebab2259SFam Zheng {
86ebab2259SFam Zheng     BdrvDirtyBitmap *bm;
87ebab2259SFam Zheng 
88ebab2259SFam Zheng     assert(name);
89ebab2259SFam Zheng     QLIST_FOREACH(bm, &bs->dirty_bitmaps, list) {
90ebab2259SFam Zheng         if (bm->name && !strcmp(name, bm->name)) {
91ebab2259SFam Zheng             return bm;
92ebab2259SFam Zheng         }
93ebab2259SFam Zheng     }
94ebab2259SFam Zheng     return NULL;
95ebab2259SFam Zheng }
96ebab2259SFam Zheng 
972119882cSPaolo Bonzini /* Called with BQL taken.  */
98ebab2259SFam Zheng void bdrv_dirty_bitmap_make_anon(BdrvDirtyBitmap *bitmap)
99ebab2259SFam Zheng {
100ebab2259SFam Zheng     assert(!bdrv_dirty_bitmap_frozen(bitmap));
101ebab2259SFam Zheng     g_free(bitmap->name);
102ebab2259SFam Zheng     bitmap->name = NULL;
103ebab2259SFam Zheng }
104ebab2259SFam Zheng 
1052119882cSPaolo Bonzini /* Called with BQL taken.  */
106ebab2259SFam Zheng BdrvDirtyBitmap *bdrv_create_dirty_bitmap(BlockDriverState *bs,
107ebab2259SFam Zheng                                           uint32_t granularity,
108ebab2259SFam Zheng                                           const char *name,
109ebab2259SFam Zheng                                           Error **errp)
110ebab2259SFam Zheng {
111ebab2259SFam Zheng     int64_t bitmap_size;
112ebab2259SFam Zheng     BdrvDirtyBitmap *bitmap;
113ebab2259SFam Zheng     uint32_t sector_granularity;
114ebab2259SFam Zheng 
115ebab2259SFam Zheng     assert((granularity & (granularity - 1)) == 0);
116ebab2259SFam Zheng 
117ebab2259SFam Zheng     if (name && bdrv_find_dirty_bitmap(bs, name)) {
118ebab2259SFam Zheng         error_setg(errp, "Bitmap already exists: %s", name);
119ebab2259SFam Zheng         return NULL;
120ebab2259SFam Zheng     }
121ebab2259SFam Zheng     sector_granularity = granularity >> BDRV_SECTOR_BITS;
122ebab2259SFam Zheng     assert(sector_granularity);
123ebab2259SFam Zheng     bitmap_size = bdrv_nb_sectors(bs);
124ebab2259SFam Zheng     if (bitmap_size < 0) {
125ebab2259SFam Zheng         error_setg_errno(errp, -bitmap_size, "could not get length of device");
126ebab2259SFam Zheng         errno = -bitmap_size;
127ebab2259SFam Zheng         return NULL;
128ebab2259SFam Zheng     }
129ebab2259SFam Zheng     bitmap = g_new0(BdrvDirtyBitmap, 1);
130b64bd51eSPaolo Bonzini     bitmap->mutex = &bs->dirty_bitmap_mutex;
131ebab2259SFam Zheng     bitmap->bitmap = hbitmap_alloc(bitmap_size, ctz32(sector_granularity));
132ebab2259SFam Zheng     bitmap->size = bitmap_size;
133ebab2259SFam Zheng     bitmap->name = g_strdup(name);
134ebab2259SFam Zheng     bitmap->disabled = false;
1352119882cSPaolo Bonzini     bdrv_dirty_bitmaps_lock(bs);
136ebab2259SFam Zheng     QLIST_INSERT_HEAD(&bs->dirty_bitmaps, bitmap, list);
1372119882cSPaolo Bonzini     bdrv_dirty_bitmaps_unlock(bs);
138ebab2259SFam Zheng     return bitmap;
139ebab2259SFam Zheng }
140ebab2259SFam Zheng 
141fb933437SFam Zheng /* bdrv_create_meta_dirty_bitmap
142fb933437SFam Zheng  *
143fb933437SFam Zheng  * Create a meta dirty bitmap that tracks the changes of bits in @bitmap. I.e.
144fb933437SFam Zheng  * when a dirty status bit in @bitmap is changed (either from reset to set or
145fb933437SFam Zheng  * the other way around), its respective meta dirty bitmap bit will be marked
146fb933437SFam Zheng  * dirty as well.
147fb933437SFam Zheng  *
148fb933437SFam Zheng  * @bitmap: the block dirty bitmap for which to create a meta dirty bitmap.
149fb933437SFam Zheng  * @chunk_size: how many bytes of bitmap data does each bit in the meta bitmap
150fb933437SFam Zheng  * track.
151fb933437SFam Zheng  */
152fb933437SFam Zheng void bdrv_create_meta_dirty_bitmap(BdrvDirtyBitmap *bitmap,
153fb933437SFam Zheng                                    int chunk_size)
154fb933437SFam Zheng {
155fb933437SFam Zheng     assert(!bitmap->meta);
156b64bd51eSPaolo Bonzini     qemu_mutex_lock(bitmap->mutex);
157fb933437SFam Zheng     bitmap->meta = hbitmap_create_meta(bitmap->bitmap,
158fb933437SFam Zheng                                        chunk_size * BITS_PER_BYTE);
159b64bd51eSPaolo Bonzini     qemu_mutex_unlock(bitmap->mutex);
160fb933437SFam Zheng }
161fb933437SFam Zheng 
162fb933437SFam Zheng void bdrv_release_meta_dirty_bitmap(BdrvDirtyBitmap *bitmap)
163fb933437SFam Zheng {
164fb933437SFam Zheng     assert(bitmap->meta);
165b64bd51eSPaolo Bonzini     qemu_mutex_lock(bitmap->mutex);
166fb933437SFam Zheng     hbitmap_free_meta(bitmap->bitmap);
167fb933437SFam Zheng     bitmap->meta = NULL;
168b64bd51eSPaolo Bonzini     qemu_mutex_unlock(bitmap->mutex);
169fb933437SFam Zheng }
170fb933437SFam Zheng 
171b64bd51eSPaolo Bonzini int bdrv_dirty_bitmap_get_meta_locked(BlockDriverState *bs,
172fb933437SFam Zheng                                       BdrvDirtyBitmap *bitmap, int64_t sector,
173fb933437SFam Zheng                                       int nb_sectors)
174fb933437SFam Zheng {
175fb933437SFam Zheng     uint64_t i;
176fb933437SFam Zheng     int sectors_per_bit = 1 << hbitmap_granularity(bitmap->meta);
177fb933437SFam Zheng 
178fb933437SFam Zheng     /* To optimize: we can make hbitmap to internally check the range in a
179fb933437SFam Zheng      * coarse level, or at least do it word by word. */
180fb933437SFam Zheng     for (i = sector; i < sector + nb_sectors; i += sectors_per_bit) {
181fb933437SFam Zheng         if (hbitmap_get(bitmap->meta, i)) {
182fb933437SFam Zheng             return true;
183fb933437SFam Zheng         }
184fb933437SFam Zheng     }
185fb933437SFam Zheng     return false;
186fb933437SFam Zheng }
187fb933437SFam Zheng 
188b64bd51eSPaolo Bonzini int bdrv_dirty_bitmap_get_meta(BlockDriverState *bs,
189b64bd51eSPaolo Bonzini                                BdrvDirtyBitmap *bitmap, int64_t sector,
190b64bd51eSPaolo Bonzini                                int nb_sectors)
191b64bd51eSPaolo Bonzini {
192b64bd51eSPaolo Bonzini     bool dirty;
193b64bd51eSPaolo Bonzini 
194b64bd51eSPaolo Bonzini     qemu_mutex_lock(bitmap->mutex);
195b64bd51eSPaolo Bonzini     dirty = bdrv_dirty_bitmap_get_meta_locked(bs, bitmap, sector, nb_sectors);
196b64bd51eSPaolo Bonzini     qemu_mutex_unlock(bitmap->mutex);
197b64bd51eSPaolo Bonzini 
198b64bd51eSPaolo Bonzini     return dirty;
199b64bd51eSPaolo Bonzini }
200b64bd51eSPaolo Bonzini 
201fb933437SFam Zheng void bdrv_dirty_bitmap_reset_meta(BlockDriverState *bs,
202fb933437SFam Zheng                                   BdrvDirtyBitmap *bitmap, int64_t sector,
203fb933437SFam Zheng                                   int nb_sectors)
204fb933437SFam Zheng {
205b64bd51eSPaolo Bonzini     qemu_mutex_lock(bitmap->mutex);
206fb933437SFam Zheng     hbitmap_reset(bitmap->meta, sector, nb_sectors);
207b64bd51eSPaolo Bonzini     qemu_mutex_unlock(bitmap->mutex);
208fb933437SFam Zheng }
209fb933437SFam Zheng 
21015891facSFam Zheng int64_t bdrv_dirty_bitmap_size(const BdrvDirtyBitmap *bitmap)
21115891facSFam Zheng {
21215891facSFam Zheng     return bitmap->size;
21315891facSFam Zheng }
21415891facSFam Zheng 
21515891facSFam Zheng const char *bdrv_dirty_bitmap_name(const BdrvDirtyBitmap *bitmap)
21615891facSFam Zheng {
21715891facSFam Zheng     return bitmap->name;
21815891facSFam Zheng }
21915891facSFam Zheng 
2202119882cSPaolo Bonzini /* Called with BQL taken.  */
221ebab2259SFam Zheng bool bdrv_dirty_bitmap_frozen(BdrvDirtyBitmap *bitmap)
222ebab2259SFam Zheng {
223ebab2259SFam Zheng     return bitmap->successor;
224ebab2259SFam Zheng }
225ebab2259SFam Zheng 
2262119882cSPaolo Bonzini /* Called with BQL taken.  */
227ebab2259SFam Zheng bool bdrv_dirty_bitmap_enabled(BdrvDirtyBitmap *bitmap)
228ebab2259SFam Zheng {
229ebab2259SFam Zheng     return !(bitmap->disabled || bitmap->successor);
230ebab2259SFam Zheng }
231ebab2259SFam Zheng 
2322119882cSPaolo Bonzini /* Called with BQL taken.  */
233ebab2259SFam Zheng DirtyBitmapStatus bdrv_dirty_bitmap_status(BdrvDirtyBitmap *bitmap)
234ebab2259SFam Zheng {
235ebab2259SFam Zheng     if (bdrv_dirty_bitmap_frozen(bitmap)) {
236ebab2259SFam Zheng         return DIRTY_BITMAP_STATUS_FROZEN;
237ebab2259SFam Zheng     } else if (!bdrv_dirty_bitmap_enabled(bitmap)) {
238ebab2259SFam Zheng         return DIRTY_BITMAP_STATUS_DISABLED;
239ebab2259SFam Zheng     } else {
240ebab2259SFam Zheng         return DIRTY_BITMAP_STATUS_ACTIVE;
241ebab2259SFam Zheng     }
242ebab2259SFam Zheng }
243ebab2259SFam Zheng 
244ebab2259SFam Zheng /**
245ebab2259SFam Zheng  * Create a successor bitmap destined to replace this bitmap after an operation.
246ebab2259SFam Zheng  * Requires that the bitmap is not frozen and has no successor.
2472119882cSPaolo Bonzini  * Called with BQL taken.
248ebab2259SFam Zheng  */
249ebab2259SFam Zheng int bdrv_dirty_bitmap_create_successor(BlockDriverState *bs,
250ebab2259SFam Zheng                                        BdrvDirtyBitmap *bitmap, Error **errp)
251ebab2259SFam Zheng {
252ebab2259SFam Zheng     uint64_t granularity;
253ebab2259SFam Zheng     BdrvDirtyBitmap *child;
254ebab2259SFam Zheng 
255ebab2259SFam Zheng     if (bdrv_dirty_bitmap_frozen(bitmap)) {
256ebab2259SFam Zheng         error_setg(errp, "Cannot create a successor for a bitmap that is "
257ebab2259SFam Zheng                    "currently frozen");
258ebab2259SFam Zheng         return -1;
259ebab2259SFam Zheng     }
260ebab2259SFam Zheng     assert(!bitmap->successor);
261ebab2259SFam Zheng 
262ebab2259SFam Zheng     /* Create an anonymous successor */
263ebab2259SFam Zheng     granularity = bdrv_dirty_bitmap_granularity(bitmap);
264ebab2259SFam Zheng     child = bdrv_create_dirty_bitmap(bs, granularity, NULL, errp);
265ebab2259SFam Zheng     if (!child) {
266ebab2259SFam Zheng         return -1;
267ebab2259SFam Zheng     }
268ebab2259SFam Zheng 
269ebab2259SFam Zheng     /* Successor will be on or off based on our current state. */
270ebab2259SFam Zheng     child->disabled = bitmap->disabled;
271ebab2259SFam Zheng 
272ebab2259SFam Zheng     /* Install the successor and freeze the parent */
273ebab2259SFam Zheng     bitmap->successor = child;
274ebab2259SFam Zheng     return 0;
275ebab2259SFam Zheng }
276ebab2259SFam Zheng 
277ebab2259SFam Zheng /**
278ebab2259SFam Zheng  * For a bitmap with a successor, yield our name to the successor,
279ebab2259SFam Zheng  * delete the old bitmap, and return a handle to the new bitmap.
2802119882cSPaolo Bonzini  * Called with BQL taken.
281ebab2259SFam Zheng  */
282ebab2259SFam Zheng BdrvDirtyBitmap *bdrv_dirty_bitmap_abdicate(BlockDriverState *bs,
283ebab2259SFam Zheng                                             BdrvDirtyBitmap *bitmap,
284ebab2259SFam Zheng                                             Error **errp)
285ebab2259SFam Zheng {
286ebab2259SFam Zheng     char *name;
287ebab2259SFam Zheng     BdrvDirtyBitmap *successor = bitmap->successor;
288ebab2259SFam Zheng 
289ebab2259SFam Zheng     if (successor == NULL) {
290ebab2259SFam Zheng         error_setg(errp, "Cannot relinquish control if "
291ebab2259SFam Zheng                    "there's no successor present");
292ebab2259SFam Zheng         return NULL;
293ebab2259SFam Zheng     }
294ebab2259SFam Zheng 
295ebab2259SFam Zheng     name = bitmap->name;
296ebab2259SFam Zheng     bitmap->name = NULL;
297ebab2259SFam Zheng     successor->name = name;
298ebab2259SFam Zheng     bitmap->successor = NULL;
299ebab2259SFam Zheng     bdrv_release_dirty_bitmap(bs, bitmap);
300ebab2259SFam Zheng 
301ebab2259SFam Zheng     return successor;
302ebab2259SFam Zheng }
303ebab2259SFam Zheng 
304ebab2259SFam Zheng /**
305ebab2259SFam Zheng  * In cases of failure where we can no longer safely delete the parent,
306ebab2259SFam Zheng  * we may wish to re-join the parent and child/successor.
307ebab2259SFam Zheng  * The merged parent will be un-frozen, but not explicitly re-enabled.
3082119882cSPaolo Bonzini  * Called with BQL taken.
309ebab2259SFam Zheng  */
310ebab2259SFam Zheng BdrvDirtyBitmap *bdrv_reclaim_dirty_bitmap(BlockDriverState *bs,
311ebab2259SFam Zheng                                            BdrvDirtyBitmap *parent,
312ebab2259SFam Zheng                                            Error **errp)
313ebab2259SFam Zheng {
314ebab2259SFam Zheng     BdrvDirtyBitmap *successor = parent->successor;
315ebab2259SFam Zheng 
316ebab2259SFam Zheng     if (!successor) {
317ebab2259SFam Zheng         error_setg(errp, "Cannot reclaim a successor when none is present");
318ebab2259SFam Zheng         return NULL;
319ebab2259SFam Zheng     }
320ebab2259SFam Zheng 
321ebab2259SFam Zheng     if (!hbitmap_merge(parent->bitmap, successor->bitmap)) {
322ebab2259SFam Zheng         error_setg(errp, "Merging of parent and successor bitmap failed");
323ebab2259SFam Zheng         return NULL;
324ebab2259SFam Zheng     }
325ebab2259SFam Zheng     bdrv_release_dirty_bitmap(bs, successor);
326ebab2259SFam Zheng     parent->successor = NULL;
327ebab2259SFam Zheng 
328ebab2259SFam Zheng     return parent;
329ebab2259SFam Zheng }
330ebab2259SFam Zheng 
331ebab2259SFam Zheng /**
332ebab2259SFam Zheng  * Truncates _all_ bitmaps attached to a BDS.
3332119882cSPaolo Bonzini  * Called with BQL taken.
334ebab2259SFam Zheng  */
335ebab2259SFam Zheng void bdrv_dirty_bitmap_truncate(BlockDriverState *bs)
336ebab2259SFam Zheng {
337ebab2259SFam Zheng     BdrvDirtyBitmap *bitmap;
338ebab2259SFam Zheng     uint64_t size = bdrv_nb_sectors(bs);
339ebab2259SFam Zheng 
3402119882cSPaolo Bonzini     bdrv_dirty_bitmaps_lock(bs);
341ebab2259SFam Zheng     QLIST_FOREACH(bitmap, &bs->dirty_bitmaps, list) {
342ebab2259SFam Zheng         assert(!bdrv_dirty_bitmap_frozen(bitmap));
343dc162c8eSFam Zheng         assert(!bitmap->active_iterators);
344ebab2259SFam Zheng         hbitmap_truncate(bitmap->bitmap, size);
345ebab2259SFam Zheng         bitmap->size = size;
346ebab2259SFam Zheng     }
3472119882cSPaolo Bonzini     bdrv_dirty_bitmaps_unlock(bs);
348ebab2259SFam Zheng }
349ebab2259SFam Zheng 
3502119882cSPaolo Bonzini /* Called with BQL taken.  */
351ebab2259SFam Zheng static void bdrv_do_release_matching_dirty_bitmap(BlockDriverState *bs,
352ebab2259SFam Zheng                                                   BdrvDirtyBitmap *bitmap,
353ebab2259SFam Zheng                                                   bool only_named)
354ebab2259SFam Zheng {
355ebab2259SFam Zheng     BdrvDirtyBitmap *bm, *next;
3562119882cSPaolo Bonzini     bdrv_dirty_bitmaps_lock(bs);
357ebab2259SFam Zheng     QLIST_FOREACH_SAFE(bm, &bs->dirty_bitmaps, list, next) {
358ebab2259SFam Zheng         if ((!bitmap || bm == bitmap) && (!only_named || bm->name)) {
359dc162c8eSFam Zheng             assert(!bm->active_iterators);
360ebab2259SFam Zheng             assert(!bdrv_dirty_bitmap_frozen(bm));
361fb933437SFam Zheng             assert(!bm->meta);
362ebab2259SFam Zheng             QLIST_REMOVE(bm, list);
363ebab2259SFam Zheng             hbitmap_free(bm->bitmap);
364ebab2259SFam Zheng             g_free(bm->name);
365ebab2259SFam Zheng             g_free(bm);
366ebab2259SFam Zheng 
367ebab2259SFam Zheng             if (bitmap) {
3682119882cSPaolo Bonzini                 goto out;
369ebab2259SFam Zheng             }
370ebab2259SFam Zheng         }
371ebab2259SFam Zheng     }
3727105007aSFam Zheng     if (bitmap) {
3737105007aSFam Zheng         abort();
3747105007aSFam Zheng     }
3752119882cSPaolo Bonzini 
3762119882cSPaolo Bonzini out:
3772119882cSPaolo Bonzini     bdrv_dirty_bitmaps_unlock(bs);
378ebab2259SFam Zheng }
379ebab2259SFam Zheng 
3802119882cSPaolo Bonzini /* Called with BQL taken.  */
381ebab2259SFam Zheng void bdrv_release_dirty_bitmap(BlockDriverState *bs, BdrvDirtyBitmap *bitmap)
382ebab2259SFam Zheng {
383ebab2259SFam Zheng     bdrv_do_release_matching_dirty_bitmap(bs, bitmap, false);
384ebab2259SFam Zheng }
385ebab2259SFam Zheng 
386ebab2259SFam Zheng /**
387ebab2259SFam Zheng  * Release all named dirty bitmaps attached to a BDS (for use in bdrv_close()).
388ebab2259SFam Zheng  * There must not be any frozen bitmaps attached.
3892119882cSPaolo Bonzini  * Called with BQL taken.
390ebab2259SFam Zheng  */
391ebab2259SFam Zheng void bdrv_release_named_dirty_bitmaps(BlockDriverState *bs)
392ebab2259SFam Zheng {
393ebab2259SFam Zheng     bdrv_do_release_matching_dirty_bitmap(bs, NULL, true);
394ebab2259SFam Zheng }
395ebab2259SFam Zheng 
3962119882cSPaolo Bonzini /* Called with BQL taken.  */
397ebab2259SFam Zheng void bdrv_disable_dirty_bitmap(BdrvDirtyBitmap *bitmap)
398ebab2259SFam Zheng {
399ebab2259SFam Zheng     assert(!bdrv_dirty_bitmap_frozen(bitmap));
400ebab2259SFam Zheng     bitmap->disabled = true;
401ebab2259SFam Zheng }
402ebab2259SFam Zheng 
4032119882cSPaolo Bonzini /* Called with BQL taken.  */
404ebab2259SFam Zheng void bdrv_enable_dirty_bitmap(BdrvDirtyBitmap *bitmap)
405ebab2259SFam Zheng {
406ebab2259SFam Zheng     assert(!bdrv_dirty_bitmap_frozen(bitmap));
407ebab2259SFam Zheng     bitmap->disabled = false;
408ebab2259SFam Zheng }
409ebab2259SFam Zheng 
410ebab2259SFam Zheng BlockDirtyInfoList *bdrv_query_dirty_bitmaps(BlockDriverState *bs)
411ebab2259SFam Zheng {
412ebab2259SFam Zheng     BdrvDirtyBitmap *bm;
413ebab2259SFam Zheng     BlockDirtyInfoList *list = NULL;
414ebab2259SFam Zheng     BlockDirtyInfoList **plist = &list;
415ebab2259SFam Zheng 
4162119882cSPaolo Bonzini     bdrv_dirty_bitmaps_lock(bs);
417ebab2259SFam Zheng     QLIST_FOREACH(bm, &bs->dirty_bitmaps, list) {
418ebab2259SFam Zheng         BlockDirtyInfo *info = g_new0(BlockDirtyInfo, 1);
419ebab2259SFam Zheng         BlockDirtyInfoList *entry = g_new0(BlockDirtyInfoList, 1);
420ebab2259SFam Zheng         info->count = bdrv_get_dirty_count(bm);
421ebab2259SFam Zheng         info->granularity = bdrv_dirty_bitmap_granularity(bm);
422ebab2259SFam Zheng         info->has_name = !!bm->name;
423ebab2259SFam Zheng         info->name = g_strdup(bm->name);
424ebab2259SFam Zheng         info->status = bdrv_dirty_bitmap_status(bm);
425ebab2259SFam Zheng         entry->value = info;
426ebab2259SFam Zheng         *plist = entry;
427ebab2259SFam Zheng         plist = &entry->next;
428ebab2259SFam Zheng     }
4292119882cSPaolo Bonzini     bdrv_dirty_bitmaps_unlock(bs);
430ebab2259SFam Zheng 
431ebab2259SFam Zheng     return list;
432ebab2259SFam Zheng }
433ebab2259SFam Zheng 
434b64bd51eSPaolo Bonzini /* Called within bdrv_dirty_bitmap_lock..unlock */
435b64bd51eSPaolo Bonzini int bdrv_get_dirty_locked(BlockDriverState *bs, BdrvDirtyBitmap *bitmap,
436ebab2259SFam Zheng                           int64_t sector)
437ebab2259SFam Zheng {
438ebab2259SFam Zheng     if (bitmap) {
439ebab2259SFam Zheng         return hbitmap_get(bitmap->bitmap, sector);
440ebab2259SFam Zheng     } else {
441ebab2259SFam Zheng         return 0;
442ebab2259SFam Zheng     }
443ebab2259SFam Zheng }
444ebab2259SFam Zheng 
445ebab2259SFam Zheng /**
446ebab2259SFam Zheng  * Chooses a default granularity based on the existing cluster size,
447ebab2259SFam Zheng  * but clamped between [4K, 64K]. Defaults to 64K in the case that there
448ebab2259SFam Zheng  * is no cluster size information available.
449ebab2259SFam Zheng  */
450ebab2259SFam Zheng uint32_t bdrv_get_default_bitmap_granularity(BlockDriverState *bs)
451ebab2259SFam Zheng {
452ebab2259SFam Zheng     BlockDriverInfo bdi;
453ebab2259SFam Zheng     uint32_t granularity;
454ebab2259SFam Zheng 
455ebab2259SFam Zheng     if (bdrv_get_info(bs, &bdi) >= 0 && bdi.cluster_size > 0) {
456ebab2259SFam Zheng         granularity = MAX(4096, bdi.cluster_size);
457ebab2259SFam Zheng         granularity = MIN(65536, granularity);
458ebab2259SFam Zheng     } else {
459ebab2259SFam Zheng         granularity = 65536;
460ebab2259SFam Zheng     }
461ebab2259SFam Zheng 
462ebab2259SFam Zheng     return granularity;
463ebab2259SFam Zheng }
464ebab2259SFam Zheng 
465ba06ff1aSVladimir Sementsov-Ogievskiy uint32_t bdrv_dirty_bitmap_granularity(const BdrvDirtyBitmap *bitmap)
466ebab2259SFam Zheng {
467ebab2259SFam Zheng     return BDRV_SECTOR_SIZE << hbitmap_granularity(bitmap->bitmap);
468ebab2259SFam Zheng }
469ebab2259SFam Zheng 
4706d3f4049SFam Zheng uint32_t bdrv_dirty_bitmap_meta_granularity(BdrvDirtyBitmap *bitmap)
4716d3f4049SFam Zheng {
4726d3f4049SFam Zheng     return BDRV_SECTOR_SIZE << hbitmap_granularity(bitmap->meta);
4736d3f4049SFam Zheng }
4746d3f4049SFam Zheng 
475dc162c8eSFam Zheng BdrvDirtyBitmapIter *bdrv_dirty_iter_new(BdrvDirtyBitmap *bitmap,
476dc162c8eSFam Zheng                                          uint64_t first_sector)
477ebab2259SFam Zheng {
478dc162c8eSFam Zheng     BdrvDirtyBitmapIter *iter = g_new(BdrvDirtyBitmapIter, 1);
479dc162c8eSFam Zheng     hbitmap_iter_init(&iter->hbi, bitmap->bitmap, first_sector);
480dc162c8eSFam Zheng     iter->bitmap = bitmap;
481dc162c8eSFam Zheng     bitmap->active_iterators++;
482dc162c8eSFam Zheng     return iter;
483dc162c8eSFam Zheng }
484dc162c8eSFam Zheng 
4856d3f4049SFam Zheng BdrvDirtyBitmapIter *bdrv_dirty_meta_iter_new(BdrvDirtyBitmap *bitmap)
4866d3f4049SFam Zheng {
4876d3f4049SFam Zheng     BdrvDirtyBitmapIter *iter = g_new(BdrvDirtyBitmapIter, 1);
4886d3f4049SFam Zheng     hbitmap_iter_init(&iter->hbi, bitmap->meta, 0);
4896d3f4049SFam Zheng     iter->bitmap = bitmap;
4906d3f4049SFam Zheng     bitmap->active_iterators++;
4916d3f4049SFam Zheng     return iter;
4926d3f4049SFam Zheng }
4936d3f4049SFam Zheng 
494dc162c8eSFam Zheng void bdrv_dirty_iter_free(BdrvDirtyBitmapIter *iter)
495dc162c8eSFam Zheng {
496dc162c8eSFam Zheng     if (!iter) {
497dc162c8eSFam Zheng         return;
498dc162c8eSFam Zheng     }
499dc162c8eSFam Zheng     assert(iter->bitmap->active_iterators > 0);
500dc162c8eSFam Zheng     iter->bitmap->active_iterators--;
501dc162c8eSFam Zheng     g_free(iter);
502dc162c8eSFam Zheng }
503dc162c8eSFam Zheng 
504dc162c8eSFam Zheng int64_t bdrv_dirty_iter_next(BdrvDirtyBitmapIter *iter)
505dc162c8eSFam Zheng {
506dc162c8eSFam Zheng     return hbitmap_iter_next(&iter->hbi);
507ebab2259SFam Zheng }
508ebab2259SFam Zheng 
509b64bd51eSPaolo Bonzini /* Called within bdrv_dirty_bitmap_lock..unlock */
510b64bd51eSPaolo Bonzini void bdrv_set_dirty_bitmap_locked(BdrvDirtyBitmap *bitmap,
5116d078599SDenis V. Lunev                                   int64_t cur_sector, int64_t nr_sectors)
512ebab2259SFam Zheng {
513ebab2259SFam Zheng     assert(bdrv_dirty_bitmap_enabled(bitmap));
514*d6883bc9SVladimir Sementsov-Ogievskiy     assert(!bdrv_dirty_bitmap_readonly(bitmap));
515ebab2259SFam Zheng     hbitmap_set(bitmap->bitmap, cur_sector, nr_sectors);
516ebab2259SFam Zheng }
517ebab2259SFam Zheng 
518b64bd51eSPaolo Bonzini void bdrv_set_dirty_bitmap(BdrvDirtyBitmap *bitmap,
519b64bd51eSPaolo Bonzini                            int64_t cur_sector, int64_t nr_sectors)
520b64bd51eSPaolo Bonzini {
521b64bd51eSPaolo Bonzini     bdrv_dirty_bitmap_lock(bitmap);
522b64bd51eSPaolo Bonzini     bdrv_set_dirty_bitmap_locked(bitmap, cur_sector, nr_sectors);
523b64bd51eSPaolo Bonzini     bdrv_dirty_bitmap_unlock(bitmap);
524b64bd51eSPaolo Bonzini }
525b64bd51eSPaolo Bonzini 
526b64bd51eSPaolo Bonzini /* Called within bdrv_dirty_bitmap_lock..unlock */
527b64bd51eSPaolo Bonzini void bdrv_reset_dirty_bitmap_locked(BdrvDirtyBitmap *bitmap,
5286d078599SDenis V. Lunev                                     int64_t cur_sector, int64_t nr_sectors)
529ebab2259SFam Zheng {
530ebab2259SFam Zheng     assert(bdrv_dirty_bitmap_enabled(bitmap));
531*d6883bc9SVladimir Sementsov-Ogievskiy     assert(!bdrv_dirty_bitmap_readonly(bitmap));
532ebab2259SFam Zheng     hbitmap_reset(bitmap->bitmap, cur_sector, nr_sectors);
533ebab2259SFam Zheng }
534ebab2259SFam Zheng 
535b64bd51eSPaolo Bonzini void bdrv_reset_dirty_bitmap(BdrvDirtyBitmap *bitmap,
536b64bd51eSPaolo Bonzini                              int64_t cur_sector, int64_t nr_sectors)
537b64bd51eSPaolo Bonzini {
538b64bd51eSPaolo Bonzini     bdrv_dirty_bitmap_lock(bitmap);
539b64bd51eSPaolo Bonzini     bdrv_reset_dirty_bitmap_locked(bitmap, cur_sector, nr_sectors);
540b64bd51eSPaolo Bonzini     bdrv_dirty_bitmap_unlock(bitmap);
541b64bd51eSPaolo Bonzini }
542b64bd51eSPaolo Bonzini 
543ebab2259SFam Zheng void bdrv_clear_dirty_bitmap(BdrvDirtyBitmap *bitmap, HBitmap **out)
544ebab2259SFam Zheng {
545ebab2259SFam Zheng     assert(bdrv_dirty_bitmap_enabled(bitmap));
546*d6883bc9SVladimir Sementsov-Ogievskiy     assert(!bdrv_dirty_bitmap_readonly(bitmap));
547b64bd51eSPaolo Bonzini     bdrv_dirty_bitmap_lock(bitmap);
548ebab2259SFam Zheng     if (!out) {
549ebab2259SFam Zheng         hbitmap_reset_all(bitmap->bitmap);
550ebab2259SFam Zheng     } else {
551ebab2259SFam Zheng         HBitmap *backup = bitmap->bitmap;
552ebab2259SFam Zheng         bitmap->bitmap = hbitmap_alloc(bitmap->size,
553ebab2259SFam Zheng                                        hbitmap_granularity(backup));
554ebab2259SFam Zheng         *out = backup;
555ebab2259SFam Zheng     }
556b64bd51eSPaolo Bonzini     bdrv_dirty_bitmap_unlock(bitmap);
557ebab2259SFam Zheng }
558ebab2259SFam Zheng 
559ebab2259SFam Zheng void bdrv_undo_clear_dirty_bitmap(BdrvDirtyBitmap *bitmap, HBitmap *in)
560ebab2259SFam Zheng {
561ebab2259SFam Zheng     HBitmap *tmp = bitmap->bitmap;
562ebab2259SFam Zheng     assert(bdrv_dirty_bitmap_enabled(bitmap));
563*d6883bc9SVladimir Sementsov-Ogievskiy     assert(!bdrv_dirty_bitmap_readonly(bitmap));
564ebab2259SFam Zheng     bitmap->bitmap = in;
565ebab2259SFam Zheng     hbitmap_free(tmp);
566ebab2259SFam Zheng }
567ebab2259SFam Zheng 
568882c36f5SVladimir Sementsov-Ogievskiy uint64_t bdrv_dirty_bitmap_serialization_size(const BdrvDirtyBitmap *bitmap,
569882c36f5SVladimir Sementsov-Ogievskiy                                               uint64_t start, uint64_t count)
570882c36f5SVladimir Sementsov-Ogievskiy {
571882c36f5SVladimir Sementsov-Ogievskiy     return hbitmap_serialization_size(bitmap->bitmap, start, count);
572882c36f5SVladimir Sementsov-Ogievskiy }
573882c36f5SVladimir Sementsov-Ogievskiy 
574882c36f5SVladimir Sementsov-Ogievskiy uint64_t bdrv_dirty_bitmap_serialization_align(const BdrvDirtyBitmap *bitmap)
575882c36f5SVladimir Sementsov-Ogievskiy {
576882c36f5SVladimir Sementsov-Ogievskiy     return hbitmap_serialization_granularity(bitmap->bitmap);
577882c36f5SVladimir Sementsov-Ogievskiy }
578882c36f5SVladimir Sementsov-Ogievskiy 
579882c36f5SVladimir Sementsov-Ogievskiy void bdrv_dirty_bitmap_serialize_part(const BdrvDirtyBitmap *bitmap,
580882c36f5SVladimir Sementsov-Ogievskiy                                       uint8_t *buf, uint64_t start,
581882c36f5SVladimir Sementsov-Ogievskiy                                       uint64_t count)
582882c36f5SVladimir Sementsov-Ogievskiy {
583882c36f5SVladimir Sementsov-Ogievskiy     hbitmap_serialize_part(bitmap->bitmap, buf, start, count);
584882c36f5SVladimir Sementsov-Ogievskiy }
585882c36f5SVladimir Sementsov-Ogievskiy 
586882c36f5SVladimir Sementsov-Ogievskiy void bdrv_dirty_bitmap_deserialize_part(BdrvDirtyBitmap *bitmap,
587882c36f5SVladimir Sementsov-Ogievskiy                                         uint8_t *buf, uint64_t start,
588882c36f5SVladimir Sementsov-Ogievskiy                                         uint64_t count, bool finish)
589882c36f5SVladimir Sementsov-Ogievskiy {
590882c36f5SVladimir Sementsov-Ogievskiy     hbitmap_deserialize_part(bitmap->bitmap, buf, start, count, finish);
591882c36f5SVladimir Sementsov-Ogievskiy }
592882c36f5SVladimir Sementsov-Ogievskiy 
593882c36f5SVladimir Sementsov-Ogievskiy void bdrv_dirty_bitmap_deserialize_zeroes(BdrvDirtyBitmap *bitmap,
594882c36f5SVladimir Sementsov-Ogievskiy                                           uint64_t start, uint64_t count,
595882c36f5SVladimir Sementsov-Ogievskiy                                           bool finish)
596882c36f5SVladimir Sementsov-Ogievskiy {
597882c36f5SVladimir Sementsov-Ogievskiy     hbitmap_deserialize_zeroes(bitmap->bitmap, start, count, finish);
598882c36f5SVladimir Sementsov-Ogievskiy }
599882c36f5SVladimir Sementsov-Ogievskiy 
6006bdc8b71SVladimir Sementsov-Ogievskiy void bdrv_dirty_bitmap_deserialize_ones(BdrvDirtyBitmap *bitmap,
6016bdc8b71SVladimir Sementsov-Ogievskiy                                         uint64_t start, uint64_t count,
6026bdc8b71SVladimir Sementsov-Ogievskiy                                         bool finish)
6036bdc8b71SVladimir Sementsov-Ogievskiy {
6046bdc8b71SVladimir Sementsov-Ogievskiy     hbitmap_deserialize_ones(bitmap->bitmap, start, count, finish);
6056bdc8b71SVladimir Sementsov-Ogievskiy }
6066bdc8b71SVladimir Sementsov-Ogievskiy 
607882c36f5SVladimir Sementsov-Ogievskiy void bdrv_dirty_bitmap_deserialize_finish(BdrvDirtyBitmap *bitmap)
608882c36f5SVladimir Sementsov-Ogievskiy {
609882c36f5SVladimir Sementsov-Ogievskiy     hbitmap_deserialize_finish(bitmap->bitmap);
610882c36f5SVladimir Sementsov-Ogievskiy }
611882c36f5SVladimir Sementsov-Ogievskiy 
612ebab2259SFam Zheng void bdrv_set_dirty(BlockDriverState *bs, int64_t cur_sector,
6136d078599SDenis V. Lunev                     int64_t nr_sectors)
614ebab2259SFam Zheng {
615ebab2259SFam Zheng     BdrvDirtyBitmap *bitmap;
6162119882cSPaolo Bonzini 
6172119882cSPaolo Bonzini     if (QLIST_EMPTY(&bs->dirty_bitmaps)) {
6182119882cSPaolo Bonzini         return;
6192119882cSPaolo Bonzini     }
6202119882cSPaolo Bonzini 
6212119882cSPaolo Bonzini     bdrv_dirty_bitmaps_lock(bs);
622ebab2259SFam Zheng     QLIST_FOREACH(bitmap, &bs->dirty_bitmaps, list) {
623ebab2259SFam Zheng         if (!bdrv_dirty_bitmap_enabled(bitmap)) {
624ebab2259SFam Zheng             continue;
625ebab2259SFam Zheng         }
626*d6883bc9SVladimir Sementsov-Ogievskiy         assert(!bdrv_dirty_bitmap_readonly(bitmap));
627ebab2259SFam Zheng         hbitmap_set(bitmap->bitmap, cur_sector, nr_sectors);
628ebab2259SFam Zheng     }
6292119882cSPaolo Bonzini     bdrv_dirty_bitmaps_unlock(bs);
630ebab2259SFam Zheng }
631ebab2259SFam Zheng 
632ebab2259SFam Zheng /**
633dc162c8eSFam Zheng  * Advance a BdrvDirtyBitmapIter to an arbitrary offset.
634ebab2259SFam Zheng  */
635dc162c8eSFam Zheng void bdrv_set_dirty_iter(BdrvDirtyBitmapIter *iter, int64_t sector_num)
636ebab2259SFam Zheng {
637dc162c8eSFam Zheng     hbitmap_iter_init(&iter->hbi, iter->hbi.hb, sector_num);
638ebab2259SFam Zheng }
639ebab2259SFam Zheng 
640ebab2259SFam Zheng int64_t bdrv_get_dirty_count(BdrvDirtyBitmap *bitmap)
641ebab2259SFam Zheng {
642ebab2259SFam Zheng     return hbitmap_count(bitmap->bitmap);
643ebab2259SFam Zheng }
6446d3f4049SFam Zheng 
6456d3f4049SFam Zheng int64_t bdrv_get_meta_dirty_count(BdrvDirtyBitmap *bitmap)
6466d3f4049SFam Zheng {
6476d3f4049SFam Zheng     return hbitmap_count(bitmap->meta);
6486d3f4049SFam Zheng }
649*d6883bc9SVladimir Sementsov-Ogievskiy 
650*d6883bc9SVladimir Sementsov-Ogievskiy bool bdrv_dirty_bitmap_readonly(const BdrvDirtyBitmap *bitmap)
651*d6883bc9SVladimir Sementsov-Ogievskiy {
652*d6883bc9SVladimir Sementsov-Ogievskiy     return bitmap->readonly;
653*d6883bc9SVladimir Sementsov-Ogievskiy }
654*d6883bc9SVladimir Sementsov-Ogievskiy 
655*d6883bc9SVladimir Sementsov-Ogievskiy /* Called with BQL taken. */
656*d6883bc9SVladimir Sementsov-Ogievskiy void bdrv_dirty_bitmap_set_readonly(BdrvDirtyBitmap *bitmap, bool value)
657*d6883bc9SVladimir Sementsov-Ogievskiy {
658*d6883bc9SVladimir Sementsov-Ogievskiy     qemu_mutex_lock(bitmap->mutex);
659*d6883bc9SVladimir Sementsov-Ogievskiy     bitmap->readonly = value;
660*d6883bc9SVladimir Sementsov-Ogievskiy     qemu_mutex_unlock(bitmap->mutex);
661*d6883bc9SVladimir Sementsov-Ogievskiy }
662*d6883bc9SVladimir Sementsov-Ogievskiy 
663*d6883bc9SVladimir Sementsov-Ogievskiy bool bdrv_has_readonly_bitmaps(BlockDriverState *bs)
664*d6883bc9SVladimir Sementsov-Ogievskiy {
665*d6883bc9SVladimir Sementsov-Ogievskiy     BdrvDirtyBitmap *bm;
666*d6883bc9SVladimir Sementsov-Ogievskiy     QLIST_FOREACH(bm, &bs->dirty_bitmaps, list) {
667*d6883bc9SVladimir Sementsov-Ogievskiy         if (bm->readonly) {
668*d6883bc9SVladimir Sementsov-Ogievskiy             return true;
669*d6883bc9SVladimir Sementsov-Ogievskiy         }
670*d6883bc9SVladimir Sementsov-Ogievskiy     }
671*d6883bc9SVladimir Sementsov-Ogievskiy 
672*d6883bc9SVladimir Sementsov-Ogievskiy     return false;
673*d6883bc9SVladimir Sementsov-Ogievskiy }
674