In AIO write request completion we just drop all the intersecting nodes in the cache, it's a simple way to keep the cache up-to-date.
Signed-off-by: Pavel Butsykin <pbutsy...@virtuozzo.com> --- block/pcache.c | 39 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/block/pcache.c b/block/pcache.c index 1f3800d..27ee6dd 100644 --- a/block/pcache.c +++ b/block/pcache.c @@ -362,15 +362,52 @@ out: return acb.ret; } +static void pcache_aio_write_cb(void *opaque, int ret) +{ + PCacheAIOCB *acb = opaque; + BDRVPCacheState *s = acb->bs->opaque; + uint64_t offset = acb->offset; + uint64_t bytes = acb->bytes; + uint64_t end_offs = offset + bytes; + + if (ret < 0) { + goto out; + } + + do { + PCacheNode *node = rbcache_search(s->cache, offset, bytes); + if (node == NULL) { + break; + } + assert(node->status == NODE_STATUS_COMPLETED || + node->status == NODE_STATUS_INFLIGHT || + node->status == NODE_STATUS_REMOVE); + + offset = node->common.offset + node->common.bytes; + bytes = end_offs - offset; + + if (node->status == NODE_STATUS_COMPLETED) { + rbcache_remove(s->cache, &node->common); + } + } while (end_offs > offset); + +out: + acb->ret = ret; + qemu_coroutine_enter(acb->co); +} + static coroutine_fn int pcache_co_pwritev(BlockDriverState *bs, uint64_t offset, uint64_t bytes, QEMUIOVector *qiov, int flags) { PCacheAIOCB acb = { .co = qemu_coroutine_self(), + .bs = bs, + .offset = offset, + .bytes = bytes, }; - bdrv_aio_pwritev(bs->file, offset, qiov, bytes, pcache_aio_cb, &acb); + bdrv_aio_pwritev(bs->file, offset, qiov, bytes, pcache_aio_write_cb, &acb); qemu_coroutine_yield(); -- 2.10.1