summaryrefslogtreecommitdiff
path: root/block/qcow2-cache.c
diff options
context:
space:
mode:
authorKevin Wolf <kwolf@redhat.com>2011-01-14 15:55:38 +0100
committerKevin Wolf <kwolf@redhat.com>2011-01-24 16:41:49 +0100
commit3de0a2944bdb3047dce275560631834bcb4afe22 (patch)
tree3549f925839388bae068f15ca148d5282ccd5beb /block/qcow2-cache.c
parent29c1a7301af752de6721e031d31faa48887204bd (diff)
qcow2: Batch flushes for COW
qcow2 calls bdrv_flush() after performing COW in order to ensure that the L2 table change is never written before the copy is safe on disk. Now that the L2 table is cached, we can wait with flushing until we write out the next L2 table. Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Diffstat (limited to 'block/qcow2-cache.c')
-rw-r--r--block/qcow2-cache.c20
1 files changed, 17 insertions, 3 deletions
diff --git a/block/qcow2-cache.c b/block/qcow2-cache.c
index 5f1740b9aa..8f2955b372 100644
--- a/block/qcow2-cache.c
+++ b/block/qcow2-cache.c
@@ -38,6 +38,7 @@ struct Qcow2Cache {
int size;
Qcow2CachedTable* entries;
struct Qcow2Cache* depends;
+ bool depends_on_flush;
bool writethrough;
};
@@ -85,13 +86,15 @@ static int qcow2_cache_flush_dependency(BlockDriverState *bs, Qcow2Cache *c)
}
c->depends = NULL;
+ c->depends_on_flush = false;
+
return 0;
}
static int qcow2_cache_entry_flush(BlockDriverState *bs, Qcow2Cache *c, int i)
{
BDRVQcowState *s = bs->opaque;
- int ret;
+ int ret = 0;
if (!c->entries[i].dirty || !c->entries[i].offset) {
return 0;
@@ -99,11 +102,17 @@ static int qcow2_cache_entry_flush(BlockDriverState *bs, Qcow2Cache *c, int i)
if (c->depends) {
ret = qcow2_cache_flush_dependency(bs, c);
- if (ret < 0) {
- return ret;
+ } else if (c->depends_on_flush) {
+ ret = bdrv_flush(bs->file);
+ if (ret >= 0) {
+ c->depends_on_flush = false;
}
}
+ if (ret < 0) {
+ return ret;
+ }
+
if (c == s->refcount_block_cache) {
BLKDBG_EVENT(bs->file, BLKDBG_REFBLOCK_UPDATE_PART);
} else if (c == s->l2_table_cache) {
@@ -167,6 +176,11 @@ int qcow2_cache_set_dependency(BlockDriverState *bs, Qcow2Cache *c,
return 0;
}
+void qcow2_cache_depends_on_flush(Qcow2Cache *c)
+{
+ c->depends_on_flush = true;
+}
+
static int qcow2_cache_find_entry_to_replace(Qcow2Cache *c)
{
int i;