|
|
26ba25 |
From fb4f98330be87d3272d91c354843eadc6db8fc73 Mon Sep 17 00:00:00 2001
|
|
|
26ba25 |
From: Kevin Wolf <kwolf@redhat.com>
|
|
|
26ba25 |
Date: Thu, 12 Jul 2018 14:42:57 +0200
|
|
|
26ba25 |
Subject: [PATCH 212/268] block: Use tracked request for truncate
|
|
|
26ba25 |
|
|
|
26ba25 |
RH-Author: Kevin Wolf <kwolf@redhat.com>
|
|
|
26ba25 |
Message-id: <20180712144258.17303-6-kwolf@redhat.com>
|
|
|
26ba25 |
Patchwork-id: 81326
|
|
|
26ba25 |
O-Subject: [RHV-7.6 qemu-kvm-rhev PATCH 5/6] block: Use tracked request for truncate
|
|
|
26ba25 |
Bugzilla: 1595173
|
|
|
26ba25 |
RH-Acked-by: Max Reitz <mreitz@redhat.com>
|
|
|
26ba25 |
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
|
|
|
26ba25 |
RH-Acked-by: John Snow <jsnow@redhat.com>
|
|
|
26ba25 |
|
|
|
26ba25 |
When growing an image, block drivers (especially protocol drivers) may
|
|
|
26ba25 |
initialise the newly added area. I/O requests to the same area need to
|
|
|
26ba25 |
wait for this initialisation to be completed so that data writes don't
|
|
|
26ba25 |
get overwritten and reads don't read uninitialised data.
|
|
|
26ba25 |
|
|
|
26ba25 |
To avoid overhead in the fast I/O path by adding new locking in the
|
|
|
26ba25 |
protocol drivers and to restrict the impact to requests that actually
|
|
|
26ba25 |
touch the new area, reuse the existing tracked request infrastructure in
|
|
|
26ba25 |
block/io.c and mark all discard requests as serialising.
|
|
|
26ba25 |
|
|
|
26ba25 |
With this change, it is safe for protocol drivers to make
|
|
|
26ba25 |
.bdrv_co_truncate actually asynchronous.
|
|
|
26ba25 |
|
|
|
26ba25 |
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
|
|
26ba25 |
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
|
|
|
26ba25 |
(cherry picked from commit 1bc5f09f2e1b2be8f6f737b8d5352b438fc41492)
|
|
|
26ba25 |
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
|
|
26ba25 |
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
|
|
|
26ba25 |
---
|
|
|
26ba25 |
block/io.c | 25 +++++++++++++++++++++++++
|
|
|
26ba25 |
include/block/block_int.h | 1 +
|
|
|
26ba25 |
2 files changed, 26 insertions(+)
|
|
|
26ba25 |
|
|
|
26ba25 |
diff --git a/block/io.c b/block/io.c
|
|
|
26ba25 |
index 32a82e3..ad8afc0 100644
|
|
|
26ba25 |
--- a/block/io.c
|
|
|
26ba25 |
+++ b/block/io.c
|
|
|
26ba25 |
@@ -2948,6 +2948,8 @@ int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset,
|
|
|
26ba25 |
{
|
|
|
26ba25 |
BlockDriverState *bs = child->bs;
|
|
|
26ba25 |
BlockDriver *drv = bs->drv;
|
|
|
26ba25 |
+ BdrvTrackedRequest req;
|
|
|
26ba25 |
+ int64_t old_size, new_bytes;
|
|
|
26ba25 |
int ret;
|
|
|
26ba25 |
|
|
|
26ba25 |
assert(child->perm & BLK_PERM_RESIZE);
|
|
|
26ba25 |
@@ -2962,7 +2964,28 @@ int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset,
|
|
|
26ba25 |
return -EINVAL;
|
|
|
26ba25 |
}
|
|
|
26ba25 |
|
|
|
26ba25 |
+ old_size = bdrv_getlength(bs);
|
|
|
26ba25 |
+ if (old_size < 0) {
|
|
|
26ba25 |
+ error_setg_errno(errp, -old_size, "Failed to get old image size");
|
|
|
26ba25 |
+ return old_size;
|
|
|
26ba25 |
+ }
|
|
|
26ba25 |
+
|
|
|
26ba25 |
+ if (offset > old_size) {
|
|
|
26ba25 |
+ new_bytes = offset - old_size;
|
|
|
26ba25 |
+ } else {
|
|
|
26ba25 |
+ new_bytes = 0;
|
|
|
26ba25 |
+ }
|
|
|
26ba25 |
+
|
|
|
26ba25 |
bdrv_inc_in_flight(bs);
|
|
|
26ba25 |
+ tracked_request_begin(&req, bs, offset, new_bytes, BDRV_TRACKED_TRUNCATE);
|
|
|
26ba25 |
+
|
|
|
26ba25 |
+ /* If we are growing the image and potentially using preallocation for the
|
|
|
26ba25 |
+ * new area, we need to make sure that no write requests are made to it
|
|
|
26ba25 |
+ * concurrently or they might be overwritten by preallocation. */
|
|
|
26ba25 |
+ if (new_bytes) {
|
|
|
26ba25 |
+ mark_request_serialising(&req, 1);
|
|
|
26ba25 |
+ wait_serialising_requests(&req;;
|
|
|
26ba25 |
+ }
|
|
|
26ba25 |
|
|
|
26ba25 |
if (!drv->bdrv_co_truncate) {
|
|
|
26ba25 |
if (bs->file && drv->is_filter) {
|
|
|
26ba25 |
@@ -2996,7 +3019,9 @@ int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset,
|
|
|
26ba25 |
atomic_inc(&bs->write_gen);
|
|
|
26ba25 |
|
|
|
26ba25 |
out:
|
|
|
26ba25 |
+ tracked_request_end(&req;;
|
|
|
26ba25 |
bdrv_dec_in_flight(bs);
|
|
|
26ba25 |
+
|
|
|
26ba25 |
return ret;
|
|
|
26ba25 |
}
|
|
|
26ba25 |
|
|
|
26ba25 |
diff --git a/include/block/block_int.h b/include/block/block_int.h
|
|
|
26ba25 |
index 6a844ec..27e168f 100644
|
|
|
26ba25 |
--- a/include/block/block_int.h
|
|
|
26ba25 |
+++ b/include/block/block_int.h
|
|
|
26ba25 |
@@ -63,6 +63,7 @@ enum BdrvTrackedRequestType {
|
|
|
26ba25 |
BDRV_TRACKED_READ,
|
|
|
26ba25 |
BDRV_TRACKED_WRITE,
|
|
|
26ba25 |
BDRV_TRACKED_DISCARD,
|
|
|
26ba25 |
+ BDRV_TRACKED_TRUNCATE,
|
|
|
26ba25 |
};
|
|
|
26ba25 |
|
|
|
26ba25 |
typedef struct BdrvTrackedRequest {
|
|
|
26ba25 |
--
|
|
|
26ba25 |
1.8.3.1
|
|
|
26ba25 |
|