mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
Merge remote-tracking branch 'remotes/stefanha/tags/block-pull-request' into staging
Block pull request # gpg: Signature made Fri 06 Jun 2014 17:08:50 BST using RSA key ID 81AB73C8 # gpg: Good signature from "Stefan Hajnoczi <stefanha@redhat.com>" # gpg: aka "Stefan Hajnoczi <stefanha@gmail.com>" * remotes/stefanha/tags/block-pull-request: (42 commits) qapi: Extract qapi/block.json definitions qapi: Extract qapi/block-core.json definitions qapi: create two block related json modules qapi: Extract qapi/common.json definitions sheepdog: reload only header in a case of live snapshot sheepdog: fix vdi object update after live snapshot rbd: Fix leaks in rbd_start_aio() error path qemu-img: Document check exit codes block: fix wrong order in live block migration setup blockdev: acquire AioContext in block_set_io_throttle throttle: add detach/attach test case throttle: add throttle_detach/attach_aio_context() dataplane: Support VIRTIO_BLK_T_SCSI_CMD virtio-blk: Factor out virtio_blk_handle_scsi_req from virtio_blk_handle_scsi virtio-blk: Allow config-wce in dataplane block: Move declaration of bdrv_get_aio_context to block.h raw-posix: drop raw_get_aio_fd() since it is no longer used dataplane: implement async flush dataplane: delete IOQueue since it is no longer used dataplane: use the QEMU block layer for I/O ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
@@ -117,15 +117,21 @@ void qemu_bh_schedule_idle(QEMUBH *bh)
|
||||
|
||||
void qemu_bh_schedule(QEMUBH *bh)
|
||||
{
|
||||
AioContext *ctx;
|
||||
|
||||
if (bh->scheduled)
|
||||
return;
|
||||
ctx = bh->ctx;
|
||||
bh->idle = 0;
|
||||
/* Make sure that idle & any writes needed by the callback are done
|
||||
* before the locations are read in the aio_bh_poll.
|
||||
/* Make sure that:
|
||||
* 1. idle & any writes needed by the callback are done before the
|
||||
* locations are read in the aio_bh_poll.
|
||||
* 2. ctx is loaded before scheduled is set and the callback has a chance
|
||||
* to execute.
|
||||
*/
|
||||
smp_wmb();
|
||||
smp_mb();
|
||||
bh->scheduled = 1;
|
||||
aio_notify(bh->ctx);
|
||||
aio_notify(ctx);
|
||||
}
|
||||
|
||||
|
||||
|
||||
+1
-2
@@ -629,6 +629,7 @@ static int block_save_setup(QEMUFile *f, void *opaque)
|
||||
block_mig_state.submitted, block_mig_state.transferred);
|
||||
|
||||
qemu_mutex_lock_iothread();
|
||||
init_blk_migration(f);
|
||||
|
||||
/* start track dirty blocks */
|
||||
ret = set_dirty_tracking();
|
||||
@@ -638,8 +639,6 @@ static int block_save_setup(QEMUFile *f, void *opaque)
|
||||
return ret;
|
||||
}
|
||||
|
||||
init_blk_migration(f);
|
||||
|
||||
qemu_mutex_unlock_iothread();
|
||||
|
||||
ret = flush_blks(f);
|
||||
|
||||
@@ -179,6 +179,7 @@ void bdrv_io_limits_enable(BlockDriverState *bs)
|
||||
{
|
||||
assert(!bs->io_limits_enabled);
|
||||
throttle_init(&bs->throttle_state,
|
||||
bdrv_get_aio_context(bs),
|
||||
QEMU_CLOCK_VIRTUAL,
|
||||
bdrv_throttle_read_timer_cb,
|
||||
bdrv_throttle_write_timer_cb,
|
||||
@@ -363,6 +364,7 @@ BlockDriverState *bdrv_new(const char *device_name, Error **errp)
|
||||
qemu_co_queue_init(&bs->throttled_reqs[0]);
|
||||
qemu_co_queue_init(&bs->throttled_reqs[1]);
|
||||
bs->refcnt = 1;
|
||||
bs->aio_context = qemu_get_aio_context();
|
||||
|
||||
return bs;
|
||||
}
|
||||
@@ -1856,7 +1858,11 @@ void bdrv_close_all(void)
|
||||
BlockDriverState *bs;
|
||||
|
||||
QTAILQ_FOREACH(bs, &bdrv_states, device_list) {
|
||||
AioContext *aio_context = bdrv_get_aio_context(bs);
|
||||
|
||||
aio_context_acquire(aio_context);
|
||||
bdrv_close(bs);
|
||||
aio_context_release(aio_context);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1881,17 +1887,6 @@ static bool bdrv_requests_pending(BlockDriverState *bs)
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool bdrv_requests_pending_all(void)
|
||||
{
|
||||
BlockDriverState *bs;
|
||||
QTAILQ_FOREACH(bs, &bdrv_states, device_list) {
|
||||
if (bdrv_requests_pending(bs)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait for pending requests to complete across all BlockDriverStates
|
||||
*
|
||||
@@ -1911,12 +1906,20 @@ void bdrv_drain_all(void)
|
||||
BlockDriverState *bs;
|
||||
|
||||
while (busy) {
|
||||
QTAILQ_FOREACH(bs, &bdrv_states, device_list) {
|
||||
bdrv_start_throttled_reqs(bs);
|
||||
}
|
||||
busy = false;
|
||||
|
||||
busy = bdrv_requests_pending_all();
|
||||
busy |= aio_poll(qemu_get_aio_context(), busy);
|
||||
QTAILQ_FOREACH(bs, &bdrv_states, device_list) {
|
||||
AioContext *aio_context = bdrv_get_aio_context(bs);
|
||||
bool bs_busy;
|
||||
|
||||
aio_context_acquire(aio_context);
|
||||
bdrv_start_throttled_reqs(bs);
|
||||
bs_busy = bdrv_requests_pending(bs);
|
||||
bs_busy |= aio_poll(aio_context, bs_busy);
|
||||
aio_context_release(aio_context);
|
||||
|
||||
busy |= bs_busy;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2352,12 +2355,17 @@ int bdrv_commit_all(void)
|
||||
BlockDriverState *bs;
|
||||
|
||||
QTAILQ_FOREACH(bs, &bdrv_states, device_list) {
|
||||
AioContext *aio_context = bdrv_get_aio_context(bs);
|
||||
|
||||
aio_context_acquire(aio_context);
|
||||
if (bs->drv && bs->backing_hd) {
|
||||
int ret = bdrv_commit(bs);
|
||||
if (ret < 0) {
|
||||
aio_context_release(aio_context);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
aio_context_release(aio_context);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -2775,10 +2783,12 @@ static int bdrv_prwv_co(BlockDriverState *bs, int64_t offset,
|
||||
/* Fast-path if already in coroutine context */
|
||||
bdrv_rw_co_entry(&rwco);
|
||||
} else {
|
||||
AioContext *aio_context = bdrv_get_aio_context(bs);
|
||||
|
||||
co = qemu_coroutine_create(bdrv_rw_co_entry);
|
||||
qemu_coroutine_enter(co, &rwco);
|
||||
while (rwco.ret == NOT_DONE) {
|
||||
qemu_aio_wait();
|
||||
aio_poll(aio_context, true);
|
||||
}
|
||||
}
|
||||
return rwco.ret;
|
||||
@@ -3831,10 +3841,15 @@ int bdrv_flush_all(void)
|
||||
int result = 0;
|
||||
|
||||
QTAILQ_FOREACH(bs, &bdrv_states, device_list) {
|
||||
int ret = bdrv_flush(bs);
|
||||
AioContext *aio_context = bdrv_get_aio_context(bs);
|
||||
int ret;
|
||||
|
||||
aio_context_acquire(aio_context);
|
||||
ret = bdrv_flush(bs);
|
||||
if (ret < 0 && !result) {
|
||||
result = ret;
|
||||
}
|
||||
aio_context_release(aio_context);
|
||||
}
|
||||
|
||||
return result;
|
||||
@@ -4025,10 +4040,12 @@ int64_t bdrv_get_block_status(BlockDriverState *bs, int64_t sector_num,
|
||||
/* Fast-path if already in coroutine context */
|
||||
bdrv_get_block_status_co_entry(&data);
|
||||
} else {
|
||||
AioContext *aio_context = bdrv_get_aio_context(bs);
|
||||
|
||||
co = qemu_coroutine_create(bdrv_get_block_status_co_entry);
|
||||
qemu_coroutine_enter(co, &data);
|
||||
while (!data.done) {
|
||||
qemu_aio_wait();
|
||||
aio_poll(aio_context, true);
|
||||
}
|
||||
}
|
||||
return data.ret;
|
||||
@@ -4621,7 +4638,7 @@ static BlockDriverAIOCB *bdrv_aio_rw_vector(BlockDriverState *bs,
|
||||
acb->is_write = is_write;
|
||||
acb->qiov = qiov;
|
||||
acb->bounce = qemu_blockalign(bs, qiov->size);
|
||||
acb->bh = qemu_bh_new(bdrv_aio_bh_cb, acb);
|
||||
acb->bh = aio_bh_new(bdrv_get_aio_context(bs), bdrv_aio_bh_cb, acb);
|
||||
|
||||
if (is_write) {
|
||||
qemu_iovec_to_buf(acb->qiov, 0, acb->bounce, qiov->size);
|
||||
@@ -4660,13 +4677,14 @@ typedef struct BlockDriverAIOCBCoroutine {
|
||||
|
||||
static void bdrv_aio_co_cancel_em(BlockDriverAIOCB *blockacb)
|
||||
{
|
||||
AioContext *aio_context = bdrv_get_aio_context(blockacb->bs);
|
||||
BlockDriverAIOCBCoroutine *acb =
|
||||
container_of(blockacb, BlockDriverAIOCBCoroutine, common);
|
||||
bool done = false;
|
||||
|
||||
acb->done = &done;
|
||||
while (!done) {
|
||||
qemu_aio_wait();
|
||||
aio_poll(aio_context, true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4703,7 +4721,7 @@ static void coroutine_fn bdrv_co_do_rw(void *opaque)
|
||||
acb->req.nb_sectors, acb->req.qiov, acb->req.flags);
|
||||
}
|
||||
|
||||
acb->bh = qemu_bh_new(bdrv_co_em_bh, acb);
|
||||
acb->bh = aio_bh_new(bdrv_get_aio_context(bs), bdrv_co_em_bh, acb);
|
||||
qemu_bh_schedule(acb->bh);
|
||||
}
|
||||
|
||||
@@ -4739,7 +4757,7 @@ static void coroutine_fn bdrv_aio_flush_co_entry(void *opaque)
|
||||
BlockDriverState *bs = acb->common.bs;
|
||||
|
||||
acb->req.error = bdrv_co_flush(bs);
|
||||
acb->bh = qemu_bh_new(bdrv_co_em_bh, acb);
|
||||
acb->bh = aio_bh_new(bdrv_get_aio_context(bs), bdrv_co_em_bh, acb);
|
||||
qemu_bh_schedule(acb->bh);
|
||||
}
|
||||
|
||||
@@ -4766,7 +4784,7 @@ static void coroutine_fn bdrv_aio_discard_co_entry(void *opaque)
|
||||
BlockDriverState *bs = acb->common.bs;
|
||||
|
||||
acb->req.error = bdrv_co_discard(bs, acb->req.sector, acb->req.nb_sectors);
|
||||
acb->bh = qemu_bh_new(bdrv_co_em_bh, acb);
|
||||
acb->bh = aio_bh_new(bdrv_get_aio_context(bs), bdrv_co_em_bh, acb);
|
||||
qemu_bh_schedule(acb->bh);
|
||||
}
|
||||
|
||||
@@ -4977,7 +4995,11 @@ void bdrv_invalidate_cache_all(Error **errp)
|
||||
Error *local_err = NULL;
|
||||
|
||||
QTAILQ_FOREACH(bs, &bdrv_states, device_list) {
|
||||
AioContext *aio_context = bdrv_get_aio_context(bs);
|
||||
|
||||
aio_context_acquire(aio_context);
|
||||
bdrv_invalidate_cache(bs, &local_err);
|
||||
aio_context_release(aio_context);
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
return;
|
||||
@@ -4990,7 +5012,11 @@ void bdrv_clear_incoming_migration_all(void)
|
||||
BlockDriverState *bs;
|
||||
|
||||
QTAILQ_FOREACH(bs, &bdrv_states, device_list) {
|
||||
AioContext *aio_context = bdrv_get_aio_context(bs);
|
||||
|
||||
aio_context_acquire(aio_context);
|
||||
bs->open_flags = bs->open_flags & ~(BDRV_O_INCOMING);
|
||||
aio_context_release(aio_context);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5006,10 +5032,12 @@ int bdrv_flush(BlockDriverState *bs)
|
||||
/* Fast-path if already in coroutine context */
|
||||
bdrv_flush_co_entry(&rwco);
|
||||
} else {
|
||||
AioContext *aio_context = bdrv_get_aio_context(bs);
|
||||
|
||||
co = qemu_coroutine_create(bdrv_flush_co_entry);
|
||||
qemu_coroutine_enter(co, &rwco);
|
||||
while (rwco.ret == NOT_DONE) {
|
||||
qemu_aio_wait();
|
||||
aio_poll(aio_context, true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5119,10 +5147,12 @@ int bdrv_discard(BlockDriverState *bs, int64_t sector_num, int nb_sectors)
|
||||
/* Fast-path if already in coroutine context */
|
||||
bdrv_discard_co_entry(&rwco);
|
||||
} else {
|
||||
AioContext *aio_context = bdrv_get_aio_context(bs);
|
||||
|
||||
co = qemu_coroutine_create(bdrv_discard_co_entry);
|
||||
qemu_coroutine_enter(co, &rwco);
|
||||
while (rwco.ret == NOT_DONE) {
|
||||
qemu_aio_wait();
|
||||
aio_poll(aio_context, true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5633,8 +5663,66 @@ out:
|
||||
|
||||
AioContext *bdrv_get_aio_context(BlockDriverState *bs)
|
||||
{
|
||||
/* Currently BlockDriverState always uses the main loop AioContext */
|
||||
return qemu_get_aio_context();
|
||||
return bs->aio_context;
|
||||
}
|
||||
|
||||
void bdrv_detach_aio_context(BlockDriverState *bs)
|
||||
{
|
||||
if (!bs->drv) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (bs->io_limits_enabled) {
|
||||
throttle_detach_aio_context(&bs->throttle_state);
|
||||
}
|
||||
if (bs->drv->bdrv_detach_aio_context) {
|
||||
bs->drv->bdrv_detach_aio_context(bs);
|
||||
}
|
||||
if (bs->file) {
|
||||
bdrv_detach_aio_context(bs->file);
|
||||
}
|
||||
if (bs->backing_hd) {
|
||||
bdrv_detach_aio_context(bs->backing_hd);
|
||||
}
|
||||
|
||||
bs->aio_context = NULL;
|
||||
}
|
||||
|
||||
void bdrv_attach_aio_context(BlockDriverState *bs,
|
||||
AioContext *new_context)
|
||||
{
|
||||
if (!bs->drv) {
|
||||
return;
|
||||
}
|
||||
|
||||
bs->aio_context = new_context;
|
||||
|
||||
if (bs->backing_hd) {
|
||||
bdrv_attach_aio_context(bs->backing_hd, new_context);
|
||||
}
|
||||
if (bs->file) {
|
||||
bdrv_attach_aio_context(bs->file, new_context);
|
||||
}
|
||||
if (bs->drv->bdrv_attach_aio_context) {
|
||||
bs->drv->bdrv_attach_aio_context(bs, new_context);
|
||||
}
|
||||
if (bs->io_limits_enabled) {
|
||||
throttle_attach_aio_context(&bs->throttle_state, new_context);
|
||||
}
|
||||
}
|
||||
|
||||
void bdrv_set_aio_context(BlockDriverState *bs, AioContext *new_context)
|
||||
{
|
||||
bdrv_drain_all(); /* ensure there are no in-flight requests */
|
||||
|
||||
bdrv_detach_aio_context(bs);
|
||||
|
||||
/* This function executes in the old AioContext so acquire the new one in
|
||||
* case it runs in a different thread.
|
||||
*/
|
||||
aio_context_acquire(new_context);
|
||||
bdrv_attach_aio_context(bs, new_context);
|
||||
aio_context_release(new_context);
|
||||
}
|
||||
|
||||
void bdrv_add_before_write_notifier(BlockDriverState *bs,
|
||||
|
||||
+1
-1
@@ -471,7 +471,7 @@ static BlockDriverAIOCB *inject_error(BlockDriverState *bs,
|
||||
acb = qemu_aio_get(&blkdebug_aiocb_info, bs, cb, opaque);
|
||||
acb->ret = -error;
|
||||
|
||||
bh = qemu_bh_new(error_callback_bh, acb);
|
||||
bh = aio_bh_new(bdrv_get_aio_context(bs), error_callback_bh, acb);
|
||||
acb->bh = bh;
|
||||
qemu_bh_schedule(bh);
|
||||
|
||||
|
||||
+34
-13
@@ -39,12 +39,13 @@ struct BlkverifyAIOCB {
|
||||
static void blkverify_aio_cancel(BlockDriverAIOCB *blockacb)
|
||||
{
|
||||
BlkverifyAIOCB *acb = (BlkverifyAIOCB *)blockacb;
|
||||
AioContext *aio_context = bdrv_get_aio_context(blockacb->bs);
|
||||
bool finished = false;
|
||||
|
||||
/* Wait until request completes, invokes its callback, and frees itself */
|
||||
acb->finished = &finished;
|
||||
while (!finished) {
|
||||
qemu_aio_wait();
|
||||
aio_poll(aio_context, true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -228,7 +229,8 @@ static void blkverify_aio_cb(void *opaque, int ret)
|
||||
acb->verify(acb);
|
||||
}
|
||||
|
||||
acb->bh = qemu_bh_new(blkverify_aio_bh, acb);
|
||||
acb->bh = aio_bh_new(bdrv_get_aio_context(acb->common.bs),
|
||||
blkverify_aio_bh, acb);
|
||||
qemu_bh_schedule(acb->bh);
|
||||
break;
|
||||
}
|
||||
@@ -302,21 +304,40 @@ static bool blkverify_recurse_is_first_non_filter(BlockDriverState *bs,
|
||||
return bdrv_recurse_is_first_non_filter(s->test_file, candidate);
|
||||
}
|
||||
|
||||
/* Propagate AioContext changes to ->test_file */
|
||||
static void blkverify_detach_aio_context(BlockDriverState *bs)
|
||||
{
|
||||
BDRVBlkverifyState *s = bs->opaque;
|
||||
|
||||
bdrv_detach_aio_context(s->test_file);
|
||||
}
|
||||
|
||||
static void blkverify_attach_aio_context(BlockDriverState *bs,
|
||||
AioContext *new_context)
|
||||
{
|
||||
BDRVBlkverifyState *s = bs->opaque;
|
||||
|
||||
bdrv_attach_aio_context(s->test_file, new_context);
|
||||
}
|
||||
|
||||
static BlockDriver bdrv_blkverify = {
|
||||
.format_name = "blkverify",
|
||||
.protocol_name = "blkverify",
|
||||
.instance_size = sizeof(BDRVBlkverifyState),
|
||||
.format_name = "blkverify",
|
||||
.protocol_name = "blkverify",
|
||||
.instance_size = sizeof(BDRVBlkverifyState),
|
||||
|
||||
.bdrv_parse_filename = blkverify_parse_filename,
|
||||
.bdrv_file_open = blkverify_open,
|
||||
.bdrv_close = blkverify_close,
|
||||
.bdrv_getlength = blkverify_getlength,
|
||||
.bdrv_parse_filename = blkverify_parse_filename,
|
||||
.bdrv_file_open = blkverify_open,
|
||||
.bdrv_close = blkverify_close,
|
||||
.bdrv_getlength = blkverify_getlength,
|
||||
|
||||
.bdrv_aio_readv = blkverify_aio_readv,
|
||||
.bdrv_aio_writev = blkverify_aio_writev,
|
||||
.bdrv_aio_flush = blkverify_aio_flush,
|
||||
.bdrv_aio_readv = blkverify_aio_readv,
|
||||
.bdrv_aio_writev = blkverify_aio_writev,
|
||||
.bdrv_aio_flush = blkverify_aio_flush,
|
||||
|
||||
.is_filter = true,
|
||||
.bdrv_attach_aio_context = blkverify_attach_aio_context,
|
||||
.bdrv_detach_aio_context = blkverify_detach_aio_context,
|
||||
|
||||
.is_filter = true,
|
||||
.bdrv_recurse_is_first_non_filter = blkverify_recurse_is_first_non_filter,
|
||||
};
|
||||
|
||||
|
||||
+115
-77
@@ -110,6 +110,7 @@ typedef struct BDRVCURLState {
|
||||
size_t readahead_size;
|
||||
bool sslverify;
|
||||
bool accept_range;
|
||||
AioContext *aio_context;
|
||||
} BDRVCURLState;
|
||||
|
||||
static void curl_clean_state(CURLState *s);
|
||||
@@ -134,25 +135,29 @@ static int curl_timer_cb(CURLM *multi, long timeout_ms, void *opaque)
|
||||
#endif
|
||||
|
||||
static int curl_sock_cb(CURL *curl, curl_socket_t fd, int action,
|
||||
void *s, void *sp)
|
||||
void *userp, void *sp)
|
||||
{
|
||||
BDRVCURLState *s;
|
||||
CURLState *state = NULL;
|
||||
curl_easy_getinfo(curl, CURLINFO_PRIVATE, (char **)&state);
|
||||
state->sock_fd = fd;
|
||||
s = state->s;
|
||||
|
||||
DPRINTF("CURL (AIO): Sock action %d on fd %d\n", action, fd);
|
||||
switch (action) {
|
||||
case CURL_POLL_IN:
|
||||
qemu_aio_set_fd_handler(fd, curl_multi_read, NULL, state);
|
||||
aio_set_fd_handler(s->aio_context, fd, curl_multi_read,
|
||||
NULL, state);
|
||||
break;
|
||||
case CURL_POLL_OUT:
|
||||
qemu_aio_set_fd_handler(fd, NULL, curl_multi_do, state);
|
||||
aio_set_fd_handler(s->aio_context, fd, NULL, curl_multi_do, state);
|
||||
break;
|
||||
case CURL_POLL_INOUT:
|
||||
qemu_aio_set_fd_handler(fd, curl_multi_read, curl_multi_do, state);
|
||||
aio_set_fd_handler(s->aio_context, fd, curl_multi_read,
|
||||
curl_multi_do, state);
|
||||
break;
|
||||
case CURL_POLL_REMOVE:
|
||||
qemu_aio_set_fd_handler(fd, NULL, NULL, NULL);
|
||||
aio_set_fd_handler(s->aio_context, fd, NULL, NULL, NULL);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -365,7 +370,7 @@ static CURLState *curl_init_state(BDRVCURLState *s)
|
||||
break;
|
||||
}
|
||||
if (!state) {
|
||||
qemu_aio_wait();
|
||||
aio_poll(state->s->aio_context, true);
|
||||
}
|
||||
} while(!state);
|
||||
|
||||
@@ -422,6 +427,51 @@ static void curl_parse_filename(const char *filename, QDict *options,
|
||||
qdict_put(options, CURL_BLOCK_OPT_URL, qstring_from_str(filename));
|
||||
}
|
||||
|
||||
static void curl_detach_aio_context(BlockDriverState *bs)
|
||||
{
|
||||
BDRVCURLState *s = bs->opaque;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < CURL_NUM_STATES; i++) {
|
||||
if (s->states[i].in_use) {
|
||||
curl_clean_state(&s->states[i]);
|
||||
}
|
||||
if (s->states[i].curl) {
|
||||
curl_easy_cleanup(s->states[i].curl);
|
||||
s->states[i].curl = NULL;
|
||||
}
|
||||
if (s->states[i].orig_buf) {
|
||||
g_free(s->states[i].orig_buf);
|
||||
s->states[i].orig_buf = NULL;
|
||||
}
|
||||
}
|
||||
if (s->multi) {
|
||||
curl_multi_cleanup(s->multi);
|
||||
s->multi = NULL;
|
||||
}
|
||||
|
||||
timer_del(&s->timer);
|
||||
}
|
||||
|
||||
static void curl_attach_aio_context(BlockDriverState *bs,
|
||||
AioContext *new_context)
|
||||
{
|
||||
BDRVCURLState *s = bs->opaque;
|
||||
|
||||
aio_timer_init(new_context, &s->timer,
|
||||
QEMU_CLOCK_REALTIME, SCALE_NS,
|
||||
curl_multi_timeout_do, s);
|
||||
|
||||
assert(!s->multi);
|
||||
s->multi = curl_multi_init();
|
||||
s->aio_context = new_context;
|
||||
curl_multi_setopt(s->multi, CURLMOPT_SOCKETFUNCTION, curl_sock_cb);
|
||||
#ifdef NEED_CURL_TIMER_CALLBACK
|
||||
curl_multi_setopt(s->multi, CURLMOPT_TIMERDATA, s);
|
||||
curl_multi_setopt(s->multi, CURLMOPT_TIMERFUNCTION, curl_timer_cb);
|
||||
#endif
|
||||
}
|
||||
|
||||
static QemuOptsList runtime_opts = {
|
||||
.name = "curl",
|
||||
.head = QTAILQ_HEAD_INITIALIZER(runtime_opts.head),
|
||||
@@ -491,6 +541,7 @@ static int curl_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
}
|
||||
|
||||
DPRINTF("CURL: Opening %s\n", file);
|
||||
s->aio_context = bdrv_get_aio_context(bs);
|
||||
s->url = g_strdup(file);
|
||||
state = curl_init_state(s);
|
||||
if (!state)
|
||||
@@ -523,19 +574,7 @@ static int curl_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
curl_easy_cleanup(state->curl);
|
||||
state->curl = NULL;
|
||||
|
||||
aio_timer_init(bdrv_get_aio_context(bs), &s->timer,
|
||||
QEMU_CLOCK_REALTIME, SCALE_NS,
|
||||
curl_multi_timeout_do, s);
|
||||
|
||||
// Now we know the file exists and its size, so let's
|
||||
// initialize the multi interface!
|
||||
|
||||
s->multi = curl_multi_init();
|
||||
curl_multi_setopt(s->multi, CURLMOPT_SOCKETFUNCTION, curl_sock_cb);
|
||||
#ifdef NEED_CURL_TIMER_CALLBACK
|
||||
curl_multi_setopt(s->multi, CURLMOPT_TIMERDATA, s);
|
||||
curl_multi_setopt(s->multi, CURLMOPT_TIMERFUNCTION, curl_timer_cb);
|
||||
#endif
|
||||
curl_attach_aio_context(bs, bdrv_get_aio_context(bs));
|
||||
|
||||
qemu_opts_del(opts);
|
||||
return 0;
|
||||
@@ -630,7 +669,7 @@ static BlockDriverAIOCB *curl_aio_readv(BlockDriverState *bs,
|
||||
acb->sector_num = sector_num;
|
||||
acb->nb_sectors = nb_sectors;
|
||||
|
||||
acb->bh = qemu_bh_new(curl_readv_bh_cb, acb);
|
||||
acb->bh = aio_bh_new(bdrv_get_aio_context(bs), curl_readv_bh_cb, acb);
|
||||
qemu_bh_schedule(acb->bh);
|
||||
return &acb->common;
|
||||
}
|
||||
@@ -638,25 +677,9 @@ static BlockDriverAIOCB *curl_aio_readv(BlockDriverState *bs,
|
||||
static void curl_close(BlockDriverState *bs)
|
||||
{
|
||||
BDRVCURLState *s = bs->opaque;
|
||||
int i;
|
||||
|
||||
DPRINTF("CURL: Close\n");
|
||||
for (i=0; i<CURL_NUM_STATES; i++) {
|
||||
if (s->states[i].in_use)
|
||||
curl_clean_state(&s->states[i]);
|
||||
if (s->states[i].curl) {
|
||||
curl_easy_cleanup(s->states[i].curl);
|
||||
s->states[i].curl = NULL;
|
||||
}
|
||||
if (s->states[i].orig_buf) {
|
||||
g_free(s->states[i].orig_buf);
|
||||
s->states[i].orig_buf = NULL;
|
||||
}
|
||||
}
|
||||
if (s->multi)
|
||||
curl_multi_cleanup(s->multi);
|
||||
|
||||
timer_del(&s->timer);
|
||||
curl_detach_aio_context(bs);
|
||||
|
||||
g_free(s->url);
|
||||
}
|
||||
@@ -668,68 +691,83 @@ static int64_t curl_getlength(BlockDriverState *bs)
|
||||
}
|
||||
|
||||
static BlockDriver bdrv_http = {
|
||||
.format_name = "http",
|
||||
.protocol_name = "http",
|
||||
.format_name = "http",
|
||||
.protocol_name = "http",
|
||||
|
||||
.instance_size = sizeof(BDRVCURLState),
|
||||
.bdrv_parse_filename = curl_parse_filename,
|
||||
.bdrv_file_open = curl_open,
|
||||
.bdrv_close = curl_close,
|
||||
.bdrv_getlength = curl_getlength,
|
||||
.instance_size = sizeof(BDRVCURLState),
|
||||
.bdrv_parse_filename = curl_parse_filename,
|
||||
.bdrv_file_open = curl_open,
|
||||
.bdrv_close = curl_close,
|
||||
.bdrv_getlength = curl_getlength,
|
||||
|
||||
.bdrv_aio_readv = curl_aio_readv,
|
||||
.bdrv_aio_readv = curl_aio_readv,
|
||||
|
||||
.bdrv_detach_aio_context = curl_detach_aio_context,
|
||||
.bdrv_attach_aio_context = curl_attach_aio_context,
|
||||
};
|
||||
|
||||
static BlockDriver bdrv_https = {
|
||||
.format_name = "https",
|
||||
.protocol_name = "https",
|
||||
.format_name = "https",
|
||||
.protocol_name = "https",
|
||||
|
||||
.instance_size = sizeof(BDRVCURLState),
|
||||
.bdrv_parse_filename = curl_parse_filename,
|
||||
.bdrv_file_open = curl_open,
|
||||
.bdrv_close = curl_close,
|
||||
.bdrv_getlength = curl_getlength,
|
||||
.instance_size = sizeof(BDRVCURLState),
|
||||
.bdrv_parse_filename = curl_parse_filename,
|
||||
.bdrv_file_open = curl_open,
|
||||
.bdrv_close = curl_close,
|
||||
.bdrv_getlength = curl_getlength,
|
||||
|
||||
.bdrv_aio_readv = curl_aio_readv,
|
||||
.bdrv_aio_readv = curl_aio_readv,
|
||||
|
||||
.bdrv_detach_aio_context = curl_detach_aio_context,
|
||||
.bdrv_attach_aio_context = curl_attach_aio_context,
|
||||
};
|
||||
|
||||
static BlockDriver bdrv_ftp = {
|
||||
.format_name = "ftp",
|
||||
.protocol_name = "ftp",
|
||||
.format_name = "ftp",
|
||||
.protocol_name = "ftp",
|
||||
|
||||
.instance_size = sizeof(BDRVCURLState),
|
||||
.bdrv_parse_filename = curl_parse_filename,
|
||||
.bdrv_file_open = curl_open,
|
||||
.bdrv_close = curl_close,
|
||||
.bdrv_getlength = curl_getlength,
|
||||
.instance_size = sizeof(BDRVCURLState),
|
||||
.bdrv_parse_filename = curl_parse_filename,
|
||||
.bdrv_file_open = curl_open,
|
||||
.bdrv_close = curl_close,
|
||||
.bdrv_getlength = curl_getlength,
|
||||
|
||||
.bdrv_aio_readv = curl_aio_readv,
|
||||
.bdrv_aio_readv = curl_aio_readv,
|
||||
|
||||
.bdrv_detach_aio_context = curl_detach_aio_context,
|
||||
.bdrv_attach_aio_context = curl_attach_aio_context,
|
||||
};
|
||||
|
||||
static BlockDriver bdrv_ftps = {
|
||||
.format_name = "ftps",
|
||||
.protocol_name = "ftps",
|
||||
.format_name = "ftps",
|
||||
.protocol_name = "ftps",
|
||||
|
||||
.instance_size = sizeof(BDRVCURLState),
|
||||
.bdrv_parse_filename = curl_parse_filename,
|
||||
.bdrv_file_open = curl_open,
|
||||
.bdrv_close = curl_close,
|
||||
.bdrv_getlength = curl_getlength,
|
||||
.instance_size = sizeof(BDRVCURLState),
|
||||
.bdrv_parse_filename = curl_parse_filename,
|
||||
.bdrv_file_open = curl_open,
|
||||
.bdrv_close = curl_close,
|
||||
.bdrv_getlength = curl_getlength,
|
||||
|
||||
.bdrv_aio_readv = curl_aio_readv,
|
||||
.bdrv_aio_readv = curl_aio_readv,
|
||||
|
||||
.bdrv_detach_aio_context = curl_detach_aio_context,
|
||||
.bdrv_attach_aio_context = curl_attach_aio_context,
|
||||
};
|
||||
|
||||
static BlockDriver bdrv_tftp = {
|
||||
.format_name = "tftp",
|
||||
.protocol_name = "tftp",
|
||||
.format_name = "tftp",
|
||||
.protocol_name = "tftp",
|
||||
|
||||
.instance_size = sizeof(BDRVCURLState),
|
||||
.bdrv_parse_filename = curl_parse_filename,
|
||||
.bdrv_file_open = curl_open,
|
||||
.bdrv_close = curl_close,
|
||||
.bdrv_getlength = curl_getlength,
|
||||
.instance_size = sizeof(BDRVCURLState),
|
||||
.bdrv_parse_filename = curl_parse_filename,
|
||||
.bdrv_file_open = curl_open,
|
||||
.bdrv_close = curl_close,
|
||||
.bdrv_getlength = curl_getlength,
|
||||
|
||||
.bdrv_aio_readv = curl_aio_readv,
|
||||
.bdrv_aio_readv = curl_aio_readv,
|
||||
|
||||
.bdrv_detach_aio_context = curl_detach_aio_context,
|
||||
.bdrv_attach_aio_context = curl_attach_aio_context,
|
||||
};
|
||||
|
||||
static void curl_block_init(void)
|
||||
|
||||
+6
-1
@@ -16,6 +16,7 @@ typedef struct GlusterAIOCB {
|
||||
int ret;
|
||||
QEMUBH *bh;
|
||||
Coroutine *coroutine;
|
||||
AioContext *aio_context;
|
||||
} GlusterAIOCB;
|
||||
|
||||
typedef struct BDRVGlusterState {
|
||||
@@ -249,7 +250,7 @@ static void gluster_finish_aiocb(struct glfs_fd *fd, ssize_t ret, void *arg)
|
||||
acb->ret = -EIO; /* Partial read/write - fail it */
|
||||
}
|
||||
|
||||
acb->bh = qemu_bh_new(qemu_gluster_complete_aio, acb);
|
||||
acb->bh = aio_bh_new(acb->aio_context, qemu_gluster_complete_aio, acb);
|
||||
qemu_bh_schedule(acb->bh);
|
||||
}
|
||||
|
||||
@@ -436,6 +437,7 @@ static coroutine_fn int qemu_gluster_co_write_zeroes(BlockDriverState *bs,
|
||||
acb->size = size;
|
||||
acb->ret = 0;
|
||||
acb->coroutine = qemu_coroutine_self();
|
||||
acb->aio_context = bdrv_get_aio_context(bs);
|
||||
|
||||
ret = glfs_zerofill_async(s->fd, offset, size, &gluster_finish_aiocb, acb);
|
||||
if (ret < 0) {
|
||||
@@ -549,6 +551,7 @@ static coroutine_fn int qemu_gluster_co_rw(BlockDriverState *bs,
|
||||
acb->size = size;
|
||||
acb->ret = 0;
|
||||
acb->coroutine = qemu_coroutine_self();
|
||||
acb->aio_context = bdrv_get_aio_context(bs);
|
||||
|
||||
if (write) {
|
||||
ret = glfs_pwritev_async(s->fd, qiov->iov, qiov->niov, offset, 0,
|
||||
@@ -605,6 +608,7 @@ static coroutine_fn int qemu_gluster_co_flush_to_disk(BlockDriverState *bs)
|
||||
acb->size = 0;
|
||||
acb->ret = 0;
|
||||
acb->coroutine = qemu_coroutine_self();
|
||||
acb->aio_context = bdrv_get_aio_context(bs);
|
||||
|
||||
ret = glfs_fsync_async(s->fd, &gluster_finish_aiocb, acb);
|
||||
if (ret < 0) {
|
||||
@@ -633,6 +637,7 @@ static coroutine_fn int qemu_gluster_co_discard(BlockDriverState *bs,
|
||||
acb->size = 0;
|
||||
acb->ret = 0;
|
||||
acb->coroutine = qemu_coroutine_self();
|
||||
acb->aio_context = bdrv_get_aio_context(bs);
|
||||
|
||||
ret = glfs_discard_async(s->fd, offset, size, &gluster_finish_aiocb, acb);
|
||||
if (ret < 0) {
|
||||
|
||||
+56
-24
@@ -49,6 +49,7 @@
|
||||
|
||||
typedef struct IscsiLun {
|
||||
struct iscsi_context *iscsi;
|
||||
AioContext *aio_context;
|
||||
int lun;
|
||||
enum scsi_inquiry_peripheral_device_type type;
|
||||
int block_size;
|
||||
@@ -73,6 +74,7 @@ typedef struct IscsiTask {
|
||||
struct scsi_task *task;
|
||||
Coroutine *co;
|
||||
QEMUBH *bh;
|
||||
IscsiLun *iscsilun;
|
||||
} IscsiTask;
|
||||
|
||||
typedef struct IscsiAIOCB {
|
||||
@@ -133,7 +135,7 @@ iscsi_schedule_bh(IscsiAIOCB *acb)
|
||||
if (acb->bh) {
|
||||
return;
|
||||
}
|
||||
acb->bh = qemu_bh_new(iscsi_bh_cb, acb);
|
||||
acb->bh = aio_bh_new(acb->iscsilun->aio_context, iscsi_bh_cb, acb);
|
||||
qemu_bh_schedule(acb->bh);
|
||||
}
|
||||
|
||||
@@ -169,7 +171,8 @@ iscsi_co_generic_cb(struct iscsi_context *iscsi, int status,
|
||||
|
||||
out:
|
||||
if (iTask->co) {
|
||||
iTask->bh = qemu_bh_new(iscsi_co_generic_bh_cb, iTask);
|
||||
iTask->bh = aio_bh_new(iTask->iscsilun->aio_context,
|
||||
iscsi_co_generic_bh_cb, iTask);
|
||||
qemu_bh_schedule(iTask->bh);
|
||||
}
|
||||
}
|
||||
@@ -177,8 +180,9 @@ out:
|
||||
static void iscsi_co_init_iscsitask(IscsiLun *iscsilun, struct IscsiTask *iTask)
|
||||
{
|
||||
*iTask = (struct IscsiTask) {
|
||||
.co = qemu_coroutine_self(),
|
||||
.retries = ISCSI_CMD_RETRIES,
|
||||
.co = qemu_coroutine_self(),
|
||||
.retries = ISCSI_CMD_RETRIES,
|
||||
.iscsilun = iscsilun,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -209,7 +213,7 @@ iscsi_aio_cancel(BlockDriverAIOCB *blockacb)
|
||||
iscsi_abort_task_cb, acb);
|
||||
|
||||
while (acb->status == -EINPROGRESS) {
|
||||
qemu_aio_wait();
|
||||
aio_poll(iscsilun->aio_context, true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -232,10 +236,11 @@ iscsi_set_events(IscsiLun *iscsilun)
|
||||
ev = POLLIN;
|
||||
ev |= iscsi_which_events(iscsi);
|
||||
if (ev != iscsilun->events) {
|
||||
qemu_aio_set_fd_handler(iscsi_get_fd(iscsi),
|
||||
iscsi_process_read,
|
||||
(ev & POLLOUT) ? iscsi_process_write : NULL,
|
||||
iscsilun);
|
||||
aio_set_fd_handler(iscsilun->aio_context,
|
||||
iscsi_get_fd(iscsi),
|
||||
iscsi_process_read,
|
||||
(ev & POLLOUT) ? iscsi_process_write : NULL,
|
||||
iscsilun);
|
||||
|
||||
}
|
||||
|
||||
@@ -791,7 +796,7 @@ static int iscsi_ioctl(BlockDriverState *bs, unsigned long int req, void *buf)
|
||||
iscsi_aio_ioctl(bs, req, buf, ioctl_cb, &status);
|
||||
|
||||
while (status == -EINPROGRESS) {
|
||||
qemu_aio_wait();
|
||||
aio_poll(iscsilun->aio_context, true);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -1195,6 +1200,40 @@ fail_with_err:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void iscsi_detach_aio_context(BlockDriverState *bs)
|
||||
{
|
||||
IscsiLun *iscsilun = bs->opaque;
|
||||
|
||||
aio_set_fd_handler(iscsilun->aio_context,
|
||||
iscsi_get_fd(iscsilun->iscsi),
|
||||
NULL, NULL, NULL);
|
||||
iscsilun->events = 0;
|
||||
|
||||
if (iscsilun->nop_timer) {
|
||||
timer_del(iscsilun->nop_timer);
|
||||
timer_free(iscsilun->nop_timer);
|
||||
iscsilun->nop_timer = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void iscsi_attach_aio_context(BlockDriverState *bs,
|
||||
AioContext *new_context)
|
||||
{
|
||||
IscsiLun *iscsilun = bs->opaque;
|
||||
|
||||
iscsilun->aio_context = new_context;
|
||||
iscsi_set_events(iscsilun);
|
||||
|
||||
#if defined(LIBISCSI_FEATURE_NOP_COUNTER)
|
||||
/* Set up a timer for sending out iSCSI NOPs */
|
||||
iscsilun->nop_timer = aio_timer_new(iscsilun->aio_context,
|
||||
QEMU_CLOCK_REALTIME, SCALE_MS,
|
||||
iscsi_nop_timed_event, iscsilun);
|
||||
timer_mod(iscsilun->nop_timer,
|
||||
qemu_clock_get_ms(QEMU_CLOCK_REALTIME) + NOP_INTERVAL);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* We support iscsi url's on the form
|
||||
* iscsi://[<username>%<password>@]<host>[:<port>]/<targetname>/<lun>
|
||||
@@ -1301,6 +1340,7 @@ static int iscsi_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
}
|
||||
|
||||
iscsilun->iscsi = iscsi;
|
||||
iscsilun->aio_context = bdrv_get_aio_context(bs);
|
||||
iscsilun->lun = iscsi_url->lun;
|
||||
iscsilun->has_write_same = true;
|
||||
|
||||
@@ -1374,11 +1414,7 @@ static int iscsi_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
scsi_free_scsi_task(task);
|
||||
task = NULL;
|
||||
|
||||
#if defined(LIBISCSI_FEATURE_NOP_COUNTER)
|
||||
/* Set up a timer for sending out iSCSI NOPs */
|
||||
iscsilun->nop_timer = timer_new_ms(QEMU_CLOCK_REALTIME, iscsi_nop_timed_event, iscsilun);
|
||||
timer_mod(iscsilun->nop_timer, qemu_clock_get_ms(QEMU_CLOCK_REALTIME) + NOP_INTERVAL);
|
||||
#endif
|
||||
iscsi_attach_aio_context(bs, iscsilun->aio_context);
|
||||
|
||||
/* Guess the internal cluster (page) size of the iscsi target by the means
|
||||
* of opt_unmap_gran. Transfer the unmap granularity only if it has a
|
||||
@@ -1422,11 +1458,7 @@ static void iscsi_close(BlockDriverState *bs)
|
||||
IscsiLun *iscsilun = bs->opaque;
|
||||
struct iscsi_context *iscsi = iscsilun->iscsi;
|
||||
|
||||
if (iscsilun->nop_timer) {
|
||||
timer_del(iscsilun->nop_timer);
|
||||
timer_free(iscsilun->nop_timer);
|
||||
}
|
||||
qemu_aio_set_fd_handler(iscsi_get_fd(iscsi), NULL, NULL, NULL);
|
||||
iscsi_detach_aio_context(bs);
|
||||
iscsi_destroy_context(iscsi);
|
||||
g_free(iscsilun->zeroblock);
|
||||
g_free(iscsilun->allocationmap);
|
||||
@@ -1530,10 +1562,7 @@ static int iscsi_create(const char *filename, QEMUOptionParameter *options,
|
||||
if (ret != 0) {
|
||||
goto out;
|
||||
}
|
||||
if (iscsilun->nop_timer) {
|
||||
timer_del(iscsilun->nop_timer);
|
||||
timer_free(iscsilun->nop_timer);
|
||||
}
|
||||
iscsi_detach_aio_context(bs);
|
||||
if (iscsilun->type != TYPE_DISK) {
|
||||
ret = -ENODEV;
|
||||
goto out;
|
||||
@@ -1604,6 +1633,9 @@ static BlockDriver bdrv_iscsi = {
|
||||
.bdrv_ioctl = iscsi_ioctl,
|
||||
.bdrv_aio_ioctl = iscsi_aio_ioctl,
|
||||
#endif
|
||||
|
||||
.bdrv_detach_aio_context = iscsi_detach_aio_context,
|
||||
.bdrv_attach_aio_context = iscsi_attach_aio_context,
|
||||
};
|
||||
|
||||
static QemuOptsList qemu_iscsi_opts = {
|
||||
|
||||
+22
-2
@@ -177,6 +177,20 @@ out_free_aiocb:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void laio_detach_aio_context(void *s_, AioContext *old_context)
|
||||
{
|
||||
struct qemu_laio_state *s = s_;
|
||||
|
||||
aio_set_event_notifier(old_context, &s->e, NULL);
|
||||
}
|
||||
|
||||
void laio_attach_aio_context(void *s_, AioContext *new_context)
|
||||
{
|
||||
struct qemu_laio_state *s = s_;
|
||||
|
||||
aio_set_event_notifier(new_context, &s->e, qemu_laio_completion_cb);
|
||||
}
|
||||
|
||||
void *laio_init(void)
|
||||
{
|
||||
struct qemu_laio_state *s;
|
||||
@@ -190,8 +204,6 @@ void *laio_init(void)
|
||||
goto out_close_efd;
|
||||
}
|
||||
|
||||
qemu_aio_set_event_notifier(&s->e, qemu_laio_completion_cb);
|
||||
|
||||
return s;
|
||||
|
||||
out_close_efd:
|
||||
@@ -200,3 +212,11 @@ out_free_state:
|
||||
g_free(s);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void laio_cleanup(void *s_)
|
||||
{
|
||||
struct qemu_laio_state *s = s_;
|
||||
|
||||
event_notifier_cleanup(&s->e);
|
||||
g_free(s);
|
||||
}
|
||||
|
||||
+20
-4
@@ -49,7 +49,7 @@ static void nbd_teardown_connection(NbdClientSession *client)
|
||||
shutdown(client->sock, 2);
|
||||
nbd_recv_coroutines_enter_all(client);
|
||||
|
||||
qemu_aio_set_fd_handler(client->sock, NULL, NULL, NULL);
|
||||
nbd_client_session_detach_aio_context(client);
|
||||
closesocket(client->sock);
|
||||
client->sock = -1;
|
||||
}
|
||||
@@ -103,11 +103,14 @@ static int nbd_co_send_request(NbdClientSession *s,
|
||||
struct nbd_request *request,
|
||||
QEMUIOVector *qiov, int offset)
|
||||
{
|
||||
AioContext *aio_context;
|
||||
int rc, ret;
|
||||
|
||||
qemu_co_mutex_lock(&s->send_mutex);
|
||||
s->send_coroutine = qemu_coroutine_self();
|
||||
qemu_aio_set_fd_handler(s->sock, nbd_reply_ready, nbd_restart_write, s);
|
||||
aio_context = bdrv_get_aio_context(s->bs);
|
||||
aio_set_fd_handler(aio_context, s->sock,
|
||||
nbd_reply_ready, nbd_restart_write, s);
|
||||
if (qiov) {
|
||||
if (!s->is_unix) {
|
||||
socket_set_cork(s->sock, 1);
|
||||
@@ -126,7 +129,7 @@ static int nbd_co_send_request(NbdClientSession *s,
|
||||
} else {
|
||||
rc = nbd_send_request(s->sock, request);
|
||||
}
|
||||
qemu_aio_set_fd_handler(s->sock, nbd_reply_ready, NULL, s);
|
||||
aio_set_fd_handler(aio_context, s->sock, nbd_reply_ready, NULL, s);
|
||||
s->send_coroutine = NULL;
|
||||
qemu_co_mutex_unlock(&s->send_mutex);
|
||||
return rc;
|
||||
@@ -335,6 +338,19 @@ int nbd_client_session_co_discard(NbdClientSession *client, int64_t sector_num,
|
||||
|
||||
}
|
||||
|
||||
void nbd_client_session_detach_aio_context(NbdClientSession *client)
|
||||
{
|
||||
aio_set_fd_handler(bdrv_get_aio_context(client->bs), client->sock,
|
||||
NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
void nbd_client_session_attach_aio_context(NbdClientSession *client,
|
||||
AioContext *new_context)
|
||||
{
|
||||
aio_set_fd_handler(new_context, client->sock,
|
||||
nbd_reply_ready, NULL, client);
|
||||
}
|
||||
|
||||
void nbd_client_session_close(NbdClientSession *client)
|
||||
{
|
||||
struct nbd_request request = {
|
||||
@@ -381,7 +397,7 @@ int nbd_client_session_init(NbdClientSession *client, BlockDriverState *bs,
|
||||
/* Now that we're connected, set the socket to be non-blocking and
|
||||
* kick the reply mechanism. */
|
||||
qemu_set_nonblock(sock);
|
||||
qemu_aio_set_fd_handler(sock, nbd_reply_ready, NULL, client);
|
||||
nbd_client_session_attach_aio_context(client, bdrv_get_aio_context(bs));
|
||||
|
||||
logout("Established connection with NBD server\n");
|
||||
return 0;
|
||||
|
||||
@@ -47,4 +47,8 @@ int nbd_client_session_co_writev(NbdClientSession *client, int64_t sector_num,
|
||||
int nbd_client_session_co_readv(NbdClientSession *client, int64_t sector_num,
|
||||
int nb_sectors, QEMUIOVector *qiov);
|
||||
|
||||
void nbd_client_session_detach_aio_context(NbdClientSession *client);
|
||||
void nbd_client_session_attach_aio_context(NbdClientSession *client,
|
||||
AioContext *new_context);
|
||||
|
||||
#endif /* NBD_CLIENT_H */
|
||||
|
||||
+54
-33
@@ -323,46 +323,67 @@ static int64_t nbd_getlength(BlockDriverState *bs)
|
||||
return s->client.size;
|
||||
}
|
||||
|
||||
static void nbd_detach_aio_context(BlockDriverState *bs)
|
||||
{
|
||||
BDRVNBDState *s = bs->opaque;
|
||||
|
||||
nbd_client_session_detach_aio_context(&s->client);
|
||||
}
|
||||
|
||||
static void nbd_attach_aio_context(BlockDriverState *bs,
|
||||
AioContext *new_context)
|
||||
{
|
||||
BDRVNBDState *s = bs->opaque;
|
||||
|
||||
nbd_client_session_attach_aio_context(&s->client, new_context);
|
||||
}
|
||||
|
||||
static BlockDriver bdrv_nbd = {
|
||||
.format_name = "nbd",
|
||||
.protocol_name = "nbd",
|
||||
.instance_size = sizeof(BDRVNBDState),
|
||||
.bdrv_parse_filename = nbd_parse_filename,
|
||||
.bdrv_file_open = nbd_open,
|
||||
.bdrv_co_readv = nbd_co_readv,
|
||||
.bdrv_co_writev = nbd_co_writev,
|
||||
.bdrv_close = nbd_close,
|
||||
.bdrv_co_flush_to_os = nbd_co_flush,
|
||||
.bdrv_co_discard = nbd_co_discard,
|
||||
.bdrv_getlength = nbd_getlength,
|
||||
.format_name = "nbd",
|
||||
.protocol_name = "nbd",
|
||||
.instance_size = sizeof(BDRVNBDState),
|
||||
.bdrv_parse_filename = nbd_parse_filename,
|
||||
.bdrv_file_open = nbd_open,
|
||||
.bdrv_co_readv = nbd_co_readv,
|
||||
.bdrv_co_writev = nbd_co_writev,
|
||||
.bdrv_close = nbd_close,
|
||||
.bdrv_co_flush_to_os = nbd_co_flush,
|
||||
.bdrv_co_discard = nbd_co_discard,
|
||||
.bdrv_getlength = nbd_getlength,
|
||||
.bdrv_detach_aio_context = nbd_detach_aio_context,
|
||||
.bdrv_attach_aio_context = nbd_attach_aio_context,
|
||||
};
|
||||
|
||||
static BlockDriver bdrv_nbd_tcp = {
|
||||
.format_name = "nbd",
|
||||
.protocol_name = "nbd+tcp",
|
||||
.instance_size = sizeof(BDRVNBDState),
|
||||
.bdrv_parse_filename = nbd_parse_filename,
|
||||
.bdrv_file_open = nbd_open,
|
||||
.bdrv_co_readv = nbd_co_readv,
|
||||
.bdrv_co_writev = nbd_co_writev,
|
||||
.bdrv_close = nbd_close,
|
||||
.bdrv_co_flush_to_os = nbd_co_flush,
|
||||
.bdrv_co_discard = nbd_co_discard,
|
||||
.bdrv_getlength = nbd_getlength,
|
||||
.format_name = "nbd",
|
||||
.protocol_name = "nbd+tcp",
|
||||
.instance_size = sizeof(BDRVNBDState),
|
||||
.bdrv_parse_filename = nbd_parse_filename,
|
||||
.bdrv_file_open = nbd_open,
|
||||
.bdrv_co_readv = nbd_co_readv,
|
||||
.bdrv_co_writev = nbd_co_writev,
|
||||
.bdrv_close = nbd_close,
|
||||
.bdrv_co_flush_to_os = nbd_co_flush,
|
||||
.bdrv_co_discard = nbd_co_discard,
|
||||
.bdrv_getlength = nbd_getlength,
|
||||
.bdrv_detach_aio_context = nbd_detach_aio_context,
|
||||
.bdrv_attach_aio_context = nbd_attach_aio_context,
|
||||
};
|
||||
|
||||
static BlockDriver bdrv_nbd_unix = {
|
||||
.format_name = "nbd",
|
||||
.protocol_name = "nbd+unix",
|
||||
.instance_size = sizeof(BDRVNBDState),
|
||||
.bdrv_parse_filename = nbd_parse_filename,
|
||||
.bdrv_file_open = nbd_open,
|
||||
.bdrv_co_readv = nbd_co_readv,
|
||||
.bdrv_co_writev = nbd_co_writev,
|
||||
.bdrv_close = nbd_close,
|
||||
.bdrv_co_flush_to_os = nbd_co_flush,
|
||||
.bdrv_co_discard = nbd_co_discard,
|
||||
.bdrv_getlength = nbd_getlength,
|
||||
.format_name = "nbd",
|
||||
.protocol_name = "nbd+unix",
|
||||
.instance_size = sizeof(BDRVNBDState),
|
||||
.bdrv_parse_filename = nbd_parse_filename,
|
||||
.bdrv_file_open = nbd_open,
|
||||
.bdrv_co_readv = nbd_co_readv,
|
||||
.bdrv_co_writev = nbd_co_writev,
|
||||
.bdrv_close = nbd_close,
|
||||
.bdrv_co_flush_to_os = nbd_co_flush,
|
||||
.bdrv_co_discard = nbd_co_discard,
|
||||
.bdrv_getlength = nbd_getlength,
|
||||
.bdrv_detach_aio_context = nbd_detach_aio_context,
|
||||
.bdrv_attach_aio_context = nbd_attach_aio_context,
|
||||
};
|
||||
|
||||
static void bdrv_nbd_init(void)
|
||||
|
||||
+54
-21
@@ -40,6 +40,7 @@ typedef struct NFSClient {
|
||||
struct nfsfh *fh;
|
||||
int events;
|
||||
bool has_zero_init;
|
||||
AioContext *aio_context;
|
||||
} NFSClient;
|
||||
|
||||
typedef struct NFSRPC {
|
||||
@@ -49,6 +50,7 @@ typedef struct NFSRPC {
|
||||
struct stat *st;
|
||||
Coroutine *co;
|
||||
QEMUBH *bh;
|
||||
NFSClient *client;
|
||||
} NFSRPC;
|
||||
|
||||
static void nfs_process_read(void *arg);
|
||||
@@ -58,10 +60,11 @@ static void nfs_set_events(NFSClient *client)
|
||||
{
|
||||
int ev = nfs_which_events(client->context);
|
||||
if (ev != client->events) {
|
||||
qemu_aio_set_fd_handler(nfs_get_fd(client->context),
|
||||
(ev & POLLIN) ? nfs_process_read : NULL,
|
||||
(ev & POLLOUT) ? nfs_process_write : NULL,
|
||||
client);
|
||||
aio_set_fd_handler(client->aio_context,
|
||||
nfs_get_fd(client->context),
|
||||
(ev & POLLIN) ? nfs_process_read : NULL,
|
||||
(ev & POLLOUT) ? nfs_process_write : NULL,
|
||||
client);
|
||||
|
||||
}
|
||||
client->events = ev;
|
||||
@@ -84,7 +87,8 @@ static void nfs_process_write(void *arg)
|
||||
static void nfs_co_init_task(NFSClient *client, NFSRPC *task)
|
||||
{
|
||||
*task = (NFSRPC) {
|
||||
.co = qemu_coroutine_self(),
|
||||
.co = qemu_coroutine_self(),
|
||||
.client = client,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -116,7 +120,8 @@ nfs_co_generic_cb(int ret, struct nfs_context *nfs, void *data,
|
||||
error_report("NFS Error: %s", nfs_get_error(nfs));
|
||||
}
|
||||
if (task->co) {
|
||||
task->bh = qemu_bh_new(nfs_co_generic_bh_cb, task);
|
||||
task->bh = aio_bh_new(task->client->aio_context,
|
||||
nfs_co_generic_bh_cb, task);
|
||||
qemu_bh_schedule(task->bh);
|
||||
}
|
||||
}
|
||||
@@ -224,13 +229,34 @@ static QemuOptsList runtime_opts = {
|
||||
},
|
||||
};
|
||||
|
||||
static void nfs_detach_aio_context(BlockDriverState *bs)
|
||||
{
|
||||
NFSClient *client = bs->opaque;
|
||||
|
||||
aio_set_fd_handler(client->aio_context,
|
||||
nfs_get_fd(client->context),
|
||||
NULL, NULL, NULL);
|
||||
client->events = 0;
|
||||
}
|
||||
|
||||
static void nfs_attach_aio_context(BlockDriverState *bs,
|
||||
AioContext *new_context)
|
||||
{
|
||||
NFSClient *client = bs->opaque;
|
||||
|
||||
client->aio_context = new_context;
|
||||
nfs_set_events(client);
|
||||
}
|
||||
|
||||
static void nfs_client_close(NFSClient *client)
|
||||
{
|
||||
if (client->context) {
|
||||
if (client->fh) {
|
||||
nfs_close(client->context, client->fh);
|
||||
}
|
||||
qemu_aio_set_fd_handler(nfs_get_fd(client->context), NULL, NULL, NULL);
|
||||
aio_set_fd_handler(client->aio_context,
|
||||
nfs_get_fd(client->context),
|
||||
NULL, NULL, NULL);
|
||||
nfs_destroy_context(client->context);
|
||||
}
|
||||
memset(client, 0, sizeof(NFSClient));
|
||||
@@ -345,6 +371,8 @@ static int nfs_file_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
QemuOpts *opts;
|
||||
Error *local_err = NULL;
|
||||
|
||||
client->aio_context = bdrv_get_aio_context(bs);
|
||||
|
||||
opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort);
|
||||
qemu_opts_absorb_qdict(opts, options, &local_err);
|
||||
if (local_err) {
|
||||
@@ -368,6 +396,8 @@ static int nfs_file_create(const char *url, QEMUOptionParameter *options,
|
||||
int64_t total_size = 0;
|
||||
NFSClient *client = g_malloc0(sizeof(NFSClient));
|
||||
|
||||
client->aio_context = qemu_get_aio_context();
|
||||
|
||||
/* Read out options */
|
||||
while (options && options->name) {
|
||||
if (!strcmp(options->name, "size")) {
|
||||
@@ -407,7 +437,7 @@ static int64_t nfs_get_allocated_file_size(BlockDriverState *bs)
|
||||
|
||||
while (!task.complete) {
|
||||
nfs_set_events(client);
|
||||
qemu_aio_wait();
|
||||
aio_poll(client->aio_context, true);
|
||||
}
|
||||
|
||||
return (task.ret < 0 ? task.ret : st.st_blocks * st.st_blksize);
|
||||
@@ -420,22 +450,25 @@ static int nfs_file_truncate(BlockDriverState *bs, int64_t offset)
|
||||
}
|
||||
|
||||
static BlockDriver bdrv_nfs = {
|
||||
.format_name = "nfs",
|
||||
.protocol_name = "nfs",
|
||||
.format_name = "nfs",
|
||||
.protocol_name = "nfs",
|
||||
|
||||
.instance_size = sizeof(NFSClient),
|
||||
.bdrv_needs_filename = true,
|
||||
.bdrv_has_zero_init = nfs_has_zero_init,
|
||||
.bdrv_get_allocated_file_size = nfs_get_allocated_file_size,
|
||||
.bdrv_truncate = nfs_file_truncate,
|
||||
.instance_size = sizeof(NFSClient),
|
||||
.bdrv_needs_filename = true,
|
||||
.bdrv_has_zero_init = nfs_has_zero_init,
|
||||
.bdrv_get_allocated_file_size = nfs_get_allocated_file_size,
|
||||
.bdrv_truncate = nfs_file_truncate,
|
||||
|
||||
.bdrv_file_open = nfs_file_open,
|
||||
.bdrv_close = nfs_file_close,
|
||||
.bdrv_create = nfs_file_create,
|
||||
.bdrv_file_open = nfs_file_open,
|
||||
.bdrv_close = nfs_file_close,
|
||||
.bdrv_create = nfs_file_create,
|
||||
|
||||
.bdrv_co_readv = nfs_co_readv,
|
||||
.bdrv_co_writev = nfs_co_writev,
|
||||
.bdrv_co_flush_to_disk = nfs_co_flush,
|
||||
.bdrv_co_readv = nfs_co_readv,
|
||||
.bdrv_co_writev = nfs_co_writev,
|
||||
.bdrv_co_flush_to_disk = nfs_co_flush,
|
||||
|
||||
.bdrv_detach_aio_context = nfs_detach_aio_context,
|
||||
.bdrv_attach_aio_context = nfs_attach_aio_context,
|
||||
};
|
||||
|
||||
static void nfs_block_init(void)
|
||||
|
||||
+4
-4
@@ -173,7 +173,7 @@ int qed_read_l1_table_sync(BDRVQEDState *s)
|
||||
qed_read_table(s, s->header.l1_table_offset,
|
||||
s->l1_table, qed_sync_cb, &ret);
|
||||
while (ret == -EINPROGRESS) {
|
||||
qemu_aio_wait();
|
||||
aio_poll(bdrv_get_aio_context(s->bs), true);
|
||||
}
|
||||
|
||||
return ret;
|
||||
@@ -194,7 +194,7 @@ int qed_write_l1_table_sync(BDRVQEDState *s, unsigned int index,
|
||||
|
||||
qed_write_l1_table(s, index, n, qed_sync_cb, &ret);
|
||||
while (ret == -EINPROGRESS) {
|
||||
qemu_aio_wait();
|
||||
aio_poll(bdrv_get_aio_context(s->bs), true);
|
||||
}
|
||||
|
||||
return ret;
|
||||
@@ -267,7 +267,7 @@ int qed_read_l2_table_sync(BDRVQEDState *s, QEDRequest *request, uint64_t offset
|
||||
|
||||
qed_read_l2_table(s, request, offset, qed_sync_cb, &ret);
|
||||
while (ret == -EINPROGRESS) {
|
||||
qemu_aio_wait();
|
||||
aio_poll(bdrv_get_aio_context(s->bs), true);
|
||||
}
|
||||
|
||||
return ret;
|
||||
@@ -289,7 +289,7 @@ int qed_write_l2_table_sync(BDRVQEDState *s, QEDRequest *request,
|
||||
|
||||
qed_write_l2_table(s, request, index, n, flush, qed_sync_cb, &ret);
|
||||
while (ret == -EINPROGRESS) {
|
||||
qemu_aio_wait();
|
||||
aio_poll(bdrv_get_aio_context(s->bs), true);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
+29
-6
@@ -21,12 +21,13 @@
|
||||
static void qed_aio_cancel(BlockDriverAIOCB *blockacb)
|
||||
{
|
||||
QEDAIOCB *acb = (QEDAIOCB *)blockacb;
|
||||
AioContext *aio_context = bdrv_get_aio_context(blockacb->bs);
|
||||
bool finished = false;
|
||||
|
||||
/* Wait for the request to finish */
|
||||
acb->finished = &finished;
|
||||
while (!finished) {
|
||||
qemu_aio_wait();
|
||||
aio_poll(aio_context, true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -373,6 +374,27 @@ static void bdrv_qed_rebind(BlockDriverState *bs)
|
||||
s->bs = bs;
|
||||
}
|
||||
|
||||
static void bdrv_qed_detach_aio_context(BlockDriverState *bs)
|
||||
{
|
||||
BDRVQEDState *s = bs->opaque;
|
||||
|
||||
qed_cancel_need_check_timer(s);
|
||||
timer_free(s->need_check_timer);
|
||||
}
|
||||
|
||||
static void bdrv_qed_attach_aio_context(BlockDriverState *bs,
|
||||
AioContext *new_context)
|
||||
{
|
||||
BDRVQEDState *s = bs->opaque;
|
||||
|
||||
s->need_check_timer = aio_timer_new(new_context,
|
||||
QEMU_CLOCK_VIRTUAL, SCALE_NS,
|
||||
qed_need_check_timer_cb, s);
|
||||
if (s->header.features & QED_F_NEED_CHECK) {
|
||||
qed_start_need_check_timer(s);
|
||||
}
|
||||
}
|
||||
|
||||
static int bdrv_qed_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
Error **errp)
|
||||
{
|
||||
@@ -496,8 +518,7 @@ static int bdrv_qed_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
}
|
||||
}
|
||||
|
||||
s->need_check_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL,
|
||||
qed_need_check_timer_cb, s);
|
||||
bdrv_qed_attach_aio_context(bs, bdrv_get_aio_context(bs));
|
||||
|
||||
out:
|
||||
if (ret) {
|
||||
@@ -528,8 +549,7 @@ static void bdrv_qed_close(BlockDriverState *bs)
|
||||
{
|
||||
BDRVQEDState *s = bs->opaque;
|
||||
|
||||
qed_cancel_need_check_timer(s);
|
||||
timer_free(s->need_check_timer);
|
||||
bdrv_qed_detach_aio_context(bs);
|
||||
|
||||
/* Ensure writes reach stable storage */
|
||||
bdrv_flush(bs->file);
|
||||
@@ -919,7 +939,8 @@ static void qed_aio_complete(QEDAIOCB *acb, int ret)
|
||||
|
||||
/* Arrange for a bh to invoke the completion function */
|
||||
acb->bh_ret = ret;
|
||||
acb->bh = qemu_bh_new(qed_aio_complete_bh, acb);
|
||||
acb->bh = aio_bh_new(bdrv_get_aio_context(acb->common.bs),
|
||||
qed_aio_complete_bh, acb);
|
||||
qemu_bh_schedule(acb->bh);
|
||||
|
||||
/* Start next allocating write request waiting behind this one. Note that
|
||||
@@ -1644,6 +1665,8 @@ static BlockDriver bdrv_qed = {
|
||||
.bdrv_change_backing_file = bdrv_qed_change_backing_file,
|
||||
.bdrv_invalidate_cache = bdrv_qed_invalidate_cache,
|
||||
.bdrv_check = bdrv_qed_check,
|
||||
.bdrv_detach_aio_context = bdrv_qed_detach_aio_context,
|
||||
.bdrv_attach_aio_context = bdrv_qed_attach_aio_context,
|
||||
};
|
||||
|
||||
static void bdrv_qed_init(void)
|
||||
|
||||
+36
-12
@@ -848,25 +848,49 @@ static void quorum_close(BlockDriverState *bs)
|
||||
g_free(s->bs);
|
||||
}
|
||||
|
||||
static void quorum_detach_aio_context(BlockDriverState *bs)
|
||||
{
|
||||
BDRVQuorumState *s = bs->opaque;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < s->num_children; i++) {
|
||||
bdrv_detach_aio_context(s->bs[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static void quorum_attach_aio_context(BlockDriverState *bs,
|
||||
AioContext *new_context)
|
||||
{
|
||||
BDRVQuorumState *s = bs->opaque;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < s->num_children; i++) {
|
||||
bdrv_attach_aio_context(s->bs[i], new_context);
|
||||
}
|
||||
}
|
||||
|
||||
static BlockDriver bdrv_quorum = {
|
||||
.format_name = "quorum",
|
||||
.protocol_name = "quorum",
|
||||
.format_name = "quorum",
|
||||
.protocol_name = "quorum",
|
||||
|
||||
.instance_size = sizeof(BDRVQuorumState),
|
||||
.instance_size = sizeof(BDRVQuorumState),
|
||||
|
||||
.bdrv_file_open = quorum_open,
|
||||
.bdrv_close = quorum_close,
|
||||
.bdrv_file_open = quorum_open,
|
||||
.bdrv_close = quorum_close,
|
||||
|
||||
.bdrv_co_flush_to_disk = quorum_co_flush,
|
||||
.bdrv_co_flush_to_disk = quorum_co_flush,
|
||||
|
||||
.bdrv_getlength = quorum_getlength,
|
||||
.bdrv_getlength = quorum_getlength,
|
||||
|
||||
.bdrv_aio_readv = quorum_aio_readv,
|
||||
.bdrv_aio_writev = quorum_aio_writev,
|
||||
.bdrv_invalidate_cache = quorum_invalidate_cache,
|
||||
.bdrv_aio_readv = quorum_aio_readv,
|
||||
.bdrv_aio_writev = quorum_aio_writev,
|
||||
.bdrv_invalidate_cache = quorum_invalidate_cache,
|
||||
|
||||
.is_filter = true,
|
||||
.bdrv_recurse_is_first_non_filter = quorum_recurse_is_first_non_filter,
|
||||
.bdrv_detach_aio_context = quorum_detach_aio_context,
|
||||
.bdrv_attach_aio_context = quorum_attach_aio_context,
|
||||
|
||||
.is_filter = true,
|
||||
.bdrv_recurse_is_first_non_filter = quorum_recurse_is_first_non_filter,
|
||||
};
|
||||
|
||||
static void bdrv_quorum_init(void)
|
||||
|
||||
@@ -34,19 +34,27 @@
|
||||
/* linux-aio.c - Linux native implementation */
|
||||
#ifdef CONFIG_LINUX_AIO
|
||||
void *laio_init(void);
|
||||
void laio_cleanup(void *s);
|
||||
BlockDriverAIOCB *laio_submit(BlockDriverState *bs, void *aio_ctx, int fd,
|
||||
int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
|
||||
BlockDriverCompletionFunc *cb, void *opaque, int type);
|
||||
void laio_detach_aio_context(void *s, AioContext *old_context);
|
||||
void laio_attach_aio_context(void *s, AioContext *new_context);
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
typedef struct QEMUWin32AIOState QEMUWin32AIOState;
|
||||
QEMUWin32AIOState *win32_aio_init(void);
|
||||
void win32_aio_cleanup(QEMUWin32AIOState *aio);
|
||||
int win32_aio_attach(QEMUWin32AIOState *aio, HANDLE hfile);
|
||||
BlockDriverAIOCB *win32_aio_submit(BlockDriverState *bs,
|
||||
QEMUWin32AIOState *aio, HANDLE hfile,
|
||||
int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
|
||||
BlockDriverCompletionFunc *cb, void *opaque, int type);
|
||||
void win32_aio_detach_aio_context(QEMUWin32AIOState *aio,
|
||||
AioContext *old_context);
|
||||
void win32_aio_attach_aio_context(QEMUWin32AIOState *aio,
|
||||
AioContext *new_context);
|
||||
#endif
|
||||
|
||||
#endif /* QEMU_RAW_AIO_H */
|
||||
|
||||
+48
-34
@@ -307,6 +307,29 @@ static void raw_parse_flags(int bdrv_flags, int *open_flags)
|
||||
}
|
||||
}
|
||||
|
||||
static void raw_detach_aio_context(BlockDriverState *bs)
|
||||
{
|
||||
#ifdef CONFIG_LINUX_AIO
|
||||
BDRVRawState *s = bs->opaque;
|
||||
|
||||
if (s->use_aio) {
|
||||
laio_detach_aio_context(s->aio_ctx, bdrv_get_aio_context(bs));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void raw_attach_aio_context(BlockDriverState *bs,
|
||||
AioContext *new_context)
|
||||
{
|
||||
#ifdef CONFIG_LINUX_AIO
|
||||
BDRVRawState *s = bs->opaque;
|
||||
|
||||
if (s->use_aio) {
|
||||
laio_attach_aio_context(s->aio_ctx, new_context);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef CONFIG_LINUX_AIO
|
||||
static int raw_set_aio(void **aio_ctx, int *use_aio, int bdrv_flags)
|
||||
{
|
||||
@@ -447,6 +470,8 @@ static int raw_open_common(BlockDriverState *bs, QDict *options,
|
||||
}
|
||||
#endif
|
||||
|
||||
raw_attach_aio_context(bs, bdrv_get_aio_context(bs));
|
||||
|
||||
ret = 0;
|
||||
fail:
|
||||
if (filename && (bdrv_flags & BDRV_O_TEMPORARY)) {
|
||||
@@ -1059,6 +1084,14 @@ static BlockDriverAIOCB *raw_aio_flush(BlockDriverState *bs,
|
||||
static void raw_close(BlockDriverState *bs)
|
||||
{
|
||||
BDRVRawState *s = bs->opaque;
|
||||
|
||||
raw_detach_aio_context(bs);
|
||||
|
||||
#ifdef CONFIG_LINUX_AIO
|
||||
if (s->use_aio) {
|
||||
laio_cleanup(s->aio_ctx);
|
||||
}
|
||||
#endif
|
||||
if (s->fd >= 0) {
|
||||
qemu_close(s->fd);
|
||||
s->fd = -1;
|
||||
@@ -1478,6 +1511,9 @@ static BlockDriver bdrv_file = {
|
||||
.bdrv_get_allocated_file_size
|
||||
= raw_get_allocated_file_size,
|
||||
|
||||
.bdrv_detach_aio_context = raw_detach_aio_context,
|
||||
.bdrv_attach_aio_context = raw_attach_aio_context,
|
||||
|
||||
.create_options = raw_create_options,
|
||||
};
|
||||
|
||||
@@ -1878,6 +1914,9 @@ static BlockDriver bdrv_host_device = {
|
||||
.bdrv_get_allocated_file_size
|
||||
= raw_get_allocated_file_size,
|
||||
|
||||
.bdrv_detach_aio_context = raw_detach_aio_context,
|
||||
.bdrv_attach_aio_context = raw_attach_aio_context,
|
||||
|
||||
/* generic scsi device */
|
||||
#ifdef __linux__
|
||||
.bdrv_ioctl = hdev_ioctl,
|
||||
@@ -2020,6 +2059,9 @@ static BlockDriver bdrv_host_floppy = {
|
||||
.bdrv_get_allocated_file_size
|
||||
= raw_get_allocated_file_size,
|
||||
|
||||
.bdrv_detach_aio_context = raw_detach_aio_context,
|
||||
.bdrv_attach_aio_context = raw_attach_aio_context,
|
||||
|
||||
/* removable device support */
|
||||
.bdrv_is_inserted = floppy_is_inserted,
|
||||
.bdrv_media_changed = floppy_media_changed,
|
||||
@@ -2145,6 +2187,9 @@ static BlockDriver bdrv_host_cdrom = {
|
||||
.bdrv_get_allocated_file_size
|
||||
= raw_get_allocated_file_size,
|
||||
|
||||
.bdrv_detach_aio_context = raw_detach_aio_context,
|
||||
.bdrv_attach_aio_context = raw_attach_aio_context,
|
||||
|
||||
/* removable device support */
|
||||
.bdrv_is_inserted = cdrom_is_inserted,
|
||||
.bdrv_eject = cdrom_eject,
|
||||
@@ -2276,6 +2321,9 @@ static BlockDriver bdrv_host_cdrom = {
|
||||
.bdrv_get_allocated_file_size
|
||||
= raw_get_allocated_file_size,
|
||||
|
||||
.bdrv_detach_aio_context = raw_detach_aio_context,
|
||||
.bdrv_attach_aio_context = raw_attach_aio_context,
|
||||
|
||||
/* removable device support */
|
||||
.bdrv_is_inserted = cdrom_is_inserted,
|
||||
.bdrv_eject = cdrom_eject,
|
||||
@@ -2283,40 +2331,6 @@ static BlockDriver bdrv_host_cdrom = {
|
||||
};
|
||||
#endif /* __FreeBSD__ */
|
||||
|
||||
#ifdef CONFIG_LINUX_AIO
|
||||
/**
|
||||
* Return the file descriptor for Linux AIO
|
||||
*
|
||||
* This function is a layering violation and should be removed when it becomes
|
||||
* possible to call the block layer outside the global mutex. It allows the
|
||||
* caller to hijack the file descriptor so I/O can be performed outside the
|
||||
* block layer.
|
||||
*/
|
||||
int raw_get_aio_fd(BlockDriverState *bs)
|
||||
{
|
||||
BDRVRawState *s;
|
||||
|
||||
if (!bs->drv) {
|
||||
return -ENOMEDIUM;
|
||||
}
|
||||
|
||||
if (bs->drv == bdrv_find_format("raw")) {
|
||||
bs = bs->file;
|
||||
}
|
||||
|
||||
/* raw-posix has several protocols so just check for raw_aio_readv */
|
||||
if (bs->drv->bdrv_aio_readv != raw_aio_readv) {
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
s = bs->opaque;
|
||||
if (!s->use_aio) {
|
||||
return -ENOTSUP;
|
||||
}
|
||||
return s->fd;
|
||||
}
|
||||
#endif /* CONFIG_LINUX_AIO */
|
||||
|
||||
static void bdrv_file_init(void)
|
||||
{
|
||||
/*
|
||||
|
||||
+41
-13
@@ -36,8 +36,6 @@
|
||||
#define FTYPE_CD 1
|
||||
#define FTYPE_HARDDISK 2
|
||||
|
||||
static QEMUWin32AIOState *aio;
|
||||
|
||||
typedef struct RawWin32AIOData {
|
||||
BlockDriverState *bs;
|
||||
HANDLE hfile;
|
||||
@@ -202,6 +200,25 @@ static int set_sparse(int fd)
|
||||
NULL, 0, NULL, 0, &returned, NULL);
|
||||
}
|
||||
|
||||
static void raw_detach_aio_context(BlockDriverState *bs)
|
||||
{
|
||||
BDRVRawState *s = bs->opaque;
|
||||
|
||||
if (s->aio) {
|
||||
win32_aio_detach_aio_context(s->aio, bdrv_get_aio_context(bs));
|
||||
}
|
||||
}
|
||||
|
||||
static void raw_attach_aio_context(BlockDriverState *bs,
|
||||
AioContext *new_context)
|
||||
{
|
||||
BDRVRawState *s = bs->opaque;
|
||||
|
||||
if (s->aio) {
|
||||
win32_aio_attach_aio_context(s->aio, new_context);
|
||||
}
|
||||
}
|
||||
|
||||
static void raw_probe_alignment(BlockDriverState *bs)
|
||||
{
|
||||
BDRVRawState *s = bs->opaque;
|
||||
@@ -300,15 +317,6 @@ static int raw_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
|
||||
raw_parse_flags(flags, &access_flags, &overlapped);
|
||||
|
||||
if ((flags & BDRV_O_NATIVE_AIO) && aio == NULL) {
|
||||
aio = win32_aio_init();
|
||||
if (aio == NULL) {
|
||||
error_setg(errp, "Could not initialize AIO");
|
||||
ret = -EINVAL;
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
if (filename[0] && filename[1] == ':') {
|
||||
snprintf(s->drive_path, sizeof(s->drive_path), "%c:\\", filename[0]);
|
||||
} else if (filename[0] == '\\' && filename[1] == '\\') {
|
||||
@@ -335,13 +343,23 @@ static int raw_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
}
|
||||
|
||||
if (flags & BDRV_O_NATIVE_AIO) {
|
||||
ret = win32_aio_attach(aio, s->hfile);
|
||||
s->aio = win32_aio_init();
|
||||
if (s->aio == NULL) {
|
||||
CloseHandle(s->hfile);
|
||||
error_setg(errp, "Could not initialize AIO");
|
||||
ret = -EINVAL;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ret = win32_aio_attach(s->aio, s->hfile);
|
||||
if (ret < 0) {
|
||||
win32_aio_cleanup(s->aio);
|
||||
CloseHandle(s->hfile);
|
||||
error_setg_errno(errp, -ret, "Could not enable AIO");
|
||||
goto fail;
|
||||
}
|
||||
s->aio = aio;
|
||||
|
||||
win32_aio_attach_aio_context(s->aio, bdrv_get_aio_context(bs));
|
||||
}
|
||||
|
||||
raw_probe_alignment(bs);
|
||||
@@ -389,6 +407,13 @@ static BlockDriverAIOCB *raw_aio_flush(BlockDriverState *bs,
|
||||
static void raw_close(BlockDriverState *bs)
|
||||
{
|
||||
BDRVRawState *s = bs->opaque;
|
||||
|
||||
if (s->aio) {
|
||||
win32_aio_detach_aio_context(s->aio, bdrv_get_aio_context(bs));
|
||||
win32_aio_cleanup(s->aio);
|
||||
s->aio = NULL;
|
||||
}
|
||||
|
||||
CloseHandle(s->hfile);
|
||||
if (bs->open_flags & BDRV_O_TEMPORARY) {
|
||||
unlink(bs->filename);
|
||||
@@ -684,6 +709,9 @@ static BlockDriver bdrv_host_device = {
|
||||
.bdrv_aio_writev = raw_aio_writev,
|
||||
.bdrv_aio_flush = raw_aio_flush,
|
||||
|
||||
.bdrv_detach_aio_context = raw_detach_aio_context,
|
||||
.bdrv_attach_aio_context = raw_attach_aio_context,
|
||||
|
||||
.bdrv_getlength = raw_getlength,
|
||||
.has_variable_length = true,
|
||||
|
||||
|
||||
+7
-3
@@ -555,7 +555,7 @@ static void qemu_rbd_aio_cancel(BlockDriverAIOCB *blockacb)
|
||||
acb->cancelled = 1;
|
||||
|
||||
while (acb->status == -EINPROGRESS) {
|
||||
qemu_aio_wait();
|
||||
aio_poll(bdrv_get_aio_context(acb->common.bs), true);
|
||||
}
|
||||
|
||||
qemu_aio_release(acb);
|
||||
@@ -588,7 +588,8 @@ static void rbd_finish_aiocb(rbd_completion_t c, RADOSCB *rcb)
|
||||
rcb->ret = rbd_aio_get_return_value(c);
|
||||
rbd_aio_release(c);
|
||||
|
||||
acb->bh = qemu_bh_new(rbd_finish_bh, rcb);
|
||||
acb->bh = aio_bh_new(bdrv_get_aio_context(acb->common.bs),
|
||||
rbd_finish_bh, rcb);
|
||||
qemu_bh_schedule(acb->bh);
|
||||
}
|
||||
|
||||
@@ -684,13 +685,16 @@ static BlockDriverAIOCB *rbd_start_aio(BlockDriverState *bs,
|
||||
}
|
||||
|
||||
if (r < 0) {
|
||||
goto failed;
|
||||
goto failed_completion;
|
||||
}
|
||||
|
||||
return &acb->common;
|
||||
|
||||
failed_completion:
|
||||
rbd_aio_release(c);
|
||||
failed:
|
||||
g_free(rcb);
|
||||
qemu_vfree(acb->bounce);
|
||||
qemu_aio_release(acb);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user