[Top][All Lists]
[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
- [Qemu-devel] [RFC 0/7] qcow2: implement lazy refcounts optimization, Stefan Hajnoczi, 2012/06/22
- [Qemu-devel] [RFC 5/7] qcow2: implement lazy refcounts, Stefan Hajnoczi, 2012/06/22
- [Qemu-devel] [RFC 2/7] qcow2: introduce dirty bit,
Stefan Hajnoczi <=
- [Qemu-devel] [RFC 1/7] docs: add dirty bit to qcow2 specification, Stefan Hajnoczi, 2012/06/22
- [Qemu-devel] [RFC 4/7] qemu-iotests: ignore qemu-img create lazy_refcounts output, Stefan Hajnoczi, 2012/06/22
- [Qemu-devel] [RFC 7/7] qemu-iotests: add 039 qcow2 lazy refcounts test, Stefan Hajnoczi, 2012/06/22
- [Qemu-devel] [RFC 6/7] qemu-io: add "abort" command to simulate program crash, Stefan Hajnoczi, 2012/06/22
- [Qemu-devel] [RFC 3/7] docs: add lazy refcounts bit to qcow2 specification, Stefan Hajnoczi, 2012/06/22