aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--block.c78
-rw-r--r--block.h8
-rw-r--r--block_int.h2
3 files changed, 86 insertions, 2 deletions
diff --git a/block.c b/block.c
index 1e49bc05cc..6fdabff12d 100644
--- a/block.c
+++ b/block.c
@@ -43,6 +43,7 @@
#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,
@@ -641,6 +642,18 @@ int bdrv_read(BlockDriverState *bs, int64_t sector_num,
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.
@@ -657,7 +670,11 @@ int bdrv_write(BlockDriverState *bs, int64_t sector_num,
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);
}
@@ -1203,6 +1220,11 @@ int bdrv_write_compressed(BlockDriverState *bs, int64_t sector_num,
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);
}
@@ -1400,6 +1422,10 @@ BlockDriverAIOCB *bdrv_aio_writev(BlockDriverState *bs, int64_t sector_num,
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);
@@ -1930,7 +1956,57 @@ BlockDriverAIOCB *bdrv_aio_ioctl(BlockDriverState *bs,
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;
+}
diff --git a/block.h b/block.h
index 6b0146f7cf..2d4f066906 100644
--- a/block.h
+++ b/block.h
@@ -80,7 +80,8 @@ void bdrv_register(BlockDriver *bdrv);
/* 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);
@@ -187,4 +188,9 @@ int bdrv_save_vmstate(BlockDriverState *bs, const uint8_t *buf,
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
diff --git a/block_int.h b/block_int.h
index 8e72abee0c..7ebe926f5b 100644
--- a/block_int.h
+++ b/block_int.h
@@ -168,6 +168,8 @@ struct BlockDriverState {
int cyls, heads, secs, translation;
int type;
char device_name[32];
+ int dirty_tracking;
+ uint8_t *dirty_bitmap;
BlockDriverState *next;
void *private;
};