Write-through is another way to keep the cache up-to-date. Even if this case will be rare, write to the cache is more optimal than drop-cache.
Signed-off-by: Pavel Butsykin <pbutsy...@virtuozzo.com> --- block/pcache.c | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/block/pcache.c b/block/pcache.c index c1cbfa7040..140f90d6d7 100644 --- a/block/pcache.c +++ b/block/pcache.c @@ -410,8 +410,26 @@ skip_large_request: return bdrv_co_preadv(bs->file, offset, bytes, qiov, flags); } -static void pcache_invalidation(BlockDriverState *bs, uint64_t offset, - uint64_t bytes) +static void write_cache_data(PCacheNode *node, uint64_t offset, uint64_t bytes, + QEMUIOVector *qiov) +{ + uint64_t qiov_offs = 0, node_offs = 0; + uint64_t size; + uint64_t copy; + + if (offset < node->common.offset) { + qiov_offs = node->common.offset - offset; + } else { + node_offs = offset - node->common.offset; + } + size = ranges_overlap_size(offset, bytes, node->common.offset, + node->common.bytes); + copy = qemu_iovec_to_buf(qiov, qiov_offs, node->data + node_offs, size); + assert(copy == size); +} + +static void pcache_write_through(BlockDriverState *bs, uint64_t offset, + uint64_t bytes, QEMUIOVector *qiov) { BDRVPCacheState *s = bs->opaque; uint64_t chunk_offset = offset, chunk_bytes = bytes; @@ -429,7 +447,7 @@ static void pcache_invalidation(BlockDriverState *bs, uint64_t offset, chunk_bytes = end_offs - chunk_offset; if (node->status & NODE_STATUS_COMPLETED) { - rbcache_remove(s->cache, &node->common); + write_cache_data(node, offset, bytes, qiov); } } while (end_offs > chunk_offset); } @@ -442,7 +460,7 @@ static coroutine_fn int pcache_co_pwritev(BlockDriverState *bs, uint64_t offset, if (ret < 0) { return ret; } - pcache_invalidation(bs, offset, bytes); + pcache_write_through(bs, offset, bytes, qiov); return ret; } -- 2.11.0