* [Qemu-devel] [PATCH v2 1/9] block: Add more types for tracked request
2015-10-29 2:14 [Qemu-devel] [PATCH v2 0/9] block: Fixes for bdrv_drain Fam Zheng
@ 2015-10-29 2:14 ` Fam Zheng
2015-10-29 2:14 ` [Qemu-devel] [PATCH v2 2/9] block: Track flush requests Fam Zheng
` (8 subsequent siblings)
9 siblings, 0 replies; 14+ messages in thread
From: Fam Zheng @ 2015-10-29 2:14 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 5ac6256..6af26c3 100644
--- a/block/io.c
+++ b/block/io.c
@@ -345,13 +345,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,
@@ -968,7 +969,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);
@@ -1289,7 +1290,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 v2 2/9] block: Track flush requests
2015-10-29 2:14 [Qemu-devel] [PATCH v2 0/9] block: Fixes for bdrv_drain Fam Zheng
2015-10-29 2:14 ` [Qemu-devel] [PATCH v2 1/9] block: Add more types for tracked request Fam Zheng
@ 2015-10-29 2:14 ` Fam Zheng
2015-10-29 2:14 ` [Qemu-devel] [PATCH v2 3/9] block: Track discard requests Fam Zheng
` (7 subsequent siblings)
9 siblings, 0 replies; 14+ messages in thread
From: Fam Zheng @ 2015-10-29 2:14 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 6af26c3..5c1f093 100644
--- a/block/io.c
+++ b/block/io.c
@@ -2315,18 +2315,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;
}
}
@@ -2366,14 +2368,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 v2 3/9] block: Track discard requests
2015-10-29 2:14 [Qemu-devel] [PATCH v2 0/9] block: Fixes for bdrv_drain Fam Zheng
2015-10-29 2:14 ` [Qemu-devel] [PATCH v2 1/9] block: Add more types for tracked request Fam Zheng
2015-10-29 2:14 ` [Qemu-devel] [PATCH v2 2/9] block: Track flush requests Fam Zheng
@ 2015-10-29 2:14 ` Fam Zheng
2015-10-29 2:14 ` [Qemu-devel] [PATCH v2 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-10-29 2:14 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>
---
block/io.c | 13 ++++++++++---
1 file changed, 10 insertions(+), 3 deletions(-)
diff --git a/block/io.c b/block/io.c
index 5c1f093..8d00c01 100644
--- a/block/io.c
+++ b/block/io.c
@@ -2421,6 +2421,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) {
@@ -2443,6 +2444,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);
@@ -2476,20 +2479,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 v2 4/9] iscsi: Emulate commands in iscsi_aio_ioctl as iscsi_ioctl
2015-10-29 2:14 [Qemu-devel] [PATCH v2 0/9] block: Fixes for bdrv_drain Fam Zheng
` (2 preceding siblings ...)
2015-10-29 2:14 ` [Qemu-devel] [PATCH v2 3/9] block: Track discard requests Fam Zheng
@ 2015-10-29 2:14 ` Fam Zheng
2015-10-29 2:14 ` [Qemu-devel] [PATCH v2 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-10-29 2:14 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>
---
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 v2 5/9] block: Add ioctl parameter fields to BlockRequest
2015-10-29 2:14 [Qemu-devel] [PATCH v2 0/9] block: Fixes for bdrv_drain Fam Zheng
` (3 preceding siblings ...)
2015-10-29 2:14 ` [Qemu-devel] [PATCH v2 4/9] iscsi: Emulate commands in iscsi_aio_ioctl as iscsi_ioctl Fam Zheng
@ 2015-10-29 2:14 ` Fam Zheng
2015-10-29 2:14 ` [Qemu-devel] [PATCH v2 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-10-29 2:14 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 v2 6/9] block: Emulate bdrv_ioctl with bdrv_aio_ioctl and track both
2015-10-29 2:14 [Qemu-devel] [PATCH v2 0/9] block: Fixes for bdrv_drain Fam Zheng
` (4 preceding siblings ...)
2015-10-29 2:14 ` [Qemu-devel] [PATCH v2 5/9] block: Add ioctl parameter fields to BlockRequest Fam Zheng
@ 2015-10-29 2:14 ` Fam Zheng
2015-11-05 15:59 ` Stefan Hajnoczi
2015-10-29 2:14 ` [Qemu-devel] [PATCH v2 7/9] block: Drop BlockDriver.bdrv_ioctl Fam Zheng
` (3 subsequent siblings)
9 siblings, 1 reply; 14+ messages in thread
From: Fam Zheng @ 2015-10-29 2:14 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>
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
---
block/io.c | 104 +++++++++++++++++++++++++++++++++++++++++++++++++++++++------
1 file changed, 95 insertions(+), 9 deletions(-)
diff --git a/block/io.c b/block/io.c
index 8d00c01..08d1e38 100644
--- a/block/io.c
+++ b/block/io.c
@@ -2525,26 +2525,112 @@ 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);
+ acb->need_bh = true;
+ acb->req.error = -EINPROGRESS;
+ acb->req.req = req;
+ acb->req.buf = buf;
+ if (qemu_in_coroutine()) {
+ /* Fast-path if already in coroutine context */
+ bdrv_co_aio_ioctl_entry(acb);
+ } else {
+ Coroutine *co = qemu_coroutine_create(bdrv_co_aio_ioctl_entry);
+ qemu_coroutine_enter(co, acb);
+ }
- if (drv && drv->bdrv_aio_ioctl)
- return drv->bdrv_aio_ioctl(bs, req, buf, cb, opaque);
- return NULL;
+ 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
* Re: [Qemu-devel] [PATCH v2 6/9] block: Emulate bdrv_ioctl with bdrv_aio_ioctl and track both
2015-10-29 2:14 ` [Qemu-devel] [PATCH v2 6/9] block: Emulate bdrv_ioctl with bdrv_aio_ioctl and track both Fam Zheng
@ 2015-11-05 15:59 ` Stefan Hajnoczi
0 siblings, 0 replies; 14+ messages in thread
From: Stefan Hajnoczi @ 2015-11-05 15:59 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: 751 bytes --]
On Thu, Oct 29, 2015 at 10:14:23AM +0800, Fam Zheng wrote:
> 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);
> + acb->need_bh = true;
> + acb->req.error = -EINPROGRESS;
> + acb->req.req = req;
> + acb->req.buf = buf;
> + if (qemu_in_coroutine()) {
> + /* Fast-path if already in coroutine context */
> + bdrv_co_aio_ioctl_entry(acb);
This is not how bdrv_aio_*() work. They never use the existing
coroutine and doing so here would be inconsistent.
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 473 bytes --]
^ permalink raw reply [flat|nested] 14+ messages in thread
* [Qemu-devel] [PATCH v2 7/9] block: Drop BlockDriver.bdrv_ioctl
2015-10-29 2:14 [Qemu-devel] [PATCH v2 0/9] block: Fixes for bdrv_drain Fam Zheng
` (5 preceding siblings ...)
2015-10-29 2:14 ` [Qemu-devel] [PATCH v2 6/9] block: Emulate bdrv_ioctl with bdrv_aio_ioctl and track both Fam Zheng
@ 2015-10-29 2:14 ` Fam Zheng
2015-10-29 2:14 ` [Qemu-devel] [PATCH v2 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-10-29 2:14 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 v2 8/9] block: Introduce BlockDriver.bdrv_drain callback
2015-10-29 2:14 [Qemu-devel] [PATCH v2 0/9] block: Fixes for bdrv_drain Fam Zheng
` (6 preceding siblings ...)
2015-10-29 2:14 ` [Qemu-devel] [PATCH v2 7/9] block: Drop BlockDriver.bdrv_ioctl Fam Zheng
@ 2015-10-29 2:14 ` Fam Zheng
2015-11-05 16:35 ` Stefan Hajnoczi
2015-10-29 2:14 ` [Qemu-devel] [PATCH v2 9/9] qed: Implement .bdrv_drain Fam Zheng
2015-11-03 12:19 ` [Qemu-devel] [PATCH v2 0/9] block: Fixes for bdrv_drain Kevin Wolf
9 siblings, 1 reply; 14+ messages in thread
From: Fam Zheng @ 2015-10-29 2:14 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 | 10 +++++++++-
include/block/block_int.h | 6 ++++++
2 files changed, 15 insertions(+), 1 deletion(-)
diff --git a/block/io.c b/block/io.c
index 08d1e38..375674f 100644
--- a/block/io.c
+++ b/block/io.c
@@ -235,7 +235,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.
@@ -246,8 +247,15 @@ 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) {
+ bdrv_drain(child->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
* Re: [Qemu-devel] [PATCH v2 8/9] block: Introduce BlockDriver.bdrv_drain callback
2015-10-29 2:14 ` [Qemu-devel] [PATCH v2 8/9] block: Introduce BlockDriver.bdrv_drain callback Fam Zheng
@ 2015-11-05 16:35 ` Stefan Hajnoczi
2015-11-05 17:11 ` Paolo Bonzini
0 siblings, 1 reply; 14+ messages in thread
From: Stefan Hajnoczi @ 2015-11-05 16:35 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: 580 bytes --]
On Thu, Oct 29, 2015 at 10:14:25AM +0800, Fam Zheng wrote:
> 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) {
> + bdrv_drain(child->bs);
> + }
> while (busy) {
> /* Keep iterating */
> bdrv_flush_io_queue(bs);
Recursing calls aio_poll() once for each BDS node and I think it's not
necessary and could be a performance problem.
Stefan
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 473 bytes --]
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [Qemu-devel] [PATCH v2 8/9] block: Introduce BlockDriver.bdrv_drain callback
2015-11-05 16:35 ` Stefan Hajnoczi
@ 2015-11-05 17:11 ` Paolo Bonzini
0 siblings, 0 replies; 14+ messages in thread
From: Paolo Bonzini @ 2015-11-05 17:11 UTC (permalink / raw)
To: Stefan Hajnoczi, Fam Zheng
Cc: Kevin Wolf, qemu-block, Peter Lieven, qemu-devel, Ronnie Sahlberg
On 05/11/2015 17:35, Stefan Hajnoczi wrote:
>> > 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) {
>> > + bdrv_drain(child->bs);
>> > + }
>> > while (busy) {
>> > /* Keep iterating */
>> > bdrv_flush_io_queue(bs);
> Recursing calls aio_poll() once for each BDS node and I think it's not
> necessary and could be a performance problem.
Indeed, only the call to bs->drv->bdrv_drain should be done recursively.
Paolo
^ permalink raw reply [flat|nested] 14+ messages in thread
* [Qemu-devel] [PATCH v2 9/9] qed: Implement .bdrv_drain
2015-10-29 2:14 [Qemu-devel] [PATCH v2 0/9] block: Fixes for bdrv_drain Fam Zheng
` (7 preceding siblings ...)
2015-10-29 2:14 ` [Qemu-devel] [PATCH v2 8/9] block: Introduce BlockDriver.bdrv_drain callback Fam Zheng
@ 2015-10-29 2:14 ` Fam Zheng
2015-11-03 12:19 ` [Qemu-devel] [PATCH v2 0/9] block: Fixes for bdrv_drain Kevin Wolf
9 siblings, 0 replies; 14+ messages in thread
From: Fam Zheng @ 2015-10-29 2:14 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 v2 0/9] block: Fixes for bdrv_drain
2015-10-29 2:14 [Qemu-devel] [PATCH v2 0/9] block: Fixes for bdrv_drain Fam Zheng
` (8 preceding siblings ...)
2015-10-29 2:14 ` [Qemu-devel] [PATCH v2 9/9] qed: Implement .bdrv_drain Fam Zheng
@ 2015-11-03 12:19 ` Kevin Wolf
9 siblings, 0 replies; 14+ messages in thread
From: Kevin Wolf @ 2015-11-03 12:19 UTC (permalink / raw)
To: Fam Zheng
Cc: Stefan Hajnoczi, qemu-block, Peter Lieven, qemu-devel,
Ronnie Sahlberg, Paolo Bonzini
Am 29.10.2015 um 03:14 hat Fam Zheng geschrieben:
> 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.
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
^ permalink raw reply [flat|nested] 14+ messages in thread