All new accounts created on Gitlab now require administrator approval. If you invite any collaborators, please let Flux staff know so they can approve the accounts.

Commit 65afd211 authored by Kevin Wolf's avatar Kevin Wolf

block: Allow waiting for overlapping requests between begin/end

Previously, it was not possible to use wait_for_overlapping_requests()
between tracked_request_begin()/end() because it would wait for itself.

Ignore the current request in the overlap check and run more of the
bdrv_co_do_preadv/pwritev code with a BdrvTrackedRequest present.
Signed-off-by: default avatarKevin Wolf <kwolf@redhat.com>
Reviewed-by: default avatarMax Reitz <mreitz@redhat.com>
Reviewed-by: default avatarBenoit Canet <benoit@irqsave.net>
parent 793ed47a
......@@ -2286,7 +2286,7 @@ static bool tracked_request_overlaps(BdrvTrackedRequest *req,
}
static void coroutine_fn wait_for_overlapping_requests(BlockDriverState *bs,
int64_t offset, unsigned int bytes)
BdrvTrackedRequest *self, int64_t offset, unsigned int bytes)
{
BdrvTrackedRequest *req;
int64_t cluster_offset;
......@@ -2304,6 +2304,9 @@ static void coroutine_fn wait_for_overlapping_requests(BlockDriverState *bs,
do {
retry = false;
QLIST_FOREACH(req, &bs->tracked_requests, list) {
if (req == self) {
continue;
}
if (tracked_request_overlaps(req, cluster_offset, cluster_bytes)) {
/* Hitting this means there was a reentrant request, for
* example, a block driver issuing nested requests. This must
......@@ -2906,10 +2909,10 @@ err:
* implemented by the caller.
*/
static int coroutine_fn bdrv_aligned_preadv(BlockDriverState *bs,
int64_t offset, unsigned int bytes, QEMUIOVector *qiov, int flags)
BdrvTrackedRequest *req, int64_t offset, unsigned int bytes,
QEMUIOVector *qiov, int flags)
{
BlockDriver *drv = bs->drv;
BdrvTrackedRequest req;
int ret;
int64_t sector_num = offset >> BDRV_SECTOR_BITS;
......@@ -2924,11 +2927,9 @@ static int coroutine_fn bdrv_aligned_preadv(BlockDriverState *bs,
}
if (bs->copy_on_read_in_flight) {
wait_for_overlapping_requests(bs, offset, bytes);
wait_for_overlapping_requests(bs, req, offset, bytes);
}
tracked_request_begin(&req, bs, offset, bytes, false);
if (flags & BDRV_REQ_COPY_ON_READ) {
int pnum;
......@@ -2975,8 +2976,6 @@ static int coroutine_fn bdrv_aligned_preadv(BlockDriverState *bs,
}
out:
tracked_request_end(&req);
if (flags & BDRV_REQ_COPY_ON_READ) {
bs->copy_on_read_in_flight--;
}
......@@ -2992,6 +2991,8 @@ static int coroutine_fn bdrv_co_do_preadv(BlockDriverState *bs,
BdrvRequestFlags flags)
{
BlockDriver *drv = bs->drv;
BdrvTrackedRequest req;
/* TODO Lift BDRV_SECTOR_SIZE restriction in BlockDriver interface */
uint64_t align = MAX(BDRV_SECTOR_SIZE, bs->request_alignment);
uint8_t *head_buf = NULL;
......@@ -3042,9 +3043,11 @@ static int coroutine_fn bdrv_co_do_preadv(BlockDriverState *bs,
bytes = ROUND_UP(bytes, align);
}
ret = bdrv_aligned_preadv(bs, offset, bytes,
tracked_request_begin(&req, bs, offset, bytes, false);
ret = bdrv_aligned_preadv(bs, &req, offset, bytes,
use_local_qiov ? &local_qiov : qiov,
flags);
tracked_request_end(&req);
if (use_local_qiov) {
qemu_iovec_destroy(&local_qiov);
......@@ -3163,10 +3166,10 @@ static int coroutine_fn bdrv_co_do_write_zeroes(BlockDriverState *bs,
* Forwards an already correctly aligned write request to the BlockDriver.
*/
static int coroutine_fn bdrv_aligned_pwritev(BlockDriverState *bs,
int64_t offset, unsigned int bytes, QEMUIOVector *qiov, int flags)
BdrvTrackedRequest *req, int64_t offset, unsigned int bytes,
QEMUIOVector *qiov, int flags)
{
BlockDriver *drv = bs->drv;
BdrvTrackedRequest req;
int ret;
int64_t sector_num = offset >> BDRV_SECTOR_BITS;
......@@ -3176,12 +3179,10 @@ static int coroutine_fn bdrv_aligned_pwritev(BlockDriverState *bs,
assert((bytes & (BDRV_SECTOR_SIZE - 1)) == 0);
if (bs->copy_on_read_in_flight) {
wait_for_overlapping_requests(bs, offset, bytes);
wait_for_overlapping_requests(bs, req, offset, bytes);
}
tracked_request_begin(&req, bs, offset, bytes, true);
ret = notifier_with_return_list_notify(&bs->before_write_notifiers, &req);
ret = notifier_with_return_list_notify(&bs->before_write_notifiers, req);
if (ret < 0) {
/* Do nothing, write notifier decided to fail this request */
......@@ -3204,8 +3205,6 @@ static int coroutine_fn bdrv_aligned_pwritev(BlockDriverState *bs,
bs->total_sectors = MAX(bs->total_sectors, sector_num + nb_sectors);
}
tracked_request_end(&req);
return ret;
}
......@@ -3216,6 +3215,7 @@ static int coroutine_fn bdrv_co_do_pwritev(BlockDriverState *bs,
int64_t offset, unsigned int bytes, QEMUIOVector *qiov,
BdrvRequestFlags flags)
{
BdrvTrackedRequest req;
int ret;
if (!bs->drv) {
......@@ -3234,7 +3234,9 @@ static int coroutine_fn bdrv_co_do_pwritev(BlockDriverState *bs,
bdrv_io_limits_intercept(bs, bytes >> BDRV_SECTOR_BITS, true);
}
ret = bdrv_aligned_pwritev(bs, offset, bytes, qiov, flags);
tracked_request_begin(&req, bs, offset, bytes, true);
ret = bdrv_aligned_pwritev(bs, &req, offset, bytes, qiov, flags);
tracked_request_end(&req);
return ret;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment