mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-02 07:13:54 -06:00
block: ignore flush requests when storage is clean
Some guests (win2008 server for example) do a lot of unnecessary flushing when underlying media has not changed. This adds additional overhead on host when calling fsync/fdatasync. This change introduces a write generation scheme in BlockDriverState. Current write generation is checked against last flushed generation to avoid unnessesary flushes. The problem with excessive flushing was found by a performance test which does parallel directory tree creation (from 2 processes). Results improved from 0.424 loops/sec to 0.432 loops/sec. Each loop creates 10^3 directories with 10 files in each. This affected some blkdebug testcases that were expecting error logs from failure-injected flushes which are now skipped entirely (tests 026 071 089). This also affects the performance of block jobs and thus BLOCK_JOB_READY events for driver-mirror and active block-commit commands now arrives faster, before QMP send successfully returns to caller (tests 141 144). Signed-off-by: Evgeny Yakovlev <eyakovlev@virtuozzo.com> Signed-off-by: Denis V. Lunev <den@openvz.org> Reviewed-by: Paolo Bonzini <pbonzini@redhat.com> Message-id: 1468870792-7411-5-git-send-email-den@openvz.org CC: Kevin Wolf <kwolf@redhat.com> CC: Max Reitz <mreitz@redhat.com> CC: Stefan Hajnoczi <stefanha@redhat.com> CC: Fam Zheng <famz@redhat.com> CC: John Snow <jsnow@redhat.com> Signed-off-by: John Snow <jsnow@redhat.com>
This commit is contained in:
parent
2dd7e10d7c
commit
3ff2f67a7c
9 changed files with 32 additions and 113 deletions
21
block/io.c
21
block/io.c
|
@ -1303,6 +1303,7 @@ static int coroutine_fn bdrv_aligned_pwritev(BlockDriverState *bs,
|
|||
}
|
||||
bdrv_debug_event(bs, BLKDBG_PWRITEV_DONE);
|
||||
|
||||
++bs->write_gen;
|
||||
bdrv_set_dirty(bs, start_sector, end_sector - start_sector);
|
||||
|
||||
if (bs->wr_highest_offset < offset + bytes) {
|
||||
|
@ -2236,6 +2237,15 @@ int coroutine_fn bdrv_co_flush(BlockDriverState *bs)
|
|||
|
||||
tracked_request_begin(&req, bs, 0, 0, BDRV_TRACKED_FLUSH);
|
||||
|
||||
int current_gen = bs->write_gen;
|
||||
|
||||
/* Wait until any previous flushes are completed */
|
||||
while (bs->flush_started_gen != bs->flushed_gen) {
|
||||
qemu_co_queue_wait(&bs->flush_queue);
|
||||
}
|
||||
|
||||
bs->flush_started_gen = current_gen;
|
||||
|
||||
/* Write back all layers by calling one driver function */
|
||||
if (bs->drv->bdrv_co_flush) {
|
||||
ret = bs->drv->bdrv_co_flush(bs);
|
||||
|
@ -2256,6 +2266,11 @@ int coroutine_fn bdrv_co_flush(BlockDriverState *bs)
|
|||
goto flush_parent;
|
||||
}
|
||||
|
||||
/* Check if we really need to flush anything */
|
||||
if (bs->flushed_gen == current_gen) {
|
||||
goto flush_parent;
|
||||
}
|
||||
|
||||
BLKDBG_EVENT(bs->file, BLKDBG_FLUSH_TO_DISK);
|
||||
if (bs->drv->bdrv_co_flush_to_disk) {
|
||||
ret = bs->drv->bdrv_co_flush_to_disk(bs);
|
||||
|
@ -2286,6 +2301,7 @@ int coroutine_fn bdrv_co_flush(BlockDriverState *bs)
|
|||
*/
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
if (ret < 0) {
|
||||
goto out;
|
||||
}
|
||||
|
@ -2296,6 +2312,10 @@ int coroutine_fn bdrv_co_flush(BlockDriverState *bs)
|
|||
flush_parent:
|
||||
ret = bs->file ? bdrv_co_flush(bs->file->bs) : 0;
|
||||
out:
|
||||
/* Notify any pending flushes that we have completed */
|
||||
bs->flushed_gen = current_gen;
|
||||
qemu_co_queue_restart_all(&bs->flush_queue);
|
||||
|
||||
tracked_request_end(&req);
|
||||
return ret;
|
||||
}
|
||||
|
@ -2421,6 +2441,7 @@ int coroutine_fn bdrv_co_discard(BlockDriverState *bs, int64_t sector_num,
|
|||
}
|
||||
ret = 0;
|
||||
out:
|
||||
++bs->write_gen;
|
||||
bdrv_set_dirty(bs, req.offset >> BDRV_SECTOR_BITS,
|
||||
req.bytes >> BDRV_SECTOR_BITS);
|
||||
tracked_request_end(&req);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue