xref: /qemu/block/dirty-bitmap.c (revision 283d7a04)
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;
41ca759622SEric Blake     HBitmap *bitmap;            /* Dirty bitmap implementation */
42fb933437SFam Zheng     HBitmap *meta;              /* Meta dirty bitmap */
434f43e953SVladimir Sementsov-Ogievskiy     bool qmp_locked;            /* Bitmap is locked, it can't be modified
444f43e953SVladimir Sementsov-Ogievskiy                                    through QMP */
45ebab2259SFam Zheng     BdrvDirtyBitmap *successor; /* Anonymous child; implies frozen status */
46ebab2259SFam Zheng     char *name;                 /* Optional non-empty unique ID */
47993e6525SEric Blake     int64_t size;               /* Size of the bitmap, in bytes */
488bfc932eSVladimir Sementsov-Ogievskiy     bool disabled;              /* Bitmap is disabled. It ignores all writes to
498bfc932eSVladimir Sementsov-Ogievskiy                                    the device */
50dc162c8eSFam Zheng     int active_iterators;       /* How many iterators are active */
51d6883bc9SVladimir Sementsov-Ogievskiy     bool readonly;              /* Bitmap is read-only. This field also
52d6883bc9SVladimir Sementsov-Ogievskiy                                    prevents the respective image from being
53d6883bc9SVladimir Sementsov-Ogievskiy                                    modified (i.e. blocks writes and discards).
54d6883bc9SVladimir Sementsov-Ogievskiy                                    Such operations must fail and both the image
55d6883bc9SVladimir Sementsov-Ogievskiy                                    and this bitmap must remain unchanged while
56d6883bc9SVladimir Sementsov-Ogievskiy                                    this flag is set. */
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 BdrvDirtyBitmap *bdrv_create_dirty_bitmap(BlockDriverState *bs,
102ebab2259SFam Zheng                                           uint32_t granularity,
103ebab2259SFam Zheng                                           const char *name,
104ebab2259SFam Zheng                                           Error **errp)
105ebab2259SFam Zheng {
106ebab2259SFam Zheng     int64_t bitmap_size;
107ebab2259SFam Zheng     BdrvDirtyBitmap *bitmap;
108ebab2259SFam Zheng 
109993e6525SEric Blake     assert(is_power_of_2(granularity) && granularity >= BDRV_SECTOR_SIZE);
110ebab2259SFam Zheng 
111ebab2259SFam Zheng     if (name && bdrv_find_dirty_bitmap(bs, name)) {
112ebab2259SFam Zheng         error_setg(errp, "Bitmap already exists: %s", name);
113ebab2259SFam Zheng         return NULL;
114ebab2259SFam Zheng     }
115993e6525SEric Blake     bitmap_size = bdrv_getlength(bs);
116ebab2259SFam Zheng     if (bitmap_size < 0) {
117ebab2259SFam Zheng         error_setg_errno(errp, -bitmap_size, "could not get length of device");
118ebab2259SFam Zheng         errno = -bitmap_size;
119ebab2259SFam Zheng         return NULL;
120ebab2259SFam Zheng     }
121ebab2259SFam Zheng     bitmap = g_new0(BdrvDirtyBitmap, 1);
122b64bd51eSPaolo Bonzini     bitmap->mutex = &bs->dirty_bitmap_mutex;
123ca759622SEric Blake     bitmap->bitmap = hbitmap_alloc(bitmap_size, ctz32(granularity));
124ebab2259SFam Zheng     bitmap->size = bitmap_size;
125ebab2259SFam Zheng     bitmap->name = g_strdup(name);
126ebab2259SFam Zheng     bitmap->disabled = false;
1272119882cSPaolo Bonzini     bdrv_dirty_bitmaps_lock(bs);
128ebab2259SFam Zheng     QLIST_INSERT_HEAD(&bs->dirty_bitmaps, bitmap, list);
1292119882cSPaolo Bonzini     bdrv_dirty_bitmaps_unlock(bs);
130ebab2259SFam Zheng     return bitmap;
131ebab2259SFam Zheng }
132ebab2259SFam Zheng 
133fb933437SFam Zheng /* bdrv_create_meta_dirty_bitmap
134fb933437SFam Zheng  *
135fb933437SFam Zheng  * Create a meta dirty bitmap that tracks the changes of bits in @bitmap. I.e.
136fb933437SFam Zheng  * when a dirty status bit in @bitmap is changed (either from reset to set or
137fb933437SFam Zheng  * the other way around), its respective meta dirty bitmap bit will be marked
138fb933437SFam Zheng  * dirty as well.
139fb933437SFam Zheng  *
140fb933437SFam Zheng  * @bitmap: the block dirty bitmap for which to create a meta dirty bitmap.
141fb933437SFam Zheng  * @chunk_size: how many bytes of bitmap data does each bit in the meta bitmap
142fb933437SFam Zheng  * track.
143fb933437SFam Zheng  */
144fb933437SFam Zheng void bdrv_create_meta_dirty_bitmap(BdrvDirtyBitmap *bitmap,
145fb933437SFam Zheng                                    int chunk_size)
146fb933437SFam Zheng {
147fb933437SFam Zheng     assert(!bitmap->meta);
148b64bd51eSPaolo Bonzini     qemu_mutex_lock(bitmap->mutex);
149fb933437SFam Zheng     bitmap->meta = hbitmap_create_meta(bitmap->bitmap,
150fb933437SFam Zheng                                        chunk_size * BITS_PER_BYTE);
151b64bd51eSPaolo Bonzini     qemu_mutex_unlock(bitmap->mutex);
152fb933437SFam Zheng }
153fb933437SFam Zheng 
154fb933437SFam Zheng void bdrv_release_meta_dirty_bitmap(BdrvDirtyBitmap *bitmap)
155fb933437SFam Zheng {
156fb933437SFam Zheng     assert(bitmap->meta);
157b64bd51eSPaolo Bonzini     qemu_mutex_lock(bitmap->mutex);
158fb933437SFam Zheng     hbitmap_free_meta(bitmap->bitmap);
159fb933437SFam Zheng     bitmap->meta = NULL;
160b64bd51eSPaolo Bonzini     qemu_mutex_unlock(bitmap->mutex);
161fb933437SFam Zheng }
162fb933437SFam Zheng 
16315891facSFam Zheng int64_t bdrv_dirty_bitmap_size(const BdrvDirtyBitmap *bitmap)
16415891facSFam Zheng {
165993e6525SEric Blake     return bitmap->size;
16615891facSFam Zheng }
16715891facSFam Zheng 
16815891facSFam Zheng const char *bdrv_dirty_bitmap_name(const BdrvDirtyBitmap *bitmap)
16915891facSFam Zheng {
17015891facSFam Zheng     return bitmap->name;
17115891facSFam Zheng }
17215891facSFam Zheng 
1732119882cSPaolo Bonzini /* Called with BQL taken.  */
174ebab2259SFam Zheng bool bdrv_dirty_bitmap_frozen(BdrvDirtyBitmap *bitmap)
175ebab2259SFam Zheng {
176ebab2259SFam Zheng     return bitmap->successor;
177ebab2259SFam Zheng }
178ebab2259SFam Zheng 
179993edc0cSJohn Snow /* Both conditions disallow user-modification via QMP. */
180993edc0cSJohn Snow bool bdrv_dirty_bitmap_user_locked(BdrvDirtyBitmap *bitmap) {
181993edc0cSJohn Snow     return bdrv_dirty_bitmap_frozen(bitmap) ||
182993edc0cSJohn Snow            bdrv_dirty_bitmap_qmp_locked(bitmap);
183993edc0cSJohn Snow }
184993edc0cSJohn Snow 
1854f43e953SVladimir Sementsov-Ogievskiy void bdrv_dirty_bitmap_set_qmp_locked(BdrvDirtyBitmap *bitmap, bool qmp_locked)
1864f43e953SVladimir Sementsov-Ogievskiy {
1874f43e953SVladimir Sementsov-Ogievskiy     qemu_mutex_lock(bitmap->mutex);
1884f43e953SVladimir Sementsov-Ogievskiy     bitmap->qmp_locked = qmp_locked;
1894f43e953SVladimir Sementsov-Ogievskiy     qemu_mutex_unlock(bitmap->mutex);
1904f43e953SVladimir Sementsov-Ogievskiy }
1914f43e953SVladimir Sementsov-Ogievskiy 
1924f43e953SVladimir Sementsov-Ogievskiy bool bdrv_dirty_bitmap_qmp_locked(BdrvDirtyBitmap *bitmap)
1934f43e953SVladimir Sementsov-Ogievskiy {
1944f43e953SVladimir Sementsov-Ogievskiy     return bitmap->qmp_locked;
1954f43e953SVladimir Sementsov-Ogievskiy }
1964f43e953SVladimir Sementsov-Ogievskiy 
1972119882cSPaolo Bonzini /* Called with BQL taken.  */
198ebab2259SFam Zheng bool bdrv_dirty_bitmap_enabled(BdrvDirtyBitmap *bitmap)
199ebab2259SFam Zheng {
200ebab2259SFam Zheng     return !(bitmap->disabled || bitmap->successor);
201ebab2259SFam Zheng }
202ebab2259SFam Zheng 
2032119882cSPaolo Bonzini /* Called with BQL taken.  */
204ebab2259SFam Zheng DirtyBitmapStatus bdrv_dirty_bitmap_status(BdrvDirtyBitmap *bitmap)
205ebab2259SFam Zheng {
206ebab2259SFam Zheng     if (bdrv_dirty_bitmap_frozen(bitmap)) {
207ebab2259SFam Zheng         return DIRTY_BITMAP_STATUS_FROZEN;
2084f43e953SVladimir Sementsov-Ogievskiy     } else if (bdrv_dirty_bitmap_qmp_locked(bitmap)) {
2094f43e953SVladimir Sementsov-Ogievskiy         return DIRTY_BITMAP_STATUS_LOCKED;
210ebab2259SFam Zheng     } else if (!bdrv_dirty_bitmap_enabled(bitmap)) {
211ebab2259SFam Zheng         return DIRTY_BITMAP_STATUS_DISABLED;
212ebab2259SFam Zheng     } else {
213ebab2259SFam Zheng         return DIRTY_BITMAP_STATUS_ACTIVE;
214ebab2259SFam Zheng     }
215ebab2259SFam Zheng }
216ebab2259SFam Zheng 
217ebab2259SFam Zheng /**
218ebab2259SFam Zheng  * Create a successor bitmap destined to replace this bitmap after an operation.
219ebab2259SFam Zheng  * Requires that the bitmap is not frozen and has no successor.
2202119882cSPaolo Bonzini  * Called with BQL taken.
221ebab2259SFam Zheng  */
222ebab2259SFam Zheng int bdrv_dirty_bitmap_create_successor(BlockDriverState *bs,
223ebab2259SFam Zheng                                        BdrvDirtyBitmap *bitmap, Error **errp)
224ebab2259SFam Zheng {
225ebab2259SFam Zheng     uint64_t granularity;
226ebab2259SFam Zheng     BdrvDirtyBitmap *child;
227ebab2259SFam Zheng 
228ebab2259SFam Zheng     if (bdrv_dirty_bitmap_frozen(bitmap)) {
229ebab2259SFam Zheng         error_setg(errp, "Cannot create a successor for a bitmap that is "
230ebab2259SFam Zheng                    "currently frozen");
231ebab2259SFam Zheng         return -1;
232ebab2259SFam Zheng     }
233ebab2259SFam Zheng     assert(!bitmap->successor);
234ebab2259SFam Zheng 
235ebab2259SFam Zheng     /* Create an anonymous successor */
236ebab2259SFam Zheng     granularity = bdrv_dirty_bitmap_granularity(bitmap);
237ebab2259SFam Zheng     child = bdrv_create_dirty_bitmap(bs, granularity, NULL, errp);
238ebab2259SFam Zheng     if (!child) {
239ebab2259SFam Zheng         return -1;
240ebab2259SFam Zheng     }
241ebab2259SFam Zheng 
242ebab2259SFam Zheng     /* Successor will be on or off based on our current state. */
243ebab2259SFam Zheng     child->disabled = bitmap->disabled;
244ebab2259SFam Zheng 
245ebab2259SFam Zheng     /* Install the successor and freeze the parent */
246ebab2259SFam Zheng     bitmap->successor = child;
247ebab2259SFam Zheng     return 0;
248ebab2259SFam Zheng }
249ebab2259SFam Zheng 
25092bcea40SVladimir Sementsov-Ogievskiy void bdrv_enable_dirty_bitmap_locked(BdrvDirtyBitmap *bitmap)
25192bcea40SVladimir Sementsov-Ogievskiy {
25292bcea40SVladimir Sementsov-Ogievskiy     assert(!bdrv_dirty_bitmap_frozen(bitmap));
25392bcea40SVladimir Sementsov-Ogievskiy     bitmap->disabled = false;
25492bcea40SVladimir Sementsov-Ogievskiy }
25592bcea40SVladimir Sementsov-Ogievskiy 
256e73a265eSVladimir Sementsov-Ogievskiy /* Called with BQL taken. */
257e73a265eSVladimir Sementsov-Ogievskiy void bdrv_dirty_bitmap_enable_successor(BdrvDirtyBitmap *bitmap)
258e73a265eSVladimir Sementsov-Ogievskiy {
25958f72b96SVladimir Sementsov-Ogievskiy     assert(bitmap->mutex == bitmap->successor->mutex);
260e73a265eSVladimir Sementsov-Ogievskiy     qemu_mutex_lock(bitmap->mutex);
26158f72b96SVladimir Sementsov-Ogievskiy     bdrv_enable_dirty_bitmap_locked(bitmap->successor);
262e73a265eSVladimir Sementsov-Ogievskiy     qemu_mutex_unlock(bitmap->mutex);
263e73a265eSVladimir Sementsov-Ogievskiy }
264e73a265eSVladimir Sementsov-Ogievskiy 
265b133c27fSPaolo Bonzini /* Called within bdrv_dirty_bitmap_lock..unlock and with BQL taken.  */
266b133c27fSPaolo Bonzini static void bdrv_release_dirty_bitmap_locked(BdrvDirtyBitmap *bitmap)
267604ab74bSVladimir Sementsov-Ogievskiy {
268b133c27fSPaolo Bonzini     assert(!bitmap->active_iterators);
269b133c27fSPaolo Bonzini     assert(!bdrv_dirty_bitmap_frozen(bitmap));
270b133c27fSPaolo Bonzini     assert(!bitmap->meta);
271b133c27fSPaolo Bonzini     QLIST_REMOVE(bitmap, list);
272b133c27fSPaolo Bonzini     hbitmap_free(bitmap->bitmap);
273b133c27fSPaolo Bonzini     g_free(bitmap->name);
274b133c27fSPaolo Bonzini     g_free(bitmap);
275604ab74bSVladimir Sementsov-Ogievskiy }
276604ab74bSVladimir Sementsov-Ogievskiy 
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;
299a88b179fSVladimir Sementsov-Ogievskiy     successor->persistent = bitmap->persistent;
300a88b179fSVladimir Sementsov-Ogievskiy     bitmap->persistent = false;
301ebab2259SFam Zheng     bdrv_release_dirty_bitmap(bs, bitmap);
302ebab2259SFam Zheng 
303ebab2259SFam Zheng     return successor;
304ebab2259SFam Zheng }
305ebab2259SFam Zheng 
306ebab2259SFam Zheng /**
307ebab2259SFam Zheng  * In cases of failure where we can no longer safely delete the parent,
308ebab2259SFam Zheng  * we may wish to re-join the parent and child/successor.
309ebab2259SFam Zheng  * The merged parent will be un-frozen, but not explicitly re-enabled.
310044ee8e1SVladimir Sementsov-Ogievskiy  * Called within bdrv_dirty_bitmap_lock..unlock and with BQL taken.
311ebab2259SFam Zheng  */
312044ee8e1SVladimir Sementsov-Ogievskiy BdrvDirtyBitmap *bdrv_reclaim_dirty_bitmap_locked(BlockDriverState *bs,
313ebab2259SFam Zheng                                                   BdrvDirtyBitmap *parent,
314ebab2259SFam Zheng                                                   Error **errp)
315ebab2259SFam Zheng {
316044ee8e1SVladimir Sementsov-Ogievskiy     BdrvDirtyBitmap *successor = parent->successor;
317ebab2259SFam Zheng 
318ebab2259SFam Zheng     if (!successor) {
319ebab2259SFam Zheng         error_setg(errp, "Cannot reclaim a successor when none is present");
320ebab2259SFam Zheng         return NULL;
321ebab2259SFam Zheng     }
322ebab2259SFam Zheng 
323fa000f2fSVladimir Sementsov-Ogievskiy     if (!hbitmap_merge(parent->bitmap, successor->bitmap, parent->bitmap)) {
324ebab2259SFam Zheng         error_setg(errp, "Merging of parent and successor bitmap failed");
325ebab2259SFam Zheng         return NULL;
326ebab2259SFam Zheng     }
327b133c27fSPaolo Bonzini     bdrv_release_dirty_bitmap_locked(successor);
328ebab2259SFam Zheng     parent->successor = NULL;
329ebab2259SFam Zheng 
330044ee8e1SVladimir Sementsov-Ogievskiy     return parent;
331044ee8e1SVladimir Sementsov-Ogievskiy }
332044ee8e1SVladimir Sementsov-Ogievskiy 
333044ee8e1SVladimir Sementsov-Ogievskiy /* Called with BQL taken. */
334044ee8e1SVladimir Sementsov-Ogievskiy BdrvDirtyBitmap *bdrv_reclaim_dirty_bitmap(BlockDriverState *bs,
335044ee8e1SVladimir Sementsov-Ogievskiy                                            BdrvDirtyBitmap *parent,
336044ee8e1SVladimir Sementsov-Ogievskiy                                            Error **errp)
337044ee8e1SVladimir Sementsov-Ogievskiy {
338044ee8e1SVladimir Sementsov-Ogievskiy     BdrvDirtyBitmap *ret;
339044ee8e1SVladimir Sementsov-Ogievskiy 
340044ee8e1SVladimir Sementsov-Ogievskiy     qemu_mutex_lock(parent->mutex);
341044ee8e1SVladimir Sementsov-Ogievskiy     ret = bdrv_reclaim_dirty_bitmap_locked(bs, parent, errp);
342604ab74bSVladimir Sementsov-Ogievskiy     qemu_mutex_unlock(parent->mutex);
343604ab74bSVladimir Sementsov-Ogievskiy 
344044ee8e1SVladimir Sementsov-Ogievskiy     return ret;
345ebab2259SFam Zheng }
346ebab2259SFam Zheng 
347ebab2259SFam Zheng /**
348ebab2259SFam Zheng  * Truncates _all_ bitmaps attached to a BDS.
3492119882cSPaolo Bonzini  * Called with BQL taken.
350ebab2259SFam Zheng  */
3511b6cc579SEric Blake void bdrv_dirty_bitmap_truncate(BlockDriverState *bs, int64_t bytes)
352ebab2259SFam Zheng {
353ebab2259SFam Zheng     BdrvDirtyBitmap *bitmap;
354ebab2259SFam Zheng 
3552119882cSPaolo Bonzini     bdrv_dirty_bitmaps_lock(bs);
356ebab2259SFam Zheng     QLIST_FOREACH(bitmap, &bs->dirty_bitmaps, list) {
357ebab2259SFam Zheng         assert(!bdrv_dirty_bitmap_frozen(bitmap));
358dc162c8eSFam Zheng         assert(!bitmap->active_iterators);
359ca759622SEric Blake         hbitmap_truncate(bitmap->bitmap, bytes);
360993e6525SEric Blake         bitmap->size = bytes;
361ebab2259SFam Zheng     }
3622119882cSPaolo Bonzini     bdrv_dirty_bitmaps_unlock(bs);
363ebab2259SFam Zheng }
364ebab2259SFam Zheng 
3652119882cSPaolo Bonzini /* Called with BQL taken.  */
366ebab2259SFam Zheng void bdrv_release_dirty_bitmap(BlockDriverState *bs, BdrvDirtyBitmap *bitmap)
367ebab2259SFam Zheng {
368b133c27fSPaolo Bonzini     bdrv_dirty_bitmaps_lock(bs);
369b133c27fSPaolo Bonzini     bdrv_release_dirty_bitmap_locked(bitmap);
370b133c27fSPaolo Bonzini     bdrv_dirty_bitmaps_unlock(bs);
371ebab2259SFam Zheng }
372ebab2259SFam Zheng 
373ebab2259SFam Zheng /**
374ebab2259SFam Zheng  * Release all named dirty bitmaps attached to a BDS (for use in bdrv_close()).
375ebab2259SFam Zheng  * There must not be any frozen bitmaps attached.
37656f364e6SVladimir Sementsov-Ogievskiy  * This function does not remove persistent bitmaps from the storage.
3772119882cSPaolo Bonzini  * Called with BQL taken.
378ebab2259SFam Zheng  */
379ebab2259SFam Zheng void bdrv_release_named_dirty_bitmaps(BlockDriverState *bs)
380ebab2259SFam Zheng {
381b133c27fSPaolo Bonzini     BdrvDirtyBitmap *bm, *next;
382b133c27fSPaolo Bonzini 
383b133c27fSPaolo Bonzini     bdrv_dirty_bitmaps_lock(bs);
384b133c27fSPaolo Bonzini     QLIST_FOREACH_SAFE(bm, &bs->dirty_bitmaps, list, next) {
385b133c27fSPaolo Bonzini         if (bdrv_dirty_bitmap_name(bm)) {
386b133c27fSPaolo Bonzini             bdrv_release_dirty_bitmap_locked(bm);
387b133c27fSPaolo Bonzini         }
388b133c27fSPaolo Bonzini     }
389b133c27fSPaolo Bonzini     bdrv_dirty_bitmaps_unlock(bs);
390615b5dcfSVladimir Sementsov-Ogievskiy }
391615b5dcfSVladimir Sementsov-Ogievskiy 
392615b5dcfSVladimir Sementsov-Ogievskiy /**
393615b5dcfSVladimir Sementsov-Ogievskiy  * Release all persistent dirty bitmaps attached to a BDS (for use in
394615b5dcfSVladimir Sementsov-Ogievskiy  * bdrv_inactivate_recurse()).
395615b5dcfSVladimir Sementsov-Ogievskiy  * There must not be any frozen bitmaps attached.
396615b5dcfSVladimir Sementsov-Ogievskiy  * This function does not remove persistent bitmaps from the storage.
397b133c27fSPaolo Bonzini  * Called with BQL taken.
398615b5dcfSVladimir Sementsov-Ogievskiy  */
399615b5dcfSVladimir Sementsov-Ogievskiy void bdrv_release_persistent_dirty_bitmaps(BlockDriverState *bs)
400615b5dcfSVladimir Sementsov-Ogievskiy {
401b133c27fSPaolo Bonzini     BdrvDirtyBitmap *bm, *next;
402b133c27fSPaolo Bonzini 
403b133c27fSPaolo Bonzini     bdrv_dirty_bitmaps_lock(bs);
404b133c27fSPaolo Bonzini     QLIST_FOREACH_SAFE(bm, &bs->dirty_bitmaps, list, next) {
405b133c27fSPaolo Bonzini         if (bdrv_dirty_bitmap_get_persistance(bm)) {
406b133c27fSPaolo Bonzini             bdrv_release_dirty_bitmap_locked(bm);
407b133c27fSPaolo Bonzini         }
408b133c27fSPaolo Bonzini     }
409b133c27fSPaolo Bonzini     bdrv_dirty_bitmaps_unlock(bs);
410ebab2259SFam Zheng }
411ebab2259SFam Zheng 
41256f364e6SVladimir Sementsov-Ogievskiy /**
41356f364e6SVladimir Sementsov-Ogievskiy  * Remove persistent dirty bitmap from the storage if it exists.
41456f364e6SVladimir Sementsov-Ogievskiy  * Absence of bitmap is not an error, because we have the following scenario:
41556f364e6SVladimir Sementsov-Ogievskiy  * BdrvDirtyBitmap can have .persistent = true but not yet saved and have no
41656f364e6SVladimir Sementsov-Ogievskiy  * stored version. For such bitmap bdrv_remove_persistent_dirty_bitmap() should
41756f364e6SVladimir Sementsov-Ogievskiy  * not fail.
41856f364e6SVladimir Sementsov-Ogievskiy  * This function doesn't release corresponding BdrvDirtyBitmap.
41956f364e6SVladimir Sementsov-Ogievskiy  */
42056f364e6SVladimir Sementsov-Ogievskiy void bdrv_remove_persistent_dirty_bitmap(BlockDriverState *bs,
42156f364e6SVladimir Sementsov-Ogievskiy                                          const char *name,
42256f364e6SVladimir Sementsov-Ogievskiy                                          Error **errp)
42356f364e6SVladimir Sementsov-Ogievskiy {
42456f364e6SVladimir Sementsov-Ogievskiy     if (bs->drv && bs->drv->bdrv_remove_persistent_dirty_bitmap) {
42556f364e6SVladimir Sementsov-Ogievskiy         bs->drv->bdrv_remove_persistent_dirty_bitmap(bs, name, errp);
42656f364e6SVladimir Sementsov-Ogievskiy     }
42756f364e6SVladimir Sementsov-Ogievskiy }
42856f364e6SVladimir Sementsov-Ogievskiy 
429ebab2259SFam Zheng void bdrv_disable_dirty_bitmap(BdrvDirtyBitmap *bitmap)
430ebab2259SFam Zheng {
4318b1402ceSVladimir Sementsov-Ogievskiy     bdrv_dirty_bitmap_lock(bitmap);
432ebab2259SFam Zheng     assert(!bdrv_dirty_bitmap_frozen(bitmap));
433ebab2259SFam Zheng     bitmap->disabled = true;
4348b1402ceSVladimir Sementsov-Ogievskiy     bdrv_dirty_bitmap_unlock(bitmap);
435ebab2259SFam Zheng }
436ebab2259SFam Zheng 
437ebab2259SFam Zheng void bdrv_enable_dirty_bitmap(BdrvDirtyBitmap *bitmap)
438ebab2259SFam Zheng {
4398b1402ceSVladimir Sementsov-Ogievskiy     bdrv_dirty_bitmap_lock(bitmap);
44092bcea40SVladimir Sementsov-Ogievskiy     bdrv_enable_dirty_bitmap_locked(bitmap);
4418b1402ceSVladimir Sementsov-Ogievskiy     bdrv_dirty_bitmap_unlock(bitmap);
442ebab2259SFam Zheng }
443ebab2259SFam Zheng 
444ebab2259SFam Zheng BlockDirtyInfoList *bdrv_query_dirty_bitmaps(BlockDriverState *bs)
445ebab2259SFam Zheng {
446ebab2259SFam Zheng     BdrvDirtyBitmap *bm;
447ebab2259SFam Zheng     BlockDirtyInfoList *list = NULL;
448ebab2259SFam Zheng     BlockDirtyInfoList **plist = &list;
449ebab2259SFam Zheng 
4502119882cSPaolo Bonzini     bdrv_dirty_bitmaps_lock(bs);
451ebab2259SFam Zheng     QLIST_FOREACH(bm, &bs->dirty_bitmaps, list) {
452ebab2259SFam Zheng         BlockDirtyInfo *info = g_new0(BlockDirtyInfo, 1);
453ebab2259SFam Zheng         BlockDirtyInfoList *entry = g_new0(BlockDirtyInfoList, 1);
4549a46dba7SEric Blake         info->count = bdrv_get_dirty_count(bm);
455ebab2259SFam Zheng         info->granularity = bdrv_dirty_bitmap_granularity(bm);
456ebab2259SFam Zheng         info->has_name = !!bm->name;
457ebab2259SFam Zheng         info->name = g_strdup(bm->name);
458ebab2259SFam Zheng         info->status = bdrv_dirty_bitmap_status(bm);
459ebab2259SFam Zheng         entry->value = info;
460ebab2259SFam Zheng         *plist = entry;
461ebab2259SFam Zheng         plist = &entry->next;
462ebab2259SFam Zheng     }
4632119882cSPaolo Bonzini     bdrv_dirty_bitmaps_unlock(bs);
464ebab2259SFam Zheng 
465ebab2259SFam Zheng     return list;
466ebab2259SFam Zheng }
467ebab2259SFam Zheng 
468b64bd51eSPaolo Bonzini /* Called within bdrv_dirty_bitmap_lock..unlock */
4693b5d4df0SEric Blake bool bdrv_get_dirty_locked(BlockDriverState *bs, BdrvDirtyBitmap *bitmap,
4703b5d4df0SEric Blake                            int64_t offset)
471ebab2259SFam Zheng {
472ebab2259SFam Zheng     if (bitmap) {
473ca759622SEric Blake         return hbitmap_get(bitmap->bitmap, offset);
474ebab2259SFam Zheng     } else {
4753b5d4df0SEric Blake         return false;
476ebab2259SFam Zheng     }
477ebab2259SFam Zheng }
478ebab2259SFam Zheng 
479ebab2259SFam Zheng /**
480ebab2259SFam Zheng  * Chooses a default granularity based on the existing cluster size,
481ebab2259SFam Zheng  * but clamped between [4K, 64K]. Defaults to 64K in the case that there
482ebab2259SFam Zheng  * is no cluster size information available.
483ebab2259SFam Zheng  */
484ebab2259SFam Zheng uint32_t bdrv_get_default_bitmap_granularity(BlockDriverState *bs)
485ebab2259SFam Zheng {
486ebab2259SFam Zheng     BlockDriverInfo bdi;
487ebab2259SFam Zheng     uint32_t granularity;
488ebab2259SFam Zheng 
489ebab2259SFam Zheng     if (bdrv_get_info(bs, &bdi) >= 0 && bdi.cluster_size > 0) {
490ebab2259SFam Zheng         granularity = MAX(4096, bdi.cluster_size);
491ebab2259SFam Zheng         granularity = MIN(65536, granularity);
492ebab2259SFam Zheng     } else {
493ebab2259SFam Zheng         granularity = 65536;
494ebab2259SFam Zheng     }
495ebab2259SFam Zheng 
496ebab2259SFam Zheng     return granularity;
497ebab2259SFam Zheng }
498ebab2259SFam Zheng 
499ba06ff1aSVladimir Sementsov-Ogievskiy uint32_t bdrv_dirty_bitmap_granularity(const BdrvDirtyBitmap *bitmap)
500ebab2259SFam Zheng {
501ca759622SEric Blake     return 1U << hbitmap_granularity(bitmap->bitmap);
502ebab2259SFam Zheng }
503ebab2259SFam Zheng 
504715a74d8SEric Blake BdrvDirtyBitmapIter *bdrv_dirty_iter_new(BdrvDirtyBitmap *bitmap)
505ebab2259SFam Zheng {
506dc162c8eSFam Zheng     BdrvDirtyBitmapIter *iter = g_new(BdrvDirtyBitmapIter, 1);
507715a74d8SEric Blake     hbitmap_iter_init(&iter->hbi, bitmap->bitmap, 0);
508dc162c8eSFam Zheng     iter->bitmap = bitmap;
509dc162c8eSFam Zheng     bitmap->active_iterators++;
510dc162c8eSFam Zheng     return iter;
511dc162c8eSFam Zheng }
512dc162c8eSFam Zheng 
5136d3f4049SFam Zheng BdrvDirtyBitmapIter *bdrv_dirty_meta_iter_new(BdrvDirtyBitmap *bitmap)
5146d3f4049SFam Zheng {
5156d3f4049SFam Zheng     BdrvDirtyBitmapIter *iter = g_new(BdrvDirtyBitmapIter, 1);
5166d3f4049SFam Zheng     hbitmap_iter_init(&iter->hbi, bitmap->meta, 0);
5176d3f4049SFam Zheng     iter->bitmap = bitmap;
5186d3f4049SFam Zheng     bitmap->active_iterators++;
5196d3f4049SFam Zheng     return iter;
5206d3f4049SFam Zheng }
5216d3f4049SFam Zheng 
522dc162c8eSFam Zheng void bdrv_dirty_iter_free(BdrvDirtyBitmapIter *iter)
523dc162c8eSFam Zheng {
524dc162c8eSFam Zheng     if (!iter) {
525dc162c8eSFam Zheng         return;
526dc162c8eSFam Zheng     }
527dc162c8eSFam Zheng     assert(iter->bitmap->active_iterators > 0);
528dc162c8eSFam Zheng     iter->bitmap->active_iterators--;
529dc162c8eSFam Zheng     g_free(iter);
530dc162c8eSFam Zheng }
531dc162c8eSFam Zheng 
532dc162c8eSFam Zheng int64_t bdrv_dirty_iter_next(BdrvDirtyBitmapIter *iter)
533dc162c8eSFam Zheng {
534a33fbb4fSMax Reitz     return hbitmap_iter_next(&iter->hbi, true);
535ebab2259SFam Zheng }
536ebab2259SFam Zheng 
53772d10a94SMax Reitz /**
53872d10a94SMax Reitz  * Return the next consecutively dirty area in the dirty bitmap
53972d10a94SMax Reitz  * belonging to the given iterator @iter.
54072d10a94SMax Reitz  *
54172d10a94SMax Reitz  * @max_offset: Maximum value that may be returned for
54272d10a94SMax Reitz  *              *offset + *bytes
54372d10a94SMax Reitz  * @offset:     Will contain the start offset of the next dirty area
54472d10a94SMax Reitz  * @bytes:      Will contain the length of the next dirty area
54572d10a94SMax Reitz  *
54672d10a94SMax Reitz  * Returns: True if a dirty area could be found before max_offset
54772d10a94SMax Reitz  *          (which means that *offset and *bytes then contain valid
54872d10a94SMax Reitz  *          values), false otherwise.
54972d10a94SMax Reitz  *
55072d10a94SMax Reitz  * Note that @iter is never advanced if false is returned.  If an area
55172d10a94SMax Reitz  * is found (which means that true is returned), it will be advanced
55272d10a94SMax Reitz  * past that area.
55372d10a94SMax Reitz  */
55472d10a94SMax Reitz bool bdrv_dirty_iter_next_area(BdrvDirtyBitmapIter *iter, uint64_t max_offset,
55572d10a94SMax Reitz                                uint64_t *offset, int *bytes)
55672d10a94SMax Reitz {
55772d10a94SMax Reitz     uint32_t granularity = bdrv_dirty_bitmap_granularity(iter->bitmap);
55872d10a94SMax Reitz     uint64_t gran_max_offset;
55972d10a94SMax Reitz     int64_t ret;
56072d10a94SMax Reitz     int size;
56172d10a94SMax Reitz 
56272d10a94SMax Reitz     if (max_offset == iter->bitmap->size) {
56372d10a94SMax Reitz         /* If max_offset points to the image end, round it up by the
56472d10a94SMax Reitz          * bitmap granularity */
56572d10a94SMax Reitz         gran_max_offset = ROUND_UP(max_offset, granularity);
56672d10a94SMax Reitz     } else {
56772d10a94SMax Reitz         gran_max_offset = max_offset;
56872d10a94SMax Reitz     }
56972d10a94SMax Reitz 
57072d10a94SMax Reitz     ret = hbitmap_iter_next(&iter->hbi, false);
57172d10a94SMax Reitz     if (ret < 0 || ret + granularity > gran_max_offset) {
57272d10a94SMax Reitz         return false;
57372d10a94SMax Reitz     }
57472d10a94SMax Reitz 
57572d10a94SMax Reitz     *offset = ret;
57672d10a94SMax Reitz     size = 0;
57772d10a94SMax Reitz 
57872d10a94SMax Reitz     assert(granularity <= INT_MAX);
57972d10a94SMax Reitz 
58072d10a94SMax Reitz     do {
58172d10a94SMax Reitz         /* Advance iterator */
58272d10a94SMax Reitz         ret = hbitmap_iter_next(&iter->hbi, true);
58372d10a94SMax Reitz         size += granularity;
58472d10a94SMax Reitz     } while (ret + granularity <= gran_max_offset &&
58572d10a94SMax Reitz              hbitmap_iter_next(&iter->hbi, false) == ret + granularity &&
58672d10a94SMax Reitz              size <= INT_MAX - granularity);
58772d10a94SMax Reitz 
58872d10a94SMax Reitz     *bytes = MIN(size, max_offset - *offset);
58972d10a94SMax Reitz     return true;
59072d10a94SMax Reitz }
59172d10a94SMax Reitz 
592b64bd51eSPaolo Bonzini /* Called within bdrv_dirty_bitmap_lock..unlock */
593b64bd51eSPaolo Bonzini void bdrv_set_dirty_bitmap_locked(BdrvDirtyBitmap *bitmap,
594e0d7f73eSEric Blake                                   int64_t offset, int64_t bytes)
595ebab2259SFam Zheng {
596ebab2259SFam Zheng     assert(bdrv_dirty_bitmap_enabled(bitmap));
597d6883bc9SVladimir Sementsov-Ogievskiy     assert(!bdrv_dirty_bitmap_readonly(bitmap));
598ca759622SEric Blake     hbitmap_set(bitmap->bitmap, offset, bytes);
599ebab2259SFam Zheng }
600ebab2259SFam Zheng 
601b64bd51eSPaolo Bonzini void bdrv_set_dirty_bitmap(BdrvDirtyBitmap *bitmap,
602e0d7f73eSEric Blake                            int64_t offset, int64_t bytes)
603b64bd51eSPaolo Bonzini {
604b64bd51eSPaolo Bonzini     bdrv_dirty_bitmap_lock(bitmap);
605e0d7f73eSEric Blake     bdrv_set_dirty_bitmap_locked(bitmap, offset, bytes);
606b64bd51eSPaolo Bonzini     bdrv_dirty_bitmap_unlock(bitmap);
607b64bd51eSPaolo Bonzini }
608b64bd51eSPaolo Bonzini 
609b64bd51eSPaolo Bonzini /* Called within bdrv_dirty_bitmap_lock..unlock */
610b64bd51eSPaolo Bonzini void bdrv_reset_dirty_bitmap_locked(BdrvDirtyBitmap *bitmap,
611e0d7f73eSEric Blake                                     int64_t offset, int64_t bytes)
612ebab2259SFam Zheng {
613ebab2259SFam Zheng     assert(bdrv_dirty_bitmap_enabled(bitmap));
614d6883bc9SVladimir Sementsov-Ogievskiy     assert(!bdrv_dirty_bitmap_readonly(bitmap));
615ca759622SEric Blake     hbitmap_reset(bitmap->bitmap, offset, bytes);
616ebab2259SFam Zheng }
617ebab2259SFam Zheng 
618b64bd51eSPaolo Bonzini void bdrv_reset_dirty_bitmap(BdrvDirtyBitmap *bitmap,
619e0d7f73eSEric Blake                              int64_t offset, int64_t bytes)
620b64bd51eSPaolo Bonzini {
621b64bd51eSPaolo Bonzini     bdrv_dirty_bitmap_lock(bitmap);
622e0d7f73eSEric Blake     bdrv_reset_dirty_bitmap_locked(bitmap, offset, bytes);
623b64bd51eSPaolo Bonzini     bdrv_dirty_bitmap_unlock(bitmap);
624b64bd51eSPaolo Bonzini }
625b64bd51eSPaolo Bonzini 
626ebab2259SFam Zheng void bdrv_clear_dirty_bitmap(BdrvDirtyBitmap *bitmap, HBitmap **out)
627ebab2259SFam Zheng {
628ebab2259SFam Zheng     assert(bdrv_dirty_bitmap_enabled(bitmap));
629d6883bc9SVladimir Sementsov-Ogievskiy     assert(!bdrv_dirty_bitmap_readonly(bitmap));
630b64bd51eSPaolo Bonzini     bdrv_dirty_bitmap_lock(bitmap);
631ebab2259SFam Zheng     if (!out) {
632ebab2259SFam Zheng         hbitmap_reset_all(bitmap->bitmap);
633ebab2259SFam Zheng     } else {
634ebab2259SFam Zheng         HBitmap *backup = bitmap->bitmap;
635ca759622SEric Blake         bitmap->bitmap = hbitmap_alloc(bitmap->size,
636ebab2259SFam Zheng                                        hbitmap_granularity(backup));
637ebab2259SFam Zheng         *out = backup;
638ebab2259SFam Zheng     }
639b64bd51eSPaolo Bonzini     bdrv_dirty_bitmap_unlock(bitmap);
640ebab2259SFam Zheng }
641ebab2259SFam Zheng 
64256bd6624SVladimir Sementsov-Ogievskiy void bdrv_restore_dirty_bitmap(BdrvDirtyBitmap *bitmap, HBitmap *backup)
643ebab2259SFam Zheng {
644ebab2259SFam Zheng     HBitmap *tmp = bitmap->bitmap;
645ebab2259SFam Zheng     assert(bdrv_dirty_bitmap_enabled(bitmap));
646d6883bc9SVladimir Sementsov-Ogievskiy     assert(!bdrv_dirty_bitmap_readonly(bitmap));
64756bd6624SVladimir Sementsov-Ogievskiy     bitmap->bitmap = backup;
648ebab2259SFam Zheng     hbitmap_free(tmp);
649ebab2259SFam Zheng }
650ebab2259SFam Zheng 
651882c36f5SVladimir Sementsov-Ogievskiy uint64_t bdrv_dirty_bitmap_serialization_size(const BdrvDirtyBitmap *bitmap,
65286f6ae67SEric Blake                                               uint64_t offset, uint64_t bytes)
653882c36f5SVladimir Sementsov-Ogievskiy {
654ca759622SEric Blake     return hbitmap_serialization_size(bitmap->bitmap, offset, bytes);
655882c36f5SVladimir Sementsov-Ogievskiy }
656882c36f5SVladimir Sementsov-Ogievskiy 
657882c36f5SVladimir Sementsov-Ogievskiy uint64_t bdrv_dirty_bitmap_serialization_align(const BdrvDirtyBitmap *bitmap)
658882c36f5SVladimir Sementsov-Ogievskiy {
659ca759622SEric Blake     return hbitmap_serialization_align(bitmap->bitmap);
660882c36f5SVladimir Sementsov-Ogievskiy }
661882c36f5SVladimir Sementsov-Ogievskiy 
662882c36f5SVladimir Sementsov-Ogievskiy void bdrv_dirty_bitmap_serialize_part(const BdrvDirtyBitmap *bitmap,
66386f6ae67SEric Blake                                       uint8_t *buf, uint64_t offset,
66486f6ae67SEric Blake                                       uint64_t bytes)
665882c36f5SVladimir Sementsov-Ogievskiy {
666ca759622SEric Blake     hbitmap_serialize_part(bitmap->bitmap, buf, offset, bytes);
667882c36f5SVladimir Sementsov-Ogievskiy }
668882c36f5SVladimir Sementsov-Ogievskiy 
669882c36f5SVladimir Sementsov-Ogievskiy void bdrv_dirty_bitmap_deserialize_part(BdrvDirtyBitmap *bitmap,
67086f6ae67SEric Blake                                         uint8_t *buf, uint64_t offset,
67186f6ae67SEric Blake                                         uint64_t bytes, bool finish)
672882c36f5SVladimir Sementsov-Ogievskiy {
673ca759622SEric Blake     hbitmap_deserialize_part(bitmap->bitmap, buf, offset, bytes, finish);
674882c36f5SVladimir Sementsov-Ogievskiy }
675882c36f5SVladimir Sementsov-Ogievskiy 
676882c36f5SVladimir Sementsov-Ogievskiy void bdrv_dirty_bitmap_deserialize_zeroes(BdrvDirtyBitmap *bitmap,
67786f6ae67SEric Blake                                           uint64_t offset, uint64_t bytes,
678882c36f5SVladimir Sementsov-Ogievskiy                                           bool finish)
679882c36f5SVladimir Sementsov-Ogievskiy {
680ca759622SEric Blake     hbitmap_deserialize_zeroes(bitmap->bitmap, offset, bytes, finish);
681882c36f5SVladimir Sementsov-Ogievskiy }
682882c36f5SVladimir Sementsov-Ogievskiy 
6836bdc8b71SVladimir Sementsov-Ogievskiy void bdrv_dirty_bitmap_deserialize_ones(BdrvDirtyBitmap *bitmap,
68486f6ae67SEric Blake                                         uint64_t offset, uint64_t bytes,
6856bdc8b71SVladimir Sementsov-Ogievskiy                                         bool finish)
6866bdc8b71SVladimir Sementsov-Ogievskiy {
687ca759622SEric Blake     hbitmap_deserialize_ones(bitmap->bitmap, offset, bytes, finish);
6886bdc8b71SVladimir Sementsov-Ogievskiy }
6896bdc8b71SVladimir Sementsov-Ogievskiy 
690882c36f5SVladimir Sementsov-Ogievskiy void bdrv_dirty_bitmap_deserialize_finish(BdrvDirtyBitmap *bitmap)
691882c36f5SVladimir Sementsov-Ogievskiy {
692882c36f5SVladimir Sementsov-Ogievskiy     hbitmap_deserialize_finish(bitmap->bitmap);
693882c36f5SVladimir Sementsov-Ogievskiy }
694882c36f5SVladimir Sementsov-Ogievskiy 
6950fdf1a4fSEric Blake void bdrv_set_dirty(BlockDriverState *bs, int64_t offset, int64_t bytes)
696ebab2259SFam Zheng {
697ebab2259SFam Zheng     BdrvDirtyBitmap *bitmap;
6982119882cSPaolo Bonzini 
6992119882cSPaolo Bonzini     if (QLIST_EMPTY(&bs->dirty_bitmaps)) {
7002119882cSPaolo Bonzini         return;
7012119882cSPaolo Bonzini     }
7022119882cSPaolo Bonzini 
7032119882cSPaolo Bonzini     bdrv_dirty_bitmaps_lock(bs);
704ebab2259SFam Zheng     QLIST_FOREACH(bitmap, &bs->dirty_bitmaps, list) {
705ebab2259SFam Zheng         if (!bdrv_dirty_bitmap_enabled(bitmap)) {
706ebab2259SFam Zheng             continue;
707ebab2259SFam Zheng         }
708d6883bc9SVladimir Sementsov-Ogievskiy         assert(!bdrv_dirty_bitmap_readonly(bitmap));
709ca759622SEric Blake         hbitmap_set(bitmap->bitmap, offset, bytes);
710ebab2259SFam Zheng     }
7112119882cSPaolo Bonzini     bdrv_dirty_bitmaps_unlock(bs);
712ebab2259SFam Zheng }
713ebab2259SFam Zheng 
714ebab2259SFam Zheng /**
715dc162c8eSFam Zheng  * Advance a BdrvDirtyBitmapIter to an arbitrary offset.
716ebab2259SFam Zheng  */
717715a74d8SEric Blake void bdrv_set_dirty_iter(BdrvDirtyBitmapIter *iter, int64_t offset)
718ebab2259SFam Zheng {
719ca759622SEric Blake     hbitmap_iter_init(&iter->hbi, iter->hbi.hb, offset);
720ebab2259SFam Zheng }
721ebab2259SFam Zheng 
722ebab2259SFam Zheng int64_t bdrv_get_dirty_count(BdrvDirtyBitmap *bitmap)
723ebab2259SFam Zheng {
724ca759622SEric Blake     return hbitmap_count(bitmap->bitmap);
725ebab2259SFam Zheng }
7266d3f4049SFam Zheng 
7276d3f4049SFam Zheng int64_t bdrv_get_meta_dirty_count(BdrvDirtyBitmap *bitmap)
7286d3f4049SFam Zheng {
7296d3f4049SFam Zheng     return hbitmap_count(bitmap->meta);
7306d3f4049SFam Zheng }
731d6883bc9SVladimir Sementsov-Ogievskiy 
732d6883bc9SVladimir Sementsov-Ogievskiy bool bdrv_dirty_bitmap_readonly(const BdrvDirtyBitmap *bitmap)
733d6883bc9SVladimir Sementsov-Ogievskiy {
734d6883bc9SVladimir Sementsov-Ogievskiy     return bitmap->readonly;
735d6883bc9SVladimir Sementsov-Ogievskiy }
736d6883bc9SVladimir Sementsov-Ogievskiy 
737d6883bc9SVladimir Sementsov-Ogievskiy /* Called with BQL taken. */
738d6883bc9SVladimir Sementsov-Ogievskiy void bdrv_dirty_bitmap_set_readonly(BdrvDirtyBitmap *bitmap, bool value)
739d6883bc9SVladimir Sementsov-Ogievskiy {
740d6883bc9SVladimir Sementsov-Ogievskiy     qemu_mutex_lock(bitmap->mutex);
741d6883bc9SVladimir Sementsov-Ogievskiy     bitmap->readonly = value;
742d6883bc9SVladimir Sementsov-Ogievskiy     qemu_mutex_unlock(bitmap->mutex);
743d6883bc9SVladimir Sementsov-Ogievskiy }
744d6883bc9SVladimir Sementsov-Ogievskiy 
745d6883bc9SVladimir Sementsov-Ogievskiy bool bdrv_has_readonly_bitmaps(BlockDriverState *bs)
746d6883bc9SVladimir Sementsov-Ogievskiy {
747d6883bc9SVladimir Sementsov-Ogievskiy     BdrvDirtyBitmap *bm;
748d6883bc9SVladimir Sementsov-Ogievskiy     QLIST_FOREACH(bm, &bs->dirty_bitmaps, list) {
749d6883bc9SVladimir Sementsov-Ogievskiy         if (bm->readonly) {
750d6883bc9SVladimir Sementsov-Ogievskiy             return true;
751d6883bc9SVladimir Sementsov-Ogievskiy         }
752d6883bc9SVladimir Sementsov-Ogievskiy     }
753d6883bc9SVladimir Sementsov-Ogievskiy 
754d6883bc9SVladimir Sementsov-Ogievskiy     return false;
755d6883bc9SVladimir Sementsov-Ogievskiy }
756a0319aacSVladimir Sementsov-Ogievskiy 
757a0319aacSVladimir Sementsov-Ogievskiy /* Called with BQL taken. */
758a88b179fSVladimir Sementsov-Ogievskiy void bdrv_dirty_bitmap_set_persistance(BdrvDirtyBitmap *bitmap, bool persistent)
759a88b179fSVladimir Sementsov-Ogievskiy {
760a88b179fSVladimir Sementsov-Ogievskiy     qemu_mutex_lock(bitmap->mutex);
761a88b179fSVladimir Sementsov-Ogievskiy     bitmap->persistent = persistent;
762a88b179fSVladimir Sementsov-Ogievskiy     qemu_mutex_unlock(bitmap->mutex);
763a88b179fSVladimir Sementsov-Ogievskiy }
764a88b179fSVladimir Sementsov-Ogievskiy 
765a88b179fSVladimir Sementsov-Ogievskiy bool bdrv_dirty_bitmap_get_persistance(BdrvDirtyBitmap *bitmap)
766a88b179fSVladimir Sementsov-Ogievskiy {
767a88b179fSVladimir Sementsov-Ogievskiy     return bitmap->persistent;
768a88b179fSVladimir Sementsov-Ogievskiy }
769a88b179fSVladimir Sementsov-Ogievskiy 
770a88b179fSVladimir Sementsov-Ogievskiy bool bdrv_has_changed_persistent_bitmaps(BlockDriverState *bs)
771a88b179fSVladimir Sementsov-Ogievskiy {
772a88b179fSVladimir Sementsov-Ogievskiy     BdrvDirtyBitmap *bm;
773a88b179fSVladimir Sementsov-Ogievskiy     QLIST_FOREACH(bm, &bs->dirty_bitmaps, list) {
774a88b179fSVladimir Sementsov-Ogievskiy         if (bm->persistent && !bm->readonly) {
775a88b179fSVladimir Sementsov-Ogievskiy             return true;
776a88b179fSVladimir Sementsov-Ogievskiy         }
777a88b179fSVladimir Sementsov-Ogievskiy     }
778a88b179fSVladimir Sementsov-Ogievskiy 
779a88b179fSVladimir Sementsov-Ogievskiy     return false;
780a88b179fSVladimir Sementsov-Ogievskiy }
7813dd10a06SVladimir Sementsov-Ogievskiy 
7823dd10a06SVladimir Sementsov-Ogievskiy BdrvDirtyBitmap *bdrv_dirty_bitmap_next(BlockDriverState *bs,
7833dd10a06SVladimir Sementsov-Ogievskiy                                         BdrvDirtyBitmap *bitmap)
7843dd10a06SVladimir Sementsov-Ogievskiy {
7853dd10a06SVladimir Sementsov-Ogievskiy     return bitmap == NULL ? QLIST_FIRST(&bs->dirty_bitmaps) :
7863dd10a06SVladimir Sementsov-Ogievskiy                             QLIST_NEXT(bitmap, list);
7873dd10a06SVladimir Sementsov-Ogievskiy }
788a3b52535SVladimir Sementsov-Ogievskiy 
789a3b52535SVladimir Sementsov-Ogievskiy char *bdrv_dirty_bitmap_sha256(const BdrvDirtyBitmap *bitmap, Error **errp)
790a3b52535SVladimir Sementsov-Ogievskiy {
791a3b52535SVladimir Sementsov-Ogievskiy     return hbitmap_sha256(bitmap->bitmap, errp);
792a3b52535SVladimir Sementsov-Ogievskiy }
79356207df5SVladimir Sementsov-Ogievskiy 
79456207df5SVladimir Sementsov-Ogievskiy int64_t bdrv_dirty_bitmap_next_zero(BdrvDirtyBitmap *bitmap, uint64_t offset)
79556207df5SVladimir Sementsov-Ogievskiy {
79656207df5SVladimir Sementsov-Ogievskiy     return hbitmap_next_zero(bitmap->bitmap, offset);
79756207df5SVladimir Sementsov-Ogievskiy }
798b598e531SVladimir Sementsov-Ogievskiy 
799b598e531SVladimir Sementsov-Ogievskiy void bdrv_merge_dirty_bitmap(BdrvDirtyBitmap *dest, const BdrvDirtyBitmap *src,
800fa000f2fSVladimir Sementsov-Ogievskiy                              HBitmap **backup, Error **errp)
801b598e531SVladimir Sementsov-Ogievskiy {
802fa000f2fSVladimir Sementsov-Ogievskiy     bool ret;
803fa000f2fSVladimir Sementsov-Ogievskiy 
804b598e531SVladimir Sementsov-Ogievskiy     /* only bitmaps from one bds are supported */
805b598e531SVladimir Sementsov-Ogievskiy     assert(dest->mutex == src->mutex);
806b598e531SVladimir Sementsov-Ogievskiy 
807b598e531SVladimir Sementsov-Ogievskiy     qemu_mutex_lock(dest->mutex);
808b598e531SVladimir Sementsov-Ogievskiy 
809*283d7a04SJohn Snow     if (bdrv_dirty_bitmap_user_locked(dest)) {
810*283d7a04SJohn Snow         error_setg(errp, "Bitmap '%s' is currently in use by another"
811*283d7a04SJohn Snow         " operation and cannot be modified", dest->name);
81206bf5006SVladimir Sementsov-Ogievskiy         goto out;
81306bf5006SVladimir Sementsov-Ogievskiy     }
81406bf5006SVladimir Sementsov-Ogievskiy 
81506bf5006SVladimir Sementsov-Ogievskiy     if (bdrv_dirty_bitmap_readonly(dest)) {
81606bf5006SVladimir Sementsov-Ogievskiy         error_setg(errp, "Bitmap '%s' is readonly and cannot be modified",
81706bf5006SVladimir Sementsov-Ogievskiy                    dest->name);
81806bf5006SVladimir Sementsov-Ogievskiy         goto out;
81906bf5006SVladimir Sementsov-Ogievskiy     }
820b598e531SVladimir Sementsov-Ogievskiy 
821fa000f2fSVladimir Sementsov-Ogievskiy     if (!hbitmap_can_merge(dest->bitmap, src->bitmap)) {
822b598e531SVladimir Sementsov-Ogievskiy         error_setg(errp, "Bitmaps are incompatible and can't be merged");
82306bf5006SVladimir Sementsov-Ogievskiy         goto out;
824b598e531SVladimir Sementsov-Ogievskiy     }
825b598e531SVladimir Sementsov-Ogievskiy 
826fa000f2fSVladimir Sementsov-Ogievskiy     if (backup) {
827fa000f2fSVladimir Sementsov-Ogievskiy         *backup = dest->bitmap;
828fa000f2fSVladimir Sementsov-Ogievskiy         dest->bitmap = hbitmap_alloc(dest->size, hbitmap_granularity(*backup));
829fa000f2fSVladimir Sementsov-Ogievskiy         ret = hbitmap_merge(*backup, src->bitmap, dest->bitmap);
830fa000f2fSVladimir Sementsov-Ogievskiy     } else {
831fa000f2fSVladimir Sementsov-Ogievskiy         ret = hbitmap_merge(dest->bitmap, src->bitmap, dest->bitmap);
832fa000f2fSVladimir Sementsov-Ogievskiy     }
833fa000f2fSVladimir Sementsov-Ogievskiy     assert(ret);
834fa000f2fSVladimir Sementsov-Ogievskiy 
83506bf5006SVladimir Sementsov-Ogievskiy out:
836b598e531SVladimir Sementsov-Ogievskiy     qemu_mutex_unlock(dest->mutex);
837b598e531SVladimir Sementsov-Ogievskiy }
838