Skip to content

Commit

Permalink
qcow2: add qcow2_cache_discard
Browse files Browse the repository at this point in the history
Whenever l2/refcount table clusters are discarded from the file we can
automatically drop unnecessary content of the cache tables. This reduces
the chance of eviction useful cache data and eliminates inconsistent data
in the cache with the data in the file.

Signed-off-by: Pavel Butsykin <[email protected]>
Reviewed-by: Max Reitz <[email protected]>
Reviewed-by: John Snow <[email protected]>
Message-id: [email protected]
Signed-off-by: Max Reitz <[email protected]>
  • Loading branch information
pbutsykin authored and XanClic committed Sep 26, 2017
1 parent 4ffca89 commit f71c08e
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 2 deletions.
26 changes: 26 additions & 0 deletions block/qcow2-cache.c
Original file line number Diff line number Diff line change
Expand Up @@ -411,3 +411,29 @@ void qcow2_cache_entry_mark_dirty(BlockDriverState *bs, Qcow2Cache *c,
assert(c->entries[i].offset != 0);
c->entries[i].dirty = true;
}

void *qcow2_cache_is_table_offset(BlockDriverState *bs, Qcow2Cache *c,
uint64_t offset)
{
int i;

for (i = 0; i < c->size; i++) {
if (c->entries[i].offset == offset) {
return qcow2_cache_get_table_addr(bs, c, i);
}
}
return NULL;
}

void qcow2_cache_discard(BlockDriverState *bs, Qcow2Cache *c, void *table)
{
int i = qcow2_cache_get_table_idx(bs, c, table);

assert(c->entries[i].ref == 0);

c->entries[i].offset = 0;
c->entries[i].lru_counter = 0;
c->entries[i].dirty = false;

qcow2_cache_table_release(bs, c, i, 1);
}
20 changes: 18 additions & 2 deletions block/qcow2-refcount.c
Original file line number Diff line number Diff line change
Expand Up @@ -861,8 +861,24 @@ static int QEMU_WARN_UNUSED_RESULT update_refcount(BlockDriverState *bs,
}
s->set_refcount(refcount_block, block_index, refcount);

if (refcount == 0 && s->discard_passthrough[type]) {
update_refcount_discard(bs, cluster_offset, s->cluster_size);
if (refcount == 0) {
void *table;

table = qcow2_cache_is_table_offset(bs, s->refcount_block_cache,
offset);
if (table != NULL) {
qcow2_cache_put(bs, s->refcount_block_cache, &refcount_block);
qcow2_cache_discard(bs, s->refcount_block_cache, table);
}

table = qcow2_cache_is_table_offset(bs, s->l2_table_cache, offset);
if (table != NULL) {
qcow2_cache_discard(bs, s->l2_table_cache, table);
}

if (s->discard_passthrough[type]) {
update_refcount_discard(bs, cluster_offset, s->cluster_size);
}
}
}

Expand Down
3 changes: 3 additions & 0 deletions block/qcow2.h
Original file line number Diff line number Diff line change
Expand Up @@ -649,6 +649,9 @@ int qcow2_cache_get(BlockDriverState *bs, Qcow2Cache *c, uint64_t offset,
int qcow2_cache_get_empty(BlockDriverState *bs, Qcow2Cache *c, uint64_t offset,
void **table);
void qcow2_cache_put(BlockDriverState *bs, Qcow2Cache *c, void **table);
void *qcow2_cache_is_table_offset(BlockDriverState *bs, Qcow2Cache *c,
uint64_t offset);
void qcow2_cache_discard(BlockDriverState *bs, Qcow2Cache *c, void *table);

/* qcow2-bitmap.c functions */
int qcow2_check_bitmaps_refcounts(BlockDriverState *bs, BdrvCheckResult *res,
Expand Down

0 comments on commit f71c08e

Please sign in to comment.