]> Git Repo - qemu.git/blob - block/dirty-bitmap.c
block/dirty-bitmap: add lock to bdrv_enable/disable_dirty_bitmap
[qemu.git] / block / dirty-bitmap.c
1 /*
2  * Block Dirty Bitmap
3  *
4  * Copyright (c) 2016-2017 Red Hat. Inc
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to deal
8  * in the Software without restriction, including without limitation the rights
9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10  * copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22  * THE SOFTWARE.
23  */
24 #include "qemu/osdep.h"
25 #include "qapi/error.h"
26 #include "qemu-common.h"
27 #include "trace.h"
28 #include "block/block_int.h"
29 #include "block/blockjob.h"
30
31 /**
32  * A BdrvDirtyBitmap can be in three possible states:
33  * (1) successor is NULL and disabled is false: full r/w mode
34  * (2) successor is NULL and disabled is true: read only mode ("disabled")
35  * (3) successor is set: frozen mode.
36  *     A frozen bitmap cannot be renamed, deleted, anonymized, cleared, set,
37  *     or enabled. A frozen bitmap can only abdicate() or reclaim().
38  */
39 struct BdrvDirtyBitmap {
40     QemuMutex *mutex;
41     HBitmap *bitmap;            /* Dirty bitmap implementation */
42     HBitmap *meta;              /* Meta dirty bitmap */
43     bool qmp_locked;            /* Bitmap is locked, it can't be modified
44                                    through QMP */
45     BdrvDirtyBitmap *successor; /* Anonymous child; implies frozen status */
46     char *name;                 /* Optional non-empty unique ID */
47     int64_t size;               /* Size of the bitmap, in bytes */
48     bool disabled;              /* Bitmap is disabled. It ignores all writes to
49                                    the device */
50     int active_iterators;       /* How many iterators are active */
51     bool readonly;              /* Bitmap is read-only. This field also
52                                    prevents the respective image from being
53                                    modified (i.e. blocks writes and discards).
54                                    Such operations must fail and both the image
55                                    and this bitmap must remain unchanged while
56                                    this flag is set. */
57     bool persistent;            /* bitmap must be saved to owner disk image */
58     QLIST_ENTRY(BdrvDirtyBitmap) list;
59 };
60
61 struct BdrvDirtyBitmapIter {
62     HBitmapIter hbi;
63     BdrvDirtyBitmap *bitmap;
64 };
65
66 static inline void bdrv_dirty_bitmaps_lock(BlockDriverState *bs)
67 {
68     qemu_mutex_lock(&bs->dirty_bitmap_mutex);
69 }
70
71 static inline void bdrv_dirty_bitmaps_unlock(BlockDriverState *bs)
72 {
73     qemu_mutex_unlock(&bs->dirty_bitmap_mutex);
74 }
75
76 void bdrv_dirty_bitmap_lock(BdrvDirtyBitmap *bitmap)
77 {
78     qemu_mutex_lock(bitmap->mutex);
79 }
80
81 void bdrv_dirty_bitmap_unlock(BdrvDirtyBitmap *bitmap)
82 {
83     qemu_mutex_unlock(bitmap->mutex);
84 }
85
86 /* Called with BQL or dirty_bitmap lock taken.  */
87 BdrvDirtyBitmap *bdrv_find_dirty_bitmap(BlockDriverState *bs, const char *name)
88 {
89     BdrvDirtyBitmap *bm;
90
91     assert(name);
92     QLIST_FOREACH(bm, &bs->dirty_bitmaps, list) {
93         if (bm->name && !strcmp(name, bm->name)) {
94             return bm;
95         }
96     }
97     return NULL;
98 }
99
100 /* Called with BQL taken.  */
101 BdrvDirtyBitmap *bdrv_create_dirty_bitmap(BlockDriverState *bs,
102                                           uint32_t granularity,
103                                           const char *name,
104                                           Error **errp)
105 {
106     int64_t bitmap_size;
107     BdrvDirtyBitmap *bitmap;
108
109     assert(is_power_of_2(granularity) && granularity >= BDRV_SECTOR_SIZE);
110
111     if (name && bdrv_find_dirty_bitmap(bs, name)) {
112         error_setg(errp, "Bitmap already exists: %s", name);
113         return NULL;
114     }
115     bitmap_size = bdrv_getlength(bs);
116     if (bitmap_size < 0) {
117         error_setg_errno(errp, -bitmap_size, "could not get length of device");
118         errno = -bitmap_size;
119         return NULL;
120     }
121     bitmap = g_new0(BdrvDirtyBitmap, 1);
122     bitmap->mutex = &bs->dirty_bitmap_mutex;
123     bitmap->bitmap = hbitmap_alloc(bitmap_size, ctz32(granularity));
124     bitmap->size = bitmap_size;
125     bitmap->name = g_strdup(name);
126     bitmap->disabled = false;
127     bdrv_dirty_bitmaps_lock(bs);
128     QLIST_INSERT_HEAD(&bs->dirty_bitmaps, bitmap, list);
129     bdrv_dirty_bitmaps_unlock(bs);
130     return bitmap;
131 }
132
133 /* bdrv_create_meta_dirty_bitmap
134  *
135  * Create a meta dirty bitmap that tracks the changes of bits in @bitmap. I.e.
136  * when a dirty status bit in @bitmap is changed (either from reset to set or
137  * the other way around), its respective meta dirty bitmap bit will be marked
138  * dirty as well.
139  *
140  * @bitmap: the block dirty bitmap for which to create a meta dirty bitmap.
141  * @chunk_size: how many bytes of bitmap data does each bit in the meta bitmap
142  * track.
143  */
144 void bdrv_create_meta_dirty_bitmap(BdrvDirtyBitmap *bitmap,
145                                    int chunk_size)
146 {
147     assert(!bitmap->meta);
148     qemu_mutex_lock(bitmap->mutex);
149     bitmap->meta = hbitmap_create_meta(bitmap->bitmap,
150                                        chunk_size * BITS_PER_BYTE);
151     qemu_mutex_unlock(bitmap->mutex);
152 }
153
154 void bdrv_release_meta_dirty_bitmap(BdrvDirtyBitmap *bitmap)
155 {
156     assert(bitmap->meta);
157     qemu_mutex_lock(bitmap->mutex);
158     hbitmap_free_meta(bitmap->bitmap);
159     bitmap->meta = NULL;
160     qemu_mutex_unlock(bitmap->mutex);
161 }
162
163 int64_t bdrv_dirty_bitmap_size(const BdrvDirtyBitmap *bitmap)
164 {
165     return bitmap->size;
166 }
167
168 const char *bdrv_dirty_bitmap_name(const BdrvDirtyBitmap *bitmap)
169 {
170     return bitmap->name;
171 }
172
173 /* Called with BQL taken.  */
174 bool bdrv_dirty_bitmap_frozen(BdrvDirtyBitmap *bitmap)
175 {
176     return bitmap->successor;
177 }
178
179 void bdrv_dirty_bitmap_set_qmp_locked(BdrvDirtyBitmap *bitmap, bool qmp_locked)
180 {
181     qemu_mutex_lock(bitmap->mutex);
182     bitmap->qmp_locked = qmp_locked;
183     qemu_mutex_unlock(bitmap->mutex);
184 }
185
186 bool bdrv_dirty_bitmap_qmp_locked(BdrvDirtyBitmap *bitmap)
187 {
188     return bitmap->qmp_locked;
189 }
190
191 /* Called with BQL taken.  */
192 bool bdrv_dirty_bitmap_enabled(BdrvDirtyBitmap *bitmap)
193 {
194     return !(bitmap->disabled || bitmap->successor);
195 }
196
197 /* Called with BQL taken.  */
198 DirtyBitmapStatus bdrv_dirty_bitmap_status(BdrvDirtyBitmap *bitmap)
199 {
200     if (bdrv_dirty_bitmap_frozen(bitmap)) {
201         return DIRTY_BITMAP_STATUS_FROZEN;
202     } else if (bdrv_dirty_bitmap_qmp_locked(bitmap)) {
203         return DIRTY_BITMAP_STATUS_LOCKED;
204     } else if (!bdrv_dirty_bitmap_enabled(bitmap)) {
205         return DIRTY_BITMAP_STATUS_DISABLED;
206     } else {
207         return DIRTY_BITMAP_STATUS_ACTIVE;
208     }
209 }
210
211 /**
212  * Create a successor bitmap destined to replace this bitmap after an operation.
213  * Requires that the bitmap is not frozen and has no successor.
214  * Called with BQL taken.
215  */
216 int bdrv_dirty_bitmap_create_successor(BlockDriverState *bs,
217                                        BdrvDirtyBitmap *bitmap, Error **errp)
218 {
219     uint64_t granularity;
220     BdrvDirtyBitmap *child;
221
222     if (bdrv_dirty_bitmap_frozen(bitmap)) {
223         error_setg(errp, "Cannot create a successor for a bitmap that is "
224                    "currently frozen");
225         return -1;
226     }
227     assert(!bitmap->successor);
228
229     /* Create an anonymous successor */
230     granularity = bdrv_dirty_bitmap_granularity(bitmap);
231     child = bdrv_create_dirty_bitmap(bs, granularity, NULL, errp);
232     if (!child) {
233         return -1;
234     }
235
236     /* Successor will be on or off based on our current state. */
237     child->disabled = bitmap->disabled;
238
239     /* Install the successor and freeze the parent */
240     bitmap->successor = child;
241     return 0;
242 }
243
244 /* Called with BQL taken. */
245 void bdrv_dirty_bitmap_enable_successor(BdrvDirtyBitmap *bitmap)
246 {
247     qemu_mutex_lock(bitmap->mutex);
248     bdrv_enable_dirty_bitmap(bitmap->successor);
249     qemu_mutex_unlock(bitmap->mutex);
250 }
251
252 /* Called within bdrv_dirty_bitmap_lock..unlock and with BQL taken.  */
253 static void bdrv_release_dirty_bitmap_locked(BdrvDirtyBitmap *bitmap)
254 {
255     assert(!bitmap->active_iterators);
256     assert(!bdrv_dirty_bitmap_frozen(bitmap));
257     assert(!bitmap->meta);
258     QLIST_REMOVE(bitmap, list);
259     hbitmap_free(bitmap->bitmap);
260     g_free(bitmap->name);
261     g_free(bitmap);
262 }
263
264 /**
265  * For a bitmap with a successor, yield our name to the successor,
266  * delete the old bitmap, and return a handle to the new bitmap.
267  * Called with BQL taken.
268  */
269 BdrvDirtyBitmap *bdrv_dirty_bitmap_abdicate(BlockDriverState *bs,
270                                             BdrvDirtyBitmap *bitmap,
271                                             Error **errp)
272 {
273     char *name;
274     BdrvDirtyBitmap *successor = bitmap->successor;
275
276     if (successor == NULL) {
277         error_setg(errp, "Cannot relinquish control if "
278                    "there's no successor present");
279         return NULL;
280     }
281
282     name = bitmap->name;
283     bitmap->name = NULL;
284     successor->name = name;
285     bitmap->successor = NULL;
286     successor->persistent = bitmap->persistent;
287     bitmap->persistent = false;
288     bdrv_release_dirty_bitmap(bs, bitmap);
289
290     return successor;
291 }
292
293 /**
294  * In cases of failure where we can no longer safely delete the parent,
295  * we may wish to re-join the parent and child/successor.
296  * The merged parent will be un-frozen, but not explicitly re-enabled.
297  * Called within bdrv_dirty_bitmap_lock..unlock and with BQL taken.
298  */
299 BdrvDirtyBitmap *bdrv_reclaim_dirty_bitmap_locked(BlockDriverState *bs,
300                                                   BdrvDirtyBitmap *parent,
301                                                   Error **errp)
302 {
303     BdrvDirtyBitmap *successor = parent->successor;
304
305     if (!successor) {
306         error_setg(errp, "Cannot reclaim a successor when none is present");
307         return NULL;
308     }
309
310     if (!hbitmap_merge(parent->bitmap, successor->bitmap)) {
311         error_setg(errp, "Merging of parent and successor bitmap failed");
312         return NULL;
313     }
314     bdrv_release_dirty_bitmap_locked(successor);
315     parent->successor = NULL;
316
317     return parent;
318 }
319
320 /* Called with BQL taken. */
321 BdrvDirtyBitmap *bdrv_reclaim_dirty_bitmap(BlockDriverState *bs,
322                                            BdrvDirtyBitmap *parent,
323                                            Error **errp)
324 {
325     BdrvDirtyBitmap *ret;
326
327     qemu_mutex_lock(parent->mutex);
328     ret = bdrv_reclaim_dirty_bitmap_locked(bs, parent, errp);
329     qemu_mutex_unlock(parent->mutex);
330
331     return ret;
332 }
333
334 /**
335  * Truncates _all_ bitmaps attached to a BDS.
336  * Called with BQL taken.
337  */
338 void bdrv_dirty_bitmap_truncate(BlockDriverState *bs, int64_t bytes)
339 {
340     BdrvDirtyBitmap *bitmap;
341
342     bdrv_dirty_bitmaps_lock(bs);
343     QLIST_FOREACH(bitmap, &bs->dirty_bitmaps, list) {
344         assert(!bdrv_dirty_bitmap_frozen(bitmap));
345         assert(!bitmap->active_iterators);
346         hbitmap_truncate(bitmap->bitmap, bytes);
347         bitmap->size = bytes;
348     }
349     bdrv_dirty_bitmaps_unlock(bs);
350 }
351
352 /* Called with BQL taken.  */
353 void bdrv_release_dirty_bitmap(BlockDriverState *bs, BdrvDirtyBitmap *bitmap)
354 {
355     bdrv_dirty_bitmaps_lock(bs);
356     bdrv_release_dirty_bitmap_locked(bitmap);
357     bdrv_dirty_bitmaps_unlock(bs);
358 }
359
360 /**
361  * Release all named dirty bitmaps attached to a BDS (for use in bdrv_close()).
362  * There must not be any frozen bitmaps attached.
363  * This function does not remove persistent bitmaps from the storage.
364  * Called with BQL taken.
365  */
366 void bdrv_release_named_dirty_bitmaps(BlockDriverState *bs)
367 {
368     BdrvDirtyBitmap *bm, *next;
369
370     bdrv_dirty_bitmaps_lock(bs);
371     QLIST_FOREACH_SAFE(bm, &bs->dirty_bitmaps, list, next) {
372         if (bdrv_dirty_bitmap_name(bm)) {
373             bdrv_release_dirty_bitmap_locked(bm);
374         }
375     }
376     bdrv_dirty_bitmaps_unlock(bs);
377 }
378
379 /**
380  * Release all persistent dirty bitmaps attached to a BDS (for use in
381  * bdrv_inactivate_recurse()).
382  * There must not be any frozen bitmaps attached.
383  * This function does not remove persistent bitmaps from the storage.
384  * Called with BQL taken.
385  */
386 void bdrv_release_persistent_dirty_bitmaps(BlockDriverState *bs)
387 {
388     BdrvDirtyBitmap *bm, *next;
389
390     bdrv_dirty_bitmaps_lock(bs);
391     QLIST_FOREACH_SAFE(bm, &bs->dirty_bitmaps, list, next) {
392         if (bdrv_dirty_bitmap_get_persistance(bm)) {
393             bdrv_release_dirty_bitmap_locked(bm);
394         }
395     }
396     bdrv_dirty_bitmaps_unlock(bs);
397 }
398
399 /**
400  * Remove persistent dirty bitmap from the storage if it exists.
401  * Absence of bitmap is not an error, because we have the following scenario:
402  * BdrvDirtyBitmap can have .persistent = true but not yet saved and have no
403  * stored version. For such bitmap bdrv_remove_persistent_dirty_bitmap() should
404  * not fail.
405  * This function doesn't release corresponding BdrvDirtyBitmap.
406  */
407 void bdrv_remove_persistent_dirty_bitmap(BlockDriverState *bs,
408                                          const char *name,
409                                          Error **errp)
410 {
411     if (bs->drv && bs->drv->bdrv_remove_persistent_dirty_bitmap) {
412         bs->drv->bdrv_remove_persistent_dirty_bitmap(bs, name, errp);
413     }
414 }
415
416 void bdrv_disable_dirty_bitmap(BdrvDirtyBitmap *bitmap)
417 {
418     bdrv_dirty_bitmap_lock(bitmap);
419     assert(!bdrv_dirty_bitmap_frozen(bitmap));
420     bitmap->disabled = true;
421     bdrv_dirty_bitmap_unlock(bitmap);
422 }
423
424 void bdrv_enable_dirty_bitmap(BdrvDirtyBitmap *bitmap)
425 {
426     bdrv_dirty_bitmap_lock(bitmap);
427     assert(!bdrv_dirty_bitmap_frozen(bitmap));
428     bitmap->disabled = false;
429     bdrv_dirty_bitmap_unlock(bitmap);
430 }
431
432 BlockDirtyInfoList *bdrv_query_dirty_bitmaps(BlockDriverState *bs)
433 {
434     BdrvDirtyBitmap *bm;
435     BlockDirtyInfoList *list = NULL;
436     BlockDirtyInfoList **plist = &list;
437
438     bdrv_dirty_bitmaps_lock(bs);
439     QLIST_FOREACH(bm, &bs->dirty_bitmaps, list) {
440         BlockDirtyInfo *info = g_new0(BlockDirtyInfo, 1);
441         BlockDirtyInfoList *entry = g_new0(BlockDirtyInfoList, 1);
442         info->count = bdrv_get_dirty_count(bm);
443         info->granularity = bdrv_dirty_bitmap_granularity(bm);
444         info->has_name = !!bm->name;
445         info->name = g_strdup(bm->name);
446         info->status = bdrv_dirty_bitmap_status(bm);
447         entry->value = info;
448         *plist = entry;
449         plist = &entry->next;
450     }
451     bdrv_dirty_bitmaps_unlock(bs);
452
453     return list;
454 }
455
456 /* Called within bdrv_dirty_bitmap_lock..unlock */
457 bool bdrv_get_dirty_locked(BlockDriverState *bs, BdrvDirtyBitmap *bitmap,
458                            int64_t offset)
459 {
460     if (bitmap) {
461         return hbitmap_get(bitmap->bitmap, offset);
462     } else {
463         return false;
464     }
465 }
466
467 /**
468  * Chooses a default granularity based on the existing cluster size,
469  * but clamped between [4K, 64K]. Defaults to 64K in the case that there
470  * is no cluster size information available.
471  */
472 uint32_t bdrv_get_default_bitmap_granularity(BlockDriverState *bs)
473 {
474     BlockDriverInfo bdi;
475     uint32_t granularity;
476
477     if (bdrv_get_info(bs, &bdi) >= 0 && bdi.cluster_size > 0) {
478         granularity = MAX(4096, bdi.cluster_size);
479         granularity = MIN(65536, granularity);
480     } else {
481         granularity = 65536;
482     }
483
484     return granularity;
485 }
486
487 uint32_t bdrv_dirty_bitmap_granularity(const BdrvDirtyBitmap *bitmap)
488 {
489     return 1U << hbitmap_granularity(bitmap->bitmap);
490 }
491
492 BdrvDirtyBitmapIter *bdrv_dirty_iter_new(BdrvDirtyBitmap *bitmap)
493 {
494     BdrvDirtyBitmapIter *iter = g_new(BdrvDirtyBitmapIter, 1);
495     hbitmap_iter_init(&iter->hbi, bitmap->bitmap, 0);
496     iter->bitmap = bitmap;
497     bitmap->active_iterators++;
498     return iter;
499 }
500
501 BdrvDirtyBitmapIter *bdrv_dirty_meta_iter_new(BdrvDirtyBitmap *bitmap)
502 {
503     BdrvDirtyBitmapIter *iter = g_new(BdrvDirtyBitmapIter, 1);
504     hbitmap_iter_init(&iter->hbi, bitmap->meta, 0);
505     iter->bitmap = bitmap;
506     bitmap->active_iterators++;
507     return iter;
508 }
509
510 void bdrv_dirty_iter_free(BdrvDirtyBitmapIter *iter)
511 {
512     if (!iter) {
513         return;
514     }
515     assert(iter->bitmap->active_iterators > 0);
516     iter->bitmap->active_iterators--;
517     g_free(iter);
518 }
519
520 int64_t bdrv_dirty_iter_next(BdrvDirtyBitmapIter *iter)
521 {
522     return hbitmap_iter_next(&iter->hbi);
523 }
524
525 /* Called within bdrv_dirty_bitmap_lock..unlock */
526 void bdrv_set_dirty_bitmap_locked(BdrvDirtyBitmap *bitmap,
527                                   int64_t offset, int64_t bytes)
528 {
529     assert(bdrv_dirty_bitmap_enabled(bitmap));
530     assert(!bdrv_dirty_bitmap_readonly(bitmap));
531     hbitmap_set(bitmap->bitmap, offset, bytes);
532 }
533
534 void bdrv_set_dirty_bitmap(BdrvDirtyBitmap *bitmap,
535                            int64_t offset, int64_t bytes)
536 {
537     bdrv_dirty_bitmap_lock(bitmap);
538     bdrv_set_dirty_bitmap_locked(bitmap, offset, bytes);
539     bdrv_dirty_bitmap_unlock(bitmap);
540 }
541
542 /* Called within bdrv_dirty_bitmap_lock..unlock */
543 void bdrv_reset_dirty_bitmap_locked(BdrvDirtyBitmap *bitmap,
544                                     int64_t offset, int64_t bytes)
545 {
546     assert(bdrv_dirty_bitmap_enabled(bitmap));
547     assert(!bdrv_dirty_bitmap_readonly(bitmap));
548     hbitmap_reset(bitmap->bitmap, offset, bytes);
549 }
550
551 void bdrv_reset_dirty_bitmap(BdrvDirtyBitmap *bitmap,
552                              int64_t offset, int64_t bytes)
553 {
554     bdrv_dirty_bitmap_lock(bitmap);
555     bdrv_reset_dirty_bitmap_locked(bitmap, offset, bytes);
556     bdrv_dirty_bitmap_unlock(bitmap);
557 }
558
559 void bdrv_clear_dirty_bitmap(BdrvDirtyBitmap *bitmap, HBitmap **out)
560 {
561     assert(bdrv_dirty_bitmap_enabled(bitmap));
562     assert(!bdrv_dirty_bitmap_readonly(bitmap));
563     bdrv_dirty_bitmap_lock(bitmap);
564     if (!out) {
565         hbitmap_reset_all(bitmap->bitmap);
566     } else {
567         HBitmap *backup = bitmap->bitmap;
568         bitmap->bitmap = hbitmap_alloc(bitmap->size,
569                                        hbitmap_granularity(backup));
570         *out = backup;
571     }
572     bdrv_dirty_bitmap_unlock(bitmap);
573 }
574
575 void bdrv_undo_clear_dirty_bitmap(BdrvDirtyBitmap *bitmap, HBitmap *in)
576 {
577     HBitmap *tmp = bitmap->bitmap;
578     assert(bdrv_dirty_bitmap_enabled(bitmap));
579     assert(!bdrv_dirty_bitmap_readonly(bitmap));
580     bitmap->bitmap = in;
581     hbitmap_free(tmp);
582 }
583
584 uint64_t bdrv_dirty_bitmap_serialization_size(const BdrvDirtyBitmap *bitmap,
585                                               uint64_t offset, uint64_t bytes)
586 {
587     return hbitmap_serialization_size(bitmap->bitmap, offset, bytes);
588 }
589
590 uint64_t bdrv_dirty_bitmap_serialization_align(const BdrvDirtyBitmap *bitmap)
591 {
592     return hbitmap_serialization_align(bitmap->bitmap);
593 }
594
595 void bdrv_dirty_bitmap_serialize_part(const BdrvDirtyBitmap *bitmap,
596                                       uint8_t *buf, uint64_t offset,
597                                       uint64_t bytes)
598 {
599     hbitmap_serialize_part(bitmap->bitmap, buf, offset, bytes);
600 }
601
602 void bdrv_dirty_bitmap_deserialize_part(BdrvDirtyBitmap *bitmap,
603                                         uint8_t *buf, uint64_t offset,
604                                         uint64_t bytes, bool finish)
605 {
606     hbitmap_deserialize_part(bitmap->bitmap, buf, offset, bytes, finish);
607 }
608
609 void bdrv_dirty_bitmap_deserialize_zeroes(BdrvDirtyBitmap *bitmap,
610                                           uint64_t offset, uint64_t bytes,
611                                           bool finish)
612 {
613     hbitmap_deserialize_zeroes(bitmap->bitmap, offset, bytes, finish);
614 }
615
616 void bdrv_dirty_bitmap_deserialize_ones(BdrvDirtyBitmap *bitmap,
617                                         uint64_t offset, uint64_t bytes,
618                                         bool finish)
619 {
620     hbitmap_deserialize_ones(bitmap->bitmap, offset, bytes, finish);
621 }
622
623 void bdrv_dirty_bitmap_deserialize_finish(BdrvDirtyBitmap *bitmap)
624 {
625     hbitmap_deserialize_finish(bitmap->bitmap);
626 }
627
628 void bdrv_set_dirty(BlockDriverState *bs, int64_t offset, int64_t bytes)
629 {
630     BdrvDirtyBitmap *bitmap;
631
632     if (QLIST_EMPTY(&bs->dirty_bitmaps)) {
633         return;
634     }
635
636     bdrv_dirty_bitmaps_lock(bs);
637     QLIST_FOREACH(bitmap, &bs->dirty_bitmaps, list) {
638         if (!bdrv_dirty_bitmap_enabled(bitmap)) {
639             continue;
640         }
641         assert(!bdrv_dirty_bitmap_readonly(bitmap));
642         hbitmap_set(bitmap->bitmap, offset, bytes);
643     }
644     bdrv_dirty_bitmaps_unlock(bs);
645 }
646
647 /**
648  * Advance a BdrvDirtyBitmapIter to an arbitrary offset.
649  */
650 void bdrv_set_dirty_iter(BdrvDirtyBitmapIter *iter, int64_t offset)
651 {
652     hbitmap_iter_init(&iter->hbi, iter->hbi.hb, offset);
653 }
654
655 int64_t bdrv_get_dirty_count(BdrvDirtyBitmap *bitmap)
656 {
657     return hbitmap_count(bitmap->bitmap);
658 }
659
660 int64_t bdrv_get_meta_dirty_count(BdrvDirtyBitmap *bitmap)
661 {
662     return hbitmap_count(bitmap->meta);
663 }
664
665 bool bdrv_dirty_bitmap_readonly(const BdrvDirtyBitmap *bitmap)
666 {
667     return bitmap->readonly;
668 }
669
670 /* Called with BQL taken. */
671 void bdrv_dirty_bitmap_set_readonly(BdrvDirtyBitmap *bitmap, bool value)
672 {
673     qemu_mutex_lock(bitmap->mutex);
674     bitmap->readonly = value;
675     qemu_mutex_unlock(bitmap->mutex);
676 }
677
678 bool bdrv_has_readonly_bitmaps(BlockDriverState *bs)
679 {
680     BdrvDirtyBitmap *bm;
681     QLIST_FOREACH(bm, &bs->dirty_bitmaps, list) {
682         if (bm->readonly) {
683             return true;
684         }
685     }
686
687     return false;
688 }
689
690 /* Called with BQL taken. */
691 void bdrv_dirty_bitmap_set_persistance(BdrvDirtyBitmap *bitmap, bool persistent)
692 {
693     qemu_mutex_lock(bitmap->mutex);
694     bitmap->persistent = persistent;
695     qemu_mutex_unlock(bitmap->mutex);
696 }
697
698 bool bdrv_dirty_bitmap_get_persistance(BdrvDirtyBitmap *bitmap)
699 {
700     return bitmap->persistent;
701 }
702
703 bool bdrv_has_changed_persistent_bitmaps(BlockDriverState *bs)
704 {
705     BdrvDirtyBitmap *bm;
706     QLIST_FOREACH(bm, &bs->dirty_bitmaps, list) {
707         if (bm->persistent && !bm->readonly) {
708             return true;
709         }
710     }
711
712     return false;
713 }
714
715 BdrvDirtyBitmap *bdrv_dirty_bitmap_next(BlockDriverState *bs,
716                                         BdrvDirtyBitmap *bitmap)
717 {
718     return bitmap == NULL ? QLIST_FIRST(&bs->dirty_bitmaps) :
719                             QLIST_NEXT(bitmap, list);
720 }
721
722 char *bdrv_dirty_bitmap_sha256(const BdrvDirtyBitmap *bitmap, Error **errp)
723 {
724     return hbitmap_sha256(bitmap->bitmap, errp);
725 }
726
727 int64_t bdrv_dirty_bitmap_next_zero(BdrvDirtyBitmap *bitmap, uint64_t offset)
728 {
729     return hbitmap_next_zero(bitmap->bitmap, offset);
730 }
This page took 0.060586 seconds and 4 git commands to generate.