|
|
357786 |
From 1b36ea8bc4840907b78867ae040231fe91f12851 Mon Sep 17 00:00:00 2001
|
|
|
357786 |
From: John Snow <jsnow@redhat.com>
|
|
|
357786 |
Date: Wed, 18 Jul 2018 22:54:45 +0200
|
|
|
357786 |
Subject: [PATCH 60/89] qcow2: add overlap check for bitmap directory
|
|
|
357786 |
|
|
|
357786 |
RH-Author: John Snow <jsnow@redhat.com>
|
|
|
357786 |
Message-id: <20180718225511.14878-10-jsnow@redhat.com>
|
|
|
357786 |
Patchwork-id: 81394
|
|
|
357786 |
O-Subject: [RHEL-7.6 qemu-kvm-rhev PATCH 09/35] qcow2: add overlap check for bitmap directory
|
|
|
357786 |
Bugzilla: 1207657
|
|
|
357786 |
RH-Acked-by: Eric Blake <eblake@redhat.com>
|
|
|
357786 |
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
|
|
|
357786 |
RH-Acked-by: Fam Zheng <famz@redhat.com>
|
|
|
357786 |
|
|
|
357786 |
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
|
|
|
357786 |
|
|
|
357786 |
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
|
|
|
357786 |
Message-id: 20180705151515.779173-1-vsementsov@virtuozzo.com
|
|
|
357786 |
Signed-off-by: Max Reitz <mreitz@redhat.com>
|
|
|
357786 |
(cherry picked from commit 0e4e4318eaa56c831001bdf617094807ec6d451c)
|
|
|
357786 |
Signed-off-by: John Snow <jsnow@redhat.com>
|
|
|
357786 |
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
|
|
|
357786 |
---
|
|
|
357786 |
block/qcow2-bitmap.c | 7 ++++++-
|
|
|
357786 |
block/qcow2-refcount.c | 10 ++++++++++
|
|
|
357786 |
block/qcow2.c | 22 ++++++++++++++--------
|
|
|
357786 |
block/qcow2.h | 45 ++++++++++++++++++++++++---------------------
|
|
|
357786 |
qapi/block-core.json | 21 ++++++++++++---------
|
|
|
357786 |
5 files changed, 66 insertions(+), 39 deletions(-)
|
|
|
357786 |
|
|
|
357786 |
diff --git a/block/qcow2-bitmap.c b/block/qcow2-bitmap.c
|
|
|
357786 |
index 3e4e4e4..14050eb 100644
|
|
|
357786 |
--- a/block/qcow2-bitmap.c
|
|
|
357786 |
+++ b/block/qcow2-bitmap.c
|
|
|
357786 |
@@ -775,7 +775,12 @@ static int bitmap_list_store(BlockDriverState *bs, Qcow2BitmapList *bm_list,
|
|
|
357786 |
}
|
|
|
357786 |
}
|
|
|
357786 |
|
|
|
357786 |
- ret = qcow2_pre_write_overlap_check(bs, 0, dir_offset, dir_size);
|
|
|
357786 |
+ /* Actually, even in in-place case ignoring QCOW2_OL_BITMAP_DIRECTORY is not
|
|
|
357786 |
+ * necessary, because we drop QCOW2_AUTOCLEAR_BITMAPS when updating bitmap
|
|
|
357786 |
+ * directory in-place (actually, turn-off the extension), which is checked
|
|
|
357786 |
+ * in qcow2_check_metadata_overlap() */
|
|
|
357786 |
+ ret = qcow2_pre_write_overlap_check(
|
|
|
357786 |
+ bs, in_place ? QCOW2_OL_BITMAP_DIRECTORY : 0, dir_offset, dir_size);
|
|
|
357786 |
if (ret < 0) {
|
|
|
357786 |
goto fail;
|
|
|
357786 |
}
|
|
|
357786 |
diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
|
|
|
357786 |
index 4e14c0a..1307069 100644
|
|
|
357786 |
--- a/block/qcow2-refcount.c
|
|
|
357786 |
+++ b/block/qcow2-refcount.c
|
|
|
357786 |
@@ -2705,6 +2705,16 @@ int qcow2_check_metadata_overlap(BlockDriverState *bs, int ign, int64_t offset,
|
|
|
357786 |
}
|
|
|
357786 |
}
|
|
|
357786 |
|
|
|
357786 |
+ if ((chk & QCOW2_OL_BITMAP_DIRECTORY) &&
|
|
|
357786 |
+ (s->autoclear_features & QCOW2_AUTOCLEAR_BITMAPS))
|
|
|
357786 |
+ {
|
|
|
357786 |
+ if (overlaps_with(s->bitmap_directory_offset,
|
|
|
357786 |
+ s->bitmap_directory_size))
|
|
|
357786 |
+ {
|
|
|
357786 |
+ return QCOW2_OL_BITMAP_DIRECTORY;
|
|
|
357786 |
+ }
|
|
|
357786 |
+ }
|
|
|
357786 |
+
|
|
|
357786 |
return 0;
|
|
|
357786 |
}
|
|
|
357786 |
|
|
|
357786 |
diff --git a/block/qcow2.c b/block/qcow2.c
|
|
|
357786 |
index 71fbfcd..c5341a4 100644
|
|
|
357786 |
--- a/block/qcow2.c
|
|
|
357786 |
+++ b/block/qcow2.c
|
|
|
357786 |
@@ -676,6 +676,11 @@ static QemuOptsList qcow2_runtime_opts = {
|
|
|
357786 |
.help = "Check for unintended writes into an inactive L2 table",
|
|
|
357786 |
},
|
|
|
357786 |
{
|
|
|
357786 |
+ .name = QCOW2_OPT_OVERLAP_BITMAP_DIRECTORY,
|
|
|
357786 |
+ .type = QEMU_OPT_BOOL,
|
|
|
357786 |
+ .help = "Check for unintended writes into the bitmap directory",
|
|
|
357786 |
+ },
|
|
|
357786 |
+ {
|
|
|
357786 |
.name = QCOW2_OPT_CACHE_SIZE,
|
|
|
357786 |
.type = QEMU_OPT_SIZE,
|
|
|
357786 |
.help = "Maximum combined metadata (L2 tables and refcount blocks) "
|
|
|
357786 |
@@ -708,14 +713,15 @@ static QemuOptsList qcow2_runtime_opts = {
|
|
|
357786 |
};
|
|
|
357786 |
|
|
|
357786 |
static const char *overlap_bool_option_names[QCOW2_OL_MAX_BITNR] = {
|
|
|
357786 |
- [QCOW2_OL_MAIN_HEADER_BITNR] = QCOW2_OPT_OVERLAP_MAIN_HEADER,
|
|
|
357786 |
- [QCOW2_OL_ACTIVE_L1_BITNR] = QCOW2_OPT_OVERLAP_ACTIVE_L1,
|
|
|
357786 |
- [QCOW2_OL_ACTIVE_L2_BITNR] = QCOW2_OPT_OVERLAP_ACTIVE_L2,
|
|
|
357786 |
- [QCOW2_OL_REFCOUNT_TABLE_BITNR] = QCOW2_OPT_OVERLAP_REFCOUNT_TABLE,
|
|
|
357786 |
- [QCOW2_OL_REFCOUNT_BLOCK_BITNR] = QCOW2_OPT_OVERLAP_REFCOUNT_BLOCK,
|
|
|
357786 |
- [QCOW2_OL_SNAPSHOT_TABLE_BITNR] = QCOW2_OPT_OVERLAP_SNAPSHOT_TABLE,
|
|
|
357786 |
- [QCOW2_OL_INACTIVE_L1_BITNR] = QCOW2_OPT_OVERLAP_INACTIVE_L1,
|
|
|
357786 |
- [QCOW2_OL_INACTIVE_L2_BITNR] = QCOW2_OPT_OVERLAP_INACTIVE_L2,
|
|
|
357786 |
+ [QCOW2_OL_MAIN_HEADER_BITNR] = QCOW2_OPT_OVERLAP_MAIN_HEADER,
|
|
|
357786 |
+ [QCOW2_OL_ACTIVE_L1_BITNR] = QCOW2_OPT_OVERLAP_ACTIVE_L1,
|
|
|
357786 |
+ [QCOW2_OL_ACTIVE_L2_BITNR] = QCOW2_OPT_OVERLAP_ACTIVE_L2,
|
|
|
357786 |
+ [QCOW2_OL_REFCOUNT_TABLE_BITNR] = QCOW2_OPT_OVERLAP_REFCOUNT_TABLE,
|
|
|
357786 |
+ [QCOW2_OL_REFCOUNT_BLOCK_BITNR] = QCOW2_OPT_OVERLAP_REFCOUNT_BLOCK,
|
|
|
357786 |
+ [QCOW2_OL_SNAPSHOT_TABLE_BITNR] = QCOW2_OPT_OVERLAP_SNAPSHOT_TABLE,
|
|
|
357786 |
+ [QCOW2_OL_INACTIVE_L1_BITNR] = QCOW2_OPT_OVERLAP_INACTIVE_L1,
|
|
|
357786 |
+ [QCOW2_OL_INACTIVE_L2_BITNR] = QCOW2_OPT_OVERLAP_INACTIVE_L2,
|
|
|
357786 |
+ [QCOW2_OL_BITMAP_DIRECTORY_BITNR] = QCOW2_OPT_OVERLAP_BITMAP_DIRECTORY,
|
|
|
357786 |
};
|
|
|
357786 |
|
|
|
357786 |
static void cache_clean_timer_cb(void *opaque)
|
|
|
357786 |
diff --git a/block/qcow2.h b/block/qcow2.h
|
|
|
357786 |
index b5e2aa3..d2c63e4 100644
|
|
|
357786 |
--- a/block/qcow2.h
|
|
|
357786 |
+++ b/block/qcow2.h
|
|
|
357786 |
@@ -98,6 +98,7 @@
|
|
|
357786 |
#define QCOW2_OPT_OVERLAP_SNAPSHOT_TABLE "overlap-check.snapshot-table"
|
|
|
357786 |
#define QCOW2_OPT_OVERLAP_INACTIVE_L1 "overlap-check.inactive-l1"
|
|
|
357786 |
#define QCOW2_OPT_OVERLAP_INACTIVE_L2 "overlap-check.inactive-l2"
|
|
|
357786 |
+#define QCOW2_OPT_OVERLAP_BITMAP_DIRECTORY "overlap-check.bitmap-directory"
|
|
|
357786 |
#define QCOW2_OPT_CACHE_SIZE "cache-size"
|
|
|
357786 |
#define QCOW2_OPT_L2_CACHE_SIZE "l2-cache-size"
|
|
|
357786 |
#define QCOW2_OPT_L2_CACHE_ENTRY_SIZE "l2-cache-entry-size"
|
|
|
357786 |
@@ -401,34 +402,36 @@ typedef enum QCow2ClusterType {
|
|
|
357786 |
} QCow2ClusterType;
|
|
|
357786 |
|
|
|
357786 |
typedef enum QCow2MetadataOverlap {
|
|
|
357786 |
- QCOW2_OL_MAIN_HEADER_BITNR = 0,
|
|
|
357786 |
- QCOW2_OL_ACTIVE_L1_BITNR = 1,
|
|
|
357786 |
- QCOW2_OL_ACTIVE_L2_BITNR = 2,
|
|
|
357786 |
- QCOW2_OL_REFCOUNT_TABLE_BITNR = 3,
|
|
|
357786 |
- QCOW2_OL_REFCOUNT_BLOCK_BITNR = 4,
|
|
|
357786 |
- QCOW2_OL_SNAPSHOT_TABLE_BITNR = 5,
|
|
|
357786 |
- QCOW2_OL_INACTIVE_L1_BITNR = 6,
|
|
|
357786 |
- QCOW2_OL_INACTIVE_L2_BITNR = 7,
|
|
|
357786 |
-
|
|
|
357786 |
- QCOW2_OL_MAX_BITNR = 8,
|
|
|
357786 |
-
|
|
|
357786 |
- QCOW2_OL_NONE = 0,
|
|
|
357786 |
- QCOW2_OL_MAIN_HEADER = (1 << QCOW2_OL_MAIN_HEADER_BITNR),
|
|
|
357786 |
- QCOW2_OL_ACTIVE_L1 = (1 << QCOW2_OL_ACTIVE_L1_BITNR),
|
|
|
357786 |
- QCOW2_OL_ACTIVE_L2 = (1 << QCOW2_OL_ACTIVE_L2_BITNR),
|
|
|
357786 |
- QCOW2_OL_REFCOUNT_TABLE = (1 << QCOW2_OL_REFCOUNT_TABLE_BITNR),
|
|
|
357786 |
- QCOW2_OL_REFCOUNT_BLOCK = (1 << QCOW2_OL_REFCOUNT_BLOCK_BITNR),
|
|
|
357786 |
- QCOW2_OL_SNAPSHOT_TABLE = (1 << QCOW2_OL_SNAPSHOT_TABLE_BITNR),
|
|
|
357786 |
- QCOW2_OL_INACTIVE_L1 = (1 << QCOW2_OL_INACTIVE_L1_BITNR),
|
|
|
357786 |
+ QCOW2_OL_MAIN_HEADER_BITNR = 0,
|
|
|
357786 |
+ QCOW2_OL_ACTIVE_L1_BITNR = 1,
|
|
|
357786 |
+ QCOW2_OL_ACTIVE_L2_BITNR = 2,
|
|
|
357786 |
+ QCOW2_OL_REFCOUNT_TABLE_BITNR = 3,
|
|
|
357786 |
+ QCOW2_OL_REFCOUNT_BLOCK_BITNR = 4,
|
|
|
357786 |
+ QCOW2_OL_SNAPSHOT_TABLE_BITNR = 5,
|
|
|
357786 |
+ QCOW2_OL_INACTIVE_L1_BITNR = 6,
|
|
|
357786 |
+ QCOW2_OL_INACTIVE_L2_BITNR = 7,
|
|
|
357786 |
+ QCOW2_OL_BITMAP_DIRECTORY_BITNR = 8,
|
|
|
357786 |
+
|
|
|
357786 |
+ QCOW2_OL_MAX_BITNR = 9,
|
|
|
357786 |
+
|
|
|
357786 |
+ QCOW2_OL_NONE = 0,
|
|
|
357786 |
+ QCOW2_OL_MAIN_HEADER = (1 << QCOW2_OL_MAIN_HEADER_BITNR),
|
|
|
357786 |
+ QCOW2_OL_ACTIVE_L1 = (1 << QCOW2_OL_ACTIVE_L1_BITNR),
|
|
|
357786 |
+ QCOW2_OL_ACTIVE_L2 = (1 << QCOW2_OL_ACTIVE_L2_BITNR),
|
|
|
357786 |
+ QCOW2_OL_REFCOUNT_TABLE = (1 << QCOW2_OL_REFCOUNT_TABLE_BITNR),
|
|
|
357786 |
+ QCOW2_OL_REFCOUNT_BLOCK = (1 << QCOW2_OL_REFCOUNT_BLOCK_BITNR),
|
|
|
357786 |
+ QCOW2_OL_SNAPSHOT_TABLE = (1 << QCOW2_OL_SNAPSHOT_TABLE_BITNR),
|
|
|
357786 |
+ QCOW2_OL_INACTIVE_L1 = (1 << QCOW2_OL_INACTIVE_L1_BITNR),
|
|
|
357786 |
/* NOTE: Checking overlaps with inactive L2 tables will result in bdrv
|
|
|
357786 |
* reads. */
|
|
|
357786 |
- QCOW2_OL_INACTIVE_L2 = (1 << QCOW2_OL_INACTIVE_L2_BITNR),
|
|
|
357786 |
+ QCOW2_OL_INACTIVE_L2 = (1 << QCOW2_OL_INACTIVE_L2_BITNR),
|
|
|
357786 |
+ QCOW2_OL_BITMAP_DIRECTORY = (1 << QCOW2_OL_BITMAP_DIRECTORY_BITNR),
|
|
|
357786 |
} QCow2MetadataOverlap;
|
|
|
357786 |
|
|
|
357786 |
/* Perform all overlap checks which can be done in constant time */
|
|
|
357786 |
#define QCOW2_OL_CONSTANT \
|
|
|
357786 |
(QCOW2_OL_MAIN_HEADER | QCOW2_OL_ACTIVE_L1 | QCOW2_OL_REFCOUNT_TABLE | \
|
|
|
357786 |
- QCOW2_OL_SNAPSHOT_TABLE)
|
|
|
357786 |
+ QCOW2_OL_SNAPSHOT_TABLE | QCOW2_OL_BITMAP_DIRECTORY)
|
|
|
357786 |
|
|
|
357786 |
/* Perform all overlap checks which don't require disk access */
|
|
|
357786 |
#define QCOW2_OL_CACHED \
|
|
|
357786 |
diff --git a/qapi/block-core.json b/qapi/block-core.json
|
|
|
357786 |
index 27ed91b..69e0cf8 100644
|
|
|
357786 |
--- a/qapi/block-core.json
|
|
|
357786 |
+++ b/qapi/block-core.json
|
|
|
357786 |
@@ -2666,18 +2666,21 @@
|
|
|
357786 |
# @template: Specifies a template mode which can be adjusted using the other
|
|
|
357786 |
# flags, defaults to 'cached'
|
|
|
357786 |
#
|
|
|
357786 |
+# @bitmap-directory: since 3.0
|
|
|
357786 |
+#
|
|
|
357786 |
# Since: 2.9
|
|
|
357786 |
##
|
|
|
357786 |
{ 'struct': 'Qcow2OverlapCheckFlags',
|
|
|
357786 |
- 'data': { '*template': 'Qcow2OverlapCheckMode',
|
|
|
357786 |
- '*main-header': 'bool',
|
|
|
357786 |
- '*active-l1': 'bool',
|
|
|
357786 |
- '*active-l2': 'bool',
|
|
|
357786 |
- '*refcount-table': 'bool',
|
|
|
357786 |
- '*refcount-block': 'bool',
|
|
|
357786 |
- '*snapshot-table': 'bool',
|
|
|
357786 |
- '*inactive-l1': 'bool',
|
|
|
357786 |
- '*inactive-l2': 'bool' } }
|
|
|
357786 |
+ 'data': { '*template': 'Qcow2OverlapCheckMode',
|
|
|
357786 |
+ '*main-header': 'bool',
|
|
|
357786 |
+ '*active-l1': 'bool',
|
|
|
357786 |
+ '*active-l2': 'bool',
|
|
|
357786 |
+ '*refcount-table': 'bool',
|
|
|
357786 |
+ '*refcount-block': 'bool',
|
|
|
357786 |
+ '*snapshot-table': 'bool',
|
|
|
357786 |
+ '*inactive-l1': 'bool',
|
|
|
357786 |
+ '*inactive-l2': 'bool',
|
|
|
357786 |
+ '*bitmap-directory': 'bool' } }
|
|
|
357786 |
|
|
|
357786 |
##
|
|
|
357786 |
# @Qcow2OverlapChecks:
|
|
|
357786 |
--
|
|
|
357786 |
1.8.3.1
|
|
|
357786 |
|