#define SECTOR_BITS 9
#define SECTOR_SIZE (1 << SECTOR_BITS)
+#define SECTORS_PER_DIRTY_CHUNK 8
static BlockDriverAIOCB *bdrv_aio_readv_em(BlockDriverState *bs,
int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
return drv->bdrv_read(bs, sector_num, buf, nb_sectors);
}
+static void set_dirty_bitmap(BlockDriverState *bs, int64_t sector_num,
+ int nb_sectors, int dirty)
+{
+ int64_t start, end;
+ start = sector_num / SECTORS_PER_DIRTY_CHUNK;
+ end = (sector_num + nb_sectors) / SECTORS_PER_DIRTY_CHUNK;
+
+ for(; start <= end; start++) {
+ bs->dirty_bitmap[start] = dirty;
+ }
+}
+
/* Return < 0 if error. Important errors are:
-EIO generic I/O error (may happen for all errors)
-ENOMEDIUM No media inserted.
return -EACCES;
if (bdrv_check_request(bs, sector_num, nb_sectors))
return -EIO;
-
+
+ if(bs->dirty_tracking) {
+ set_dirty_bitmap(bs, sector_num, nb_sectors, 1);
+ }
+
return drv->bdrv_write(bs, sector_num, buf, nb_sectors);
}
return -ENOTSUP;
if (bdrv_check_request(bs, sector_num, nb_sectors))
return -EIO;
+
+ if(bs->dirty_tracking) {
+ set_dirty_bitmap(bs, sector_num, nb_sectors, 1);
+ }
+
return drv->bdrv_write_compressed(bs, sector_num, buf, nb_sectors);
}
if (bdrv_check_request(bs, sector_num, nb_sectors))
return NULL;
+ if(bs->dirty_tracking) {
+ set_dirty_bitmap(bs, sector_num, nb_sectors, 1);
+ }
+
ret = drv->bdrv_aio_writev(bs, sector_num, qiov, nb_sectors,
cb, opaque);
return NULL;
}
+
+
void *qemu_blockalign(BlockDriverState *bs, size_t size)
{
return qemu_memalign((bs && bs->buffer_alignment) ? bs->buffer_alignment : 512, size);
}
+
+void bdrv_set_dirty_tracking(BlockDriverState *bs, int enable)
+{
+ int64_t bitmap_size;
+ if(enable) {
+ if(bs->dirty_tracking == 0) {
+ int64_t i;
+ uint8_t test;
+ bitmap_size = (bdrv_getlength(bs) >> SECTOR_BITS);
+ bitmap_size /= SECTORS_PER_DIRTY_CHUNK;
+ bitmap_size++;
+
+ bs->dirty_bitmap = qemu_mallocz(bitmap_size);
+
+ bs->dirty_tracking = enable;
+ for(i = 0; i < bitmap_size; i++) test = bs->dirty_bitmap[i];
+ }
+ } else {
+ if(bs->dirty_tracking != 0) {
+ qemu_free(bs->dirty_bitmap);
+ bs->dirty_tracking = enable;
+ }
+ }
+}
+
+int bdrv_get_dirty(BlockDriverState *bs, int64_t sector)
+{
+ int64_t chunk = sector / (int64_t)SECTORS_PER_DIRTY_CHUNK;
+
+ if(bs->dirty_bitmap != NULL &&
+ (sector << SECTOR_BITS) <= bdrv_getlength(bs)) {
+ return bs->dirty_bitmap[chunk];
+ } else {
+ return 0;
+ }
+}
+
+void bdrv_reset_dirty(BlockDriverState *bs, int64_t cur_sector,
+ int nr_sectors)
+{
+ set_dirty_bitmap(bs, cur_sector, nr_sectors, 0);
+}
+
+int bdrv_get_sectors_per_chunk(void)
+{
+ /* size must be 2^x */
+ return SECTORS_PER_DIRTY_CHUNK;
+}
/* async block I/O */
typedef struct BlockDriverAIOCB BlockDriverAIOCB;
typedef void BlockDriverCompletionFunc(void *opaque, int ret);
-
+typedef void BlockDriverDirtyHandler(BlockDriverState *bs, int64_t sector,
+ int sector_num);
BlockDriverAIOCB *bdrv_aio_readv(BlockDriverState *bs, int64_t sector_num,
QEMUIOVector *iov, int nb_sectors,
BlockDriverCompletionFunc *cb, void *opaque);
int bdrv_load_vmstate(BlockDriverState *bs, uint8_t *buf,
int64_t pos, int size);
+void bdrv_set_dirty_tracking(BlockDriverState *bs, int enable);
+int bdrv_get_dirty(BlockDriverState *bs, int64_t sector);
+void bdrv_reset_dirty(BlockDriverState *bs, int64_t cur_sector,
+ int nr_sectors);
+int bdrv_get_sectors_per_chunk(void);
#endif