So that NBD export cannot submit IO during bdrv_drain_all(). Signed-off-by: Fam Zheng <f...@redhat.com> --- nbd.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+)
diff --git a/nbd.c b/nbd.c index 06b501b..b5026af 100644 --- a/nbd.c +++ b/nbd.c @@ -160,6 +160,8 @@ struct NBDExport { uint32_t nbdflags; QTAILQ_HEAD(, NBDClient) clients; QTAILQ_ENTRY(NBDExport) next; + Notifier blocker_notifier; + bool io_blocked; AioContext *ctx; }; @@ -1053,6 +1055,22 @@ static void blk_aio_detach(void *opaque) exp->ctx = NULL; } +static void nbd_op_blocker_changed(Notifier *notifier, void *data) +{ + BlockOpEvent *event = data; + NBDClient *client; + NBDExport *exp = container_of(notifier, NBDExport, blocker_notifier); + + if (event->type != BLOCK_OP_TYPE_DEVICE_IO) { + return; + } + exp->io_blocked = event->blocking; + + QTAILQ_FOREACH(client, &exp->clients, next) { + nbd_update_can_read(client); + } +} + NBDExport *nbd_export_new(BlockBackend *blk, off_t dev_offset, off_t size, uint32_t nbdflags, void (*close)(NBDExport *), Error **errp) @@ -1081,6 +1099,8 @@ NBDExport *nbd_export_new(BlockBackend *blk, off_t dev_offset, off_t size, * access since the export could be available before migration handover. */ blk_invalidate_cache(blk, NULL); + exp->blocker_notifier.notify = nbd_op_blocker_changed; + blk_op_blocker_add_notifier(blk, &exp->blocker_notifier); return exp; fail: @@ -1132,6 +1152,7 @@ void nbd_export_close(NBDExport *exp) nbd_export_set_name(exp, NULL); nbd_export_put(exp); if (exp->blk) { + notifier_remove(&exp->blocker_notifier); blk_remove_aio_context_notifier(exp->blk, blk_aio_attached, blk_aio_detach, exp); blk_unref(exp->blk); @@ -1455,6 +1476,9 @@ static void nbd_update_can_read(NBDClient *client) bool can_read = client->recv_coroutine || client->nb_requests < MAX_NBD_REQUESTS; + if (client->exp && client->exp->io_blocked) { + can_read = false; + } if (can_read != client->can_read) { client->can_read = can_read; nbd_set_handlers(client); -- 2.4.1