xref: /qemu/block/dirty-bitmap.c (revision fb933437)
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 {
40ebab2259SFam Zheng     HBitmap *bitmap;            /* Dirty sector bitmap implementation */
41*fb933437SFam Zheng     HBitmap *meta;              /* Meta dirty bitmap */
42ebab2259SFam Zheng     BdrvDirtyBitmap *successor; /* Anonymous child; implies frozen status */
43ebab2259SFam Zheng     char *name;                 /* Optional non-empty unique ID */
44ebab2259SFam Zheng     int64_t size;               /* Size of the bitmap (Number of sectors) */
45ebab2259SFam Zheng     bool disabled;              /* Bitmap is read-only */
46dc162c8eSFam Zheng     int active_iterators;       /* How many iterators are active */
47ebab2259SFam Zheng     QLIST_ENTRY(BdrvDirtyBitmap) list;
48ebab2259SFam Zheng };
49ebab2259SFam Zheng 
50dc162c8eSFam Zheng struct BdrvDirtyBitmapIter {
51dc162c8eSFam Zheng     HBitmapIter hbi;
52dc162c8eSFam Zheng     BdrvDirtyBitmap *bitmap;
53dc162c8eSFam Zheng };
54dc162c8eSFam Zheng 
55ebab2259SFam Zheng BdrvDirtyBitmap *bdrv_find_dirty_bitmap(BlockDriverState *bs, const char *name)
56ebab2259SFam Zheng {
57ebab2259SFam Zheng     BdrvDirtyBitmap *bm;
58ebab2259SFam Zheng 
59ebab2259SFam Zheng     assert(name);
60ebab2259SFam Zheng     QLIST_FOREACH(bm, &bs->dirty_bitmaps, list) {
61ebab2259SFam Zheng         if (bm->name && !strcmp(name, bm->name)) {
62ebab2259SFam Zheng             return bm;
63ebab2259SFam Zheng         }
64ebab2259SFam Zheng     }
65ebab2259SFam Zheng     return NULL;
66ebab2259SFam Zheng }
67ebab2259SFam Zheng 
68ebab2259SFam Zheng void bdrv_dirty_bitmap_make_anon(BdrvDirtyBitmap *bitmap)
69ebab2259SFam Zheng {
70ebab2259SFam Zheng     assert(!bdrv_dirty_bitmap_frozen(bitmap));
71ebab2259SFam Zheng     g_free(bitmap->name);
72ebab2259SFam Zheng     bitmap->name = NULL;
73ebab2259SFam Zheng }
74ebab2259SFam Zheng 
75ebab2259SFam Zheng BdrvDirtyBitmap *bdrv_create_dirty_bitmap(BlockDriverState *bs,
76ebab2259SFam Zheng                                           uint32_t granularity,
77ebab2259SFam Zheng                                           const char *name,
78ebab2259SFam Zheng                                           Error **errp)
79ebab2259SFam Zheng {
80ebab2259SFam Zheng     int64_t bitmap_size;
81ebab2259SFam Zheng     BdrvDirtyBitmap *bitmap;
82ebab2259SFam Zheng     uint32_t sector_granularity;
83ebab2259SFam Zheng 
84ebab2259SFam Zheng     assert((granularity & (granularity - 1)) == 0);
85ebab2259SFam Zheng 
86ebab2259SFam Zheng     if (name && bdrv_find_dirty_bitmap(bs, name)) {
87ebab2259SFam Zheng         error_setg(errp, "Bitmap already exists: %s", name);
88ebab2259SFam Zheng         return NULL;
89ebab2259SFam Zheng     }
90ebab2259SFam Zheng     sector_granularity = granularity >> BDRV_SECTOR_BITS;
91ebab2259SFam Zheng     assert(sector_granularity);
92ebab2259SFam Zheng     bitmap_size = bdrv_nb_sectors(bs);
93ebab2259SFam Zheng     if (bitmap_size < 0) {
94ebab2259SFam Zheng         error_setg_errno(errp, -bitmap_size, "could not get length of device");
95ebab2259SFam Zheng         errno = -bitmap_size;
96ebab2259SFam Zheng         return NULL;
97ebab2259SFam Zheng     }
98ebab2259SFam Zheng     bitmap = g_new0(BdrvDirtyBitmap, 1);
99ebab2259SFam Zheng     bitmap->bitmap = hbitmap_alloc(bitmap_size, ctz32(sector_granularity));
100ebab2259SFam Zheng     bitmap->size = bitmap_size;
101ebab2259SFam Zheng     bitmap->name = g_strdup(name);
102ebab2259SFam Zheng     bitmap->disabled = false;
103ebab2259SFam Zheng     QLIST_INSERT_HEAD(&bs->dirty_bitmaps, bitmap, list);
104ebab2259SFam Zheng     return bitmap;
105ebab2259SFam Zheng }
106ebab2259SFam Zheng 
107*fb933437SFam Zheng /* bdrv_create_meta_dirty_bitmap
108*fb933437SFam Zheng  *
109*fb933437SFam Zheng  * Create a meta dirty bitmap that tracks the changes of bits in @bitmap. I.e.
110*fb933437SFam Zheng  * when a dirty status bit in @bitmap is changed (either from reset to set or
111*fb933437SFam Zheng  * the other way around), its respective meta dirty bitmap bit will be marked
112*fb933437SFam Zheng  * dirty as well.
113*fb933437SFam Zheng  *
114*fb933437SFam Zheng  * @bitmap: the block dirty bitmap for which to create a meta dirty bitmap.
115*fb933437SFam Zheng  * @chunk_size: how many bytes of bitmap data does each bit in the meta bitmap
116*fb933437SFam Zheng  * track.
117*fb933437SFam Zheng  */
118*fb933437SFam Zheng void bdrv_create_meta_dirty_bitmap(BdrvDirtyBitmap *bitmap,
119*fb933437SFam Zheng                                    int chunk_size)
120*fb933437SFam Zheng {
121*fb933437SFam Zheng     assert(!bitmap->meta);
122*fb933437SFam Zheng     bitmap->meta = hbitmap_create_meta(bitmap->bitmap,
123*fb933437SFam Zheng                                        chunk_size * BITS_PER_BYTE);
124*fb933437SFam Zheng }
125*fb933437SFam Zheng 
126*fb933437SFam Zheng void bdrv_release_meta_dirty_bitmap(BdrvDirtyBitmap *bitmap)
127*fb933437SFam Zheng {
128*fb933437SFam Zheng     assert(bitmap->meta);
129*fb933437SFam Zheng     hbitmap_free_meta(bitmap->bitmap);
130*fb933437SFam Zheng     bitmap->meta = NULL;
131*fb933437SFam Zheng }
132*fb933437SFam Zheng 
133*fb933437SFam Zheng int bdrv_dirty_bitmap_get_meta(BlockDriverState *bs,
134*fb933437SFam Zheng                                BdrvDirtyBitmap *bitmap, int64_t sector,
135*fb933437SFam Zheng                                int nb_sectors)
136*fb933437SFam Zheng {
137*fb933437SFam Zheng     uint64_t i;
138*fb933437SFam Zheng     int sectors_per_bit = 1 << hbitmap_granularity(bitmap->meta);
139*fb933437SFam Zheng 
140*fb933437SFam Zheng     /* To optimize: we can make hbitmap to internally check the range in a
141*fb933437SFam Zheng      * coarse level, or at least do it word by word. */
142*fb933437SFam Zheng     for (i = sector; i < sector + nb_sectors; i += sectors_per_bit) {
143*fb933437SFam Zheng         if (hbitmap_get(bitmap->meta, i)) {
144*fb933437SFam Zheng             return true;
145*fb933437SFam Zheng         }
146*fb933437SFam Zheng     }
147*fb933437SFam Zheng     return false;
148*fb933437SFam Zheng }
149*fb933437SFam Zheng 
150*fb933437SFam Zheng void bdrv_dirty_bitmap_reset_meta(BlockDriverState *bs,
151*fb933437SFam Zheng                                   BdrvDirtyBitmap *bitmap, int64_t sector,
152*fb933437SFam Zheng                                   int nb_sectors)
153*fb933437SFam Zheng {
154*fb933437SFam Zheng     hbitmap_reset(bitmap->meta, sector, nb_sectors);
155*fb933437SFam Zheng }
156*fb933437SFam Zheng 
157ebab2259SFam Zheng bool bdrv_dirty_bitmap_frozen(BdrvDirtyBitmap *bitmap)
158ebab2259SFam Zheng {
159ebab2259SFam Zheng     return bitmap->successor;
160ebab2259SFam Zheng }
161ebab2259SFam Zheng 
162ebab2259SFam Zheng bool bdrv_dirty_bitmap_enabled(BdrvDirtyBitmap *bitmap)
163ebab2259SFam Zheng {
164ebab2259SFam Zheng     return !(bitmap->disabled || bitmap->successor);
165ebab2259SFam Zheng }
166ebab2259SFam Zheng 
167ebab2259SFam Zheng DirtyBitmapStatus bdrv_dirty_bitmap_status(BdrvDirtyBitmap *bitmap)
168ebab2259SFam Zheng {
169ebab2259SFam Zheng     if (bdrv_dirty_bitmap_frozen(bitmap)) {
170ebab2259SFam Zheng         return DIRTY_BITMAP_STATUS_FROZEN;
171ebab2259SFam Zheng     } else if (!bdrv_dirty_bitmap_enabled(bitmap)) {
172ebab2259SFam Zheng         return DIRTY_BITMAP_STATUS_DISABLED;
173ebab2259SFam Zheng     } else {
174ebab2259SFam Zheng         return DIRTY_BITMAP_STATUS_ACTIVE;
175ebab2259SFam Zheng     }
176ebab2259SFam Zheng }
177ebab2259SFam Zheng 
178ebab2259SFam Zheng /**
179ebab2259SFam Zheng  * Create a successor bitmap destined to replace this bitmap after an operation.
180ebab2259SFam Zheng  * Requires that the bitmap is not frozen and has no successor.
181ebab2259SFam Zheng  */
182ebab2259SFam Zheng int bdrv_dirty_bitmap_create_successor(BlockDriverState *bs,
183ebab2259SFam Zheng                                        BdrvDirtyBitmap *bitmap, Error **errp)
184ebab2259SFam Zheng {
185ebab2259SFam Zheng     uint64_t granularity;
186ebab2259SFam Zheng     BdrvDirtyBitmap *child;
187ebab2259SFam Zheng 
188ebab2259SFam Zheng     if (bdrv_dirty_bitmap_frozen(bitmap)) {
189ebab2259SFam Zheng         error_setg(errp, "Cannot create a successor for a bitmap that is "
190ebab2259SFam Zheng                    "currently frozen");
191ebab2259SFam Zheng         return -1;
192ebab2259SFam Zheng     }
193ebab2259SFam Zheng     assert(!bitmap->successor);
194ebab2259SFam Zheng 
195ebab2259SFam Zheng     /* Create an anonymous successor */
196ebab2259SFam Zheng     granularity = bdrv_dirty_bitmap_granularity(bitmap);
197ebab2259SFam Zheng     child = bdrv_create_dirty_bitmap(bs, granularity, NULL, errp);
198ebab2259SFam Zheng     if (!child) {
199ebab2259SFam Zheng         return -1;
200ebab2259SFam Zheng     }
201ebab2259SFam Zheng 
202ebab2259SFam Zheng     /* Successor will be on or off based on our current state. */
203ebab2259SFam Zheng     child->disabled = bitmap->disabled;
204ebab2259SFam Zheng 
205ebab2259SFam Zheng     /* Install the successor and freeze the parent */
206ebab2259SFam Zheng     bitmap->successor = child;
207ebab2259SFam Zheng     return 0;
208ebab2259SFam Zheng }
209ebab2259SFam Zheng 
210ebab2259SFam Zheng /**
211ebab2259SFam Zheng  * For a bitmap with a successor, yield our name to the successor,
212ebab2259SFam Zheng  * delete the old bitmap, and return a handle to the new bitmap.
213ebab2259SFam Zheng  */
214ebab2259SFam Zheng BdrvDirtyBitmap *bdrv_dirty_bitmap_abdicate(BlockDriverState *bs,
215ebab2259SFam Zheng                                             BdrvDirtyBitmap *bitmap,
216ebab2259SFam Zheng                                             Error **errp)
217ebab2259SFam Zheng {
218ebab2259SFam Zheng     char *name;
219ebab2259SFam Zheng     BdrvDirtyBitmap *successor = bitmap->successor;
220ebab2259SFam Zheng 
221ebab2259SFam Zheng     if (successor == NULL) {
222ebab2259SFam Zheng         error_setg(errp, "Cannot relinquish control if "
223ebab2259SFam Zheng                    "there's no successor present");
224ebab2259SFam Zheng         return NULL;
225ebab2259SFam Zheng     }
226ebab2259SFam Zheng 
227ebab2259SFam Zheng     name = bitmap->name;
228ebab2259SFam Zheng     bitmap->name = NULL;
229ebab2259SFam Zheng     successor->name = name;
230ebab2259SFam Zheng     bitmap->successor = NULL;
231ebab2259SFam Zheng     bdrv_release_dirty_bitmap(bs, bitmap);
232ebab2259SFam Zheng 
233ebab2259SFam Zheng     return successor;
234ebab2259SFam Zheng }
235ebab2259SFam Zheng 
236ebab2259SFam Zheng /**
237ebab2259SFam Zheng  * In cases of failure where we can no longer safely delete the parent,
238ebab2259SFam Zheng  * we may wish to re-join the parent and child/successor.
239ebab2259SFam Zheng  * The merged parent will be un-frozen, but not explicitly re-enabled.
240ebab2259SFam Zheng  */
241ebab2259SFam Zheng BdrvDirtyBitmap *bdrv_reclaim_dirty_bitmap(BlockDriverState *bs,
242ebab2259SFam Zheng                                            BdrvDirtyBitmap *parent,
243ebab2259SFam Zheng                                            Error **errp)
244ebab2259SFam Zheng {
245ebab2259SFam Zheng     BdrvDirtyBitmap *successor = parent->successor;
246ebab2259SFam Zheng 
247ebab2259SFam Zheng     if (!successor) {
248ebab2259SFam Zheng         error_setg(errp, "Cannot reclaim a successor when none is present");
249ebab2259SFam Zheng         return NULL;
250ebab2259SFam Zheng     }
251ebab2259SFam Zheng 
252ebab2259SFam Zheng     if (!hbitmap_merge(parent->bitmap, successor->bitmap)) {
253ebab2259SFam Zheng         error_setg(errp, "Merging of parent and successor bitmap failed");
254ebab2259SFam Zheng         return NULL;
255ebab2259SFam Zheng     }
256ebab2259SFam Zheng     bdrv_release_dirty_bitmap(bs, successor);
257ebab2259SFam Zheng     parent->successor = NULL;
258ebab2259SFam Zheng 
259ebab2259SFam Zheng     return parent;
260ebab2259SFam Zheng }
261ebab2259SFam Zheng 
262ebab2259SFam Zheng /**
263ebab2259SFam Zheng  * Truncates _all_ bitmaps attached to a BDS.
264ebab2259SFam Zheng  */
265ebab2259SFam Zheng void bdrv_dirty_bitmap_truncate(BlockDriverState *bs)
266ebab2259SFam Zheng {
267ebab2259SFam Zheng     BdrvDirtyBitmap *bitmap;
268ebab2259SFam Zheng     uint64_t size = bdrv_nb_sectors(bs);
269ebab2259SFam Zheng 
270ebab2259SFam Zheng     QLIST_FOREACH(bitmap, &bs->dirty_bitmaps, list) {
271ebab2259SFam Zheng         assert(!bdrv_dirty_bitmap_frozen(bitmap));
272dc162c8eSFam Zheng         assert(!bitmap->active_iterators);
273ebab2259SFam Zheng         hbitmap_truncate(bitmap->bitmap, size);
274ebab2259SFam Zheng         bitmap->size = size;
275ebab2259SFam Zheng     }
276ebab2259SFam Zheng }
277ebab2259SFam Zheng 
278ebab2259SFam Zheng static void bdrv_do_release_matching_dirty_bitmap(BlockDriverState *bs,
279ebab2259SFam Zheng                                                   BdrvDirtyBitmap *bitmap,
280ebab2259SFam Zheng                                                   bool only_named)
281ebab2259SFam Zheng {
282ebab2259SFam Zheng     BdrvDirtyBitmap *bm, *next;
283ebab2259SFam Zheng     QLIST_FOREACH_SAFE(bm, &bs->dirty_bitmaps, list, next) {
284ebab2259SFam Zheng         if ((!bitmap || bm == bitmap) && (!only_named || bm->name)) {
285dc162c8eSFam Zheng             assert(!bm->active_iterators);
286ebab2259SFam Zheng             assert(!bdrv_dirty_bitmap_frozen(bm));
287*fb933437SFam Zheng             assert(!bm->meta);
288ebab2259SFam Zheng             QLIST_REMOVE(bm, list);
289ebab2259SFam Zheng             hbitmap_free(bm->bitmap);
290ebab2259SFam Zheng             g_free(bm->name);
291ebab2259SFam Zheng             g_free(bm);
292ebab2259SFam Zheng 
293ebab2259SFam Zheng             if (bitmap) {
294ebab2259SFam Zheng                 return;
295ebab2259SFam Zheng             }
296ebab2259SFam Zheng         }
297ebab2259SFam Zheng     }
298ebab2259SFam Zheng }
299ebab2259SFam Zheng 
300ebab2259SFam Zheng void bdrv_release_dirty_bitmap(BlockDriverState *bs, BdrvDirtyBitmap *bitmap)
301ebab2259SFam Zheng {
302ebab2259SFam Zheng     bdrv_do_release_matching_dirty_bitmap(bs, bitmap, false);
303ebab2259SFam Zheng }
304ebab2259SFam Zheng 
305ebab2259SFam Zheng /**
306ebab2259SFam Zheng  * Release all named dirty bitmaps attached to a BDS (for use in bdrv_close()).
307ebab2259SFam Zheng  * There must not be any frozen bitmaps attached.
308ebab2259SFam Zheng  */
309ebab2259SFam Zheng void bdrv_release_named_dirty_bitmaps(BlockDriverState *bs)
310ebab2259SFam Zheng {
311ebab2259SFam Zheng     bdrv_do_release_matching_dirty_bitmap(bs, NULL, true);
312ebab2259SFam Zheng }
313ebab2259SFam Zheng 
314ebab2259SFam Zheng void bdrv_disable_dirty_bitmap(BdrvDirtyBitmap *bitmap)
315ebab2259SFam Zheng {
316ebab2259SFam Zheng     assert(!bdrv_dirty_bitmap_frozen(bitmap));
317ebab2259SFam Zheng     bitmap->disabled = true;
318ebab2259SFam Zheng }
319ebab2259SFam Zheng 
320ebab2259SFam Zheng void bdrv_enable_dirty_bitmap(BdrvDirtyBitmap *bitmap)
321ebab2259SFam Zheng {
322ebab2259SFam Zheng     assert(!bdrv_dirty_bitmap_frozen(bitmap));
323ebab2259SFam Zheng     bitmap->disabled = false;
324ebab2259SFam Zheng }
325ebab2259SFam Zheng 
326ebab2259SFam Zheng BlockDirtyInfoList *bdrv_query_dirty_bitmaps(BlockDriverState *bs)
327ebab2259SFam Zheng {
328ebab2259SFam Zheng     BdrvDirtyBitmap *bm;
329ebab2259SFam Zheng     BlockDirtyInfoList *list = NULL;
330ebab2259SFam Zheng     BlockDirtyInfoList **plist = &list;
331ebab2259SFam Zheng 
332ebab2259SFam Zheng     QLIST_FOREACH(bm, &bs->dirty_bitmaps, list) {
333ebab2259SFam Zheng         BlockDirtyInfo *info = g_new0(BlockDirtyInfo, 1);
334ebab2259SFam Zheng         BlockDirtyInfoList *entry = g_new0(BlockDirtyInfoList, 1);
335ebab2259SFam Zheng         info->count = bdrv_get_dirty_count(bm);
336ebab2259SFam Zheng         info->granularity = bdrv_dirty_bitmap_granularity(bm);
337ebab2259SFam Zheng         info->has_name = !!bm->name;
338ebab2259SFam Zheng         info->name = g_strdup(bm->name);
339ebab2259SFam Zheng         info->status = bdrv_dirty_bitmap_status(bm);
340ebab2259SFam Zheng         entry->value = info;
341ebab2259SFam Zheng         *plist = entry;
342ebab2259SFam Zheng         plist = &entry->next;
343ebab2259SFam Zheng     }
344ebab2259SFam Zheng 
345ebab2259SFam Zheng     return list;
346ebab2259SFam Zheng }
347ebab2259SFam Zheng 
348ebab2259SFam Zheng int bdrv_get_dirty(BlockDriverState *bs, BdrvDirtyBitmap *bitmap,
349ebab2259SFam Zheng                    int64_t sector)
350ebab2259SFam Zheng {
351ebab2259SFam Zheng     if (bitmap) {
352ebab2259SFam Zheng         return hbitmap_get(bitmap->bitmap, sector);
353ebab2259SFam Zheng     } else {
354ebab2259SFam Zheng         return 0;
355ebab2259SFam Zheng     }
356ebab2259SFam Zheng }
357ebab2259SFam Zheng 
358ebab2259SFam Zheng /**
359ebab2259SFam Zheng  * Chooses a default granularity based on the existing cluster size,
360ebab2259SFam Zheng  * but clamped between [4K, 64K]. Defaults to 64K in the case that there
361ebab2259SFam Zheng  * is no cluster size information available.
362ebab2259SFam Zheng  */
363ebab2259SFam Zheng uint32_t bdrv_get_default_bitmap_granularity(BlockDriverState *bs)
364ebab2259SFam Zheng {
365ebab2259SFam Zheng     BlockDriverInfo bdi;
366ebab2259SFam Zheng     uint32_t granularity;
367ebab2259SFam Zheng 
368ebab2259SFam Zheng     if (bdrv_get_info(bs, &bdi) >= 0 && bdi.cluster_size > 0) {
369ebab2259SFam Zheng         granularity = MAX(4096, bdi.cluster_size);
370ebab2259SFam Zheng         granularity = MIN(65536, granularity);
371ebab2259SFam Zheng     } else {
372ebab2259SFam Zheng         granularity = 65536;
373ebab2259SFam Zheng     }
374ebab2259SFam Zheng 
375ebab2259SFam Zheng     return granularity;
376ebab2259SFam Zheng }
377ebab2259SFam Zheng 
378ebab2259SFam Zheng uint32_t bdrv_dirty_bitmap_granularity(BdrvDirtyBitmap *bitmap)
379ebab2259SFam Zheng {
380ebab2259SFam Zheng     return BDRV_SECTOR_SIZE << hbitmap_granularity(bitmap->bitmap);
381ebab2259SFam Zheng }
382ebab2259SFam Zheng 
383dc162c8eSFam Zheng BdrvDirtyBitmapIter *bdrv_dirty_iter_new(BdrvDirtyBitmap *bitmap,
384dc162c8eSFam Zheng                                          uint64_t first_sector)
385ebab2259SFam Zheng {
386dc162c8eSFam Zheng     BdrvDirtyBitmapIter *iter = g_new(BdrvDirtyBitmapIter, 1);
387dc162c8eSFam Zheng     hbitmap_iter_init(&iter->hbi, bitmap->bitmap, first_sector);
388dc162c8eSFam Zheng     iter->bitmap = bitmap;
389dc162c8eSFam Zheng     bitmap->active_iterators++;
390dc162c8eSFam Zheng     return iter;
391dc162c8eSFam Zheng }
392dc162c8eSFam Zheng 
393dc162c8eSFam Zheng void bdrv_dirty_iter_free(BdrvDirtyBitmapIter *iter)
394dc162c8eSFam Zheng {
395dc162c8eSFam Zheng     if (!iter) {
396dc162c8eSFam Zheng         return;
397dc162c8eSFam Zheng     }
398dc162c8eSFam Zheng     assert(iter->bitmap->active_iterators > 0);
399dc162c8eSFam Zheng     iter->bitmap->active_iterators--;
400dc162c8eSFam Zheng     g_free(iter);
401dc162c8eSFam Zheng }
402dc162c8eSFam Zheng 
403dc162c8eSFam Zheng int64_t bdrv_dirty_iter_next(BdrvDirtyBitmapIter *iter)
404dc162c8eSFam Zheng {
405dc162c8eSFam Zheng     return hbitmap_iter_next(&iter->hbi);
406ebab2259SFam Zheng }
407ebab2259SFam Zheng 
408ebab2259SFam Zheng void bdrv_set_dirty_bitmap(BdrvDirtyBitmap *bitmap,
4096d078599SDenis V. Lunev                            int64_t cur_sector, int64_t nr_sectors)
410ebab2259SFam Zheng {
411ebab2259SFam Zheng     assert(bdrv_dirty_bitmap_enabled(bitmap));
412ebab2259SFam Zheng     hbitmap_set(bitmap->bitmap, cur_sector, nr_sectors);
413ebab2259SFam Zheng }
414ebab2259SFam Zheng 
415ebab2259SFam Zheng void bdrv_reset_dirty_bitmap(BdrvDirtyBitmap *bitmap,
4166d078599SDenis V. Lunev                              int64_t cur_sector, int64_t nr_sectors)
417ebab2259SFam Zheng {
418ebab2259SFam Zheng     assert(bdrv_dirty_bitmap_enabled(bitmap));
419ebab2259SFam Zheng     hbitmap_reset(bitmap->bitmap, cur_sector, nr_sectors);
420ebab2259SFam Zheng }
421ebab2259SFam Zheng 
422ebab2259SFam Zheng void bdrv_clear_dirty_bitmap(BdrvDirtyBitmap *bitmap, HBitmap **out)
423ebab2259SFam Zheng {
424ebab2259SFam Zheng     assert(bdrv_dirty_bitmap_enabled(bitmap));
425ebab2259SFam Zheng     if (!out) {
426ebab2259SFam Zheng         hbitmap_reset_all(bitmap->bitmap);
427ebab2259SFam Zheng     } else {
428ebab2259SFam Zheng         HBitmap *backup = bitmap->bitmap;
429ebab2259SFam Zheng         bitmap->bitmap = hbitmap_alloc(bitmap->size,
430ebab2259SFam Zheng                                        hbitmap_granularity(backup));
431ebab2259SFam Zheng         *out = backup;
432ebab2259SFam Zheng     }
433ebab2259SFam Zheng }
434ebab2259SFam Zheng 
435ebab2259SFam Zheng void bdrv_undo_clear_dirty_bitmap(BdrvDirtyBitmap *bitmap, HBitmap *in)
436ebab2259SFam Zheng {
437ebab2259SFam Zheng     HBitmap *tmp = bitmap->bitmap;
438ebab2259SFam Zheng     assert(bdrv_dirty_bitmap_enabled(bitmap));
439ebab2259SFam Zheng     bitmap->bitmap = in;
440ebab2259SFam Zheng     hbitmap_free(tmp);
441ebab2259SFam Zheng }
442ebab2259SFam Zheng 
443ebab2259SFam Zheng void bdrv_set_dirty(BlockDriverState *bs, int64_t cur_sector,
4446d078599SDenis V. Lunev                     int64_t nr_sectors)
445ebab2259SFam Zheng {
446ebab2259SFam Zheng     BdrvDirtyBitmap *bitmap;
447ebab2259SFam Zheng     QLIST_FOREACH(bitmap, &bs->dirty_bitmaps, list) {
448ebab2259SFam Zheng         if (!bdrv_dirty_bitmap_enabled(bitmap)) {
449ebab2259SFam Zheng             continue;
450ebab2259SFam Zheng         }
451ebab2259SFam Zheng         hbitmap_set(bitmap->bitmap, cur_sector, nr_sectors);
452ebab2259SFam Zheng     }
453ebab2259SFam Zheng }
454ebab2259SFam Zheng 
455ebab2259SFam Zheng /**
456dc162c8eSFam Zheng  * Advance a BdrvDirtyBitmapIter to an arbitrary offset.
457ebab2259SFam Zheng  */
458dc162c8eSFam Zheng void bdrv_set_dirty_iter(BdrvDirtyBitmapIter *iter, int64_t sector_num)
459ebab2259SFam Zheng {
460dc162c8eSFam Zheng     hbitmap_iter_init(&iter->hbi, iter->hbi.hb, sector_num);
461ebab2259SFam Zheng }
462ebab2259SFam Zheng 
463ebab2259SFam Zheng int64_t bdrv_get_dirty_count(BdrvDirtyBitmap *bitmap)
464ebab2259SFam Zheng {
465ebab2259SFam Zheng     return hbitmap_count(bitmap->bitmap);
466ebab2259SFam Zheng }
467