[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-block] [PATCH 2/4] nbd/client: do negotiation in coroutine
From: |
Vladimir Sementsov-Ogievskiy |
Subject: |
[Qemu-block] [PATCH 2/4] nbd/client: do negotiation in coroutine |
Date: |
Mon, 11 Feb 2019 15:55:59 +0300 |
As a first step to non-blocking negotiation, move it to coroutine.
Signed-off-by: Vladimir Sementsov-Ogievskiy <address@hidden>
---
nbd/client.c | 123 +++++++++++++++++++++++++++++++++++++++++++++------
1 file changed, 109 insertions(+), 14 deletions(-)
diff --git a/nbd/client.c b/nbd/client.c
index 10a52ad7d0..2ba2220a4a 100644
--- a/nbd/client.c
+++ b/nbd/client.c
@@ -859,13 +859,14 @@ static int nbd_list_meta_contexts(QIOChannel *ioc,
* 2: server is newstyle, but lacks structured replies
* 3: server is newstyle and set up for structured replies
*/
-static int nbd_start_negotiate(QIOChannel *ioc, QCryptoTLSCreds *tlscreds,
- const char *hostname, QIOChannel **outioc,
- bool structured_reply, bool *zeroes,
- Error **errp)
+static int coroutine_fn nbd_co_start_negotiate(
+ QIOChannel *ioc, QCryptoTLSCreds *tlscreds, const char *hostname,
+ QIOChannel **outioc, bool structured_reply, bool *zeroes, Error **errp)
{
uint64_t magic;
+ assert(qemu_in_coroutine());
+
trace_nbd_start_negotiate(tlscreds, hostname ? hostname : "<null>");
if (zeroes) {
@@ -990,19 +991,20 @@ static int nbd_negotiate_finish_oldstyle(QIOChannel *ioc,
NBDExportInfo *info,
* Returns: negative errno: failure talking to server
* 0: server is connected
*/
-int nbd_receive_negotiate(QIOChannel *ioc, QCryptoTLSCreds *tlscreds,
- const char *hostname, QIOChannel **outioc,
- NBDExportInfo *info, Error **errp)
+static int coroutine_fn nbd_co_receive_negotiate(
+ QIOChannel *ioc, QCryptoTLSCreds *tlscreds, const char *hostname,
+ QIOChannel **outioc, NBDExportInfo *info, Error **errp)
{
int result;
bool zeroes;
bool base_allocation = info->base_allocation;
+ assert(qemu_in_coroutine());
assert(info->name);
trace_nbd_receive_negotiate_name(info->name);
- result = nbd_start_negotiate(ioc, tlscreds, hostname, outioc,
- info->structured_reply, &zeroes, errp);
+ result = nbd_co_start_negotiate(ioc, tlscreds, hostname, outioc,
+ info->structured_reply, &zeroes, errp);
info->structured_reply = false;
info->base_allocation = false;
@@ -1108,9 +1110,9 @@ void nbd_free_export_list(NBDExportInfo *info, int count)
* in @info by the server, or -1 on error. Caller must free @info using
* nbd_free_export_list().
*/
-int nbd_receive_export_list(QIOChannel *ioc, QCryptoTLSCreds *tlscreds,
- const char *hostname, NBDExportInfo **info,
- Error **errp)
+static int coroutine_fn nbd_co_receive_export_list(
+ QIOChannel *ioc, QCryptoTLSCreds *tlscreds, const char *hostname,
+ NBDExportInfo **info, Error **errp)
{
int result;
int count = 0;
@@ -1120,9 +1122,10 @@ int nbd_receive_export_list(QIOChannel *ioc,
QCryptoTLSCreds *tlscreds,
NBDExportInfo *array = NULL;
QIOChannel *sioc = NULL;
+ assert(qemu_in_coroutine());
*info = NULL;
- result = nbd_start_negotiate(ioc, tlscreds, hostname, &sioc, true, NULL,
- errp);
+ result = nbd_co_start_negotiate(ioc, tlscreds, hostname, &sioc, true, NULL,
+ errp);
if (tlscreds && sioc) {
ioc = sioc;
}
@@ -1212,6 +1215,98 @@ int nbd_receive_export_list(QIOChannel *ioc,
QCryptoTLSCreds *tlscreds,
return ret;
}
+typedef struct NbdReceiveNegotiateCo {
+ QIOChannel *ioc;
+ QCryptoTLSCreds *tlscreds;
+ const char *hostname;
+ union {
+ struct {
+ QIOChannel **outioc;
+ NBDExportInfo *info;
+ } negotiate;
+ struct {
+ NBDExportInfo **info;
+ } export_list;
+ };
+ Error **errp;
+ int ret;
+} NbdReceiveNegotiateCo;
+
+static void coroutine_fn nbd_receive_negotiate_entry(void *opaque)
+{
+ NbdReceiveNegotiateCo *s = opaque;
+
+ s->ret = nbd_co_receive_negotiate(s->ioc, s->tlscreds, s->hostname,
+ s->negotiate.outioc, s->negotiate.info,
+ s->errp);
+}
+
+static void coroutine_fn nbd_receive_export_list_entry(void *opaque)
+{
+ NbdReceiveNegotiateCo *s = opaque;
+
+ s->ret = nbd_co_receive_export_list(s->ioc, s->tlscreds, s->hostname,
+ s->export_list.info, s->errp);
+}
+
+static int nbd_receive_common(CoroutineEntry *entry,
+ NbdReceiveNegotiateCo *data)
+{
+ data->ret = -EINPROGRESS;
+
+ if (qemu_in_coroutine()) {
+ entry(data);
+ } else {
+ AioContext *ctx = qio_channel_get_attached_aio_context(data->ioc);
+ bool attach = !ctx;
+
+ if (attach) {
+ ctx = qemu_get_current_aio_context();
+ qio_channel_attach_aio_context(data->ioc, ctx);
+ }
+
+ qemu_aio_coroutine_enter(ctx, qemu_coroutine_create(entry, data));
+ AIO_WAIT_WHILE(ctx, data->ret == -EINPROGRESS);
+
+ if (attach) {
+ qio_channel_detach_aio_context(data->ioc);
+ }
+ }
+
+ return data->ret;
+}
+
+int nbd_receive_negotiate(
+ QIOChannel *ioc, QCryptoTLSCreds *tlscreds, const char *hostname,
+ QIOChannel **outioc, NBDExportInfo *info, Error **errp)
+{
+ NbdReceiveNegotiateCo data = {
+ .ioc = ioc,
+ .tlscreds = tlscreds,
+ .hostname = hostname,
+ .negotiate.outioc = outioc,
+ .negotiate.info = info,
+ .errp = errp,
+ };
+
+ return nbd_receive_common(nbd_receive_negotiate_entry, &data);
+}
+
+int nbd_receive_export_list(
+ QIOChannel *ioc, QCryptoTLSCreds *tlscreds, const char *hostname,
+ NBDExportInfo **info, Error **errp)
+{
+ NbdReceiveNegotiateCo data = {
+ .ioc = ioc,
+ .tlscreds = tlscreds,
+ .hostname = hostname,
+ .export_list.info = info,
+ .errp = errp,
+ };
+
+ return nbd_receive_common(nbd_receive_export_list_entry, &data);
+}
+
#ifdef __linux__
int nbd_init(int fd, QIOChannelSocket *sioc, NBDExportInfo *info,
Error **errp)
--
2.18.0