From: fangying <fangying1(a)huawei.com>
When qemu or qemu-nbd process that uses a qcow2 file and configured with
'cache = none', it will write to the qcow2 file which uses qcow2 with a
cache to cache L2 tables, the process will not use L2 tables without
explicitly calling the flush command or closing the mirror flash into
the disk. Which causes the disk data to be inconsistent with the written
data for a long time. If an abnormal process exit occurs here, the written
data will be lost.
Therefore, we need to flush the changes to the L2 entry to the disk in time
for the newly allocated cluster.
Signed-off-by: Ying Fang <fangying1(a)huawei.com>
diff --git a/block/qcow2-cache.c b/block/qcow2-cache.c
index 7444b9c4ab..ab6e812c84 100644
--- a/block/qcow2-cache.c
+++ b/block/qcow2-cache.c
@@ -266,6 +266,22 @@ int qcow2_cache_flush(BlockDriverState *bs, Qcow2Cache *c)
return result;
}
+#define L2_ENTRIES_PER_SECTOR 64
+int qcow2_cache_l2_write_entry(BlockDriverState *bs, Qcow2Cache *c,
+ void *table, int index, int num)
+{
+ int ret;
+ int i = qcow2_cache_get_table_idx(c, table);
+ int start_sector = index / L2_ENTRIES_PER_SECTOR;
+ int end_sector = (index + num - 1) / L2_ENTRIES_PER_SECTOR;
+ int nr_sectors = end_sector - start_sector + 1;
+ ret = bdrv_pwrite(bs->file,
+ c->entries[i].offset + start_sector * BDRV_SECTOR_SIZE,
+ table + start_sector * BDRV_SECTOR_SIZE,
+ nr_sectors * BDRV_SECTOR_SIZE);
+ return ret;
+}
+
int qcow2_cache_set_dependency(BlockDriverState *bs, Qcow2Cache *c,
Qcow2Cache *dependency)
{
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index a677ba9f5c..ae49a83972 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -998,6 +998,9 @@ int qcow2_alloc_cluster_link_l2(BlockDriverState *bs, QCowL2Meta *m)
}
+ ret = qcow2_cache_l2_write_entry(bs, s->l2_table_cache, l2_slice,
+ l2_index, m->nb_clusters);
+
qcow2_cache_put(s->l2_table_cache, (void **) &l2_slice);
/*
diff --git a/block/qcow2.h b/block/qcow2.h
index 7ce2c23bdb..168ab5918e 100644
--- a/block/qcow2.h
+++ b/block/qcow2.h
@@ -748,6 +748,8 @@ int qcow2_cache_destroy(Qcow2Cache *c);
void qcow2_cache_entry_mark_dirty(Qcow2Cache *c, void *table);
int qcow2_cache_flush(BlockDriverState *bs, Qcow2Cache *c);
int qcow2_cache_write(BlockDriverState *bs, Qcow2Cache *c);
+int qcow2_cache_l2_write_entry(BlockDriverState *bs, Qcow2Cache *c,
+ void *table, int index, int num);
int qcow2_cache_set_dependency(BlockDriverState *bs, Qcow2Cache *c,
Qcow2Cache *dependency);
void qcow2_cache_depends_on_flush(Qcow2Cache *c);
--
2.23.0