diff options
author | Stefan Hajnoczi <stefanha@redhat.com> | 2014-07-30 09:53:30 +0100 |
---|---|---|
committer | Stefan Hajnoczi <stefanha@redhat.com> | 2014-08-29 14:09:43 +0100 |
commit | 391827eb106d2d02062b2582d1545a7c221631c6 (patch) | |
tree | 74840acba94091d0ab90caa619f2dd9b0754ab00 | |
parent | f21492817bc426a3bc0b98fa852df95be9dea1e8 (diff) |
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>
-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; |