[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PULL 06/44] block: Emulate bdrv_ioctl with bdrv_aio_ioctl
From: |
Stefan Hajnoczi |
Subject: |
[Qemu-devel] [PULL 06/44] block: Emulate bdrv_ioctl with bdrv_aio_ioctl and track both |
Date: |
Tue, 10 Nov 2015 14:14:01 +0000 |
From: Fam Zheng <address@hidden>
Currently all drivers that support .bdrv_aio_ioctl also implement
.bdrv_ioctl redundantly. To track ioctl requests in block layer it is
easier if we unify the two paths, because we'll need to run it in a
coroutine, as required by tracked_request_begin. While we're at it, use
.bdrv_aio_ioctl plus aio_poll() to emulate bdrv_ioctl().
Signed-off-by: Fam Zheng <address@hidden>
Message-id: address@hidden
Signed-off-by: Stefan Hajnoczi <address@hidden>
---
block/io.c | 101 +++++++++++++++++++++++++++++++++++++++++++++++++++++++------
1 file changed, 92 insertions(+), 9 deletions(-)
diff --git a/block/io.c b/block/io.c
index 324ae5a..4ecb171 100644
--- a/block/io.c
+++ b/block/io.c
@@ -2528,26 +2528,109 @@ int bdrv_discard(BlockDriverState *bs, int64_t
sector_num, int nb_sectors)
return rwco.ret;
}
+typedef struct {
+ CoroutineIOCompletion *co;
+ QEMUBH *bh;
+} BdrvIoctlCompletionData;
+
+static void bdrv_ioctl_bh_cb(void *opaque)
+{
+ BdrvIoctlCompletionData *data = opaque;
+
+ bdrv_co_io_em_complete(data->co, -ENOTSUP);
+ qemu_bh_delete(data->bh);
+}
+
+static int bdrv_co_do_ioctl(BlockDriverState *bs, int req, void *buf)
+{
+ BlockDriver *drv = bs->drv;
+ BdrvTrackedRequest tracked_req;
+ CoroutineIOCompletion co = {
+ .coroutine = qemu_coroutine_self(),
+ };
+ BlockAIOCB *acb;
+
+ tracked_request_begin(&tracked_req, bs, 0, 0, BDRV_TRACKED_IOCTL);
+ if (!drv || !drv->bdrv_aio_ioctl) {
+ co.ret = -ENOTSUP;
+ goto out;
+ }
+
+ acb = drv->bdrv_aio_ioctl(bs, req, buf, bdrv_co_io_em_complete, &co);
+ if (!acb) {
+ BdrvIoctlCompletionData *data = g_new(BdrvIoctlCompletionData, 1);
+ data->bh = aio_bh_new(bdrv_get_aio_context(bs),
+ bdrv_ioctl_bh_cb, data);
+ data->co = &co;
+ qemu_bh_schedule(data->bh);
+ }
+ qemu_coroutine_yield();
+out:
+ tracked_request_end(&tracked_req);
+ return co.ret;
+}
+
+typedef struct {
+ BlockDriverState *bs;
+ int req;
+ void *buf;
+ int ret;
+} BdrvIoctlCoData;
+
+static void coroutine_fn bdrv_co_ioctl_entry(void *opaque)
+{
+ BdrvIoctlCoData *data = opaque;
+ data->ret = bdrv_co_do_ioctl(data->bs, data->req, data->buf);
+}
+
/* needed for generic scsi interface */
-
int bdrv_ioctl(BlockDriverState *bs, unsigned long int req, void *buf)
{
- BlockDriver *drv = bs->drv;
+ BdrvIoctlCoData data = {
+ .bs = bs,
+ .req = req,
+ .buf = buf,
+ .ret = -EINPROGRESS,
+ };
- if (drv && drv->bdrv_ioctl)
- return drv->bdrv_ioctl(bs, req, buf);
- return -ENOTSUP;
+ if (qemu_in_coroutine()) {
+ /* Fast-path if already in coroutine context */
+ bdrv_co_ioctl_entry(&data);
+ } else {
+ Coroutine *co = qemu_coroutine_create(bdrv_co_ioctl_entry);
+ qemu_coroutine_enter(co, &data);
+ }
+ while (data.ret == -EINPROGRESS) {
+ aio_poll(bdrv_get_aio_context(bs), true);
+ }
+ return data.ret;
+}
+
+static void coroutine_fn bdrv_co_aio_ioctl_entry(void *opaque)
+{
+ BlockAIOCBCoroutine *acb = opaque;
+ acb->req.error = bdrv_co_do_ioctl(acb->common.bs,
+ acb->req.req, acb->req.buf);
+ bdrv_co_complete(acb);
}
BlockAIOCB *bdrv_aio_ioctl(BlockDriverState *bs,
unsigned long int req, void *buf,
BlockCompletionFunc *cb, void *opaque)
{
- BlockDriver *drv = bs->drv;
+ BlockAIOCBCoroutine *acb = qemu_aio_get(&bdrv_em_co_aiocb_info,
+ bs, cb, opaque);
+ Coroutine *co;
- if (drv && drv->bdrv_aio_ioctl)
- return drv->bdrv_aio_ioctl(bs, req, buf, cb, opaque);
- return NULL;
+ acb->need_bh = true;
+ acb->req.error = -EINPROGRESS;
+ acb->req.req = req;
+ acb->req.buf = buf;
+ co = qemu_coroutine_create(bdrv_co_aio_ioctl_entry);
+ qemu_coroutine_enter(co, acb);
+
+ bdrv_co_maybe_schedule_bh(acb);
+ return &acb->common;
}
void *qemu_blockalign(BlockDriverState *bs, size_t size)
--
2.5.0
- [Qemu-devel] [PULL 00/44] Block patches, Stefan Hajnoczi, 2015/11/10
- [Qemu-devel] [PULL 01/44] block: Add more types for tracked request, Stefan Hajnoczi, 2015/11/10
- [Qemu-devel] [PULL 04/44] iscsi: Emulate commands in iscsi_aio_ioctl as iscsi_ioctl, Stefan Hajnoczi, 2015/11/10
- [Qemu-devel] [PULL 02/44] block: Track flush requests, Stefan Hajnoczi, 2015/11/10
- [Qemu-devel] [PULL 03/44] block: Track discard requests, Stefan Hajnoczi, 2015/11/10
- [Qemu-devel] [PULL 05/44] block: Add ioctl parameter fields to BlockRequest, Stefan Hajnoczi, 2015/11/10
- [Qemu-devel] [PULL 06/44] block: Emulate bdrv_ioctl with bdrv_aio_ioctl and track both,
Stefan Hajnoczi <=
- [Qemu-devel] [PULL 09/44] qed: Implement .bdrv_drain, Stefan Hajnoczi, 2015/11/10
- [Qemu-devel] [PULL 07/44] block: Drop BlockDriver.bdrv_ioctl, Stefan Hajnoczi, 2015/11/10
- [Qemu-devel] [PULL 08/44] block: Introduce BlockDriver.bdrv_drain callback, Stefan Hajnoczi, 2015/11/10
- [Qemu-devel] [PULL 10/44] qapi: Add transaction support to block-dirty-bitmap operations, Stefan Hajnoczi, 2015/11/10
- [Qemu-devel] [PULL 11/44] iotests: add transactional incremental backup test, Stefan Hajnoczi, 2015/11/10
- [Qemu-devel] [PULL 13/44] backup: Extract dirty bitmap handling as a separate function, Stefan Hajnoczi, 2015/11/10
- [Qemu-devel] [PULL 12/44] block: rename BlkTransactionState and BdrvActionOps, Stefan Hajnoczi, 2015/11/10
- [Qemu-devel] [PULL 14/44] blockjob: Introduce reference count and fix reference to job->bs, Stefan Hajnoczi, 2015/11/10
- [Qemu-devel] [PULL 16/44] blockjob: Add "completed" and "ret" in BlockJob, Stefan Hajnoczi, 2015/11/10
- [Qemu-devel] [PULL 18/44] block: Add block job transactions, Stefan Hajnoczi, 2015/11/10