qemu with hax to log dma reads & writes jcs.org/2018/11/12/vfio

qcow2: add qcow2_cache_discard

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 <pbutsykin@virtuozzo.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Reviewed-by: John Snow <jsnow@redhat.com>
Message-id: 20170918124230.8152-3-pbutsykin@virtuozzo.com
Signed-off-by: Max Reitz <mreitz@redhat.com>

authored by

Pavel Butsykin and committed by
Max Reitz
f71c08ea 4ffca890

+47 -2
+26
block/qcow2-cache.c
··· 411 411 assert(c->entries[i].offset != 0); 412 412 c->entries[i].dirty = true; 413 413 } 414 + 415 + void *qcow2_cache_is_table_offset(BlockDriverState *bs, Qcow2Cache *c, 416 + uint64_t offset) 417 + { 418 + int i; 419 + 420 + for (i = 0; i < c->size; i++) { 421 + if (c->entries[i].offset == offset) { 422 + return qcow2_cache_get_table_addr(bs, c, i); 423 + } 424 + } 425 + return NULL; 426 + } 427 + 428 + void qcow2_cache_discard(BlockDriverState *bs, Qcow2Cache *c, void *table) 429 + { 430 + int i = qcow2_cache_get_table_idx(bs, c, table); 431 + 432 + assert(c->entries[i].ref == 0); 433 + 434 + c->entries[i].offset = 0; 435 + c->entries[i].lru_counter = 0; 436 + c->entries[i].dirty = false; 437 + 438 + qcow2_cache_table_release(bs, c, i, 1); 439 + }
+18 -2
block/qcow2-refcount.c
··· 861 861 } 862 862 s->set_refcount(refcount_block, block_index, refcount); 863 863 864 - if (refcount == 0 && s->discard_passthrough[type]) { 865 - update_refcount_discard(bs, cluster_offset, s->cluster_size); 864 + if (refcount == 0) { 865 + void *table; 866 + 867 + table = qcow2_cache_is_table_offset(bs, s->refcount_block_cache, 868 + offset); 869 + if (table != NULL) { 870 + qcow2_cache_put(bs, s->refcount_block_cache, &refcount_block); 871 + qcow2_cache_discard(bs, s->refcount_block_cache, table); 872 + } 873 + 874 + table = qcow2_cache_is_table_offset(bs, s->l2_table_cache, offset); 875 + if (table != NULL) { 876 + qcow2_cache_discard(bs, s->l2_table_cache, table); 877 + } 878 + 879 + if (s->discard_passthrough[type]) { 880 + update_refcount_discard(bs, cluster_offset, s->cluster_size); 881 + } 866 882 } 867 883 } 868 884
+3
block/qcow2.h
··· 649 649 int qcow2_cache_get_empty(BlockDriverState *bs, Qcow2Cache *c, uint64_t offset, 650 650 void **table); 651 651 void qcow2_cache_put(BlockDriverState *bs, Qcow2Cache *c, void **table); 652 + void *qcow2_cache_is_table_offset(BlockDriverState *bs, Qcow2Cache *c, 653 + uint64_t offset); 654 + void qcow2_cache_discard(BlockDriverState *bs, Qcow2Cache *c, void *table); 652 655 653 656 /* qcow2-bitmap.c functions */ 654 657 int qcow2_check_bitmaps_refcounts(BlockDriverState *bs, BdrvCheckResult *res,