diff options
author | Stefan Hajnoczi | 2014-07-30 10:53:30 +0200 |
---|---|---|
committer | Stefan Hajnoczi | 2014-08-29 15:09:43 +0200 |
commit | 391827eb106d2d02062b2582d1545a7c221631c6 (patch) | |
tree | 74840acba94091d0ab90caa619f2dd9b0754ab00 /block.c | |
parent | nbd: Follow the BDS' AIO context (diff) | |
download | qemu-391827eb106d2d02062b2582d1545a7c221631c6.tar.gz qemu-391827eb106d2d02062b2582d1545a7c221631c6.tar.xz qemu-391827eb106d2d02062b2582d1545a7c221631c6.zip |
block: fix overlapping multiwrite requests
When request A is a strict superset of request B:
AAAAAAAA
BBBB
multiwrite_merge() merges them as follows:
AABBBB
The tail of request A should have been included:
AABBBBAA
This patch fixes data loss but this code path is probably rare. Since
guests cannot assume ordering between in-flight requests, few
applications submit overlapping write requests.
Reported-by: Slava Pestov <sviatoslav.pestov@gmail.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Benoit Canet <benoit@irqsave.net>
Diffstat (limited to 'block.c')
-rw-r--r-- | block.c | 6 |
1 files changed, 6 insertions, 0 deletions
@@ -4553,6 +4553,12 @@ static int multiwrite_merge(BlockDriverState *bs, BlockRequest *reqs, // Add the second request qemu_iovec_concat(qiov, reqs[i].qiov, 0, reqs[i].qiov->size); + // Add tail of first request, if necessary + if (qiov->size < reqs[outidx].qiov->size) { + qemu_iovec_concat(qiov, reqs[outidx].qiov, qiov->size, + reqs[outidx].qiov->size - qiov->size); + } + reqs[outidx].nb_sectors = qiov->size >> 9; reqs[outidx].qiov = qiov; |