From nobody Sat May 4 16:32:28 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=virtuozzo.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1528392288287332.6090923558115; Thu, 7 Jun 2018 10:24:48 -0700 (PDT) Received: from localhost ([::1]:59423 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fQyeV-0007oP-EO for importer@patchew.org; Thu, 07 Jun 2018 13:24:47 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:34203) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fQyUs-0008Ap-8Y for qemu-devel@nongnu.org; Thu, 07 Jun 2018 13:14:53 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fQyUo-00085N-Tl for qemu-devel@nongnu.org; Thu, 07 Jun 2018 13:14:50 -0400 Received: from relay.sw.ru ([195.214.232.25]:52024) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1fQyUo-0007zy-Ca; Thu, 07 Jun 2018 13:14:46 -0400 Received: from msk-vpn.virtuozzo.com ([195.214.232.6] helo=kvm.sw.ru) by relay.sw.ru with esmtp (Exim 4.90_1) (envelope-from ) id 1fQyUk-0007DI-32; Thu, 07 Jun 2018 20:14:42 +0300 From: Vladimir Sementsov-Ogievskiy To: qemu-devel@nongnu.org, qemu-block@nongnu.org Date: Thu, 7 Jun 2018 20:14:31 +0300 Message-Id: <20180607171441.64079-2-vsementsov@virtuozzo.com> X-Mailer: git-send-email 2.11.1 In-Reply-To: <20180607171441.64079-1-vsementsov@virtuozzo.com> References: <20180607171441.64079-1-vsementsov@virtuozzo.com> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x [fuzzy] X-Received-From: 195.214.232.25 Subject: [Qemu-devel] [PATCH v2 01/11] block/nbd-client: split channel errors from export errors X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: kwolf@redhat.com, vsementsov@virtuozzo.com, armbru@redhat.com, mreitz@redhat.com, den@openvz.org, pbonzini@redhat.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" To implement nbd reconnect in further patches, we need to distinguish error codes, returned by nbd server, from channel errors, to reconnect only in the latter case. Signed-off-by: Vladimir Sementsov-Ogievskiy --- block/nbd-client.c | 83 +++++++++++++++++++++++++++++++-------------------= ---- 1 file changed, 47 insertions(+), 36 deletions(-) diff --git a/block/nbd-client.c b/block/nbd-client.c index 8d69eaaa32..9b9a82fef1 100644 --- a/block/nbd-client.c +++ b/block/nbd-client.c @@ -501,11 +501,11 @@ static coroutine_fn int nbd_co_do_receive_one_chunk( */ static coroutine_fn int nbd_co_receive_one_chunk( NBDClientSession *s, uint64_t handle, bool only_structured, - QEMUIOVector *qiov, NBDReply *reply, void **payload, Error **errp) + int *request_ret, QEMUIOVector *qiov, NBDReply *reply, void **payl= oad, + Error **errp) { - int request_ret; int ret =3D nbd_co_do_receive_one_chunk(s, handle, only_structured, - &request_ret, qiov, payload, err= p); + request_ret, qiov, payload, errp= ); =20 if (ret < 0) { s->quit =3D true; @@ -515,7 +515,6 @@ static coroutine_fn int nbd_co_receive_one_chunk( *reply =3D s->reply; } s->reply.handle =3D 0; - ret =3D request_ret; } =20 if (s->read_reply_co) { @@ -527,22 +526,17 @@ static coroutine_fn int nbd_co_receive_one_chunk( =20 typedef struct NBDReplyChunkIter { int ret; - bool fatal; + int request_ret; Error *err; bool done, only_structured; } NBDReplyChunkIter; =20 -static void nbd_iter_error(NBDReplyChunkIter *iter, bool fatal, - int ret, Error **local_err) +static void nbd_iter_channel_error(NBDReplyChunkIter *iter, + int ret, Error **local_err) { assert(ret < 0); =20 - if ((fatal && !iter->fatal) || iter->ret =3D=3D 0) { - if (iter->ret !=3D 0) { - error_free(iter->err); - iter->err =3D NULL; - } - iter->fatal =3D fatal; + if (!iter->ret) { iter->ret =3D ret; error_propagate(&iter->err, *local_err); } else { @@ -552,6 +546,15 @@ static void nbd_iter_error(NBDReplyChunkIter *iter, bo= ol fatal, *local_err =3D NULL; } =20 +static void nbd_iter_request_error(NBDReplyChunkIter *iter, int ret) +{ + assert(ret < 0); + + if (!iter->request_ret) { + iter->request_ret =3D ret; + } +} + /* NBD_FOREACH_REPLY_CHUNK */ #define NBD_FOREACH_REPLY_CHUNK(s, iter, handle, structured, \ @@ -567,13 +570,13 @@ static bool nbd_reply_chunk_iter_receive(NBDClientSes= sion *s, QEMUIOVector *qiov, NBDReply *rep= ly, void **payload) { - int ret; + int ret, request_ret; NBDReply local_reply; NBDStructuredReplyChunk *chunk; Error *local_err =3D NULL; if (s->quit) { error_setg(&local_err, "Connection closed"); - nbd_iter_error(iter, true, -EIO, &local_err); + nbd_iter_channel_error(iter, -EIO, &local_err); goto break_loop; } =20 @@ -587,10 +590,12 @@ static bool nbd_reply_chunk_iter_receive(NBDClientSes= sion *s, } =20 ret =3D nbd_co_receive_one_chunk(s, handle, iter->only_structured, - qiov, reply, payload, &local_err); + &request_ret, qiov, reply, payload, + &local_err); if (ret < 0) { - /* If it is a fatal error s->quit is set by nbd_co_receive_one_chu= nk */ - nbd_iter_error(iter, s->quit, ret, &local_err); + nbd_iter_channel_error(iter, ret, &local_err); + } else if (request_ret < 0) { + nbd_iter_request_error(iter, request_ret); } =20 /* Do not execute the body of NBD_FOREACH_REPLY_CHUNK for simple reply= . */ @@ -627,7 +632,7 @@ break_loop: } =20 static int nbd_co_receive_return_code(NBDClientSession *s, uint64_t handle, - Error **errp) + int *request_ret, Error **errp) { NBDReplyChunkIter iter; =20 @@ -636,12 +641,13 @@ static int nbd_co_receive_return_code(NBDClientSessio= n *s, uint64_t handle, } =20 error_propagate(errp, iter.err); + *request_ret =3D iter.request_ret; return iter.ret; } =20 static int nbd_co_receive_cmdread_reply(NBDClientSession *s, uint64_t hand= le, uint64_t offset, QEMUIOVector *qio= v, - Error **errp) + int *request_ret, Error **errp) { NBDReplyChunkIter iter; NBDReply reply; @@ -666,7 +672,7 @@ static int nbd_co_receive_cmdread_reply(NBDClientSessio= n *s, uint64_t handle, offset, qiov, &local_err); if (ret < 0) { s->quit =3D true; - nbd_iter_error(&iter, true, ret, &local_err); + nbd_iter_channel_error(&iter, ret, &local_err); } break; default: @@ -676,7 +682,7 @@ static int nbd_co_receive_cmdread_reply(NBDClientSessio= n *s, uint64_t handle, error_setg(&local_err, "Unexpected reply type: %d (%s) for CMD_READ", chunk->type, nbd_reply_type_lookup(chunk->type)= ); - nbd_iter_error(&iter, true, -EINVAL, &local_err); + nbd_iter_channel_error(&iter, -EINVAL, &local_err); } } =20 @@ -685,12 +691,14 @@ static int nbd_co_receive_cmdread_reply(NBDClientSess= ion *s, uint64_t handle, } =20 error_propagate(errp, iter.err); + *request_ret =3D iter.request_ret; return iter.ret; } =20 static int nbd_co_receive_blockstatus_reply(NBDClientSession *s, uint64_t handle, uint64_t leng= th, - NBDExtent *extent, Error **err= p) + NBDExtent *extent, + int *request_ret, Error **errp) { NBDReplyChunkIter iter; NBDReply reply; @@ -712,7 +720,7 @@ static int nbd_co_receive_blockstatus_reply(NBDClientSe= ssion *s, if (received) { s->quit =3D true; error_setg(&local_err, "Several BLOCK_STATUS chunks in rep= ly"); - nbd_iter_error(&iter, true, -EINVAL, &local_err); + nbd_iter_channel_error(&iter, -EINVAL, &local_err); } received =3D true; =20 @@ -721,7 +729,7 @@ static int nbd_co_receive_blockstatus_reply(NBDClientSe= ssion *s, &local_err); if (ret < 0) { s->quit =3D true; - nbd_iter_error(&iter, true, ret, &local_err); + nbd_iter_channel_error(&iter, ret, &local_err); } break; default: @@ -731,7 +739,7 @@ static int nbd_co_receive_blockstatus_reply(NBDClientSe= ssion *s, "Unexpected reply type: %d (%s) " "for CMD_BLOCK_STATUS", chunk->type, nbd_reply_type_lookup(chunk->type)= ); - nbd_iter_error(&iter, true, -EINVAL, &local_err); + nbd_iter_channel_error(&iter, -EINVAL, &local_err); } } =20 @@ -746,14 +754,16 @@ static int nbd_co_receive_blockstatus_reply(NBDClient= Session *s, iter.ret =3D -EIO; } } + error_propagate(errp, iter.err); + *request_ret =3D iter.request_ret; return iter.ret; } =20 static int nbd_co_request(BlockDriverState *bs, NBDRequest *request, QEMUIOVector *write_qiov) { - int ret; + int ret, request_ret; Error *local_err =3D NULL; NBDClientSession *client =3D nbd_get_client_session(bs); =20 @@ -769,17 +779,18 @@ static int nbd_co_request(BlockDriverState *bs, NBDRe= quest *request, return ret; } =20 - ret =3D nbd_co_receive_return_code(client, request->handle, &local_err= ); + ret =3D nbd_co_receive_return_code(client, request->handle, + &request_ret, &local_err); if (local_err) { error_report_err(local_err); } - return ret; + return ret ? ret : request_ret; } =20 int nbd_client_co_preadv(BlockDriverState *bs, uint64_t offset, uint64_t bytes, QEMUIOVector *qiov, int flags) { - int ret; + int ret, request_ret; Error *local_err =3D NULL; NBDClientSession *client =3D nbd_get_client_session(bs); NBDRequest request =3D { @@ -800,11 +811,11 @@ int nbd_client_co_preadv(BlockDriverState *bs, uint64= _t offset, } =20 ret =3D nbd_co_receive_cmdread_reply(client, request.handle, offset, q= iov, - &local_err); + &request_ret, &local_err); if (local_err) { error_report_err(local_err); } - return ret; + return ret ? ret : request_ret; } =20 int nbd_client_co_pwritev(BlockDriverState *bs, uint64_t offset, @@ -898,7 +909,7 @@ int coroutine_fn nbd_client_co_block_status(BlockDriver= State *bs, int64_t *pnum, int64_t *map, BlockDriverState **file) { - int64_t ret; + int ret, request_ret; NBDExtent extent =3D { 0 }; NBDClientSession *client =3D nbd_get_client_session(bs); Error *local_err =3D NULL; @@ -923,12 +934,12 @@ int coroutine_fn nbd_client_co_block_status(BlockDriv= erState *bs, } =20 ret =3D nbd_co_receive_blockstatus_reply(client, request.handle, bytes, - &extent, &local_err); + &extent, &request_ret, &local_e= rr); if (local_err) { error_report_err(local_err); } - if (ret < 0) { - return ret; + if (ret < 0 || request_ret < 0) { + return ret ? ret : request_ret; } =20 assert(extent.length); --=20 2.11.1 From nobody Sat May 4 16:32:28 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=virtuozzo.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1528392125522658.1971475636143; Thu, 7 Jun 2018 10:22:05 -0700 (PDT) Received: from localhost ([::1]:59407 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fQybs-0005J7-My for importer@patchew.org; Thu, 07 Jun 2018 13:22:04 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:34200) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fQyUs-0008Am-8F for qemu-devel@nongnu.org; Thu, 07 Jun 2018 13:14:52 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fQyUo-000845-OY for qemu-devel@nongnu.org; Thu, 07 Jun 2018 13:14:50 -0400 Received: from relay.sw.ru ([195.214.232.25]:52006) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1fQyUo-0007zq-Cx; Thu, 07 Jun 2018 13:14:46 -0400 Received: from msk-vpn.virtuozzo.com ([195.214.232.6] helo=kvm.sw.ru) by relay.sw.ru with esmtp (Exim 4.90_1) (envelope-from ) id 1fQyUk-0007DI-7b; Thu, 07 Jun 2018 20:14:42 +0300 From: Vladimir Sementsov-Ogievskiy To: qemu-devel@nongnu.org, qemu-block@nongnu.org Date: Thu, 7 Jun 2018 20:14:32 +0300 Message-Id: <20180607171441.64079-3-vsementsov@virtuozzo.com> X-Mailer: git-send-email 2.11.1 In-Reply-To: <20180607171441.64079-1-vsementsov@virtuozzo.com> References: <20180607171441.64079-1-vsementsov@virtuozzo.com> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x [fuzzy] X-Received-From: 195.214.232.25 Subject: [Qemu-devel] [PATCH v2 02/11] block/nbd: move connection code from block/nbd to block/nbd-client X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: kwolf@redhat.com, vsementsov@virtuozzo.com, armbru@redhat.com, mreitz@redhat.com, den@openvz.org, pbonzini@redhat.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Keep all connection code in one file, to be able to implement reconnect in further patches. Signed-off-by: Vladimir Sementsov-Ogievskiy --- block/nbd-client.h | 2 +- block/nbd-client.c | 37 +++++++++++++++++++++++++++++++++++-- block/nbd.c | 41 ++--------------------------------------- 3 files changed, 38 insertions(+), 42 deletions(-) diff --git a/block/nbd-client.h b/block/nbd-client.h index 0ece76e5af..a93f2114b9 100644 --- a/block/nbd-client.h +++ b/block/nbd-client.h @@ -41,7 +41,7 @@ typedef struct NBDClientSession { NBDClientSession *nbd_get_client_session(BlockDriverState *bs); =20 int nbd_client_init(BlockDriverState *bs, - QIOChannelSocket *sock, + SocketAddress *saddr, const char *export_name, QCryptoTLSCreds *tlscreds, const char *hostname, diff --git a/block/nbd-client.c b/block/nbd-client.c index 9b9a82fef1..6ff505c4b8 100644 --- a/block/nbd-client.c +++ b/block/nbd-client.c @@ -976,8 +976,31 @@ void nbd_client_close(BlockDriverState *bs) nbd_teardown_connection(bs); } =20 +static QIOChannelSocket *nbd_establish_connection(SocketAddress *saddr, + Error **errp) +{ + QIOChannelSocket *sioc; + Error *local_err =3D NULL; + + sioc =3D qio_channel_socket_new(); + qio_channel_set_name(QIO_CHANNEL(sioc), "nbd-client"); + + qio_channel_socket_connect_sync(sioc, + saddr, + &local_err); + if (local_err) { + object_unref(OBJECT(sioc)); + error_propagate(errp, local_err); + return NULL; + } + + qio_channel_set_delay(QIO_CHANNEL(sioc), false); + + return sioc; +} + int nbd_client_init(BlockDriverState *bs, - QIOChannelSocket *sioc, + SocketAddress *saddr, const char *export, QCryptoTLSCreds *tlscreds, const char *hostname, @@ -986,6 +1009,15 @@ int nbd_client_init(BlockDriverState *bs, NBDClientSession *client =3D nbd_get_client_session(bs); int ret; =20 + /* establish TCP connection, return error if it fails + * TODO: Configurable retry-until-timeout behaviour. + */ + QIOChannelSocket *sioc =3D nbd_establish_connection(saddr, errp); + + if (!sioc) { + return -ECONNREFUSED; + } + /* NBD handshake */ logout("session init %s\n", export); qio_channel_set_blocking(QIO_CHANNEL(sioc), true, NULL); @@ -998,12 +1030,14 @@ int nbd_client_init(BlockDriverState *bs, &client->ioc, &client->info, errp); if (ret < 0) { logout("Failed to negotiate with the NBD server\n"); + object_unref(OBJECT(sioc)); return ret; } if (client->info.flags & NBD_FLAG_READ_ONLY && !bdrv_is_read_only(bs)) { error_setg(errp, "request for write access conflicts with read-only expo= rt"); + object_unref(OBJECT(sioc)); return -EACCES; } if (client->info.flags & NBD_FLAG_SEND_FUA) { @@ -1017,7 +1051,6 @@ int nbd_client_init(BlockDriverState *bs, qemu_co_mutex_init(&client->send_mutex); qemu_co_queue_init(&client->free_sema); client->sioc =3D sioc; - object_ref(OBJECT(client->sioc)); =20 if (!client->ioc) { client->ioc =3D QIO_CHANNEL(sioc); diff --git a/block/nbd.c b/block/nbd.c index ff8333e3c1..a851b8cd68 100644 --- a/block/nbd.c +++ b/block/nbd.c @@ -305,30 +305,6 @@ NBDClientSession *nbd_get_client_session(BlockDriverSt= ate *bs) return &s->client; } =20 -static QIOChannelSocket *nbd_establish_connection(SocketAddress *saddr, - Error **errp) -{ - QIOChannelSocket *sioc; - Error *local_err =3D NULL; - - sioc =3D qio_channel_socket_new(); - qio_channel_set_name(QIO_CHANNEL(sioc), "nbd-client"); - - qio_channel_socket_connect_sync(sioc, - saddr, - &local_err); - if (local_err) { - object_unref(OBJECT(sioc)); - error_propagate(errp, local_err); - return NULL; - } - - qio_channel_set_delay(QIO_CHANNEL(sioc), false); - - return sioc; -} - - static QCryptoTLSCreds *nbd_get_tls_creds(const char *id, Error **errp) { Object *obj; @@ -398,7 +374,6 @@ static int nbd_open(BlockDriverState *bs, QDict *option= s, int flags, BDRVNBDState *s =3D bs->opaque; QemuOpts *opts =3D NULL; Error *local_err =3D NULL; - QIOChannelSocket *sioc =3D NULL; QCryptoTLSCreds *tlscreds =3D NULL; const char *hostname =3D NULL; int ret =3D -EINVAL; @@ -438,22 +413,10 @@ static int nbd_open(BlockDriverState *bs, QDict *opti= ons, int flags, hostname =3D s->saddr->u.inet.host; } =20 - /* establish TCP connection, return error if it fails - * TODO: Configurable retry-until-timeout behaviour. - */ - sioc =3D nbd_establish_connection(s->saddr, errp); - if (!sioc) { - ret =3D -ECONNREFUSED; - goto error; - } - /* NBD handshake */ - ret =3D nbd_client_init(bs, sioc, s->export, - tlscreds, hostname, errp); + ret =3D nbd_client_init(bs, s->saddr, s->export, tlscreds, hostname, e= rrp); + error: - if (sioc) { - object_unref(OBJECT(sioc)); - } if (tlscreds) { object_unref(OBJECT(tlscreds)); } --=20 2.11.1 From nobody Sat May 4 16:32:28 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=virtuozzo.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1528391896674902.6359337195269; Thu, 7 Jun 2018 10:18:16 -0700 (PDT) Received: from localhost ([::1]:59387 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fQyY7-000242-RB for importer@patchew.org; Thu, 07 Jun 2018 13:18:11 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:34210) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fQyUs-0008Ax-Ao for qemu-devel@nongnu.org; Thu, 07 Jun 2018 13:14:51 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fQyUo-00084s-Q3 for qemu-devel@nongnu.org; Thu, 07 Jun 2018 13:14:50 -0400 Received: from relay.sw.ru ([195.214.232.25]:52040) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1fQyUo-000802-DB; Thu, 07 Jun 2018 13:14:46 -0400 Received: from msk-vpn.virtuozzo.com ([195.214.232.6] helo=kvm.sw.ru) by relay.sw.ru with esmtp (Exim 4.90_1) (envelope-from ) id 1fQyUk-0007DI-Cr; Thu, 07 Jun 2018 20:14:42 +0300 From: Vladimir Sementsov-Ogievskiy To: qemu-devel@nongnu.org, qemu-block@nongnu.org Date: Thu, 7 Jun 2018 20:14:33 +0300 Message-Id: <20180607171441.64079-4-vsementsov@virtuozzo.com> X-Mailer: git-send-email 2.11.1 In-Reply-To: <20180607171441.64079-1-vsementsov@virtuozzo.com> References: <20180607171441.64079-1-vsementsov@virtuozzo.com> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x [fuzzy] X-Received-From: 195.214.232.25 Subject: [Qemu-devel] [PATCH v2 03/11] block/nbd-client: split connection from initialization X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: kwolf@redhat.com, vsementsov@virtuozzo.com, armbru@redhat.com, mreitz@redhat.com, den@openvz.org, pbonzini@redhat.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Split connection code to reuse it for reconnect. Signed-off-by: Vladimir Sementsov-Ogievskiy --- block/nbd-client.c | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/block/nbd-client.c b/block/nbd-client.c index 6ff505c4b8..14b42f31df 100644 --- a/block/nbd-client.c +++ b/block/nbd-client.c @@ -999,12 +999,12 @@ static QIOChannelSocket *nbd_establish_connection(Soc= ketAddress *saddr, return sioc; } =20 -int nbd_client_init(BlockDriverState *bs, - SocketAddress *saddr, - const char *export, - QCryptoTLSCreds *tlscreds, - const char *hostname, - Error **errp) +static int nbd_client_connect(BlockDriverState *bs, + SocketAddress *saddr, + const char *export, + QCryptoTLSCreds *tlscreds, + const char *hostname, + Error **errp) { NBDClientSession *client =3D nbd_get_client_session(bs); int ret; @@ -1048,8 +1048,6 @@ int nbd_client_init(BlockDriverState *bs, bs->supported_zero_flags |=3D BDRV_REQ_MAY_UNMAP; } =20 - qemu_co_mutex_init(&client->send_mutex); - qemu_co_queue_init(&client->free_sema); client->sioc =3D sioc; =20 if (!client->ioc) { @@ -1066,3 +1064,18 @@ int nbd_client_init(BlockDriverState *bs, logout("Established connection with NBD server\n"); return 0; } + +int nbd_client_init(BlockDriverState *bs, + SocketAddress *saddr, + const char *export, + QCryptoTLSCreds *tlscreds, + const char *hostname, + Error **errp) +{ + NBDClientSession *client =3D nbd_get_client_session(bs); + + qemu_co_mutex_init(&client->send_mutex); + qemu_co_queue_init(&client->free_sema); + + return nbd_client_connect(bs, saddr, export, tlscreds, hostname, errp); +} --=20 2.11.1 From nobody Sat May 4 16:32:28 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=virtuozzo.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1528392087548296.09163945797; Thu, 7 Jun 2018 10:21:27 -0700 (PDT) Received: from localhost ([::1]:59404 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fQybG-0004p2-Q8 for importer@patchew.org; Thu, 07 Jun 2018 13:21:26 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:34211) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fQyUs-0008Az-BA for qemu-devel@nongnu.org; Thu, 07 Jun 2018 13:14:51 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fQyUo-00084L-NA for qemu-devel@nongnu.org; Thu, 07 Jun 2018 13:14:50 -0400 Received: from relay.sw.ru ([195.214.232.25]:52020) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1fQyUo-0007zv-D1; Thu, 07 Jun 2018 13:14:46 -0400 Received: from msk-vpn.virtuozzo.com ([195.214.232.6] helo=kvm.sw.ru) by relay.sw.ru with esmtp (Exim 4.90_1) (envelope-from ) id 1fQyUk-0007DI-FG; Thu, 07 Jun 2018 20:14:42 +0300 From: Vladimir Sementsov-Ogievskiy To: qemu-devel@nongnu.org, qemu-block@nongnu.org Date: Thu, 7 Jun 2018 20:14:34 +0300 Message-Id: <20180607171441.64079-5-vsementsov@virtuozzo.com> X-Mailer: git-send-email 2.11.1 In-Reply-To: <20180607171441.64079-1-vsementsov@virtuozzo.com> References: <20180607171441.64079-1-vsementsov@virtuozzo.com> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x [fuzzy] X-Received-From: 195.214.232.25 Subject: [Qemu-devel] [PATCH v2 04/11] block/nbd-client: fix nbd_reply_chunk_iter_receive X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: kwolf@redhat.com, vsementsov@virtuozzo.com, armbru@redhat.com, mreitz@redhat.com, den@openvz.org, pbonzini@redhat.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Use exported report, not the variable to be reused (should not really matter). Signed-off-by: Vladimir Sementsov-Ogievskiy --- block/nbd-client.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/block/nbd-client.c b/block/nbd-client.c index 14b42f31df..dd712c59b3 100644 --- a/block/nbd-client.c +++ b/block/nbd-client.c @@ -599,7 +599,7 @@ static bool nbd_reply_chunk_iter_receive(NBDClientSessi= on *s, } =20 /* Do not execute the body of NBD_FOREACH_REPLY_CHUNK for simple reply= . */ - if (nbd_reply_is_simple(&s->reply) || s->quit) { + if (nbd_reply_is_simple(reply) || s->quit) { goto break_loop; } =20 --=20 2.11.1 From nobody Sat May 4 16:32:28 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=virtuozzo.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1528391933109983.0370408740589; Thu, 7 Jun 2018 10:18:53 -0700 (PDT) Received: from localhost ([::1]:59389 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fQyYi-0002VD-OD for importer@patchew.org; Thu, 07 Jun 2018 13:18:48 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:34205) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fQyUs-0008Ar-9J for qemu-devel@nongnu.org; Thu, 07 Jun 2018 13:14:51 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fQyUo-00084I-PH for qemu-devel@nongnu.org; Thu, 07 Jun 2018 13:14:50 -0400 Received: from relay.sw.ru ([195.214.232.25]:52046) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1fQyUo-000804-Ct; Thu, 07 Jun 2018 13:14:46 -0400 Received: from msk-vpn.virtuozzo.com ([195.214.232.6] helo=kvm.sw.ru) by relay.sw.ru with esmtp (Exim 4.90_1) (envelope-from ) id 1fQyUk-0007DI-KZ; Thu, 07 Jun 2018 20:14:42 +0300 From: Vladimir Sementsov-Ogievskiy To: qemu-devel@nongnu.org, qemu-block@nongnu.org Date: Thu, 7 Jun 2018 20:14:35 +0300 Message-Id: <20180607171441.64079-6-vsementsov@virtuozzo.com> X-Mailer: git-send-email 2.11.1 In-Reply-To: <20180607171441.64079-1-vsementsov@virtuozzo.com> References: <20180607171441.64079-1-vsementsov@virtuozzo.com> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x [fuzzy] X-Received-From: 195.214.232.25 Subject: [Qemu-devel] [PATCH v2 05/11] block/nbd-client: don't check ioc X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: kwolf@redhat.com, vsementsov@virtuozzo.com, armbru@redhat.com, mreitz@redhat.com, den@openvz.org, pbonzini@redhat.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" We have several paranoiac checks for ioc !=3D NULL. But ioc may become NULL only on close, which should not happen during requests handling. Also, we check ioc only sometimes, not after each yield, which is inconsistent. Let's drop these checks. However, for safety, lets leave asserts instead. Signed-off-by: Vladimir Sementsov-Ogievskiy --- block/nbd-client.c | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/block/nbd-client.c b/block/nbd-client.c index dd712c59b3..1589ceb475 100644 --- a/block/nbd-client.c +++ b/block/nbd-client.c @@ -51,9 +51,7 @@ static void nbd_teardown_connection(BlockDriverState *bs) { NBDClientSession *client =3D nbd_get_client_session(bs); =20 - if (!client->ioc) { /* Already closed */ - return; - } + assert(client->ioc); =20 /* finish any pending coroutines */ qio_channel_shutdown(client->ioc, @@ -150,10 +148,7 @@ static int nbd_co_send_request(BlockDriverState *bs, rc =3D -EIO; goto err; } - if (!s->ioc) { - rc =3D -EPIPE; - goto err; - } + assert(s->ioc); =20 if (qiov) { qio_channel_set_cork(s->ioc, true); @@ -426,10 +421,11 @@ static coroutine_fn int nbd_co_do_receive_one_chunk( s->requests[i].receiving =3D true; qemu_coroutine_yield(); s->requests[i].receiving =3D false; - if (!s->ioc || s->quit) { + if (s->quit) { error_setg(errp, "Connection closed"); return -EIO; } + assert(s->ioc); =20 assert(s->reply.handle =3D=3D handle); =20 @@ -967,9 +963,7 @@ void nbd_client_close(BlockDriverState *bs) NBDClientSession *client =3D nbd_get_client_session(bs); NBDRequest request =3D { .type =3D NBD_CMD_DISC }; =20 - if (client->ioc =3D=3D NULL) { - return; - } + assert(client->ioc); =20 nbd_send_request(client->ioc, &request); =20 --=20 2.11.1 From nobody Sat May 4 16:32:28 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=virtuozzo.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1528391978640463.20537374719595; Thu, 7 Jun 2018 10:19:38 -0700 (PDT) Received: from localhost ([::1]:59390 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fQyZV-00035x-QM for importer@patchew.org; Thu, 07 Jun 2018 13:19:37 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:34204) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fQyUs-0008Aq-8u for qemu-devel@nongnu.org; Thu, 07 Jun 2018 13:14:53 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fQyUo-00085G-Tv for qemu-devel@nongnu.org; Thu, 07 Jun 2018 13:14:50 -0400 Received: from relay.sw.ru ([195.214.232.25]:52036) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1fQyUo-000801-CX; Thu, 07 Jun 2018 13:14:46 -0400 Received: from msk-vpn.virtuozzo.com ([195.214.232.6] helo=kvm.sw.ru) by relay.sw.ru with esmtp (Exim 4.90_1) (envelope-from ) id 1fQyUk-0007DI-No; Thu, 07 Jun 2018 20:14:42 +0300 From: Vladimir Sementsov-Ogievskiy To: qemu-devel@nongnu.org, qemu-block@nongnu.org Date: Thu, 7 Jun 2018 20:14:36 +0300 Message-Id: <20180607171441.64079-7-vsementsov@virtuozzo.com> X-Mailer: git-send-email 2.11.1 In-Reply-To: <20180607171441.64079-1-vsementsov@virtuozzo.com> References: <20180607171441.64079-1-vsementsov@virtuozzo.com> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x [fuzzy] X-Received-From: 195.214.232.25 Subject: [Qemu-devel] [PATCH v2 06/11] block/nbd-client: move from quit to state X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: kwolf@redhat.com, vsementsov@virtuozzo.com, armbru@redhat.com, mreitz@redhat.com, den@openvz.org, pbonzini@redhat.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" To implement reconnect we need several states for the client: CONNECTED, QUIT and several CONNECTING states. CONNECTING states will be realized in the following patches. This patch implements CONNECTED and QUIT. QUIT means, that we should close the connection and fail all current and further requests (like old quit =3D true). CONNECTED means that connection is ok, we can send requests (like old quit =3D false). For receiving loop we use a comparison of the current state with QUIT, because reconnect will be in the same loop, so it should be looping until the end. Opposite, for requests we use a comparison of the current state with CONNECTED, as we don't want to send requests in CONNECTING states ( which are unreachable now, but will be reachable after the following commits) Signed-off-by: Vladimir Sementsov-Ogievskiy --- block/nbd-client.h | 10 +++++++++- block/nbd-client.c | 47 ++++++++++++++++++++++++++++------------------- 2 files changed, 37 insertions(+), 20 deletions(-) diff --git a/block/nbd-client.h b/block/nbd-client.h index a93f2114b9..014015cd7e 100644 --- a/block/nbd-client.h +++ b/block/nbd-client.h @@ -23,6 +23,14 @@ typedef struct { bool receiving; /* waiting for read_reply_co? */ } NBDClientRequest; =20 +typedef enum NBDClientState { + NBD_CLIENT_CONNECTING_INIT, + NBD_CLIENT_CONNECTING_WAIT, + NBD_CLIENT_CONNECTING_NOWAIT, + NBD_CLIENT_CONNECTED, + NBD_CLIENT_QUIT +} NBDClientState; + typedef struct NBDClientSession { QIOChannelSocket *sioc; /* The master data channel */ QIOChannel *ioc; /* The current I/O channel which may differ (eg TLS) = */ @@ -32,10 +40,10 @@ typedef struct NBDClientSession { CoQueue free_sema; Coroutine *read_reply_co; int in_flight; + NBDClientState state; =20 NBDClientRequest requests[MAX_NBD_REQUESTS]; NBDReply reply; - bool quit; } NBDClientSession; =20 NBDClientSession *nbd_get_client_session(BlockDriverState *bs); diff --git a/block/nbd-client.c b/block/nbd-client.c index 1589ceb475..592fc9196c 100644 --- a/block/nbd-client.c +++ b/block/nbd-client.c @@ -34,6 +34,12 @@ #define HANDLE_TO_INDEX(bs, handle) ((handle) ^ (uint64_t)(intptr_t)(bs)) #define INDEX_TO_HANDLE(bs, index) ((index) ^ (uint64_t)(intptr_t)(bs)) =20 +/* @ret would be used for reconnect in future */ +static void nbd_channel_error(NBDClientSession *s, int ret) +{ + s->state =3D NBD_CLIENT_QUIT; +} + static void nbd_recv_coroutines_wake_all(NBDClientSession *s) { int i; @@ -73,14 +79,15 @@ static coroutine_fn void nbd_read_reply_entry(void *opa= que) int ret =3D 0; Error *local_err =3D NULL; =20 - while (!s->quit) { + while (s->state !=3D NBD_CLIENT_QUIT) { assert(s->reply.handle =3D=3D 0); ret =3D nbd_receive_reply(s->ioc, &s->reply, &local_err); if (local_err) { error_report_err(local_err); } if (ret <=3D 0) { - break; + nbd_channel_error(s, ret ? ret : -EIO); + continue; } =20 /* There's no need for a mutex on the receive side, because the @@ -93,7 +100,8 @@ static coroutine_fn void nbd_read_reply_entry(void *opaq= ue) !s->requests[i].receiving || (nbd_reply_is_structured(&s->reply) && !s->info.structured_rep= ly)) { - break; + nbd_channel_error(s, -EINVAL); + continue; } =20 /* We're woken up again by the request itself. Note that there @@ -111,7 +119,6 @@ static coroutine_fn void nbd_read_reply_entry(void *opa= que) qemu_coroutine_yield(); } =20 - s->quit =3D true; nbd_recv_coroutines_wake_all(s); s->read_reply_co =3D NULL; } @@ -127,6 +134,12 @@ static int nbd_co_send_request(BlockDriverState *bs, while (s->in_flight =3D=3D MAX_NBD_REQUESTS) { qemu_co_queue_wait(&s->free_sema, &s->send_mutex); } + + if (s->state !=3D NBD_CLIENT_CONNECTED) { + rc =3D -EIO; + goto err; + } + s->in_flight++; =20 for (i =3D 0; i < MAX_NBD_REQUESTS; i++) { @@ -144,16 +157,12 @@ static int nbd_co_send_request(BlockDriverState *bs, =20 request->handle =3D INDEX_TO_HANDLE(s, i); =20 - if (s->quit) { - rc =3D -EIO; - goto err; - } assert(s->ioc); =20 if (qiov) { qio_channel_set_cork(s->ioc, true); rc =3D nbd_send_request(s->ioc, request); - if (rc >=3D 0 && !s->quit) { + if (rc >=3D 0 && s->state =3D=3D NBD_CLIENT_CONNECTED) { if (qio_channel_writev_all(s->ioc, qiov->iov, qiov->niov, NULL) < 0) { rc =3D -EIO; @@ -168,7 +177,7 @@ static int nbd_co_send_request(BlockDriverState *bs, =20 err: if (rc < 0) { - s->quit =3D true; + nbd_channel_error(s, rc); s->requests[i].coroutine =3D NULL; s->in_flight--; qemu_co_queue_next(&s->free_sema); @@ -421,7 +430,7 @@ static coroutine_fn int nbd_co_do_receive_one_chunk( s->requests[i].receiving =3D true; qemu_coroutine_yield(); s->requests[i].receiving =3D false; - if (s->quit) { + if (s->state !=3D NBD_CLIENT_CONNECTED) { error_setg(errp, "Connection closed"); return -EIO; } @@ -504,7 +513,7 @@ static coroutine_fn int nbd_co_receive_one_chunk( request_ret, qiov, payload, errp= ); =20 if (ret < 0) { - s->quit =3D true; + nbd_channel_error(s, ret); } else { /* For assert at loop start in nbd_read_reply_entry */ if (reply) { @@ -570,7 +579,7 @@ static bool nbd_reply_chunk_iter_receive(NBDClientSessi= on *s, NBDReply local_reply; NBDStructuredReplyChunk *chunk; Error *local_err =3D NULL; - if (s->quit) { + if (s->state !=3D NBD_CLIENT_CONNECTED) { error_setg(&local_err, "Connection closed"); nbd_iter_channel_error(iter, -EIO, &local_err); goto break_loop; @@ -595,7 +604,7 @@ static bool nbd_reply_chunk_iter_receive(NBDClientSessi= on *s, } =20 /* Do not execute the body of NBD_FOREACH_REPLY_CHUNK for simple reply= . */ - if (nbd_reply_is_simple(reply) || s->quit) { + if (nbd_reply_is_simple(reply) || s->state !=3D NBD_CLIENT_CONNECTED) { goto break_loop; } =20 @@ -667,14 +676,14 @@ static int nbd_co_receive_cmdread_reply(NBDClientSess= ion *s, uint64_t handle, ret =3D nbd_parse_offset_hole_payload(&reply.structured, paylo= ad, offset, qiov, &local_err); if (ret < 0) { - s->quit =3D true; + nbd_channel_error(s, ret); nbd_iter_channel_error(&iter, ret, &local_err); } break; default: if (!nbd_reply_type_is_error(chunk->type)) { /* not allowed reply type */ - s->quit =3D true; + nbd_channel_error(s, -EINVAL); error_setg(&local_err, "Unexpected reply type: %d (%s) for CMD_READ", chunk->type, nbd_reply_type_lookup(chunk->type)= ); @@ -714,7 +723,7 @@ static int nbd_co_receive_blockstatus_reply(NBDClientSe= ssion *s, switch (chunk->type) { case NBD_REPLY_TYPE_BLOCK_STATUS: if (received) { - s->quit =3D true; + nbd_channel_error(s, -EINVAL); error_setg(&local_err, "Several BLOCK_STATUS chunks in rep= ly"); nbd_iter_channel_error(&iter, -EINVAL, &local_err); } @@ -724,13 +733,13 @@ static int nbd_co_receive_blockstatus_reply(NBDClient= Session *s, payload, length, extent, &local_err); if (ret < 0) { - s->quit =3D true; + nbd_channel_error(s, ret); nbd_iter_channel_error(&iter, ret, &local_err); } break; default: if (!nbd_reply_type_is_error(chunk->type)) { - s->quit =3D true; + nbd_channel_error(s, -EINVAL); error_setg(&local_err, "Unexpected reply type: %d (%s) " "for CMD_BLOCK_STATUS", --=20 2.11.1 From nobody Sat May 4 16:32:28 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=virtuozzo.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1528392107267735.8346175244598; Thu, 7 Jun 2018 10:21:47 -0700 (PDT) Received: from localhost ([::1]:59406 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fQyba-000591-Af for importer@patchew.org; Thu, 07 Jun 2018 13:21:46 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:34216) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fQyUs-0008B2-Cl for qemu-devel@nongnu.org; Thu, 07 Jun 2018 13:14:52 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fQyUo-00084U-Q2 for qemu-devel@nongnu.org; Thu, 07 Jun 2018 13:14:50 -0400 Received: from relay.sw.ru ([195.214.232.25]:52018) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1fQyUo-0007zx-D9; Thu, 07 Jun 2018 13:14:46 -0400 Received: from msk-vpn.virtuozzo.com ([195.214.232.6] helo=kvm.sw.ru) by relay.sw.ru with esmtp (Exim 4.90_1) (envelope-from ) id 1fQyUk-0007DI-Qm; Thu, 07 Jun 2018 20:14:42 +0300 From: Vladimir Sementsov-Ogievskiy To: qemu-devel@nongnu.org, qemu-block@nongnu.org Date: Thu, 7 Jun 2018 20:14:37 +0300 Message-Id: <20180607171441.64079-8-vsementsov@virtuozzo.com> X-Mailer: git-send-email 2.11.1 In-Reply-To: <20180607171441.64079-1-vsementsov@virtuozzo.com> References: <20180607171441.64079-1-vsementsov@virtuozzo.com> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x [fuzzy] X-Received-From: 195.214.232.25 Subject: [Qemu-devel] [PATCH v2 07/11] block/nbd-client: rename read_reply_co to connection_co X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: kwolf@redhat.com, vsementsov@virtuozzo.com, armbru@redhat.com, mreitz@redhat.com, den@openvz.org, pbonzini@redhat.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" This coroutine will serve nbd reconnects, so, rename it to be something more generic. Signed-off-by: Vladimir Sementsov-Ogievskiy --- block/nbd-client.h | 4 ++-- block/nbd-client.c | 24 ++++++++++++------------ 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/block/nbd-client.h b/block/nbd-client.h index 014015cd7e..7cb31e72e6 100644 --- a/block/nbd-client.h +++ b/block/nbd-client.h @@ -20,7 +20,7 @@ typedef struct { Coroutine *coroutine; uint64_t offset; /* original offset of the request */ - bool receiving; /* waiting for read_reply_co? */ + bool receiving; /* waiting for connection_co? */ } NBDClientRequest; =20 typedef enum NBDClientState { @@ -38,7 +38,7 @@ typedef struct NBDClientSession { =20 CoMutex send_mutex; CoQueue free_sema; - Coroutine *read_reply_co; + Coroutine *connection_co; int in_flight; NBDClientState state; =20 diff --git a/block/nbd-client.c b/block/nbd-client.c index 592fc9196c..97bbb4339a 100644 --- a/block/nbd-client.c +++ b/block/nbd-client.c @@ -63,7 +63,7 @@ static void nbd_teardown_connection(BlockDriverState *bs) qio_channel_shutdown(client->ioc, QIO_CHANNEL_SHUTDOWN_BOTH, NULL); - BDRV_POLL_WHILE(bs, client->read_reply_co); + BDRV_POLL_WHILE(bs, client->connection_co); =20 nbd_client_detach_aio_context(bs); object_unref(OBJECT(client->sioc)); @@ -72,7 +72,7 @@ static void nbd_teardown_connection(BlockDriverState *bs) client->ioc =3D NULL; } =20 -static coroutine_fn void nbd_read_reply_entry(void *opaque) +static coroutine_fn void nbd_connection_entry(void *opaque) { NBDClientSession *s =3D opaque; uint64_t i; @@ -105,14 +105,14 @@ static coroutine_fn void nbd_read_reply_entry(void *o= paque) } =20 /* We're woken up again by the request itself. Note that there - * is no race between yielding and reentering read_reply_co. This + * is no race between yielding and reentering connection_co. This * is because: * * - if the request runs on the same AioContext, it is only * entered after we yield * * - if the request runs on a different AioContext, reentering - * read_reply_co happens through a bottom half, which can only + * connection_co happens through a bottom half, which can only * run after we yield. */ aio_co_wake(s->requests[i].coroutine); @@ -120,7 +120,7 @@ static coroutine_fn void nbd_read_reply_entry(void *opa= que) } =20 nbd_recv_coroutines_wake_all(s); - s->read_reply_co =3D NULL; + s->connection_co =3D NULL; } =20 static int nbd_co_send_request(BlockDriverState *bs, @@ -426,7 +426,7 @@ static coroutine_fn int nbd_co_do_receive_one_chunk( } *request_ret =3D 0; =20 - /* Wait until we're woken up by nbd_read_reply_entry. */ + /* Wait until we're woken up by nbd_connection_entry. */ s->requests[i].receiving =3D true; qemu_coroutine_yield(); s->requests[i].receiving =3D false; @@ -501,7 +501,7 @@ static coroutine_fn int nbd_co_do_receive_one_chunk( } =20 /* nbd_co_receive_one_chunk - * Read reply, wake up read_reply_co and set s->quit if needed. + * Read reply, wake up connection_co and set s->quit if needed. * Return value is a fatal error code or normal nbd reply error code */ static coroutine_fn int nbd_co_receive_one_chunk( @@ -515,15 +515,15 @@ static coroutine_fn int nbd_co_receive_one_chunk( if (ret < 0) { nbd_channel_error(s, ret); } else { - /* For assert at loop start in nbd_read_reply_entry */ + /* For assert at loop start in nbd_connection_entry */ if (reply) { *reply =3D s->reply; } s->reply.handle =3D 0; } =20 - if (s->read_reply_co) { - aio_co_wake(s->read_reply_co); + if (s->connection_co) { + aio_co_wake(s->connection_co); } =20 return ret; @@ -964,7 +964,7 @@ void nbd_client_attach_aio_context(BlockDriverState *bs, { NBDClientSession *client =3D nbd_get_client_session(bs); qio_channel_attach_aio_context(QIO_CHANNEL(client->ioc), new_context); - aio_co_schedule(new_context, client->read_reply_co); + aio_co_schedule(new_context, client->connection_co); } =20 void nbd_client_close(BlockDriverState *bs) @@ -1061,7 +1061,7 @@ static int nbd_client_connect(BlockDriverState *bs, /* Now that we're connected, set the socket to be non-blocking and * kick the reply mechanism. */ qio_channel_set_blocking(QIO_CHANNEL(sioc), false, NULL); - client->read_reply_co =3D qemu_coroutine_create(nbd_read_reply_entry, = client); + client->connection_co =3D qemu_coroutine_create(nbd_connection_entry, = client); nbd_client_attach_aio_context(bs, bdrv_get_aio_context(bs)); =20 logout("Established connection with NBD server\n"); --=20 2.11.1 From nobody Sat May 4 16:32:28 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=virtuozzo.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1528392298243892.9281548315329; Thu, 7 Jun 2018 10:24:58 -0700 (PDT) Received: from localhost ([::1]:59429 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fQyef-00089F-BT for importer@patchew.org; Thu, 07 Jun 2018 13:24:57 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:34220) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fQyUs-0008B5-DO for qemu-devel@nongnu.org; Thu, 07 Jun 2018 13:14:52 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fQyUo-00084D-MS for qemu-devel@nongnu.org; Thu, 07 Jun 2018 13:14:50 -0400 Received: from relay.sw.ru ([195.214.232.25]:52016) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1fQyUo-0007zr-Co; Thu, 07 Jun 2018 13:14:46 -0400 Received: from msk-vpn.virtuozzo.com ([195.214.232.6] helo=kvm.sw.ru) by relay.sw.ru with esmtp (Exim 4.90_1) (envelope-from ) id 1fQyUk-0007DI-Uc; Thu, 07 Jun 2018 20:14:43 +0300 From: Vladimir Sementsov-Ogievskiy To: qemu-devel@nongnu.org, qemu-block@nongnu.org Date: Thu, 7 Jun 2018 20:14:38 +0300 Message-Id: <20180607171441.64079-9-vsementsov@virtuozzo.com> X-Mailer: git-send-email 2.11.1 In-Reply-To: <20180607171441.64079-1-vsementsov@virtuozzo.com> References: <20180607171441.64079-1-vsementsov@virtuozzo.com> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x [fuzzy] X-Received-From: 195.214.232.25 Subject: [Qemu-devel] [PATCH v2 08/11] block/nbd-client: move connecting to connection_co X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: kwolf@redhat.com, vsementsov@virtuozzo.com, armbru@redhat.com, mreitz@redhat.com, den@openvz.org, pbonzini@redhat.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" As a first step to nbd reconnect, move connection to connection_co coroutine. The key point in this patch is nbd_client_attach_aio_context() change: We schedule to connection_co only if it is waiting for read from the channel. We should not schedule it if it is some other yield, and if it is currently executing (we call nbd_client_attach_aio_context from connection code). Signed-off-by: Vladimir Sementsov-Ogievskiy --- block/nbd-client.h | 3 +++ block/nbd-client.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++= ---- 2 files changed, 57 insertions(+), 4 deletions(-) diff --git a/block/nbd-client.h b/block/nbd-client.h index 7cb31e72e6..f6c8052573 100644 --- a/block/nbd-client.h +++ b/block/nbd-client.h @@ -41,6 +41,9 @@ typedef struct NBDClientSession { Coroutine *connection_co; int in_flight; NBDClientState state; + bool receiving; + int connect_status; + Error *connect_err; =20 NBDClientRequest requests[MAX_NBD_REQUESTS]; NBDReply reply; diff --git a/block/nbd-client.c b/block/nbd-client.c index 97bbb4339a..b74b964041 100644 --- a/block/nbd-client.c +++ b/block/nbd-client.c @@ -34,6 +34,13 @@ #define HANDLE_TO_INDEX(bs, handle) ((handle) ^ (uint64_t)(intptr_t)(bs)) #define INDEX_TO_HANDLE(bs, index) ((index) ^ (uint64_t)(intptr_t)(bs)) =20 +static int nbd_client_connect(BlockDriverState *bs, + SocketAddress *saddr, + const char *export, + QCryptoTLSCreds *tlscreds, + const char *hostname, + Error **errp); + /* @ret would be used for reconnect in future */ static void nbd_channel_error(NBDClientSession *s, int ret) { @@ -63,6 +70,7 @@ static void nbd_teardown_connection(BlockDriverState *bs) qio_channel_shutdown(client->ioc, QIO_CHANNEL_SHUTDOWN_BOTH, NULL); + client->state =3D NBD_CLIENT_QUIT; BDRV_POLL_WHILE(bs, client->connection_co); =20 nbd_client_detach_aio_context(bs); @@ -72,16 +80,38 @@ static void nbd_teardown_connection(BlockDriverState *b= s) client->ioc =3D NULL; } =20 +typedef struct NBDConnection { + BlockDriverState *bs; + SocketAddress *saddr; + const char *export; + QCryptoTLSCreds *tlscreds; + const char *hostname; +} NBDConnection; + static coroutine_fn void nbd_connection_entry(void *opaque) { - NBDClientSession *s =3D opaque; + NBDConnection *con =3D opaque; + NBDClientSession *s =3D nbd_get_client_session(con->bs); uint64_t i; int ret =3D 0; Error *local_err =3D NULL; =20 + s->connect_status =3D nbd_client_connect(con->bs, con->saddr, + con->export, con->tlscreds, + con->hostname, &s->connect_err); + if (s->connect_status < 0) { + nbd_channel_error(s, s->connect_status); + return; + } + + /* successfully connected */ + s->state =3D NBD_CLIENT_CONNECTED; + while (s->state !=3D NBD_CLIENT_QUIT) { assert(s->reply.handle =3D=3D 0); + s->receiving =3D true; ret =3D nbd_receive_reply(s->ioc, &s->reply, &local_err); + s->receiving =3D false; if (local_err) { error_report_err(local_err); } @@ -964,7 +994,9 @@ void nbd_client_attach_aio_context(BlockDriverState *bs, { NBDClientSession *client =3D nbd_get_client_session(bs); qio_channel_attach_aio_context(QIO_CHANNEL(client->ioc), new_context); - aio_co_schedule(new_context, client->connection_co); + if (client->receiving) { + aio_co_schedule(new_context, client->connection_co); + } } =20 void nbd_client_close(BlockDriverState *bs) @@ -1061,7 +1093,6 @@ static int nbd_client_connect(BlockDriverState *bs, /* Now that we're connected, set the socket to be non-blocking and * kick the reply mechanism. */ qio_channel_set_blocking(QIO_CHANNEL(sioc), false, NULL); - client->connection_co =3D qemu_coroutine_create(nbd_connection_entry, = client); nbd_client_attach_aio_context(bs, bdrv_get_aio_context(bs)); =20 logout("Established connection with NBD server\n"); @@ -1076,9 +1107,28 @@ int nbd_client_init(BlockDriverState *bs, Error **errp) { NBDClientSession *client =3D nbd_get_client_session(bs); + NBDConnection *con =3D g_new(NBDConnection, 1); + + con->bs =3D bs; + con->saddr =3D saddr; + con->export =3D export; + con->tlscreds =3D tlscreds; + con->hostname =3D hostname; =20 qemu_co_mutex_init(&client->send_mutex); qemu_co_queue_init(&client->free_sema); + client->state =3D NBD_CLIENT_CONNECTING_INIT; =20 - return nbd_client_connect(bs, saddr, export, tlscreds, hostname, errp); + client->connection_co =3D qemu_coroutine_create(nbd_connection_entry, = con); + aio_co_schedule(bdrv_get_aio_context(bs), client->connection_co); + BDRV_POLL_WHILE(bs, client->state =3D=3D NBD_CLIENT_CONNECTING_INIT); + + if (client->state !=3D NBD_CLIENT_CONNECTED) { + assert(client->connect_status < 0 && client->connect_err); + error_propagate(errp, client->connect_err); + client->connect_err =3D NULL; + return client->connect_status; + } + + return 0; } --=20 2.11.1 From nobody Sat May 4 16:32:28 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=virtuozzo.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1528392274389616.5586361128924; Thu, 7 Jun 2018 10:24:34 -0700 (PDT) Received: from localhost ([::1]:59420 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fQyeD-0007WZ-9w for importer@patchew.org; Thu, 07 Jun 2018 13:24:29 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:34209) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fQyUs-0008Aw-As for qemu-devel@nongnu.org; Thu, 07 Jun 2018 13:14:52 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fQyUo-00084e-PN for qemu-devel@nongnu.org; Thu, 07 Jun 2018 13:14:50 -0400 Received: from relay.sw.ru ([195.214.232.25]:52032) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1fQyUo-000800-D4; Thu, 07 Jun 2018 13:14:46 -0400 Received: from msk-vpn.virtuozzo.com ([195.214.232.6] helo=kvm.sw.ru) by relay.sw.ru with esmtp (Exim 4.90_1) (envelope-from ) id 1fQyUl-0007DI-39; Thu, 07 Jun 2018 20:14:43 +0300 From: Vladimir Sementsov-Ogievskiy To: qemu-devel@nongnu.org, qemu-block@nongnu.org Date: Thu, 7 Jun 2018 20:14:39 +0300 Message-Id: <20180607171441.64079-10-vsementsov@virtuozzo.com> X-Mailer: git-send-email 2.11.1 In-Reply-To: <20180607171441.64079-1-vsementsov@virtuozzo.com> References: <20180607171441.64079-1-vsementsov@virtuozzo.com> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x [fuzzy] X-Received-From: 195.214.232.25 Subject: [Qemu-devel] [PATCH v2 09/11] block/nbd: add cmdline and qapi parameters for nbd reconnect X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: kwolf@redhat.com, vsementsov@virtuozzo.com, armbru@redhat.com, mreitz@redhat.com, den@openvz.org, pbonzini@redhat.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Add two parameters: reconnect-attempts, which defines maximum number of reconnects, after which: - open will fail - block operations will fail Note: on open, we actually have reconnect-attempts+1 connection attempts, the first one is not REconnect. reconnect-timeout, timeout in nanoseconds between reconnects. Realization of these options is in the following patch. Signed-off-by: Vladimir Sementsov-Ogievskiy --- qapi/block-core.json | 12 +++++++++++- block/nbd-client.h | 2 ++ block/nbd-client.c | 13 +++++++++++++ block/nbd.c | 22 +++++++++++++++++++++- 4 files changed, 47 insertions(+), 2 deletions(-) diff --git a/qapi/block-core.json b/qapi/block-core.json index 4b1de474a9..4abba9d38e 100644 --- a/qapi/block-core.json +++ b/qapi/block-core.json @@ -3356,12 +3356,22 @@ # # @tls-creds: TLS credentials ID # +# @reconnect-attempts: number of connection attempts on disconnect. +# Must be >=3D 0. Default is 0. On nbd disk open, the= re would +# be maximum of @reconnect-attempts + 1 total tries to +# connect +# +# @reconnect-timeout: timeout between reconnect attempts in nanoseconds. D= efault +# is 1000000000 (one second) +# # Since: 2.9 ## { 'struct': 'BlockdevOptionsNbd', 'data': { 'server': 'SocketAddress', '*export': 'str', - '*tls-creds': 'str' } } + '*tls-creds': 'str', + '*reconnect-attempts': 'uint64', + '*reconnect-timeout': 'uint64' } } =20 ## # @BlockdevOptionsRaw: diff --git a/block/nbd-client.h b/block/nbd-client.h index f6c8052573..2561e1ea42 100644 --- a/block/nbd-client.h +++ b/block/nbd-client.h @@ -56,6 +56,8 @@ int nbd_client_init(BlockDriverState *bs, const char *export_name, QCryptoTLSCreds *tlscreds, const char *hostname, + uint64_t reconnect_attempts, + uint64_t reconnect_timeout, Error **errp); void nbd_client_close(BlockDriverState *bs); =20 diff --git a/block/nbd-client.c b/block/nbd-client.c index b74b964041..17ed7575c7 100644 --- a/block/nbd-client.c +++ b/block/nbd-client.c @@ -86,6 +86,8 @@ typedef struct NBDConnection { const char *export; QCryptoTLSCreds *tlscreds; const char *hostname; + uint64_t reconnect_attempts; + uint64_t reconnect_timeout; } NBDConnection; =20 static coroutine_fn void nbd_connection_entry(void *opaque) @@ -96,6 +98,13 @@ static coroutine_fn void nbd_connection_entry(void *opaq= ue) int ret =3D 0; Error *local_err =3D NULL; =20 + if (con->reconnect_attempts !=3D 0) { + error_setg(&s->connect_err, "Reconnect is not supported yet"); + s->connect_status =3D -EINVAL; + nbd_channel_error(s, s->connect_status); + return; + } + s->connect_status =3D nbd_client_connect(con->bs, con->saddr, con->export, con->tlscreds, con->hostname, &s->connect_err); @@ -1104,6 +1113,8 @@ int nbd_client_init(BlockDriverState *bs, const char *export, QCryptoTLSCreds *tlscreds, const char *hostname, + uint64_t reconnect_attempts, + uint64_t reconnect_timeout, Error **errp) { NBDClientSession *client =3D nbd_get_client_session(bs); @@ -1114,6 +1125,8 @@ int nbd_client_init(BlockDriverState *bs, con->export =3D export; con->tlscreds =3D tlscreds; con->hostname =3D hostname; + con->reconnect_attempts =3D reconnect_attempts; + con->reconnect_timeout =3D reconnect_timeout; =20 qemu_co_mutex_init(&client->send_mutex); qemu_co_queue_init(&client->free_sema); diff --git a/block/nbd.c b/block/nbd.c index a851b8cd68..8c81d4a151 100644 --- a/block/nbd.c +++ b/block/nbd.c @@ -364,6 +364,20 @@ static QemuOptsList nbd_runtime_opts =3D { .type =3D QEMU_OPT_STRING, .help =3D "ID of the TLS credentials to use", }, + { + .name =3D "reconnect-attempts", + .type =3D QEMU_OPT_NUMBER, + .help =3D "Number of connection attempts on disconnect. " + "Must be >=3D 0. Default is 0. On nbd disk open, there= would " + "be maximum of @reconnect-attempts + 1 total tries to " + "connect", + }, + { + .name =3D "reconnect-timeout", + .type =3D QEMU_OPT_NUMBER, + .help =3D "Timeout between reconnect attempts in nanoseconds. " + "Default is 1000000000 (one second)", + }, { /* end of list */ } }, }; @@ -376,6 +390,8 @@ static int nbd_open(BlockDriverState *bs, QDict *option= s, int flags, Error *local_err =3D NULL; QCryptoTLSCreds *tlscreds =3D NULL; const char *hostname =3D NULL; + uint64_t reconnect_attempts; + uint64_t reconnect_timeout; int ret =3D -EINVAL; =20 opts =3D qemu_opts_create(&nbd_runtime_opts, NULL, 0, &error_abort); @@ -413,8 +429,12 @@ static int nbd_open(BlockDriverState *bs, QDict *optio= ns, int flags, hostname =3D s->saddr->u.inet.host; } =20 + reconnect_attempts =3D qemu_opt_get_number(opts, "reconnect-attempts",= 0); + reconnect_timeout =3D qemu_opt_get_number(opts, "reconnect-timeout", + 1000000000L); /* NBD handshake */ - ret =3D nbd_client_init(bs, s->saddr, s->export, tlscreds, hostname, e= rrp); + ret =3D nbd_client_init(bs, s->saddr, s->export, tlscreds, hostname, + reconnect_attempts, reconnect_timeout, errp); =20 error: if (tlscreds) { --=20 2.11.1 From nobody Sat May 4 16:32:28 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=virtuozzo.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1528392447503250.75815248013532; Thu, 7 Jun 2018 10:27:27 -0700 (PDT) Received: from localhost ([::1]:59449 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fQyh4-0002JV-KM for importer@patchew.org; Thu, 07 Jun 2018 13:27:26 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:34213) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fQyUs-0008B0-BN for qemu-devel@nongnu.org; Thu, 07 Jun 2018 13:14:53 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fQyUo-00085T-VN for qemu-devel@nongnu.org; Thu, 07 Jun 2018 13:14:50 -0400 Received: from relay.sw.ru ([195.214.232.25]:52028) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1fQyUo-0007zu-Ch; Thu, 07 Jun 2018 13:14:46 -0400 Received: from msk-vpn.virtuozzo.com ([195.214.232.6] helo=kvm.sw.ru) by relay.sw.ru with esmtp (Exim 4.90_1) (envelope-from ) id 1fQyUl-0007DI-8Q; Thu, 07 Jun 2018 20:14:43 +0300 From: Vladimir Sementsov-Ogievskiy To: qemu-devel@nongnu.org, qemu-block@nongnu.org Date: Thu, 7 Jun 2018 20:14:40 +0300 Message-Id: <20180607171441.64079-11-vsementsov@virtuozzo.com> X-Mailer: git-send-email 2.11.1 In-Reply-To: <20180607171441.64079-1-vsementsov@virtuozzo.com> References: <20180607171441.64079-1-vsementsov@virtuozzo.com> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x [fuzzy] X-Received-From: 195.214.232.25 Subject: [Qemu-devel] [PATCH v2 10/11] block/nbd-client: nbd reconnect X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: kwolf@redhat.com, vsementsov@virtuozzo.com, armbru@redhat.com, mreitz@redhat.com, den@openvz.org, pbonzini@redhat.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Implement reconnect. To achieve this: 1. Move from quit bool variable to state. 4 states are introduced: connecting-wait: means, that reconnecting is in progress, and there were small number of reconnect attempts, so all requests are waiting for the connection. connecting-nowait: reconnecting is in progress, there were a lot of attempts of reconnect, all requests will return errors. connected: normal state quit: exiting after fatal error or on close Possible transitions are: * -> quit connecting-* -> connected connecting-wait -> connecting-nowait connected -> connecting-wait 2. Implement reconnect in connection_co. So, in connecting-* mode, connection_co, tries to reconnect every NBD_RECONNECT_NS. Configuring of this parameter (as well as NBD_RECONNECT_ATTEMPTS, which specifies bound of transition from connecting-wait to connecting-nowait) may be done as a follow-up patch. 3. Retry nbd queries on channel error, if we are in connecting-wait state. 4. In init, wait until for connection until transition to connecting-nowait. So, NBD_RECONNECT_ATTEMPTS is a bound of fail for initial connection too. Signed-off-by: Vladimir Sementsov-Ogievskiy --- block/nbd-client.h | 2 + block/nbd-client.c | 170 ++++++++++++++++++++++++++++++++++++++-----------= ---- 2 files changed, 123 insertions(+), 49 deletions(-) diff --git a/block/nbd-client.h b/block/nbd-client.h index 2561e1ea42..1249f2eb52 100644 --- a/block/nbd-client.h +++ b/block/nbd-client.h @@ -44,6 +44,8 @@ typedef struct NBDClientSession { bool receiving; int connect_status; Error *connect_err; + int connect_attempts; + bool wait_in_flight; =20 NBDClientRequest requests[MAX_NBD_REQUESTS]; NBDReply reply; diff --git a/block/nbd-client.c b/block/nbd-client.c index 17ed7575c7..c071ac911a 100644 --- a/block/nbd-client.c +++ b/block/nbd-client.c @@ -41,10 +41,16 @@ static int nbd_client_connect(BlockDriverState *bs, const char *hostname, Error **errp); =20 -/* @ret would be used for reconnect in future */ static void nbd_channel_error(NBDClientSession *s, int ret) { - s->state =3D NBD_CLIENT_QUIT; + if (ret =3D=3D -EIO) { + if (s->state =3D=3D NBD_CLIENT_CONNECTED) { + s->state =3D NBD_CLIENT_CONNECTING_WAIT; + s->connect_attempts =3D 0; + } + } else { + s->state =3D NBD_CLIENT_QUIT; + } } =20 static void nbd_recv_coroutines_wake_all(NBDClientSession *s) @@ -90,6 +96,19 @@ typedef struct NBDConnection { uint64_t reconnect_timeout; } NBDConnection; =20 +static bool nbd_client_connecting(NBDClientSession *client) +{ + return client->state =3D=3D NBD_CLIENT_CONNECTING_WAIT || + client->state =3D=3D NBD_CLIENT_CONNECTING_NOWAIT || + client->state =3D=3D NBD_CLIENT_CONNECTING_INIT; +} + +static bool nbd_client_connecting_wait(NBDClientSession *client) +{ + return client->state =3D=3D NBD_CLIENT_CONNECTING_WAIT || + client->state =3D=3D NBD_CLIENT_CONNECTING_INIT; +} + static coroutine_fn void nbd_connection_entry(void *opaque) { NBDConnection *con =3D opaque; @@ -98,26 +117,55 @@ static coroutine_fn void nbd_connection_entry(void *op= aque) int ret =3D 0; Error *local_err =3D NULL; =20 - if (con->reconnect_attempts !=3D 0) { - error_setg(&s->connect_err, "Reconnect is not supported yet"); - s->connect_status =3D -EINVAL; - nbd_channel_error(s, s->connect_status); - return; - } + while (s->state !=3D NBD_CLIENT_QUIT) { + assert(s->reply.handle =3D=3D 0); =20 - s->connect_status =3D nbd_client_connect(con->bs, con->saddr, - con->export, con->tlscreds, - con->hostname, &s->connect_err); - if (s->connect_status < 0) { - nbd_channel_error(s, s->connect_status); - return; - } + if (nbd_client_connecting(s)) { + if (s->connect_attempts =3D=3D con->reconnect_attempts) { + s->state =3D NBD_CLIENT_CONNECTING_NOWAIT; + qemu_co_queue_restart_all(&s->free_sema); + } =20 - /* successfully connected */ - s->state =3D NBD_CLIENT_CONNECTED; + qemu_co_mutex_lock(&s->send_mutex); + + while (s->in_flight > 0) { + qemu_co_mutex_unlock(&s->send_mutex); + nbd_recv_coroutines_wake_all(s); + s->wait_in_flight =3D true; + qemu_coroutine_yield(); + s->wait_in_flight =3D false; + qemu_co_mutex_lock(&s->send_mutex); + } + + qemu_co_mutex_unlock(&s->send_mutex); + + /* Now we are sure, that nobody accessing the channel now and = nobody + * will try to access the channel, until we set state to CONNE= CTED + */ + + s->connect_status =3D nbd_client_connect(con->bs, con->saddr, + con->export, con->tlscr= eds, + con->hostname, &local_e= rr); + s->connect_attempts++; + error_free(s->connect_err); + s->connect_err =3D NULL; + error_propagate(&s->connect_err, local_err); + local_err =3D NULL; + if (s->connect_status =3D=3D -EINVAL) { + /* Protocol error or something like this */ + nbd_channel_error(s, s->connect_status); + continue; + } + if (s->connect_status < 0) { + qemu_co_sleep_ns(QEMU_CLOCK_REALTIME, con->reconnect_timeo= ut); + continue; + } + + /* successfully connected */ + s->state =3D NBD_CLIENT_CONNECTED; + qemu_co_queue_restart_all(&s->free_sema); + } =20 - while (s->state !=3D NBD_CLIENT_QUIT) { - assert(s->reply.handle =3D=3D 0); s->receiving =3D true; ret =3D nbd_receive_reply(s->ioc, &s->reply, &local_err); s->receiving =3D false; @@ -158,6 +206,7 @@ static coroutine_fn void nbd_connection_entry(void *opa= que) qemu_coroutine_yield(); } =20 + qemu_co_queue_restart_all(&s->free_sema); nbd_recv_coroutines_wake_all(s); s->connection_co =3D NULL; } @@ -170,7 +219,7 @@ static int nbd_co_send_request(BlockDriverState *bs, int rc, i; =20 qemu_co_mutex_lock(&s->send_mutex); - while (s->in_flight =3D=3D MAX_NBD_REQUESTS) { + while (s->in_flight =3D=3D MAX_NBD_REQUESTS || nbd_client_connecting_w= ait(s)) { qemu_co_queue_wait(&s->free_sema, &s->send_mutex); } =20 @@ -219,7 +268,11 @@ err: nbd_channel_error(s, rc); s->requests[i].coroutine =3D NULL; s->in_flight--; - qemu_co_queue_next(&s->free_sema); + if (s->in_flight =3D=3D 0 && s->wait_in_flight) { + aio_co_wake(s->connection_co); + } else { + qemu_co_queue_next(&s->free_sema); + } } qemu_co_mutex_unlock(&s->send_mutex); return rc; @@ -669,7 +722,11 @@ break_loop: =20 qemu_co_mutex_lock(&s->send_mutex); s->in_flight--; - qemu_co_queue_next(&s->free_sema); + if (s->in_flight =3D=3D 0 && s->wait_in_flight) { + aio_co_wake(s->connection_co); + } else { + qemu_co_queue_next(&s->free_sema); + } qemu_co_mutex_unlock(&s->send_mutex); =20 return false; @@ -818,16 +875,21 @@ static int nbd_co_request(BlockDriverState *bs, NBDRe= quest *request, } else { assert(request->type !=3D NBD_CMD_WRITE); } - ret =3D nbd_co_send_request(bs, request, write_qiov); - if (ret < 0) { - return ret; - } =20 - ret =3D nbd_co_receive_return_code(client, request->handle, - &request_ret, &local_err); - if (local_err) { - error_report_err(local_err); - } + do { + ret =3D nbd_co_send_request(bs, request, write_qiov); + if (ret < 0) { + continue; + } + + ret =3D nbd_co_receive_return_code(client, request->handle, + &request_ret, &local_err); + if (local_err) { + error_report_err(local_err); + local_err =3D NULL; + } + } while (ret < 0 && nbd_client_connecting_wait(client)); + return ret ? ret : request_ret; } =20 @@ -849,16 +911,21 @@ int nbd_client_co_preadv(BlockDriverState *bs, uint64= _t offset, if (!bytes) { return 0; } - ret =3D nbd_co_send_request(bs, &request, NULL); - if (ret < 0) { - return ret; - } =20 - ret =3D nbd_co_receive_cmdread_reply(client, request.handle, offset, q= iov, - &request_ret, &local_err); - if (local_err) { - error_report_err(local_err); - } + do { + ret =3D nbd_co_send_request(bs, &request, NULL); + if (ret < 0) { + continue; + } + + ret =3D nbd_co_receive_cmdread_reply(client, request.handle, offse= t, qiov, + &request_ret, &local_err); + if (local_err) { + error_report_err(local_err); + local_err =3D NULL; + } + } while (ret < 0 && nbd_client_connecting_wait(client)); + return ret ? ret : request_ret; } =20 @@ -972,16 +1039,21 @@ int coroutine_fn nbd_client_co_block_status(BlockDri= verState *bs, return BDRV_BLOCK_DATA; } =20 - ret =3D nbd_co_send_request(bs, &request, NULL); - if (ret < 0) { - return ret; - } + do { + ret =3D nbd_co_send_request(bs, &request, NULL); + if (ret < 0) { + continue; + } + + ret =3D nbd_co_receive_blockstatus_reply(client, request.handle, b= ytes, + &extent, &request_ret, + &local_err); + if (local_err) { + error_report_err(local_err); + local_err =3D NULL; + } + } while (ret < 0 && nbd_client_connecting_wait(client)); =20 - ret =3D nbd_co_receive_blockstatus_reply(client, request.handle, bytes, - &extent, &request_ret, &local_e= rr); - if (local_err) { - error_report_err(local_err); - } if (ret < 0 || request_ret < 0) { return ret ? ret : request_ret; } --=20 2.11.1 From nobody Sat May 4 16:32:28 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=virtuozzo.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1528392166821163.71212675444667; Thu, 7 Jun 2018 10:22:46 -0700 (PDT) Received: from localhost ([::1]:59408 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fQycY-0005tw-1f for importer@patchew.org; Thu, 07 Jun 2018 13:22:46 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:34202) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fQyUs-0008Ao-8m for qemu-devel@nongnu.org; Thu, 07 Jun 2018 13:14:53 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fQyUo-00084l-Q8 for qemu-devel@nongnu.org; Thu, 07 Jun 2018 13:14:50 -0400 Received: from relay.sw.ru ([195.214.232.25]:52012) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1fQyUo-0007zs-Cz; Thu, 07 Jun 2018 13:14:46 -0400 Received: from msk-vpn.virtuozzo.com ([195.214.232.6] helo=kvm.sw.ru) by relay.sw.ru with esmtp (Exim 4.90_1) (envelope-from ) id 1fQyUl-0007DI-Eh; Thu, 07 Jun 2018 20:14:43 +0300 From: Vladimir Sementsov-Ogievskiy To: qemu-devel@nongnu.org, qemu-block@nongnu.org Date: Thu, 7 Jun 2018 20:14:41 +0300 Message-Id: <20180607171441.64079-12-vsementsov@virtuozzo.com> X-Mailer: git-send-email 2.11.1 In-Reply-To: <20180607171441.64079-1-vsementsov@virtuozzo.com> References: <20180607171441.64079-1-vsementsov@virtuozzo.com> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x [fuzzy] X-Received-From: 195.214.232.25 Subject: [Qemu-devel] [PATCH v2 11/11] iotests: test nbd reconnect X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: kwolf@redhat.com, vsementsov@virtuozzo.com, armbru@redhat.com, mreitz@redhat.com, den@openvz.org, pbonzini@redhat.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Add test, which starts backup to nbd target and restarts nbd server during backup. Signed-off-by: Vladimir Sementsov-Ogievskiy --- tests/qemu-iotests/220 | 68 +++++++++++++++++++++++++++++++++++++++= ++++ tests/qemu-iotests/220.out | 7 +++++ tests/qemu-iotests/group | 1 + tests/qemu-iotests/iotests.py | 4 +++ 4 files changed, 80 insertions(+) create mode 100755 tests/qemu-iotests/220 create mode 100644 tests/qemu-iotests/220.out diff --git a/tests/qemu-iotests/220 b/tests/qemu-iotests/220 new file mode 100755 index 0000000000..f1c26a2796 --- /dev/null +++ b/tests/qemu-iotests/220 @@ -0,0 +1,68 @@ +#!/usr/bin/env python +# +# Test nbd reconnect +# +# Copyright (c) 2018 Virtuozzo International GmbH +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + +import time + +import iotests +from iotests import qemu_img_create, file_path, qemu_nbd_popen + +disk_a, disk_b, nbd_sock =3D file_path('disk_a', 'disk_b', 'nbd-sock') +nbd_uri =3D 'nbd+unix:///exp?socket=3D' + nbd_sock + +qemu_img_create('-f', iotests.imgfmt, disk_a, '5M') +qemu_img_create('-f', iotests.imgfmt, disk_b, '5M') +srv =3D qemu_nbd_popen('-k', nbd_sock, '-x', 'exp', '-f', iotests.imgfmt, = disk_b) +time.sleep(1) + +vm =3D iotests.VM().add_drive(disk_a) +vm.launch() +vm.hmp_qemu_io('drive0', 'write 0 5M') + +print 'blockdev-add:', vm.qmp('blockdev-add', node_name=3D'backup0', drive= r=3D'raw', + file=3D{'driver':'nbd', + 'reconnect-attempts':10, + 'export': 'exp', + 'server': {'type': 'unix', + 'path': nbd_sock}}) +print 'blockdev-backup:', vm.qmp('blockdev-backup', device=3D'drive0', + sync=3D'full', target=3D'backup0') + +time.sleep(1) +print 'Kill NBD server' +srv.kill() + +jobs =3D vm.qmp('query-block-jobs')['return'] +if jobs and jobs[0]['offset'] < jobs[0]['len']: + print 'Backup job is still in progress' + +time.sleep(1) + +print 'Start NBD server' +srv =3D qemu_nbd_popen('-k', nbd_sock, '-x', 'exp', '-f', iotests.imgfmt, = disk_b) + +try: + e =3D vm.event_wait('BLOCK_JOB_COMPLETED') + print e['event'], ':', e['data'] +except: + pass + +print 'blockdev-del:', vm.qmp('blockdev-del', node_name=3D'backup0') +srv.kill() +vm.shutdown() diff --git a/tests/qemu-iotests/220.out b/tests/qemu-iotests/220.out new file mode 100644 index 0000000000..dae1a49d9f --- /dev/null +++ b/tests/qemu-iotests/220.out @@ -0,0 +1,7 @@ +blockdev-add: {u'return': {}} +blockdev-backup: {u'return': {}} +Kill NBD server +Backup job is still in progress +Start NBD server +BLOCK_JOB_COMPLETED : {u'device': u'drive0', u'type': u'backup', u'speed':= 0, u'len': 5242880, u'offset': 5242880} +blockdev-del: {u'return': {}} diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group index 93f93d71ba..cc5a1cf2a4 100644 --- a/tests/qemu-iotests/group +++ b/tests/qemu-iotests/group @@ -217,3 +217,4 @@ 216 rw auto quick 218 rw auto quick 219 rw auto +220 rw auto quick diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py index fdbdd8b300..7071318c9e 100644 --- a/tests/qemu-iotests/iotests.py +++ b/tests/qemu-iotests/iotests.py @@ -175,6 +175,10 @@ def qemu_nbd(*args): '''Run qemu-nbd in daemon mode and return the parent's exit code''' return subprocess.call(qemu_nbd_args + ['--fork'] + list(args)) =20 +def qemu_nbd_popen(*args): + '''Run qemu-nbd in daemon mode and return the parent's exit code''' + return subprocess.Popen(qemu_nbd_args + ['--persistent'] + list(args)) + def compare_images(img1, img2, fmt1=3Dimgfmt, fmt2=3Dimgfmt): '''Return True if two image files are identical''' return qemu_img('compare', '-f', fmt1, --=20 2.11.1