qcow2: introduce dirty bit

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.

Update qemu-iotests 031 and 036 since the extension header size changes
when we add feature bit table entries.

Signed-off-by: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
master
Stefan Hajnoczi 2012-07-27 09:05:19 +01:00 committed by Kevin Wolf
parent 0f6d767aa8
commit c61d0004bc
4 changed files with 67 additions and 15 deletions

View File

@ -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_INCOMPAT_DIRTY) {
int ret = bdrv_flush(bs);
if (ret < 0) {
return ret;
}
s->incompatible_features &= ~QCOW2_INCOMPAT_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_INCOMPAT_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_INCOMPAT_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_INCOMPAT_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};
@ -785,6 +823,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);
@ -949,7 +989,11 @@ int qcow2_update_header(BlockDriverState *bs)
/* Feature table */
Qcow2Feature features[] = {
/* no feature defined yet */
{
.type = QCOW2_FEAT_TYPE_INCOMPATIBLE,
.bit = QCOW2_INCOMPAT_DIRTY_BITNR,
.name = "dirty bit",
},
};
ret = header_ext_add(buf, QCOW2_EXT_MAGIC_FEATURE_TABLE,

View File

@ -110,6 +110,14 @@ enum {
QCOW2_FEAT_TYPE_AUTOCLEAR = 2,
};
/* Incompatible feature bits */
enum {
QCOW2_INCOMPAT_DIRTY_BITNR = 0,
QCOW2_INCOMPAT_DIRTY = 1 << QCOW2_INCOMPAT_DIRTY_BITNR,
QCOW2_INCOMPAT_MASK = QCOW2_INCOMPAT_DIRTY,
};
typedef struct Qcow2Feature {
uint8_t type;
uint8_t bit;

View File

@ -54,8 +54,8 @@ header_length 72
Header extension:
magic 0x6803f857
length 0
data ''
length 48
data <binary>
Header extension:
magic 0x12345678
@ -68,7 +68,7 @@ No errors were found on the image.
magic 0x514649fb
version 2
backing_file_offset 0x98
backing_file_offset 0xc8
backing_file_size 0x17
cluster_bits 16
size 67108864
@ -92,8 +92,8 @@ data 'host_device'
Header extension:
magic 0x6803f857
length 0
data ''
length 48
data <binary>
Header extension:
magic 0x12345678
@ -155,8 +155,8 @@ header_length 104
Header extension:
magic 0x6803f857
length 0
data ''
length 48
data <binary>
Header extension:
magic 0x12345678
@ -169,7 +169,7 @@ No errors were found on the image.
magic 0x514649fb
version 3
backing_file_offset 0xb8
backing_file_offset 0xe8
backing_file_size 0x17
cluster_bits 16
size 67108864
@ -193,8 +193,8 @@ data 'host_device'
Header extension:
magic 0x6803f857
length 0
data ''
length 48
data <binary>
Header extension:
magic 0x12345678

View File

@ -46,7 +46,7 @@ header_length 104
Header extension:
magic 0x6803f857
length 0
data ''
length 48
data <binary>
*** done