All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH v3 0/9] block: Fixes for bdrv_drain
@ 2015-11-09  2:56 Fam Zheng
  2015-11-09  2:56 ` [Qemu-devel] [PATCH v3 1/9] block: Add more types for tracked request Fam Zheng
                   ` (9 more replies)
  0 siblings, 10 replies; 14+ messages in thread
From: Fam Zheng @ 2015-11-09  2:56 UTC (permalink / raw)
  To: qemu-devel
  Cc: Kevin Wolf, Stefan Hajnoczi, qemu-block, Peter Lieven,
	Ronnie Sahlberg, Paolo Bonzini

v3: Don't reuse coroutine in bdrv_aio_ioctl. [Stefan]
    Recursely call .bdrv_drain callback only. [Stefan, Paolo]
    Added Kevin's reviewed-by in other patches.

v2: Add Kevin's reviewed-by in patches 1, 2, 5-7, 9.
    Address Kevin's reviewing comments which are:
    - Explicit "ret = 0" before out label in patch 3.
    - Add missing qemu_aio_unref() in patch 4.
    - Recurse into all children in bdrv_drain in patch 8.

Previously bdrv_drain and bdrv_drain_all don't handle ioctl, flush and discard
requests (which are fundamentally the same as read and write requests that
change disk state).  Forgetting such requests leaves us in risk of violating
the invariant that bdrv_drain() callers rely on - all asynchronous requests
must have completed after bdrv_drain returns.

Enrich the tracked request types, and add tracked_request_begin/end pairs to
all three code paths. As a prerequisite, ioctl code is moved into coroutine
too.

The last two patches take care of QED's "need check" timer, so that after
bdrv_drain returns, the driver is in a consistent state.

Fam


Fam Zheng (9):
  block: Add more types for tracked request
  block: Track flush requests
  block: Track discard requests
  iscsi: Emulate commands in iscsi_aio_ioctl as iscsi_ioctl
  block: Add ioctl parameter fields to BlockRequest
  block: Emulate bdrv_ioctl with bdrv_aio_ioctl and track both
  block: Drop BlockDriver.bdrv_ioctl
  block: Introduce BlockDriver.bdrv_drain callback
  qed: Implement .bdrv_drain

 block/io.c                | 147 +++++++++++++++++++++++++++++++++++++++-------
 block/iscsi.c             |  73 ++++++++++++-----------
 block/qed.c               |  13 ++++
 block/raw-posix.c         |   8 ---
 block/raw_bsd.c           |   6 --
 include/block/block.h     |  16 +++--
 include/block/block_int.h |  17 +++++-
 7 files changed, 205 insertions(+), 75 deletions(-)

-- 
2.4.3

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [Qemu-devel] [PATCH v3 1/9] block: Add more types for tracked request
  2015-11-09  2:56 [Qemu-devel] [PATCH v3 0/9] block: Fixes for bdrv_drain Fam Zheng
@ 2015-11-09  2:56 ` Fam Zheng
  2015-11-09  2:56 ` [Qemu-devel] [PATCH v3 2/9] block: Track flush requests Fam Zheng
                   ` (8 subsequent siblings)
  9 siblings, 0 replies; 14+ messages in thread
From: Fam Zheng @ 2015-11-09  2:56 UTC (permalink / raw)
  To: qemu-devel
  Cc: Kevin Wolf, Stefan Hajnoczi, qemu-block, Peter Lieven,
	Ronnie Sahlberg, Paolo Bonzini

We'll track more request types besides read and write, change the
boolean field to an enum.

Signed-off-by: Fam Zheng <famz@redhat.com>
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
---
 block/io.c                |  9 +++++----
 include/block/block_int.h | 10 +++++++++-
 2 files changed, 14 insertions(+), 5 deletions(-)

diff --git a/block/io.c b/block/io.c
index 8dcad3b..793809a 100644
--- a/block/io.c
+++ b/block/io.c
@@ -348,13 +348,14 @@ static void tracked_request_end(BdrvTrackedRequest *req)
 static void tracked_request_begin(BdrvTrackedRequest *req,
                                   BlockDriverState *bs,
                                   int64_t offset,
-                                  unsigned int bytes, bool is_write)
+                                  unsigned int bytes,
+                                  enum BdrvTrackedRequestType type)
 {
     *req = (BdrvTrackedRequest){
         .bs = bs,
         .offset         = offset,
         .bytes          = bytes,
-        .is_write       = is_write,
+        .type           = type,
         .co             = qemu_coroutine_self(),
         .serialising    = false,
         .overlap_offset = offset,
@@ -971,7 +972,7 @@ static int coroutine_fn bdrv_co_do_preadv(BlockDriverState *bs,
         bytes = ROUND_UP(bytes, align);
     }
 
-    tracked_request_begin(&req, bs, offset, bytes, false);
+    tracked_request_begin(&req, bs, offset, bytes, BDRV_TRACKED_READ);
     ret = bdrv_aligned_preadv(bs, &req, offset, bytes, align,
                               use_local_qiov ? &local_qiov : qiov,
                               flags);
@@ -1292,7 +1293,7 @@ static int coroutine_fn bdrv_co_do_pwritev(BlockDriverState *bs,
      * Pad qiov with the read parts and be sure to have a tracked request not
      * only for bdrv_aligned_pwritev, but also for the reads of the RMW cycle.
      */
-    tracked_request_begin(&req, bs, offset, bytes, true);
+    tracked_request_begin(&req, bs, offset, bytes, BDRV_TRACKED_WRITE);
 
     if (!qiov) {
         ret = bdrv_co_do_zero_pwritev(bs, offset, bytes, flags, &req);
diff --git a/include/block/block_int.h b/include/block/block_int.h
index 3ceeb5a..7db9900 100644
--- a/include/block/block_int.h
+++ b/include/block/block_int.h
@@ -60,11 +60,19 @@
 
 #define BLOCK_PROBE_BUF_SIZE        512
 
+enum BdrvTrackedRequestType {
+    BDRV_TRACKED_READ,
+    BDRV_TRACKED_WRITE,
+    BDRV_TRACKED_FLUSH,
+    BDRV_TRACKED_IOCTL,
+    BDRV_TRACKED_DISCARD,
+};
+
 typedef struct BdrvTrackedRequest {
     BlockDriverState *bs;
     int64_t offset;
     unsigned int bytes;
-    bool is_write;
+    enum BdrvTrackedRequestType type;
 
     bool serialising;
     int64_t overlap_offset;
-- 
2.4.3

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [Qemu-devel] [PATCH v3 2/9] block: Track flush requests
  2015-11-09  2:56 [Qemu-devel] [PATCH v3 0/9] block: Fixes for bdrv_drain Fam Zheng
  2015-11-09  2:56 ` [Qemu-devel] [PATCH v3 1/9] block: Add more types for tracked request Fam Zheng
@ 2015-11-09  2:56 ` Fam Zheng
  2015-11-09  2:56 ` [Qemu-devel] [PATCH v3 3/9] block: Track discard requests Fam Zheng
                   ` (7 subsequent siblings)
  9 siblings, 0 replies; 14+ messages in thread
From: Fam Zheng @ 2015-11-09  2:56 UTC (permalink / raw)
  To: qemu-devel
  Cc: Kevin Wolf, Stefan Hajnoczi, qemu-block, Peter Lieven,
	Ronnie Sahlberg, Paolo Bonzini

Both bdrv_flush and bdrv_aio_flush eventually call bdrv_co_flush, add
tracked_request_begin and tracked_request_end pair in that function so
that all flush requests are now tracked.

Signed-off-by: Fam Zheng <famz@redhat.com>
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
---
 block/io.c | 11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/block/io.c b/block/io.c
index 793809a..a9a49e4 100644
--- a/block/io.c
+++ b/block/io.c
@@ -2318,18 +2318,20 @@ static void coroutine_fn bdrv_flush_co_entry(void *opaque)
 int coroutine_fn bdrv_co_flush(BlockDriverState *bs)
 {
     int ret;
+    BdrvTrackedRequest req;
 
     if (!bs || !bdrv_is_inserted(bs) || bdrv_is_read_only(bs) ||
         bdrv_is_sg(bs)) {
         return 0;
     }
 
+    tracked_request_begin(&req, bs, 0, 0, BDRV_TRACKED_FLUSH);
     /* Write back cached data to the OS even with cache=unsafe */
     BLKDBG_EVENT(bs->file, BLKDBG_FLUSH_TO_OS);
     if (bs->drv->bdrv_co_flush_to_os) {
         ret = bs->drv->bdrv_co_flush_to_os(bs);
         if (ret < 0) {
-            return ret;
+            goto out;
         }
     }
 
@@ -2369,14 +2371,17 @@ int coroutine_fn bdrv_co_flush(BlockDriverState *bs)
         ret = 0;
     }
     if (ret < 0) {
-        return ret;
+        goto out;
     }
 
     /* Now flush the underlying protocol.  It will also have BDRV_O_NO_FLUSH
      * in the case of cache=unsafe, so there are no useless flushes.
      */
 flush_parent:
-    return bs->file ? bdrv_co_flush(bs->file->bs) : 0;
+    ret = bs->file ? bdrv_co_flush(bs->file->bs) : 0;
+out:
+    tracked_request_end(&req);
+    return ret;
 }
 
 int bdrv_flush(BlockDriverState *bs)
-- 
2.4.3

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [Qemu-devel] [PATCH v3 3/9] block: Track discard requests
  2015-11-09  2:56 [Qemu-devel] [PATCH v3 0/9] block: Fixes for bdrv_drain Fam Zheng
  2015-11-09  2:56 ` [Qemu-devel] [PATCH v3 1/9] block: Add more types for tracked request Fam Zheng
  2015-11-09  2:56 ` [Qemu-devel] [PATCH v3 2/9] block: Track flush requests Fam Zheng
@ 2015-11-09  2:56 ` Fam Zheng
  2015-11-09  2:56 ` [Qemu-devel] [PATCH v3 4/9] iscsi: Emulate commands in iscsi_aio_ioctl as iscsi_ioctl Fam Zheng
                   ` (6 subsequent siblings)
  9 siblings, 0 replies; 14+ messages in thread
From: Fam Zheng @ 2015-11-09  2:56 UTC (permalink / raw)
  To: qemu-devel
  Cc: Kevin Wolf, Stefan Hajnoczi, qemu-block, Peter Lieven,
	Ronnie Sahlberg, Paolo Bonzini

Both bdrv_discard and bdrv_aio_discard will call into bdrv_co_discard,
so add tracked_request_begin/end calls around the loop.

Signed-off-by: Fam Zheng <famz@redhat.com>
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
---
 block/io.c | 13 ++++++++++---
 1 file changed, 10 insertions(+), 3 deletions(-)

diff --git a/block/io.c b/block/io.c
index a9a49e4..324ae5a 100644
--- a/block/io.c
+++ b/block/io.c
@@ -2424,6 +2424,7 @@ static void coroutine_fn bdrv_discard_co_entry(void *opaque)
 int coroutine_fn bdrv_co_discard(BlockDriverState *bs, int64_t sector_num,
                                  int nb_sectors)
 {
+    BdrvTrackedRequest req;
     int max_discard, ret;
 
     if (!bs->drv) {
@@ -2446,6 +2447,8 @@ int coroutine_fn bdrv_co_discard(BlockDriverState *bs, int64_t sector_num,
         return 0;
     }
 
+    tracked_request_begin(&req, bs, sector_num, nb_sectors,
+                          BDRV_TRACKED_DISCARD);
     bdrv_set_dirty(bs, sector_num, nb_sectors);
 
     max_discard = MIN_NON_ZERO(bs->bl.max_discard, BDRV_REQUEST_MAX_SECTORS);
@@ -2479,20 +2482,24 @@ int coroutine_fn bdrv_co_discard(BlockDriverState *bs, int64_t sector_num,
             acb = bs->drv->bdrv_aio_discard(bs, sector_num, nb_sectors,
                                             bdrv_co_io_em_complete, &co);
             if (acb == NULL) {
-                return -EIO;
+                ret = -EIO;
+                goto out;
             } else {
                 qemu_coroutine_yield();
                 ret = co.ret;
             }
         }
         if (ret && ret != -ENOTSUP) {
-            return ret;
+            goto out;
         }
 
         sector_num += num;
         nb_sectors -= num;
     }
-    return 0;
+    ret = 0;
+out:
+    tracked_request_end(&req);
+    return ret;
 }
 
 int bdrv_discard(BlockDriverState *bs, int64_t sector_num, int nb_sectors)
-- 
2.4.3

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [Qemu-devel] [PATCH v3 4/9] iscsi: Emulate commands in iscsi_aio_ioctl as iscsi_ioctl
  2015-11-09  2:56 [Qemu-devel] [PATCH v3 0/9] block: Fixes for bdrv_drain Fam Zheng
                   ` (2 preceding siblings ...)
  2015-11-09  2:56 ` [Qemu-devel] [PATCH v3 3/9] block: Track discard requests Fam Zheng
@ 2015-11-09  2:56 ` Fam Zheng
  2015-11-09  2:56 ` [Qemu-devel] [PATCH v3 5/9] block: Add ioctl parameter fields to BlockRequest Fam Zheng
                   ` (5 subsequent siblings)
  9 siblings, 0 replies; 14+ messages in thread
From: Fam Zheng @ 2015-11-09  2:56 UTC (permalink / raw)
  To: qemu-devel
  Cc: Kevin Wolf, Stefan Hajnoczi, qemu-block, Peter Lieven,
	Ronnie Sahlberg, Paolo Bonzini

iscsi_ioctl emulates SG_GET_VERSION_NUM and SG_GET_SCSI_ID. Now that
bdrv_ioctl() will be emulated with .bdrv_aio_ioctl, replicate the logic
into iscsi_aio_ioctl to make them consistent.

Signed-off-by: Fam Zheng <famz@redhat.com>
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
---
 block/iscsi.c | 40 ++++++++++++++++++++++++++++++++++++++--
 1 file changed, 38 insertions(+), 2 deletions(-)

diff --git a/block/iscsi.c b/block/iscsi.c
index 9a628b7..b3fa0a0 100644
--- a/block/iscsi.c
+++ b/block/iscsi.c
@@ -96,6 +96,7 @@ typedef struct IscsiAIOCB {
     int status;
     int64_t sector_num;
     int nb_sectors;
+    int ret;
 #ifdef __linux__
     sg_io_hdr_t *ioh;
 #endif
@@ -726,6 +727,38 @@ iscsi_aio_ioctl_cb(struct iscsi_context *iscsi, int status,
     iscsi_schedule_bh(acb);
 }
 
+static void iscsi_ioctl_bh_completion(void *opaque)
+{
+    IscsiAIOCB *acb = opaque;
+
+    qemu_bh_delete(acb->bh);
+    acb->common.cb(acb->common.opaque, acb->ret);
+    qemu_aio_unref(acb);
+}
+
+static void iscsi_ioctl_handle_emulated(IscsiAIOCB *acb, int req, void *buf)
+{
+    BlockDriverState *bs = acb->common.bs;
+    IscsiLun *iscsilun = bs->opaque;
+    int ret = 0;
+
+    switch (req) {
+    case SG_GET_VERSION_NUM:
+        *(int *)buf = 30000;
+        break;
+    case SG_GET_SCSI_ID:
+        ((struct sg_scsi_id *)buf)->scsi_type = iscsilun->type;
+        break;
+    default:
+        ret = -EINVAL;
+    }
+    assert(!acb->bh);
+    acb->bh = aio_bh_new(bdrv_get_aio_context(bs),
+                         iscsi_ioctl_bh_completion, acb);
+    acb->ret = ret;
+    qemu_bh_schedule(acb->bh);
+}
+
 static BlockAIOCB *iscsi_aio_ioctl(BlockDriverState *bs,
         unsigned long int req, void *buf,
         BlockCompletionFunc *cb, void *opaque)
@@ -735,8 +768,6 @@ static BlockAIOCB *iscsi_aio_ioctl(BlockDriverState *bs,
     struct iscsi_data data;
     IscsiAIOCB *acb;
 
-    assert(req == SG_IO);
-
     acb = qemu_aio_get(&iscsi_aiocb_info, bs, cb, opaque);
 
     acb->iscsilun = iscsilun;
@@ -745,6 +776,11 @@ static BlockAIOCB *iscsi_aio_ioctl(BlockDriverState *bs,
     acb->buf         = NULL;
     acb->ioh         = buf;
 
+    if (req != SG_IO) {
+        iscsi_ioctl_handle_emulated(acb, req, buf);
+        return &acb->common;
+    }
+
     acb->task = malloc(sizeof(struct scsi_task));
     if (acb->task == NULL) {
         error_report("iSCSI: Failed to allocate task for scsi command. %s",
-- 
2.4.3

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [Qemu-devel] [PATCH v3 5/9] block: Add ioctl parameter fields to BlockRequest
  2015-11-09  2:56 [Qemu-devel] [PATCH v3 0/9] block: Fixes for bdrv_drain Fam Zheng
                   ` (3 preceding siblings ...)
  2015-11-09  2:56 ` [Qemu-devel] [PATCH v3 4/9] iscsi: Emulate commands in iscsi_aio_ioctl as iscsi_ioctl Fam Zheng
@ 2015-11-09  2:56 ` Fam Zheng
  2015-11-09  2:56 ` [Qemu-devel] [PATCH v3 6/9] block: Emulate bdrv_ioctl with bdrv_aio_ioctl and track both Fam Zheng
                   ` (4 subsequent siblings)
  9 siblings, 0 replies; 14+ messages in thread
From: Fam Zheng @ 2015-11-09  2:56 UTC (permalink / raw)
  To: qemu-devel
  Cc: Kevin Wolf, Stefan Hajnoczi, qemu-block, Peter Lieven,
	Ronnie Sahlberg, Paolo Bonzini

The two fields that will be used by ioctl handling code later are added
as union, because it's used exclusively by ioctl code which dosn't need
the four fields in the other struct of the union.

Signed-off-by: Fam Zheng <famz@redhat.com>
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
---
 include/block/block.h | 16 ++++++++++++----
 1 file changed, 12 insertions(+), 4 deletions(-)

diff --git a/include/block/block.h b/include/block/block.h
index 610db92..c8b40b7 100644
--- a/include/block/block.h
+++ b/include/block/block.h
@@ -335,10 +335,18 @@ void bdrv_aio_cancel_async(BlockAIOCB *acb);
 
 typedef struct BlockRequest {
     /* Fields to be filled by multiwrite caller */
-    int64_t sector;
-    int nb_sectors;
-    int flags;
-    QEMUIOVector *qiov;
+    union {
+        struct {
+            int64_t sector;
+            int nb_sectors;
+            int flags;
+            QEMUIOVector *qiov;
+        };
+        struct {
+            int req;
+            void *buf;
+        };
+    };
     BlockCompletionFunc *cb;
     void *opaque;
 
-- 
2.4.3

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [Qemu-devel] [PATCH v3 6/9] block: Emulate bdrv_ioctl with bdrv_aio_ioctl and track both
  2015-11-09  2:56 [Qemu-devel] [PATCH v3 0/9] block: Fixes for bdrv_drain Fam Zheng
                   ` (4 preceding siblings ...)
  2015-11-09  2:56 ` [Qemu-devel] [PATCH v3 5/9] block: Add ioctl parameter fields to BlockRequest Fam Zheng
@ 2015-11-09  2:56 ` Fam Zheng
  2015-11-09  2:56 ` [Qemu-devel] [PATCH v3 7/9] block: Drop BlockDriver.bdrv_ioctl Fam Zheng
                   ` (3 subsequent siblings)
  9 siblings, 0 replies; 14+ messages in thread
From: Fam Zheng @ 2015-11-09  2:56 UTC (permalink / raw)
  To: qemu-devel
  Cc: Kevin Wolf, Stefan Hajnoczi, qemu-block, Peter Lieven,
	Ronnie Sahlberg, Paolo Bonzini

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 <famz@redhat.com>
---
 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.4.3

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [Qemu-devel] [PATCH v3 7/9] block: Drop BlockDriver.bdrv_ioctl
  2015-11-09  2:56 [Qemu-devel] [PATCH v3 0/9] block: Fixes for bdrv_drain Fam Zheng
                   ` (5 preceding siblings ...)
  2015-11-09  2:56 ` [Qemu-devel] [PATCH v3 6/9] block: Emulate bdrv_ioctl with bdrv_aio_ioctl and track both Fam Zheng
@ 2015-11-09  2:56 ` Fam Zheng
  2015-11-09  2:56 ` [Qemu-devel] [PATCH v3 8/9] block: Introduce BlockDriver.bdrv_drain callback Fam Zheng
                   ` (2 subsequent siblings)
  9 siblings, 0 replies; 14+ messages in thread
From: Fam Zheng @ 2015-11-09  2:56 UTC (permalink / raw)
  To: qemu-devel
  Cc: Kevin Wolf, Stefan Hajnoczi, qemu-block, Peter Lieven,
	Ronnie Sahlberg, Paolo Bonzini

Now the callback is not used any more, drop the field along with all
implementations in block drivers, which are iscsi and raw.

Signed-off-by: Fam Zheng <famz@redhat.com>
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
---
 block/iscsi.c             | 33 ---------------------------------
 block/raw-posix.c         |  8 --------
 block/raw_bsd.c           |  6 ------
 include/block/block_int.h |  1 -
 4 files changed, 48 deletions(-)

diff --git a/block/iscsi.c b/block/iscsi.c
index b3fa0a0..002d29b 100644
--- a/block/iscsi.c
+++ b/block/iscsi.c
@@ -845,38 +845,6 @@ static BlockAIOCB *iscsi_aio_ioctl(BlockDriverState *bs,
     return &acb->common;
 }
 
-static void ioctl_cb(void *opaque, int status)
-{
-    int *p_status = opaque;
-    *p_status = status;
-}
-
-static int iscsi_ioctl(BlockDriverState *bs, unsigned long int req, void *buf)
-{
-    IscsiLun *iscsilun = bs->opaque;
-    int status;
-
-    switch (req) {
-    case SG_GET_VERSION_NUM:
-        *(int *)buf = 30000;
-        break;
-    case SG_GET_SCSI_ID:
-        ((struct sg_scsi_id *)buf)->scsi_type = iscsilun->type;
-        break;
-    case SG_IO:
-        status = -EINPROGRESS;
-        iscsi_aio_ioctl(bs, req, buf, ioctl_cb, &status);
-
-        while (status == -EINPROGRESS) {
-            aio_poll(iscsilun->aio_context, true);
-        }
-
-        return 0;
-    default:
-        return -1;
-    }
-    return 0;
-}
 #endif
 
 static int64_t
@@ -1807,7 +1775,6 @@ static BlockDriver bdrv_iscsi = {
     .bdrv_co_flush_to_disk = iscsi_co_flush,
 
 #ifdef __linux__
-    .bdrv_ioctl       = iscsi_ioctl,
     .bdrv_aio_ioctl   = iscsi_aio_ioctl,
 #endif
 
diff --git a/block/raw-posix.c b/block/raw-posix.c
index 918c756..aec9ec6 100644
--- a/block/raw-posix.c
+++ b/block/raw-posix.c
@@ -2175,12 +2175,6 @@ static int hdev_open(BlockDriverState *bs, QDict *options, int flags,
 }
 
 #if defined(__linux__)
-static int hdev_ioctl(BlockDriverState *bs, unsigned long int req, void *buf)
-{
-    BDRVRawState *s = bs->opaque;
-
-    return ioctl(s->fd, req, buf);
-}
 
 static BlockAIOCB *hdev_aio_ioctl(BlockDriverState *bs,
         unsigned long int req, void *buf,
@@ -2338,7 +2332,6 @@ static BlockDriver bdrv_host_device = {
 
     /* generic scsi device */
 #ifdef __linux__
-    .bdrv_ioctl         = hdev_ioctl,
     .bdrv_aio_ioctl     = hdev_aio_ioctl,
 #endif
 };
@@ -2471,7 +2464,6 @@ static BlockDriver bdrv_host_cdrom = {
     .bdrv_lock_medium   = cdrom_lock_medium,
 
     /* generic scsi device */
-    .bdrv_ioctl         = hdev_ioctl,
     .bdrv_aio_ioctl     = hdev_aio_ioctl,
 };
 #endif /* __linux__ */
diff --git a/block/raw_bsd.c b/block/raw_bsd.c
index 0aded31..915d6fd 100644
--- a/block/raw_bsd.c
+++ b/block/raw_bsd.c
@@ -169,11 +169,6 @@ static void raw_lock_medium(BlockDriverState *bs, bool locked)
     bdrv_lock_medium(bs->file->bs, locked);
 }
 
-static int raw_ioctl(BlockDriverState *bs, unsigned long int req, void *buf)
-{
-    return bdrv_ioctl(bs->file->bs, req, buf);
-}
-
 static BlockAIOCB *raw_aio_ioctl(BlockDriverState *bs,
                                  unsigned long int req, void *buf,
                                  BlockCompletionFunc *cb,
@@ -262,7 +257,6 @@ BlockDriver bdrv_raw = {
     .bdrv_media_changed   = &raw_media_changed,
     .bdrv_eject           = &raw_eject,
     .bdrv_lock_medium     = &raw_lock_medium,
-    .bdrv_ioctl           = &raw_ioctl,
     .bdrv_aio_ioctl       = &raw_aio_ioctl,
     .create_opts          = &raw_create_opts,
     .bdrv_has_zero_init   = &raw_has_zero_init
diff --git a/include/block/block_int.h b/include/block/block_int.h
index 7db9900..550ce18 100644
--- a/include/block/block_int.h
+++ b/include/block/block_int.h
@@ -227,7 +227,6 @@ struct BlockDriver {
     void (*bdrv_lock_medium)(BlockDriverState *bs, bool locked);
 
     /* to control generic scsi devices */
-    int (*bdrv_ioctl)(BlockDriverState *bs, unsigned long int req, void *buf);
     BlockAIOCB *(*bdrv_aio_ioctl)(BlockDriverState *bs,
         unsigned long int req, void *buf,
         BlockCompletionFunc *cb, void *opaque);
-- 
2.4.3

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [Qemu-devel] [PATCH v3 8/9] block: Introduce BlockDriver.bdrv_drain callback
  2015-11-09  2:56 [Qemu-devel] [PATCH v3 0/9] block: Fixes for bdrv_drain Fam Zheng
                   ` (6 preceding siblings ...)
  2015-11-09  2:56 ` [Qemu-devel] [PATCH v3 7/9] block: Drop BlockDriver.bdrv_ioctl Fam Zheng
@ 2015-11-09  2:56 ` Fam Zheng
  2015-11-09  9:24   ` Paolo Bonzini
  2015-11-09  2:56 ` [Qemu-devel] [PATCH v3 9/9] qed: Implement .bdrv_drain Fam Zheng
  2015-11-09 11:42 ` [Qemu-devel] [PATCH v3 0/9] block: Fixes for bdrv_drain Stefan Hajnoczi
  9 siblings, 1 reply; 14+ messages in thread
From: Fam Zheng @ 2015-11-09  2:56 UTC (permalink / raw)
  To: qemu-devel
  Cc: Kevin Wolf, Stefan Hajnoczi, qemu-block, Peter Lieven,
	Ronnie Sahlberg, Paolo Bonzini

Drivers can have internal request sources that generate IO, like the
need_check_timer in QED. Since we want quiesced periods that contain
nested event loops in block layer, we need to have a way to disable such
event sources.

Block drivers must implement the "bdrv_drain" callback if it has any
internal sources that can generate I/O activity, like a timer or a
worker thread (even in a library) that can schedule QEMUBH in an
asynchronous callback.

Update the comments of bdrv_drain and bdrv_drained_begin accordingly.

Like bdrv_requests_pending(), we should consider all the children of bs.
Before, the while loop just works, as bdrv_requests_pending() already
tracks its children; now we mustn't miss the callback, so recurse down
explicitly.

Signed-off-by: Fam Zheng <famz@redhat.com>
---
 block/io.c                | 13 ++++++++++++-
 include/block/block_int.h |  6 ++++++
 2 files changed, 18 insertions(+), 1 deletion(-)

diff --git a/block/io.c b/block/io.c
index 4ecb171..136849c 100644
--- a/block/io.c
+++ b/block/io.c
@@ -238,7 +238,8 @@ bool bdrv_requests_pending(BlockDriverState *bs)
 }
 
 /*
- * Wait for pending requests to complete on a single BlockDriverState subtree
+ * Wait for pending requests to complete on a single BlockDriverState subtree,
+ * and suspend block driver's internal I/O until next request arrives.
  *
  * Note that unlike bdrv_drain_all(), the caller must hold the BlockDriverState
  * AioContext.
@@ -249,8 +250,18 @@ bool bdrv_requests_pending(BlockDriverState *bs)
  */
 void bdrv_drain(BlockDriverState *bs)
 {
+    BdrvChild *child;
     bool busy = true;
 
+    if (bs->drv && bs->drv->bdrv_drain) {
+        bs->drv->bdrv_drain(bs);
+    }
+    QLIST_FOREACH(child, &bs->children, next) {
+        BlockDriverState *cbs = child->bs;
+        if (cbs->drv && cbs->drv->bdrv_drain) {
+            cbs->drv->bdrv_drain(bs);
+        }
+    }
     while (busy) {
         /* Keep iterating */
          bdrv_flush_io_queue(bs);
diff --git a/include/block/block_int.h b/include/block/block_int.h
index 550ce18..4a9f8ff 100644
--- a/include/block/block_int.h
+++ b/include/block/block_int.h
@@ -295,6 +295,12 @@ struct BlockDriver {
      */
     int (*bdrv_probe_geometry)(BlockDriverState *bs, HDGeometry *geo);
 
+    /**
+     * Drain and stop any internal sources of requests in the driver, and
+     * remain so until next I/O callback (e.g. bdrv_co_writev) is called.
+     */
+    void (*bdrv_drain)(BlockDriverState *bs);
+
     QLIST_ENTRY(BlockDriver) list;
 };
 
-- 
2.4.3

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [Qemu-devel] [PATCH v3 9/9] qed: Implement .bdrv_drain
  2015-11-09  2:56 [Qemu-devel] [PATCH v3 0/9] block: Fixes for bdrv_drain Fam Zheng
                   ` (7 preceding siblings ...)
  2015-11-09  2:56 ` [Qemu-devel] [PATCH v3 8/9] block: Introduce BlockDriver.bdrv_drain callback Fam Zheng
@ 2015-11-09  2:56 ` Fam Zheng
  2015-11-09 11:42 ` [Qemu-devel] [PATCH v3 0/9] block: Fixes for bdrv_drain Stefan Hajnoczi
  9 siblings, 0 replies; 14+ messages in thread
From: Fam Zheng @ 2015-11-09  2:56 UTC (permalink / raw)
  To: qemu-devel
  Cc: Kevin Wolf, Stefan Hajnoczi, qemu-block, Peter Lieven,
	Ronnie Sahlberg, Paolo Bonzini

The "need_check_timer" is used to clear the "NEED_CHECK" flag in the
image header after a grace period once metadata update has finished. In
compliance to the bdrv_drain semantics we should make sure it remains
deleted once .bdrv_drain is called.

We cannot reuse qed_need_check_timer_cb because here it doesn't satisfy
the assertion.  Do the "plug" and "flush" calls manually.

Signed-off-by: Fam Zheng <famz@redhat.com>
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
---
 block/qed.c | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/block/qed.c b/block/qed.c
index 5ea05d4..9b88895 100644
--- a/block/qed.c
+++ b/block/qed.c
@@ -375,6 +375,18 @@ static void bdrv_qed_attach_aio_context(BlockDriverState *bs,
     }
 }
 
+static void bdrv_qed_drain(BlockDriverState *bs)
+{
+    BDRVQEDState *s = bs->opaque;
+
+    /* Cancel timer and start doing I/O that were meant to happen as if it
+     * fired, that way we get bdrv_drain() taking care of the ongoing requests
+     * correctly. */
+    qed_cancel_need_check_timer(s);
+    qed_plug_allocating_write_reqs(s);
+    bdrv_aio_flush(s->bs, qed_clear_need_check, s);
+}
+
 static int bdrv_qed_open(BlockDriverState *bs, QDict *options, int flags,
                          Error **errp)
 {
@@ -1676,6 +1688,7 @@ static BlockDriver bdrv_qed = {
     .bdrv_check               = bdrv_qed_check,
     .bdrv_detach_aio_context  = bdrv_qed_detach_aio_context,
     .bdrv_attach_aio_context  = bdrv_qed_attach_aio_context,
+    .bdrv_drain               = bdrv_qed_drain,
 };
 
 static void bdrv_qed_init(void)
-- 
2.4.3

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: [Qemu-devel] [PATCH v3 8/9] block: Introduce BlockDriver.bdrv_drain callback
  2015-11-09  2:56 ` [Qemu-devel] [PATCH v3 8/9] block: Introduce BlockDriver.bdrv_drain callback Fam Zheng
@ 2015-11-09  9:24   ` Paolo Bonzini
  2015-11-09  9:38     ` Fam Zheng
  0 siblings, 1 reply; 14+ messages in thread
From: Paolo Bonzini @ 2015-11-09  9:24 UTC (permalink / raw)
  To: Fam Zheng, qemu-devel
  Cc: Kevin Wolf, Ronnie Sahlberg, Peter Lieven, qemu-block, Stefan Hajnoczi



On 09/11/2015 03:56, Fam Zheng wrote:
> +    if (bs->drv && bs->drv->bdrv_drain) {
> +        bs->drv->bdrv_drain(bs);
> +    }
> +    QLIST_FOREACH(child, &bs->children, next) {
> +        BlockDriverState *cbs = child->bs;
> +        if (cbs->drv && cbs->drv->bdrv_drain) {
> +            cbs->drv->bdrv_drain(bs);
> +        }
> +    }

I think this is not enough, because the children could have children as
well.

Perhaps you can do it like bdrv_flush: one function does the call to
bdrv_drain and the recursion on children; bdrv_drain calls that one
function and then does the "while (busy)" loop.

Paolo

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [Qemu-devel] [PATCH v3 8/9] block: Introduce BlockDriver.bdrv_drain callback
  2015-11-09  9:24   ` Paolo Bonzini
@ 2015-11-09  9:38     ` Fam Zheng
  0 siblings, 0 replies; 14+ messages in thread
From: Fam Zheng @ 2015-11-09  9:38 UTC (permalink / raw)
  To: Paolo Bonzini
  Cc: Kevin Wolf, Stefan Hajnoczi, qemu-block, Peter Lieven,
	qemu-devel, Ronnie Sahlberg

On Mon, 11/09 10:24, Paolo Bonzini wrote:
> 
> 
> On 09/11/2015 03:56, Fam Zheng wrote:
> > +    if (bs->drv && bs->drv->bdrv_drain) {
> > +        bs->drv->bdrv_drain(bs);
> > +    }
> > +    QLIST_FOREACH(child, &bs->children, next) {
> > +        BlockDriverState *cbs = child->bs;
> > +        if (cbs->drv && cbs->drv->bdrv_drain) {
> > +            cbs->drv->bdrv_drain(bs);
> > +        }
> > +    }
> 
> I think this is not enough, because the children could have children as
> well.
> 
> Perhaps you can do it like bdrv_flush: one function does the call to
> bdrv_drain and the recursion on children; bdrv_drain calls that one
> function and then does the "while (busy)" loop.
> 

Right, this function is no longer recursive and only goes to one layer down.

Will fix.

Thanks,

Fam

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [Qemu-devel] [PATCH v3 0/9] block: Fixes for bdrv_drain
  2015-11-09  2:56 [Qemu-devel] [PATCH v3 0/9] block: Fixes for bdrv_drain Fam Zheng
                   ` (8 preceding siblings ...)
  2015-11-09  2:56 ` [Qemu-devel] [PATCH v3 9/9] qed: Implement .bdrv_drain Fam Zheng
@ 2015-11-09 11:42 ` Stefan Hajnoczi
  2015-11-09 13:15   ` Fam Zheng
  9 siblings, 1 reply; 14+ messages in thread
From: Stefan Hajnoczi @ 2015-11-09 11:42 UTC (permalink / raw)
  To: Fam Zheng
  Cc: Kevin Wolf, qemu-block, Peter Lieven, qemu-devel,
	Ronnie Sahlberg, Paolo Bonzini

[-- Attachment #1: Type: text/plain, Size: 459 bytes --]

On Mon, Nov 09, 2015 at 10:56:39AM +0800, Fam Zheng wrote:
> v3: Don't reuse coroutine in bdrv_aio_ioctl. [Stefan]
>     Recursely call .bdrv_drain callback only. [Stefan, Paolo]

I don't understand this change.  I thought you want .bdrv_drain() to be
called on the whole tree, but the latest code seems to call it on the
root and children only.  It doesn't recurse the only the root and first
level of the tree get .bdrv_drain() calls.  Is this intentional?

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 473 bytes --]

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [Qemu-devel] [PATCH v3 0/9] block: Fixes for bdrv_drain
  2015-11-09 11:42 ` [Qemu-devel] [PATCH v3 0/9] block: Fixes for bdrv_drain Stefan Hajnoczi
@ 2015-11-09 13:15   ` Fam Zheng
  0 siblings, 0 replies; 14+ messages in thread
From: Fam Zheng @ 2015-11-09 13:15 UTC (permalink / raw)
  To: Stefan Hajnoczi
  Cc: Kevin Wolf, qemu-block, Peter Lieven, qemu-devel,
	Ronnie Sahlberg, Paolo Bonzini

On Mon, 11/09 11:42, Stefan Hajnoczi wrote:
> On Mon, Nov 09, 2015 at 10:56:39AM +0800, Fam Zheng wrote:
> > v3: Don't reuse coroutine in bdrv_aio_ioctl. [Stefan]
> >     Recursely call .bdrv_drain callback only. [Stefan, Paolo]
> 
> I don't understand this change.  I thought you want .bdrv_drain() to be
> called on the whole tree, but the latest code seems to call it on the
> root and children only.  It doesn't recurse the only the root and first
> level of the tree get .bdrv_drain() calls.  Is this intentional?

Right, v4 posted, please ignore this.

^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2015-11-09 13:15 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-11-09  2:56 [Qemu-devel] [PATCH v3 0/9] block: Fixes for bdrv_drain Fam Zheng
2015-11-09  2:56 ` [Qemu-devel] [PATCH v3 1/9] block: Add more types for tracked request Fam Zheng
2015-11-09  2:56 ` [Qemu-devel] [PATCH v3 2/9] block: Track flush requests Fam Zheng
2015-11-09  2:56 ` [Qemu-devel] [PATCH v3 3/9] block: Track discard requests Fam Zheng
2015-11-09  2:56 ` [Qemu-devel] [PATCH v3 4/9] iscsi: Emulate commands in iscsi_aio_ioctl as iscsi_ioctl Fam Zheng
2015-11-09  2:56 ` [Qemu-devel] [PATCH v3 5/9] block: Add ioctl parameter fields to BlockRequest Fam Zheng
2015-11-09  2:56 ` [Qemu-devel] [PATCH v3 6/9] block: Emulate bdrv_ioctl with bdrv_aio_ioctl and track both Fam Zheng
2015-11-09  2:56 ` [Qemu-devel] [PATCH v3 7/9] block: Drop BlockDriver.bdrv_ioctl Fam Zheng
2015-11-09  2:56 ` [Qemu-devel] [PATCH v3 8/9] block: Introduce BlockDriver.bdrv_drain callback Fam Zheng
2015-11-09  9:24   ` Paolo Bonzini
2015-11-09  9:38     ` Fam Zheng
2015-11-09  2:56 ` [Qemu-devel] [PATCH v3 9/9] qed: Implement .bdrv_drain Fam Zheng
2015-11-09 11:42 ` [Qemu-devel] [PATCH v3 0/9] block: Fixes for bdrv_drain Stefan Hajnoczi
2015-11-09 13:15   ` Fam Zheng

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.