9ae3a8
From 0e79ef6691f77a7c0da31dff9276b6dad42441a0 Mon Sep 17 00:00:00 2001
9ae3a8
From: Max Reitz <mreitz@redhat.com>
9ae3a8
Date: Mon, 4 Nov 2013 22:31:59 +0100
9ae3a8
Subject: [PATCH 06/87] qcow2: Add corrupt bit
9ae3a8
9ae3a8
RH-Author: Max Reitz <mreitz@redhat.com>
9ae3a8
Message-id: <1383604354-12743-9-git-send-email-mreitz@redhat.com>
9ae3a8
Patchwork-id: 55308
9ae3a8
O-Subject: [RHEL-7.0 qemu-kvm PATCH 08/43] qcow2: Add corrupt bit
9ae3a8
Bugzilla: 1004347
9ae3a8
RH-Acked-by: Kevin Wolf <kwolf@redhat.com>
9ae3a8
RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
9ae3a8
RH-Acked-by: Fam Zheng <famz@redhat.com>
9ae3a8
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
9ae3a8
9ae3a8
BZ: 1004347
9ae3a8
9ae3a8
This adds an incompatible bit indicating corruption to qcow2. Any image
9ae3a8
with this bit set may not be written to unless for repairing (and
9ae3a8
subsequently clearing the bit if the repair has been successful).
9ae3a8
9ae3a8
Signed-off-by: Max Reitz <mreitz@redhat.com>
9ae3a8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9ae3a8
(cherry picked from commit 69c98726537627e708abb8fcb33e3a2b10e40bf1)
9ae3a8
9ae3a8
Signed-off-by: Max Reitz <mreitz@redhat.com>
9ae3a8
---
9ae3a8
 block/qcow2.c              | 47 ++++++++++++++++++++++++++++++++++++++++++++++
9ae3a8
 block/qcow2.h              |  7 ++++++-
9ae3a8
 docs/specs/qcow2.txt       |  7 ++++++-
9ae3a8
 tests/qemu-iotests/031.out | 12 ++++++------
9ae3a8
 tests/qemu-iotests/036.out |  2 +-
9ae3a8
 5 files changed, 66 insertions(+), 9 deletions(-)
9ae3a8
9ae3a8
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
9ae3a8
---
9ae3a8
 block/qcow2.c              |   47 ++++++++++++++++++++++++++++++++++++++++++++
9ae3a8
 block/qcow2.h              |    7 +++++-
9ae3a8
 docs/specs/qcow2.txt       |    7 +++++-
9ae3a8
 tests/qemu-iotests/031.out |   12 +++++-----
9ae3a8
 tests/qemu-iotests/036.out |    2 +-
9ae3a8
 5 files changed, 66 insertions(+), 9 deletions(-)
9ae3a8
9ae3a8
diff --git a/block/qcow2.c b/block/qcow2.c
9ae3a8
index c2728c9..aa9dd23 100644
9ae3a8
--- a/block/qcow2.c
9ae3a8
+++ b/block/qcow2.c
9ae3a8
@@ -272,6 +272,37 @@ static int qcow2_mark_clean(BlockDriverState *bs)
9ae3a8
     return 0;
9ae3a8
 }
9ae3a8
 
9ae3a8
+/*
9ae3a8
+ * Marks the image as corrupt.
9ae3a8
+ */
9ae3a8
+int qcow2_mark_corrupt(BlockDriverState *bs)
9ae3a8
+{
9ae3a8
+    BDRVQcowState *s = bs->opaque;
9ae3a8
+
9ae3a8
+    s->incompatible_features |= QCOW2_INCOMPAT_CORRUPT;
9ae3a8
+    return qcow2_update_header(bs);
9ae3a8
+}
9ae3a8
+
9ae3a8
+/*
9ae3a8
+ * Marks the image as consistent, i.e., unsets the corrupt bit, and flushes
9ae3a8
+ * before if necessary.
9ae3a8
+ */
9ae3a8
+int qcow2_mark_consistent(BlockDriverState *bs)
9ae3a8
+{
9ae3a8
+    BDRVQcowState *s = bs->opaque;
9ae3a8
+
9ae3a8
+    if (s->incompatible_features & QCOW2_INCOMPAT_CORRUPT) {
9ae3a8
+        int ret = bdrv_flush(bs);
9ae3a8
+        if (ret < 0) {
9ae3a8
+            return ret;
9ae3a8
+        }
9ae3a8
+
9ae3a8
+        s->incompatible_features &= ~QCOW2_INCOMPAT_CORRUPT;
9ae3a8
+        return qcow2_update_header(bs);
9ae3a8
+    }
9ae3a8
+    return 0;
9ae3a8
+}
9ae3a8
+
9ae3a8
 static int qcow2_check(BlockDriverState *bs, BdrvCheckResult *result,
9ae3a8
                        BdrvCheckMode fix)
9ae3a8
 {
9ae3a8
@@ -402,6 +433,17 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags)
9ae3a8
         goto fail;
9ae3a8
     }
9ae3a8
 
9ae3a8
+    if (s->incompatible_features & QCOW2_INCOMPAT_CORRUPT) {
9ae3a8
+        /* Corrupt images may not be written to unless they are being repaired
9ae3a8
+         */
9ae3a8
+        if ((flags & BDRV_O_RDWR) && !(flags & BDRV_O_CHECK)) {
9ae3a8
+            error_report("qcow2: Image is corrupt; cannot be opened "
9ae3a8
+                    "read/write.");
9ae3a8
+            ret = -EACCES;
9ae3a8
+            goto fail;
9ae3a8
+        }
9ae3a8
+    }
9ae3a8
+
9ae3a8
     /* Check support for various header values */
9ae3a8
     if (header.refcount_order != 4) {
9ae3a8
         report_unsupported(bs, "%d bit reference counts",
9ae3a8
@@ -1140,6 +1182,11 @@ int qcow2_update_header(BlockDriverState *bs)
9ae3a8
             .name = "dirty bit",
9ae3a8
         },
9ae3a8
         {
9ae3a8
+            .type = QCOW2_FEAT_TYPE_INCOMPATIBLE,
9ae3a8
+            .bit  = QCOW2_INCOMPAT_CORRUPT_BITNR,
9ae3a8
+            .name = "corrupt bit",
9ae3a8
+        },
9ae3a8
+        {
9ae3a8
             .type = QCOW2_FEAT_TYPE_COMPATIBLE,
9ae3a8
             .bit  = QCOW2_COMPAT_LAZY_REFCOUNTS_BITNR,
9ae3a8
             .name = "lazy refcounts",
9ae3a8
diff --git a/block/qcow2.h b/block/qcow2.h
9ae3a8
index dba9771..4297487 100644
9ae3a8
--- a/block/qcow2.h
9ae3a8
+++ b/block/qcow2.h
9ae3a8
@@ -119,9 +119,12 @@ enum {
9ae3a8
 /* Incompatible feature bits */
9ae3a8
 enum {
9ae3a8
     QCOW2_INCOMPAT_DIRTY_BITNR   = 0,
9ae3a8
+    QCOW2_INCOMPAT_CORRUPT_BITNR = 1,
9ae3a8
     QCOW2_INCOMPAT_DIRTY         = 1 << QCOW2_INCOMPAT_DIRTY_BITNR,
9ae3a8
+    QCOW2_INCOMPAT_CORRUPT       = 1 << QCOW2_INCOMPAT_CORRUPT_BITNR,
9ae3a8
 
9ae3a8
-    QCOW2_INCOMPAT_MASK          = QCOW2_INCOMPAT_DIRTY,
9ae3a8
+    QCOW2_INCOMPAT_MASK          = QCOW2_INCOMPAT_DIRTY
9ae3a8
+                                 | QCOW2_INCOMPAT_CORRUPT,
9ae3a8
 };
9ae3a8
 
9ae3a8
 /* Compatible feature bits */
9ae3a8
@@ -361,6 +364,8 @@ int qcow2_backing_read1(BlockDriverState *bs, QEMUIOVector *qiov,
9ae3a8
                   int64_t sector_num, int nb_sectors);
9ae3a8
 
9ae3a8
 int qcow2_mark_dirty(BlockDriverState *bs);
9ae3a8
+int qcow2_mark_corrupt(BlockDriverState *bs);
9ae3a8
+int qcow2_mark_consistent(BlockDriverState *bs);
9ae3a8
 int qcow2_update_header(BlockDriverState *bs);
9ae3a8
 
9ae3a8
 /* qcow2-refcount.c functions */
9ae3a8
diff --git a/docs/specs/qcow2.txt b/docs/specs/qcow2.txt
9ae3a8
index 36a559d..33eca36 100644
9ae3a8
--- a/docs/specs/qcow2.txt
9ae3a8
+++ b/docs/specs/qcow2.txt
9ae3a8
@@ -80,7 +80,12 @@ in the description of a field.
9ae3a8
                                 tables to repair refcounts before accessing the
9ae3a8
                                 image.
9ae3a8
 
9ae3a8
-                    Bits 1-63:  Reserved (set to 0)
9ae3a8
+                    Bit 1:      Corrupt bit.  If this bit is set then any data
9ae3a8
+                                structure may be corrupt and the image must not
9ae3a8
+                                be written to (unless for regaining
9ae3a8
+                                consistency).
9ae3a8
+
9ae3a8
+                    Bits 2-63:  Reserved (set to 0)
9ae3a8
 
9ae3a8
          80 -  87:  compatible_features
9ae3a8
                     Bitmask of compatible features. An implementation can
9ae3a8
diff --git a/tests/qemu-iotests/031.out b/tests/qemu-iotests/031.out
9ae3a8
index 796c993..a943344 100644
9ae3a8
--- a/tests/qemu-iotests/031.out
9ae3a8
+++ b/tests/qemu-iotests/031.out
9ae3a8
@@ -54,7 +54,7 @@ header_length             72
9ae3a8
 
9ae3a8
 Header extension:
9ae3a8
 magic                     0x6803f857
9ae3a8
-length                    96
9ae3a8
+length                    144
9ae3a8
 data                      <binary>
9ae3a8
 
9ae3a8
 Header extension:
9ae3a8
@@ -68,7 +68,7 @@ No errors were found on the image.
9ae3a8
 
9ae3a8
 magic                     0x514649fb
9ae3a8
 version                   2
9ae3a8
-backing_file_offset       0xf8
9ae3a8
+backing_file_offset       0x128
9ae3a8
 backing_file_size         0x17
9ae3a8
 cluster_bits              16
9ae3a8
 size                      67108864
9ae3a8
@@ -92,7 +92,7 @@ data                      'host_device'
9ae3a8
 
9ae3a8
 Header extension:
9ae3a8
 magic                     0x6803f857
9ae3a8
-length                    96
9ae3a8
+length                    144
9ae3a8
 data                      <binary>
9ae3a8
 
9ae3a8
 Header extension:
9ae3a8
@@ -155,7 +155,7 @@ header_length             104
9ae3a8
 
9ae3a8
 Header extension:
9ae3a8
 magic                     0x6803f857
9ae3a8
-length                    96
9ae3a8
+length                    144
9ae3a8
 data                      <binary>
9ae3a8
 
9ae3a8
 Header extension:
9ae3a8
@@ -169,7 +169,7 @@ No errors were found on the image.
9ae3a8
 
9ae3a8
 magic                     0x514649fb
9ae3a8
 version                   3
9ae3a8
-backing_file_offset       0x118
9ae3a8
+backing_file_offset       0x148
9ae3a8
 backing_file_size         0x17
9ae3a8
 cluster_bits              16
9ae3a8
 size                      67108864
9ae3a8
@@ -193,7 +193,7 @@ data                      'host_device'
9ae3a8
 
9ae3a8
 Header extension:
9ae3a8
 magic                     0x6803f857
9ae3a8
-length                    96
9ae3a8
+length                    144
9ae3a8
 data                      <binary>
9ae3a8
 
9ae3a8
 Header extension:
9ae3a8
diff --git a/tests/qemu-iotests/036.out b/tests/qemu-iotests/036.out
9ae3a8
index 063ca22..55a3e6e 100644
9ae3a8
--- a/tests/qemu-iotests/036.out
9ae3a8
+++ b/tests/qemu-iotests/036.out
9ae3a8
@@ -46,7 +46,7 @@ header_length             104
9ae3a8
 
9ae3a8
 Header extension:
9ae3a8
 magic                     0x6803f857
9ae3a8
-length                    96
9ae3a8
+length                    144
9ae3a8
 data                      <binary>
9ae3a8
 
9ae3a8
 *** done
9ae3a8
-- 
9ae3a8
1.7.1
9ae3a8