#include <windows.h>
#endif
+struct BdrvDirtyBitmap {
+ HBitmap *bitmap;
+ QLIST_ENTRY(BdrvDirtyBitmap) list;
+};
+
#define NOT_DONE 0x7fffffff /* used while emulated sync operation in progress */
static void bdrv_dev_change_media_cb(BlockDriverState *bs, bool load);
BlockDriverState *bs;
bs = g_malloc0(sizeof(BlockDriverState));
+ QLIST_INIT(&bs->dirty_bitmaps);
pstrcpy(bs->device_name, sizeof(bs->device_name), device_name);
if (device_name[0] != '\0') {
QTAILQ_INSERT_TAIL(&bdrv_states, bs, list);
bs_dest->iostatus = bs_src->iostatus;
/* dirty bitmap */
- bs_dest->dirty_bitmap = bs_src->dirty_bitmap;
+ bs_dest->dirty_bitmaps = bs_src->dirty_bitmaps;
/* reference count */
bs_dest->refcnt = bs_src->refcnt;
/* bs_new must be anonymous and shouldn't have anything fancy enabled */
assert(bs_new->device_name[0] == '\0');
- assert(bs_new->dirty_bitmap == NULL);
+ assert(QLIST_EMPTY(&bs_new->dirty_bitmaps));
assert(bs_new->job == NULL);
assert(bs_new->dev == NULL);
assert(bs_new->in_use == 0);
assert(!bs->job);
assert(!bs->in_use);
assert(!bs->refcnt);
+ assert(QLIST_EMPTY(&bs->dirty_bitmaps));
bdrv_close(bs);
ret = bdrv_co_flush(bs);
}
- if (bs->dirty_bitmap) {
- bdrv_set_dirty(bs, sector_num, nb_sectors);
- }
+ bdrv_set_dirty(bs, sector_num, nb_sectors);
if (bs->wr_highest_sector < sector_num + nb_sectors - 1) {
bs->wr_highest_sector = sector_num + nb_sectors - 1;
if (bdrv_check_request(bs, sector_num, nb_sectors))
return -EIO;
- assert(!bs->dirty_bitmap);
+ assert(QLIST_EMPTY(&bs->dirty_bitmaps));
return drv->bdrv_write_compressed(bs, sector_num, buf, nb_sectors);
}
return -ENOTSUP;
}
+int bdrv_debug_remove_breakpoint(BlockDriverState *bs, const char *tag)
+{
+ while (bs && bs->drv && !bs->drv->bdrv_debug_remove_breakpoint) {
+ bs = bs->file;
+ }
+
+ if (bs && bs->drv && bs->drv->bdrv_debug_remove_breakpoint) {
+ return bs->drv->bdrv_debug_remove_breakpoint(bs, tag);
+ }
+
+ return -ENOTSUP;
+}
+
int bdrv_debug_resume(BlockDriverState *bs, const char *tag)
{
while (bs && bs->drv && !bs->drv->bdrv_debug_resume) {
return -EROFS;
}
- if (bs->dirty_bitmap) {
- bdrv_reset_dirty(bs, sector_num, nb_sectors);
- }
+ bdrv_reset_dirty(bs, sector_num, nb_sectors);
/* Do nothing if disabled. */
if (!(bs->open_flags & BDRV_O_UNMAP)) {
return true;
}
-void bdrv_set_dirty_tracking(BlockDriverState *bs, int granularity)
+BdrvDirtyBitmap *bdrv_create_dirty_bitmap(BlockDriverState *bs, int granularity)
{
int64_t bitmap_size;
+ BdrvDirtyBitmap *bitmap;
assert((granularity & (granularity - 1)) == 0);
- if (granularity) {
- granularity >>= BDRV_SECTOR_BITS;
- assert(!bs->dirty_bitmap);
- bitmap_size = (bdrv_getlength(bs) >> BDRV_SECTOR_BITS);
- bs->dirty_bitmap = hbitmap_alloc(bitmap_size, ffs(granularity) - 1);
- } else {
- if (bs->dirty_bitmap) {
- hbitmap_free(bs->dirty_bitmap);
- bs->dirty_bitmap = NULL;
+ granularity >>= BDRV_SECTOR_BITS;
+ assert(granularity);
+ bitmap_size = (bdrv_getlength(bs) >> BDRV_SECTOR_BITS);
+ bitmap = g_malloc0(sizeof(BdrvDirtyBitmap));
+ bitmap->bitmap = hbitmap_alloc(bitmap_size, ffs(granularity) - 1);
+ QLIST_INSERT_HEAD(&bs->dirty_bitmaps, bitmap, list);
+ return bitmap;
+}
+
+void bdrv_release_dirty_bitmap(BlockDriverState *bs, BdrvDirtyBitmap *bitmap)
+{
+ BdrvDirtyBitmap *bm, *next;
+ QLIST_FOREACH_SAFE(bm, &bs->dirty_bitmaps, list, next) {
+ if (bm == bitmap) {
+ QLIST_REMOVE(bitmap, list);
+ hbitmap_free(bitmap->bitmap);
+ g_free(bitmap);
+ return;
}
}
}
-int bdrv_get_dirty(BlockDriverState *bs, int64_t sector)
+BlockDirtyInfoList *bdrv_query_dirty_bitmaps(BlockDriverState *bs)
+{
+ BdrvDirtyBitmap *bm;
+ BlockDirtyInfoList *list = NULL;
+ BlockDirtyInfoList **plist = &list;
+
+ QLIST_FOREACH(bm, &bs->dirty_bitmaps, list) {
+ BlockDirtyInfo *info = g_malloc0(sizeof(BlockDirtyInfo));
+ BlockDirtyInfoList *entry = g_malloc0(sizeof(BlockDirtyInfoList));
+ info->count = bdrv_get_dirty_count(bs, bm);
+ info->granularity =
+ ((int64_t) BDRV_SECTOR_SIZE << hbitmap_granularity(bm->bitmap));
+ entry->value = info;
+ *plist = entry;
+ plist = &entry->next;
+ }
+
+ return list;
+}
+
+int bdrv_get_dirty(BlockDriverState *bs, BdrvDirtyBitmap *bitmap, int64_t sector)
{
- if (bs->dirty_bitmap) {
- return hbitmap_get(bs->dirty_bitmap, sector);
+ if (bitmap) {
+ return hbitmap_get(bitmap->bitmap, sector);
} else {
return 0;
}
}
-void bdrv_dirty_iter_init(BlockDriverState *bs, HBitmapIter *hbi)
+void bdrv_dirty_iter_init(BlockDriverState *bs,
+ BdrvDirtyBitmap *bitmap, HBitmapIter *hbi)
{
- hbitmap_iter_init(hbi, bs->dirty_bitmap, 0);
+ hbitmap_iter_init(hbi, bitmap->bitmap, 0);
}
void bdrv_set_dirty(BlockDriverState *bs, int64_t cur_sector,
int nr_sectors)
{
- hbitmap_set(bs->dirty_bitmap, cur_sector, nr_sectors);
+ BdrvDirtyBitmap *bitmap;
+ QLIST_FOREACH(bitmap, &bs->dirty_bitmaps, list) {
+ hbitmap_set(bitmap->bitmap, cur_sector, nr_sectors);
+ }
}
-void bdrv_reset_dirty(BlockDriverState *bs, int64_t cur_sector,
- int nr_sectors)
+void bdrv_reset_dirty(BlockDriverState *bs, int64_t cur_sector, int nr_sectors)
{
- hbitmap_reset(bs->dirty_bitmap, cur_sector, nr_sectors);
+ BdrvDirtyBitmap *bitmap;
+ QLIST_FOREACH(bitmap, &bs->dirty_bitmaps, list) {
+ hbitmap_reset(bitmap->bitmap, cur_sector, nr_sectors);
+ }
}
-int64_t bdrv_get_dirty_count(BlockDriverState *bs)
+int64_t bdrv_get_dirty_count(BlockDriverState *bs, BdrvDirtyBitmap *bitmap)
{
- if (bs->dirty_bitmap) {
- return hbitmap_count(bs->dirty_bitmap);
- } else {
- return 0;
- }
+ return hbitmap_count(bitmap->bitmap);
}
/* Get a reference to bs */