aboutsummaryrefslogtreecommitdiff
path: root/block.c
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2014-09-23 12:08:55 +0100
committerPeter Maydell <peter.maydell@linaro.org>2014-09-23 12:08:55 +0100
commit380f649e02f9545159dc3158d7c1b2e70c1005e3 (patch)
tree0b78130d8ffe96e3020f0435e4b75d33c74da8b8 /block.c
parent17336812c7906b554765d1b48b7f1f51c5c79702 (diff)
parent52b53c04faab9f7a9879c8dc014930649a3e698d (diff)
downloadqemu-380f649e02f9545159dc3158d7c1b2e70c1005e3.zip
qemu-380f649e02f9545159dc3158d7c1b2e70c1005e3.tar.gz
qemu-380f649e02f9545159dc3158d7c1b2e70c1005e3.tar.bz2
Merge remote-tracking branch 'remotes/stefanha/tags/block-pull-request' into staging
# gpg: Signature made Mon 22 Sep 2014 12:41:59 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: (59 commits) block: Always compile virtio-blk dataplane vring: Better error handling if num is too large virtio: Import virtio_vring.h async: aio_context_new(): Handle event_notifier_init failure block: vhdx - fix reading beyond pointer during image creation block: delete cow block driver block/archipelago: Fix typo in qemu_archipelago_truncate() ahci: Add test_identify case to ahci-test. ahci: Add test_hba_enable to ahci-test. ahci: Add test_hba_spec to ahci-test. ahci: properly shadow the TFD register ahci: add test_pci_enable to ahci-test. ahci: Add test_pci_spec to ahci-test. ahci: MSI capability should be at 0x80, not 0x50. ahci: Adding basic functionality qtest. layout: Add generators for refcount table and blocks fuzz: Add fuzzing functions for entries of refcount table and blocks docs: List all image elements currently supported by the fuzzer qapi/block-core: Add "new" qcow2 options qcow2: Add overlap-check.template option ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'block.c')
-rw-r--r--block.c72
1 files changed, 36 insertions, 36 deletions
diff --git a/block.c b/block.c
index bcd952a..a857913 100644
--- a/block.c
+++ b/block.c
@@ -4640,7 +4640,28 @@ int bdrv_aio_multiwrite(BlockDriverState *bs, BlockRequest *reqs, int num_reqs)
void bdrv_aio_cancel(BlockDriverAIOCB *acb)
{
- acb->aiocb_info->cancel(acb);
+ qemu_aio_ref(acb);
+ bdrv_aio_cancel_async(acb);
+ while (acb->refcnt > 1) {
+ if (acb->aiocb_info->get_aio_context) {
+ aio_poll(acb->aiocb_info->get_aio_context(acb), true);
+ } else if (acb->bs) {
+ aio_poll(bdrv_get_aio_context(acb->bs), true);
+ } else {
+ abort();
+ }
+ }
+ qemu_aio_unref(acb);
+}
+
+/* Async version of aio cancel. The caller is not blocked if the acb implements
+ * cancel_async, otherwise we do nothing and let the request normally complete.
+ * In either case the completion callback must be called. */
+void bdrv_aio_cancel_async(BlockDriverAIOCB *acb)
+{
+ if (acb->aiocb_info->cancel_async) {
+ acb->aiocb_info->cancel_async(acb);
+ }
}
/**************************************************************/
@@ -4656,18 +4677,8 @@ typedef struct BlockDriverAIOCBSync {
int is_write;
} BlockDriverAIOCBSync;
-static void bdrv_aio_cancel_em(BlockDriverAIOCB *blockacb)
-{
- BlockDriverAIOCBSync *acb =
- container_of(blockacb, BlockDriverAIOCBSync, common);
- qemu_bh_delete(acb->bh);
- acb->bh = NULL;
- qemu_aio_release(acb);
-}
-
static const AIOCBInfo bdrv_em_aiocb_info = {
.aiocb_size = sizeof(BlockDriverAIOCBSync),
- .cancel = bdrv_aio_cancel_em,
};
static void bdrv_aio_bh_cb(void *opaque)
@@ -4681,7 +4692,7 @@ static void bdrv_aio_bh_cb(void *opaque)
acb->common.cb(acb->common.opaque, acb->ret);
qemu_bh_delete(acb->bh);
acb->bh = NULL;
- qemu_aio_release(acb);
+ qemu_aio_unref(acb);
}
static BlockDriverAIOCB *bdrv_aio_rw_vector(BlockDriverState *bs,
@@ -4738,22 +4749,8 @@ typedef struct BlockDriverAIOCBCoroutine {
QEMUBH* bh;
} 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) {
- aio_poll(aio_context, true);
- }
-}
-
static const AIOCBInfo bdrv_em_co_aiocb_info = {
.aiocb_size = sizeof(BlockDriverAIOCBCoroutine),
- .cancel = bdrv_aio_co_cancel_em,
};
static void bdrv_co_em_bh(void *opaque)
@@ -4762,12 +4759,8 @@ static void bdrv_co_em_bh(void *opaque)
acb->common.cb(acb->common.opaque, acb->req.error);
- if (acb->done) {
- *acb->done = true;
- }
-
qemu_bh_delete(acb->bh);
- qemu_aio_release(acb);
+ qemu_aio_unref(acb);
}
/* Invoke bdrv_co_do_readv/bdrv_co_do_writev */
@@ -4806,7 +4799,6 @@ static BlockDriverAIOCB *bdrv_co_aio_rw_vector(BlockDriverState *bs,
acb->req.qiov = qiov;
acb->req.flags = flags;
acb->is_write = is_write;
- acb->done = NULL;
co = qemu_coroutine_create(bdrv_co_do_rw);
qemu_coroutine_enter(co, acb);
@@ -4833,7 +4825,6 @@ BlockDriverAIOCB *bdrv_aio_flush(BlockDriverState *bs,
BlockDriverAIOCBCoroutine *acb;
acb = qemu_aio_get(&bdrv_em_co_aiocb_info, bs, cb, opaque);
- acb->done = NULL;
co = qemu_coroutine_create(bdrv_aio_flush_co_entry);
qemu_coroutine_enter(co, acb);
@@ -4863,7 +4854,6 @@ BlockDriverAIOCB *bdrv_aio_discard(BlockDriverState *bs,
acb = qemu_aio_get(&bdrv_em_co_aiocb_info, bs, cb, opaque);
acb->req.sector = sector_num;
acb->req.nb_sectors = nb_sectors;
- acb->done = NULL;
co = qemu_coroutine_create(bdrv_aio_discard_co_entry);
qemu_coroutine_enter(co, acb);
@@ -4891,13 +4881,23 @@ void *qemu_aio_get(const AIOCBInfo *aiocb_info, BlockDriverState *bs,
acb->bs = bs;
acb->cb = cb;
acb->opaque = opaque;
+ acb->refcnt = 1;
return acb;
}
-void qemu_aio_release(void *p)
+void qemu_aio_ref(void *p)
+{
+ BlockDriverAIOCB *acb = p;
+ acb->refcnt++;
+}
+
+void qemu_aio_unref(void *p)
{
BlockDriverAIOCB *acb = p;
- g_slice_free1(acb->aiocb_info->aiocb_size, acb);
+ assert(acb->refcnt > 0);
+ if (--acb->refcnt == 0) {
+ g_slice_free1(acb->aiocb_info->aiocb_size, acb);
+ }
}
/**************************************************************/