qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [RFC 2/7] qcow2: introduce dirty bit


From: Stefan Hajnoczi
Subject: [Qemu-devel] [RFC 2/7] qcow2: introduce dirty bit
Date: Fri, 22 Jun 2012 16:08:41 +0100

This patch adds an incompatible feature bit to mark images that have not
been closed cleanly.  When a dirty image file is opened a consistency
check and repair is performed.

Signed-off-by: Stefan Hajnoczi <address@hidden>
---
 block/qcow2.c |   44 ++++++++++++++++++++++++++++++++++++++++++--
 block/qcow2.h |    3 +++
 2 files changed, 45 insertions(+), 2 deletions(-)

diff --git a/block/qcow2.c b/block/qcow2.c
index 2c1cd0a..cc30784 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -214,6 +214,27 @@ static void report_unsupported_feature(BlockDriverState 
*bs,
     }
 }
 
+/*
+ * Clears the dirty bit and flushes before if necessary.  Only call this
+ * function when there are no pending requests, it does not guard against
+ * concurrent requests dirtying the image.
+ */
+static int qcow2_mark_clean(BlockDriverState *bs)
+{
+    BDRVQcowState *s = bs->opaque;
+
+    if (s->incompatible_features & QCOW2_INCOMPATIBLE_FEAT_DIRTY) {
+        int ret = bdrv_flush(bs);
+        if (ret < 0) {
+            return ret;
+        }
+
+        s->incompatible_features &= ~QCOW2_INCOMPATIBLE_FEAT_DIRTY;
+        return qcow2_update_header(bs);
+    }
+    return 0;
+}
+
 static int qcow2_open(BlockDriverState *bs, int flags)
 {
     BDRVQcowState *s = bs->opaque;
@@ -287,12 +308,13 @@ static int qcow2_open(BlockDriverState *bs, int flags)
     s->compatible_features      = header.compatible_features;
     s->autoclear_features       = header.autoclear_features;
 
-    if (s->incompatible_features != 0) {
+    if (s->incompatible_features & ~QCOW2_INCOMPATIBLE_FEAT_MASK) {
         void *feature_table = NULL;
         qcow2_read_extensions(bs, header.header_length, ext_end,
                               &feature_table);
         report_unsupported_feature(bs, feature_table,
-                                   s->incompatible_features);
+                                   s->incompatible_features &
+                                   ~QCOW2_INCOMPATIBLE_FEAT_MASK);
         ret = -ENOTSUP;
         goto fail;
     }
@@ -412,6 +434,22 @@ static int qcow2_open(BlockDriverState *bs, int flags)
     /* Initialise locks */
     qemu_co_mutex_init(&s->lock);
 
+    /* Repair image if dirty */
+    if ((s->incompatible_features & QCOW2_INCOMPATIBLE_FEAT_DIRTY) &&
+        !bs->read_only) {
+        BdrvCheckResult result = {0};
+
+        ret = qcow2_check_refcounts(bs, &result, BDRV_FIX_ERRORS);
+        if (ret < 0) {
+            goto fail;
+        }
+
+        ret = qcow2_mark_clean(bs);
+        if (ret < 0) {
+            goto fail;
+        }
+    }
+
 #ifdef DEBUG_ALLOC
     {
         BdrvCheckResult result = {0};
@@ -788,6 +826,8 @@ static void qcow2_close(BlockDriverState *bs)
     qcow2_cache_flush(bs, s->l2_table_cache);
     qcow2_cache_flush(bs, s->refcount_block_cache);
 
+    qcow2_mark_clean(bs);
+
     qcow2_cache_destroy(bs, s->l2_table_cache);
     qcow2_cache_destroy(bs, s->refcount_block_cache);
 
diff --git a/block/qcow2.h b/block/qcow2.h
index 455b6d7..5c7cfb6 100644
--- a/block/qcow2.h
+++ b/block/qcow2.h
@@ -108,6 +108,9 @@ enum {
     QCOW2_FEAT_TYPE_INCOMPATIBLE    = 0,
     QCOW2_FEAT_TYPE_COMPATIBLE      = 1,
     QCOW2_FEAT_TYPE_AUTOCLEAR       = 2,
+
+    QCOW2_INCOMPATIBLE_FEAT_DIRTY   = 0x1,
+    QCOW2_INCOMPATIBLE_FEAT_MASK    = QCOW2_INCOMPATIBLE_FEAT_DIRTY,
 };
 
 typedef struct Qcow2Feature {
-- 
1.7.10




reply via email to

[Prev in Thread] Current Thread [Next in Thread]