diff --git a/block.c b/block.c
index fa0de25..d316eeb 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,
@@ -609,6 +610,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.
@@ -625,7 +638,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);
 }
 
@@ -1162,6 +1179,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);
 }
 
@@ -1359,6 +1381,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);
 
@@ -1883,7 +1909,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 a966afb..8a5e7ce 100644
--- a/block.h
+++ b/block.h
@@ -78,7 +78,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);
@@ -184,4 +185,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 8e72abe..7ebe926 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;
 };
