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>
This commit is contained in:
parent
0f6d767aa8
commit
c61d0004bc
@ -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,
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -46,7 +46,7 @@ header_length 104
|
||||
|
||||
Header extension:
|
||||
magic 0x6803f857
|
||||
length 0
|
||||
data ''
|
||||
length 48
|
||||
data <binary>
|
||||
|
||||
*** done
|
||||
|
Loading…
Reference in New Issue
Block a user