mirror of https://github.com/xemu-project/xemu.git
qcow2: always operate caches in writeback mode
Writethrough does not need special-casing anymore in the qcow2 caches. The block layer adds flushes after every guest-initiated data write, and these will also flush the qcow2 caches to the OS. Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
This commit is contained in:
parent
7cdd481cdf
commit
6af4e9ead4
|
@ -40,11 +40,9 @@ struct Qcow2Cache {
|
||||||
struct Qcow2Cache* depends;
|
struct Qcow2Cache* depends;
|
||||||
int size;
|
int size;
|
||||||
bool depends_on_flush;
|
bool depends_on_flush;
|
||||||
bool writethrough;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Qcow2Cache *qcow2_cache_create(BlockDriverState *bs, int num_tables,
|
Qcow2Cache *qcow2_cache_create(BlockDriverState *bs, int num_tables)
|
||||||
bool writethrough)
|
|
||||||
{
|
{
|
||||||
BDRVQcowState *s = bs->opaque;
|
BDRVQcowState *s = bs->opaque;
|
||||||
Qcow2Cache *c;
|
Qcow2Cache *c;
|
||||||
|
@ -53,7 +51,6 @@ Qcow2Cache *qcow2_cache_create(BlockDriverState *bs, int num_tables,
|
||||||
c = g_malloc0(sizeof(*c));
|
c = g_malloc0(sizeof(*c));
|
||||||
c->size = num_tables;
|
c->size = num_tables;
|
||||||
c->entries = g_malloc0(sizeof(*c->entries) * num_tables);
|
c->entries = g_malloc0(sizeof(*c->entries) * num_tables);
|
||||||
c->writethrough = writethrough;
|
|
||||||
|
|
||||||
for (i = 0; i < c->size; i++) {
|
for (i = 0; i < c->size; i++) {
|
||||||
c->entries[i].table = qemu_blockalign(bs, s->cluster_size);
|
c->entries[i].table = qemu_blockalign(bs, s->cluster_size);
|
||||||
|
@ -307,12 +304,7 @@ found:
|
||||||
*table = NULL;
|
*table = NULL;
|
||||||
|
|
||||||
assert(c->entries[i].ref >= 0);
|
assert(c->entries[i].ref >= 0);
|
||||||
|
|
||||||
if (c->writethrough) {
|
|
||||||
return qcow2_cache_entry_flush(bs, c, i);
|
|
||||||
} else {
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void qcow2_cache_entry_mark_dirty(Qcow2Cache *c, void *table)
|
void qcow2_cache_entry_mark_dirty(Qcow2Cache *c, void *table)
|
||||||
|
@ -329,16 +321,3 @@ void qcow2_cache_entry_mark_dirty(Qcow2Cache *c, void *table)
|
||||||
found:
|
found:
|
||||||
c->entries[i].dirty = true;
|
c->entries[i].dirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool qcow2_cache_set_writethrough(BlockDriverState *bs, Qcow2Cache *c,
|
|
||||||
bool enable)
|
|
||||||
{
|
|
||||||
bool old = c->writethrough;
|
|
||||||
|
|
||||||
if (!old && enable) {
|
|
||||||
qcow2_cache_flush(bs, c);
|
|
||||||
}
|
|
||||||
|
|
||||||
c->writethrough = enable;
|
|
||||||
return old;
|
|
||||||
}
|
|
||||||
|
|
|
@ -726,13 +726,6 @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs,
|
||||||
int64_t old_offset, old_l2_offset;
|
int64_t old_offset, old_l2_offset;
|
||||||
int i, j, l1_modified = 0, nb_csectors, refcount;
|
int i, j, l1_modified = 0, nb_csectors, refcount;
|
||||||
int ret;
|
int ret;
|
||||||
bool old_l2_writethrough, old_refcount_writethrough;
|
|
||||||
|
|
||||||
/* Switch caches to writeback mode during update */
|
|
||||||
old_l2_writethrough =
|
|
||||||
qcow2_cache_set_writethrough(bs, s->l2_table_cache, false);
|
|
||||||
old_refcount_writethrough =
|
|
||||||
qcow2_cache_set_writethrough(bs, s->refcount_block_cache, false);
|
|
||||||
|
|
||||||
l2_table = NULL;
|
l2_table = NULL;
|
||||||
l1_table = NULL;
|
l1_table = NULL;
|
||||||
|
@ -856,11 +849,6 @@ fail:
|
||||||
qcow2_cache_put(bs, s->l2_table_cache, (void**) &l2_table);
|
qcow2_cache_put(bs, s->l2_table_cache, (void**) &l2_table);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Enable writethrough cache mode again */
|
|
||||||
qcow2_cache_set_writethrough(bs, s->l2_table_cache, old_l2_writethrough);
|
|
||||||
qcow2_cache_set_writethrough(bs, s->refcount_block_cache,
|
|
||||||
old_refcount_writethrough);
|
|
||||||
|
|
||||||
/* Update L1 only if it isn't deleted anyway (addend = -1) */
|
/* Update L1 only if it isn't deleted anyway (addend = -1) */
|
||||||
if (addend >= 0 && l1_modified) {
|
if (addend >= 0 && l1_modified) {
|
||||||
for(i = 0; i < l1_size; i++)
|
for(i = 0; i < l1_size; i++)
|
||||||
|
|
|
@ -220,7 +220,6 @@ static int qcow2_open(BlockDriverState *bs, int flags)
|
||||||
int len, i, ret = 0;
|
int len, i, ret = 0;
|
||||||
QCowHeader header;
|
QCowHeader header;
|
||||||
uint64_t ext_end;
|
uint64_t ext_end;
|
||||||
bool writethrough;
|
|
||||||
|
|
||||||
ret = bdrv_pread(bs->file, 0, &header, sizeof(header));
|
ret = bdrv_pread(bs->file, 0, &header, sizeof(header));
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
|
@ -367,10 +366,8 @@ static int qcow2_open(BlockDriverState *bs, int flags)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* alloc L2 table/refcount block cache */
|
/* alloc L2 table/refcount block cache */
|
||||||
writethrough = ((flags & BDRV_O_CACHE_WB) == 0);
|
s->l2_table_cache = qcow2_cache_create(bs, L2_CACHE_SIZE);
|
||||||
s->l2_table_cache = qcow2_cache_create(bs, L2_CACHE_SIZE, writethrough);
|
s->refcount_block_cache = qcow2_cache_create(bs, REFCOUNT_CACHE_SIZE);
|
||||||
s->refcount_block_cache = qcow2_cache_create(bs, REFCOUNT_CACHE_SIZE,
|
|
||||||
writethrough);
|
|
||||||
|
|
||||||
s->cluster_cache = g_malloc(s->cluster_size);
|
s->cluster_cache = g_malloc(s->cluster_size);
|
||||||
/* one more sector for decompressed data alignment */
|
/* one more sector for decompressed data alignment */
|
||||||
|
|
|
@ -297,11 +297,8 @@ void qcow2_free_snapshots(BlockDriverState *bs);
|
||||||
int qcow2_read_snapshots(BlockDriverState *bs);
|
int qcow2_read_snapshots(BlockDriverState *bs);
|
||||||
|
|
||||||
/* qcow2-cache.c functions */
|
/* qcow2-cache.c functions */
|
||||||
Qcow2Cache *qcow2_cache_create(BlockDriverState *bs, int num_tables,
|
Qcow2Cache *qcow2_cache_create(BlockDriverState *bs, int num_tables);
|
||||||
bool writethrough);
|
|
||||||
int qcow2_cache_destroy(BlockDriverState* bs, Qcow2Cache *c);
|
int qcow2_cache_destroy(BlockDriverState* bs, Qcow2Cache *c);
|
||||||
bool qcow2_cache_set_writethrough(BlockDriverState *bs, Qcow2Cache *c,
|
|
||||||
bool enable);
|
|
||||||
|
|
||||||
void qcow2_cache_entry_mark_dirty(Qcow2Cache *c, void *table);
|
void qcow2_cache_entry_mark_dirty(Qcow2Cache *c, void *table);
|
||||||
int qcow2_cache_flush(BlockDriverState *bs, Qcow2Cache *c);
|
int qcow2_cache_flush(BlockDriverState *bs, Qcow2Cache *c);
|
||||||
|
|
Loading…
Reference in New Issue