mirror of https://github.com/xemu-project/xemu.git
block: wait for overlapping requests
When copy-on-read is enabled it is necessary to wait for overlapping requests before issuing new requests. This prevents races between the copy-on-read and a write request. Signed-off-by: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
This commit is contained in:
parent
53fec9d3fd
commit
f4658285f9
35
block.c
35
block.c
|
@ -1099,6 +1099,7 @@ struct BdrvTrackedRequest {
|
||||||
int nb_sectors;
|
int nb_sectors;
|
||||||
bool is_write;
|
bool is_write;
|
||||||
QLIST_ENTRY(BdrvTrackedRequest) list;
|
QLIST_ENTRY(BdrvTrackedRequest) list;
|
||||||
|
CoQueue wait_queue; /* coroutines blocked on this request */
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1109,6 +1110,7 @@ struct BdrvTrackedRequest {
|
||||||
static void tracked_request_end(BdrvTrackedRequest *req)
|
static void tracked_request_end(BdrvTrackedRequest *req)
|
||||||
{
|
{
|
||||||
QLIST_REMOVE(req, list);
|
QLIST_REMOVE(req, list);
|
||||||
|
qemu_co_queue_restart_all(&req->wait_queue);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1126,9 +1128,34 @@ static void tracked_request_begin(BdrvTrackedRequest *req,
|
||||||
.is_write = is_write,
|
.is_write = is_write,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
qemu_co_queue_init(&req->wait_queue);
|
||||||
|
|
||||||
QLIST_INSERT_HEAD(&bs->tracked_requests, req, list);
|
QLIST_INSERT_HEAD(&bs->tracked_requests, req, list);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool tracked_request_overlaps(BdrvTrackedRequest *req,
|
||||||
|
int64_t sector_num, int nb_sectors) {
|
||||||
|
return false; /* not yet implemented */
|
||||||
|
}
|
||||||
|
|
||||||
|
static void coroutine_fn wait_for_overlapping_requests(BlockDriverState *bs,
|
||||||
|
int64_t sector_num, int nb_sectors)
|
||||||
|
{
|
||||||
|
BdrvTrackedRequest *req;
|
||||||
|
bool retry;
|
||||||
|
|
||||||
|
do {
|
||||||
|
retry = false;
|
||||||
|
QLIST_FOREACH(req, &bs->tracked_requests, list) {
|
||||||
|
if (tracked_request_overlaps(req, sector_num, nb_sectors)) {
|
||||||
|
qemu_co_queue_wait(&req->wait_queue);
|
||||||
|
retry = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while (retry);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Return values:
|
* Return values:
|
||||||
* 0 - success
|
* 0 - success
|
||||||
|
@ -1423,6 +1450,10 @@ static int coroutine_fn bdrv_co_do_readv(BlockDriverState *bs,
|
||||||
bdrv_io_limits_intercept(bs, false, nb_sectors);
|
bdrv_io_limits_intercept(bs, false, nb_sectors);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (bs->copy_on_read) {
|
||||||
|
wait_for_overlapping_requests(bs, sector_num, nb_sectors);
|
||||||
|
}
|
||||||
|
|
||||||
tracked_request_begin(&req, bs, sector_num, nb_sectors, false);
|
tracked_request_begin(&req, bs, sector_num, nb_sectors, false);
|
||||||
ret = drv->bdrv_co_readv(bs, sector_num, nb_sectors, qiov);
|
ret = drv->bdrv_co_readv(bs, sector_num, nb_sectors, qiov);
|
||||||
tracked_request_end(&req);
|
tracked_request_end(&req);
|
||||||
|
@ -1462,6 +1493,10 @@ static int coroutine_fn bdrv_co_do_writev(BlockDriverState *bs,
|
||||||
bdrv_io_limits_intercept(bs, true, nb_sectors);
|
bdrv_io_limits_intercept(bs, true, nb_sectors);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (bs->copy_on_read) {
|
||||||
|
wait_for_overlapping_requests(bs, sector_num, nb_sectors);
|
||||||
|
}
|
||||||
|
|
||||||
tracked_request_begin(&req, bs, sector_num, nb_sectors, true);
|
tracked_request_begin(&req, bs, sector_num, nb_sectors, true);
|
||||||
|
|
||||||
ret = drv->bdrv_co_writev(bs, sector_num, nb_sectors, qiov);
|
ret = drv->bdrv_co_writev(bs, sector_num, nb_sectors, qiov);
|
||||||
|
|
Loading…
Reference in New Issue