|
|
ae23c9 |
From 58bdc00e94d7a965f91881022386ec73fe081c2f Mon Sep 17 00:00:00 2001
|
|
|
ae23c9 |
From: John Snow <jsnow@redhat.com>
|
|
|
ae23c9 |
Date: Tue, 24 Jul 2018 12:59:12 +0200
|
|
|
ae23c9 |
Subject: [PATCH 237/268] block/io: fix copy_range
|
|
|
ae23c9 |
|
|
|
ae23c9 |
RH-Author: John Snow <jsnow@redhat.com>
|
|
|
ae23c9 |
Message-id: <20180718225511.14878-20-jsnow@redhat.com>
|
|
|
ae23c9 |
Patchwork-id: 81420
|
|
|
ae23c9 |
O-Subject: [RHEL-7.6 qemu-kvm-rhev PATCH 19/35] block/io: fix copy_range
|
|
|
ae23c9 |
Bugzilla: 1207657
|
|
|
ae23c9 |
RH-Acked-by: Eric Blake <eblake@redhat.com>
|
|
|
ae23c9 |
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
|
|
|
ae23c9 |
RH-Acked-by: Fam Zheng <famz@redhat.com>
|
|
|
ae23c9 |
|
|
|
ae23c9 |
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
|
|
|
ae23c9 |
|
|
|
ae23c9 |
Here two things are fixed:
|
|
|
ae23c9 |
|
|
|
ae23c9 |
1. Architecture
|
|
|
ae23c9 |
|
|
|
ae23c9 |
On each recursion step, we go to the child of src or dst, only for one
|
|
|
ae23c9 |
of them. So, it's wrong to create tracked requests for both on each
|
|
|
ae23c9 |
step. It leads to tracked requests duplication.
|
|
|
ae23c9 |
|
|
|
ae23c9 |
2. Wait for serializing requests on write path independently of
|
|
|
ae23c9 |
BDRV_REQ_NO_SERIALISING
|
|
|
ae23c9 |
|
|
|
ae23c9 |
Before commit 9ded4a01149 "backup: Use copy offloading",
|
|
|
ae23c9 |
BDRV_REQ_NO_SERIALISING was used for only one case: read in
|
|
|
ae23c9 |
copy-on-write operation during backup. Also, the flag was handled only
|
|
|
ae23c9 |
on read path (in bdrv_co_preadv and bdrv_aligned_preadv).
|
|
|
ae23c9 |
|
|
|
ae23c9 |
After 9ded4a01149, flag is used for not waiting serializing operations
|
|
|
ae23c9 |
on backup target (in same case of copy-on-write operation). This
|
|
|
ae23c9 |
behavior change is unsubstantiated and potentially dangerous, let's
|
|
|
ae23c9 |
drop it and add additional asserts and documentation.
|
|
|
ae23c9 |
|
|
|
ae23c9 |
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
|
|
|
ae23c9 |
Reviewed-by: Fam Zheng <famz@redhat.com>
|
|
|
ae23c9 |
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
|
|
ae23c9 |
(cherry picked from commit 999658a05e61a8d87b65827da665302bb44ce8c9)
|
|
|
ae23c9 |
Signed-off-by: John Snow <jsnow@redhat.com>
|
|
|
ae23c9 |
---
|
|
|
ae23c9 |
block/io.c | 43 +++++++++++++++++++++++++++----------------
|
|
|
ae23c9 |
include/block/block.h | 12 ++++++++++++
|
|
|
ae23c9 |
2 files changed, 39 insertions(+), 16 deletions(-)
|
|
|
ae23c9 |
|
|
|
ae23c9 |
diff --git a/block/io.c b/block/io.c
|
|
|
ae23c9 |
index b6754f3..f8de42f 100644
|
|
|
ae23c9 |
--- a/block/io.c
|
|
|
ae23c9 |
+++ b/block/io.c
|
|
|
ae23c9 |
@@ -1505,6 +1505,8 @@ static int coroutine_fn bdrv_aligned_pwritev(BdrvChild *child,
|
|
|
ae23c9 |
max_transfer = QEMU_ALIGN_DOWN(MIN_NON_ZERO(bs->bl.max_transfer, INT_MAX),
|
|
|
ae23c9 |
align);
|
|
|
ae23c9 |
|
|
|
ae23c9 |
+ /* BDRV_REQ_NO_SERIALISING is only for read operation */
|
|
|
ae23c9 |
+ assert(!(flags & BDRV_REQ_NO_SERIALISING));
|
|
|
ae23c9 |
waited = wait_serialising_requests(req);
|
|
|
ae23c9 |
assert(!waited || !req->serialising);
|
|
|
ae23c9 |
assert(req->overlap_offset <= offset);
|
|
|
ae23c9 |
@@ -2847,7 +2849,7 @@ static int coroutine_fn bdrv_co_copy_range_internal(BdrvChild *src,
|
|
|
ae23c9 |
BdrvRequestFlags flags,
|
|
|
ae23c9 |
bool recurse_src)
|
|
|
ae23c9 |
{
|
|
|
ae23c9 |
- BdrvTrackedRequest src_req, dst_req;
|
|
|
ae23c9 |
+ BdrvTrackedRequest req;
|
|
|
ae23c9 |
int ret;
|
|
|
ae23c9 |
|
|
|
ae23c9 |
if (!dst || !dst->bs) {
|
|
|
ae23c9 |
@@ -2876,32 +2878,41 @@ static int coroutine_fn bdrv_co_copy_range_internal(BdrvChild *src,
|
|
|
ae23c9 |
return -ENOTSUP;
|
|
|
ae23c9 |
}
|
|
|
ae23c9 |
|
|
|
ae23c9 |
- bdrv_inc_in_flight(src->bs);
|
|
|
ae23c9 |
- bdrv_inc_in_flight(dst->bs);
|
|
|
ae23c9 |
- tracked_request_begin(&src_req, src->bs, src_offset,
|
|
|
ae23c9 |
- bytes, BDRV_TRACKED_READ);
|
|
|
ae23c9 |
- tracked_request_begin(&dst_req, dst->bs, dst_offset,
|
|
|
ae23c9 |
- bytes, BDRV_TRACKED_WRITE);
|
|
|
ae23c9 |
-
|
|
|
ae23c9 |
- if (!(flags & BDRV_REQ_NO_SERIALISING)) {
|
|
|
ae23c9 |
- wait_serialising_requests(&src_req);
|
|
|
ae23c9 |
- wait_serialising_requests(&dst_req);
|
|
|
ae23c9 |
- }
|
|
|
ae23c9 |
if (recurse_src) {
|
|
|
ae23c9 |
+ bdrv_inc_in_flight(src->bs);
|
|
|
ae23c9 |
+ tracked_request_begin(&req, src->bs, src_offset, bytes,
|
|
|
ae23c9 |
+ BDRV_TRACKED_READ);
|
|
|
ae23c9 |
+
|
|
|
ae23c9 |
+ if (!(flags & BDRV_REQ_NO_SERIALISING)) {
|
|
|
ae23c9 |
+ wait_serialising_requests(&req;;
|
|
|
ae23c9 |
+ }
|
|
|
ae23c9 |
+
|
|
|
ae23c9 |
ret = src->bs->drv->bdrv_co_copy_range_from(src->bs,
|
|
|
ae23c9 |
src, src_offset,
|
|
|
ae23c9 |
dst, dst_offset,
|
|
|
ae23c9 |
bytes, flags);
|
|
|
ae23c9 |
+
|
|
|
ae23c9 |
+ tracked_request_end(&req;;
|
|
|
ae23c9 |
+ bdrv_dec_in_flight(src->bs);
|
|
|
ae23c9 |
} else {
|
|
|
ae23c9 |
+ bdrv_inc_in_flight(dst->bs);
|
|
|
ae23c9 |
+ tracked_request_begin(&req, dst->bs, dst_offset, bytes,
|
|
|
ae23c9 |
+ BDRV_TRACKED_WRITE);
|
|
|
ae23c9 |
+
|
|
|
ae23c9 |
+ /* BDRV_REQ_NO_SERIALISING is only for read operation,
|
|
|
ae23c9 |
+ * so we ignore it in flags.
|
|
|
ae23c9 |
+ */
|
|
|
ae23c9 |
+ wait_serialising_requests(&req;;
|
|
|
ae23c9 |
+
|
|
|
ae23c9 |
ret = dst->bs->drv->bdrv_co_copy_range_to(dst->bs,
|
|
|
ae23c9 |
src, src_offset,
|
|
|
ae23c9 |
dst, dst_offset,
|
|
|
ae23c9 |
bytes, flags);
|
|
|
ae23c9 |
+
|
|
|
ae23c9 |
+ tracked_request_end(&req;;
|
|
|
ae23c9 |
+ bdrv_dec_in_flight(dst->bs);
|
|
|
ae23c9 |
}
|
|
|
ae23c9 |
- tracked_request_end(&src_req);
|
|
|
ae23c9 |
- tracked_request_end(&dst_req);
|
|
|
ae23c9 |
- bdrv_dec_in_flight(src->bs);
|
|
|
ae23c9 |
- bdrv_dec_in_flight(dst->bs);
|
|
|
ae23c9 |
+
|
|
|
ae23c9 |
return ret;
|
|
|
ae23c9 |
}
|
|
|
ae23c9 |
|
|
|
ae23c9 |
diff --git a/include/block/block.h b/include/block/block.h
|
|
|
ae23c9 |
index e1d5e47..716fb5b 100644
|
|
|
ae23c9 |
--- a/include/block/block.h
|
|
|
ae23c9 |
+++ b/include/block/block.h
|
|
|
ae23c9 |
@@ -50,6 +50,18 @@ typedef enum {
|
|
|
ae23c9 |
* opened with BDRV_O_UNMAP.
|
|
|
ae23c9 |
*/
|
|
|
ae23c9 |
BDRV_REQ_MAY_UNMAP = 0x4,
|
|
|
ae23c9 |
+
|
|
|
ae23c9 |
+ /*
|
|
|
ae23c9 |
+ * The BDRV_REQ_NO_SERIALISING flag is only valid for reads and means that
|
|
|
ae23c9 |
+ * we don't want wait_serialising_requests() during the read operation.
|
|
|
ae23c9 |
+ *
|
|
|
ae23c9 |
+ * This flag is used for backup copy-on-write operations, when we need to
|
|
|
ae23c9 |
+ * read old data before write (write notifier triggered). It is okay since
|
|
|
ae23c9 |
+ * we already waited for other serializing requests in the initiating write
|
|
|
ae23c9 |
+ * (see bdrv_aligned_pwritev), and it is necessary if the initiating write
|
|
|
ae23c9 |
+ * is already serializing (without the flag, the read would deadlock
|
|
|
ae23c9 |
+ * waiting for the serialising write to complete).
|
|
|
ae23c9 |
+ */
|
|
|
ae23c9 |
BDRV_REQ_NO_SERIALISING = 0x8,
|
|
|
ae23c9 |
BDRV_REQ_FUA = 0x10,
|
|
|
ae23c9 |
BDRV_REQ_WRITE_COMPRESSED = 0x20,
|
|
|
ae23c9 |
--
|
|
|
ae23c9 |
1.8.3.1
|
|
|
ae23c9 |
|