From nobody Fri May 3 23:54:14 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.zoho.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; Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1486138254729719.3649614897992; Fri, 3 Feb 2017 08:10:54 -0800 (PST) Received: from localhost ([::1]:35527 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cZgRm-0001jK-Kl for importer@patchew.org; Fri, 03 Feb 2017 11:10:50 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:36720) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cZg5n-0007nq-Mp for qemu-devel@nongnu.org; Fri, 03 Feb 2017 10:48:10 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1cZg5i-00080y-K3 for qemu-devel@nongnu.org; Fri, 03 Feb 2017 10:48:07 -0500 Received: from mailhub.sw.ru ([195.214.232.25]:29031 helo=relay.sw.ru) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1cZg5i-0007yG-7v for qemu-devel@nongnu.org; Fri, 03 Feb 2017 10:48:02 -0500 Received: from kvm.qa.sw.ru. (msk-vpn.virtuozzo.com [195.214.232.6]) by relay.sw.ru (8.13.4/8.13.4) with ESMTP id v13Flv7g011039; Fri, 3 Feb 2017 18:47:57 +0300 (MSK) From: Vladimir Sementsov-Ogievskiy To: qemu-block@nongnu.org, qemu-devel@nongnu.org Date: Fri, 3 Feb 2017 18:47:40 +0300 Message-Id: <20170203154757.36140-2-vsementsov@virtuozzo.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20170203154757.36140-1-vsementsov@virtuozzo.com> References: <20170203154757.36140-1-vsementsov@virtuozzo.com> X-detected-operating-system: by eggs.gnu.org: OpenBSD 3.x [fuzzy] X-Received-From: 195.214.232.25 Subject: [Qemu-devel] [PATCH 01/18] nbd: rename NBD_REPLY_MAGIC to NBD_SIMPLE_REPLY_MAGIC 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, famz@redhat.com, den@virtuozzo.com, armbru@redhat.com, mreitz@redhat.com, stefanha@redhat.com, pbonzini@redhat.com, jsnow@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 be consistent when NBD_STRUCTURED_REPLY_MAGIC will be introduced. Signed-off-by: Vladimir Sementsov-Ogievskiy Reviewed-by: Eric Blake --- nbd/client.c | 4 ++-- nbd/nbd-internal.h | 2 +- nbd/server.c | 4 ++-- tests/qemu-iotests/nbd-fault-injector.py | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/nbd/client.c b/nbd/client.c index ffb0743bce..de5c9366c7 100644 --- a/nbd/client.c +++ b/nbd/client.c @@ -788,7 +788,7 @@ ssize_t nbd_receive_reply(QIOChannel *ioc, NBDReply *re= ply) } =20 /* Reply - [ 0 .. 3] magic (NBD_REPLY_MAGIC) + [ 0 .. 3] magic (NBD_SIMPLE_REPLY_MAGIC) [ 4 .. 7] error (0 =3D=3D no error) [ 7 .. 15] handle */ @@ -808,7 +808,7 @@ ssize_t nbd_receive_reply(QIOChannel *ioc, NBDReply *re= ply) ", handle =3D %" PRIu64" }", magic, reply->error, reply->handle); =20 - if (magic !=3D NBD_REPLY_MAGIC) { + if (magic !=3D NBD_SIMPLE_REPLY_MAGIC) { LOG("invalid magic (got 0x%" PRIx32 ")", magic); return -EINVAL; } diff --git a/nbd/nbd-internal.h b/nbd/nbd-internal.h index eee20abc25..49b66b6896 100644 --- a/nbd/nbd-internal.h +++ b/nbd/nbd-internal.h @@ -59,7 +59,7 @@ #define NBD_REQUEST_SIZE (4 + 2 + 2 + 8 + 8 + 4) #define NBD_REPLY_SIZE (4 + 4 + 8) #define NBD_REQUEST_MAGIC 0x25609513 -#define NBD_REPLY_MAGIC 0x67446698 +#define NBD_SIMPLE_REPLY_MAGIC 0x67446698 #define NBD_OPTS_MAGIC 0x49484156454F5054LL #define NBD_CLIENT_MAGIC 0x0000420281861253LL #define NBD_REP_MAGIC 0x0003e889045565a9LL diff --git a/nbd/server.c b/nbd/server.c index 5b76261666..b63a8b85e3 100644 --- a/nbd/server.c +++ b/nbd/server.c @@ -750,11 +750,11 @@ static ssize_t nbd_send_reply(QIOChannel *ioc, NBDRep= ly *reply) reply->error, reply->handle); =20 /* Reply - [ 0 .. 3] magic (NBD_REPLY_MAGIC) + [ 0 .. 3] magic (NBD_SIMPLE_REPLY_MAGIC) [ 4 .. 7] error (0 =3D=3D no error) [ 7 .. 15] handle */ - stl_be_p(buf, NBD_REPLY_MAGIC); + stl_be_p(buf, NBD_SIMPLE_REPLY_MAGIC); stl_be_p(buf + 4, reply->error); stq_be_p(buf + 8, reply->handle); =20 diff --git a/tests/qemu-iotests/nbd-fault-injector.py b/tests/qemu-iotests/= nbd-fault-injector.py index 6c07191a5a..5d092ee1f6 100755 --- a/tests/qemu-iotests/nbd-fault-injector.py +++ b/tests/qemu-iotests/nbd-fault-injector.py @@ -56,7 +56,7 @@ NBD_CMD_READ =3D 0 NBD_CMD_WRITE =3D 1 NBD_CMD_DISC =3D 2 NBD_REQUEST_MAGIC =3D 0x25609513 -NBD_REPLY_MAGIC =3D 0x67446698 +NBD_SIMPLE_REPLY_MAGIC =3D 0x67446698 NBD_PASSWD =3D 0x4e42444d41474943 NBD_OPTS_MAGIC =3D 0x49484156454F5054 NBD_CLIENT_MAGIC =3D 0x0000420281861253 @@ -166,7 +166,7 @@ def read_request(conn): return req =20 def write_reply(conn, error, handle): - buf =3D reply_struct.pack(NBD_REPLY_MAGIC, error, handle) + buf =3D reply_struct.pack(NBD_SIMPLE_REPLY_MAGIC, error, handle) conn.send(buf, event=3D'reply') =20 def handle_connection(conn, use_export): --=20 2.11.0 From nobody Fri May 3 23:54:14 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.zoho.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; Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1486137542172125.72527068262968; Fri, 3 Feb 2017 07:59:02 -0800 (PST) Received: from localhost ([::1]:35443 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cZgGK-0008Rh-7i for importer@patchew.org; Fri, 03 Feb 2017 10:59:00 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:36694) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cZg5n-0007nX-Bg for qemu-devel@nongnu.org; Fri, 03 Feb 2017 10:48:09 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1cZg5i-00080f-Bj for qemu-devel@nongnu.org; Fri, 03 Feb 2017 10:48:07 -0500 Received: from mailhub.sw.ru ([195.214.232.25]:40088 helo=relay.sw.ru) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1cZg5i-0007xa-0N for qemu-devel@nongnu.org; Fri, 03 Feb 2017 10:48:02 -0500 Received: from kvm.qa.sw.ru. (msk-vpn.virtuozzo.com [195.214.232.6]) by relay.sw.ru (8.13.4/8.13.4) with ESMTP id v13Flv7h011039; Fri, 3 Feb 2017 18:47:57 +0300 (MSK) From: Vladimir Sementsov-Ogievskiy To: qemu-block@nongnu.org, qemu-devel@nongnu.org Date: Fri, 3 Feb 2017 18:47:41 +0300 Message-Id: <20170203154757.36140-3-vsementsov@virtuozzo.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20170203154757.36140-1-vsementsov@virtuozzo.com> References: <20170203154757.36140-1-vsementsov@virtuozzo.com> X-detected-operating-system: by eggs.gnu.org: OpenBSD 3.x [fuzzy] X-Received-From: 195.214.232.25 Subject: [Qemu-devel] [PATCH 02/18] nbd-server: refactor simple reply sending 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, famz@redhat.com, den@virtuozzo.com, armbru@redhat.com, mreitz@redhat.com, stefanha@redhat.com, pbonzini@redhat.com, jsnow@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" Rename functions appropriately and also make a separate copy of NBDReply - NBDSimpleReply, to replace NBDReply for the server. NBDReply itself will be upgraded in future patches to handle both simple and structured replies in the client. Signed-off-by: Vladimir Sementsov-Ogievskiy Reviewed-by: Eric Blake --- include/block/nbd.h | 7 +++++++ nbd/server.c | 25 +++++++++++++------------ 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/include/block/nbd.h b/include/block/nbd.h index 3e373f0498..3c65cf8d87 100644 --- a/include/block/nbd.h +++ b/include/block/nbd.h @@ -63,6 +63,13 @@ struct NBDReply { }; typedef struct NBDReply NBDReply; =20 +struct NBDSimpleReply { + /* uint32_t NBD_SIMPLE_REPLY_MAGIC */ + uint64_t handle; + uint32_t error; +}; +typedef struct NBDSimpleReply NBDSimpleReply; + /* Transmission (export) flags: sent from server to client during handshak= e, but describe what will happen during transmission */ #define NBD_FLAG_HAS_FLAGS (1 << 0) /* Flags are there */ diff --git a/nbd/server.c b/nbd/server.c index b63a8b85e3..4cfc02123b 100644 --- a/nbd/server.c +++ b/nbd/server.c @@ -738,7 +738,7 @@ static ssize_t nbd_receive_request(QIOChannel *ioc, NBD= Request *request) return 0; } =20 -static ssize_t nbd_send_reply(QIOChannel *ioc, NBDReply *reply) +static ssize_t nbd_send_simple_reply(QIOChannel *ioc, NBDSimpleReply *repl= y) { uint8_t buf[NBD_REPLY_SIZE]; ssize_t ret; @@ -1036,8 +1036,8 @@ void nbd_export_close_all(void) } } =20 -static ssize_t nbd_co_send_reply(NBDRequestData *req, NBDReply *reply, - int len) +static ssize_t nbd_co_send_simple_reply(NBDRequestData *req, + NBDSimpleReply *reply, int len) { NBDClient *client =3D req->client; ssize_t rc, ret; @@ -1048,10 +1048,10 @@ static ssize_t nbd_co_send_reply(NBDRequestData *re= q, NBDReply *reply, nbd_set_handlers(client); =20 if (!len) { - rc =3D nbd_send_reply(client->ioc, reply); + rc =3D nbd_send_simple_reply(client->ioc, reply); } else { qio_channel_set_cork(client->ioc, true); - rc =3D nbd_send_reply(client->ioc, reply); + rc =3D nbd_send_simple_reply(client->ioc, reply); if (rc >=3D 0) { ret =3D write_sync(client->ioc, req->data, len); if (ret !=3D len) { @@ -1174,7 +1174,7 @@ static void nbd_trip(void *opaque) NBDExport *exp =3D client->exp; NBDRequestData *req; NBDRequest request; - NBDReply reply; + NBDSimpleReply reply; ssize_t ret; int flags; =20 @@ -1231,8 +1231,9 @@ static void nbd_trip(void *opaque) } =20 TRACE("Read %" PRIu32" byte(s)", request.len); - if (nbd_co_send_reply(req, &reply, request.len) < 0) + if (nbd_co_send_simple_reply(req, &reply, request.len) < 0) { goto out; + } break; case NBD_CMD_WRITE: TRACE("Request type is WRITE"); @@ -1257,7 +1258,7 @@ static void nbd_trip(void *opaque) goto error_reply; } =20 - if (nbd_co_send_reply(req, &reply, 0) < 0) { + if (nbd_co_send_simple_reply(req, &reply, 0) < 0) { goto out; } break; @@ -1288,7 +1289,7 @@ static void nbd_trip(void *opaque) goto error_reply; } =20 - if (nbd_co_send_reply(req, &reply, 0) < 0) { + if (nbd_co_send_simple_reply(req, &reply, 0) < 0) { goto out; } break; @@ -1305,7 +1306,7 @@ static void nbd_trip(void *opaque) LOG("flush failed"); reply.error =3D -ret; } - if (nbd_co_send_reply(req, &reply, 0) < 0) { + if (nbd_co_send_simple_reply(req, &reply, 0) < 0) { goto out; } break; @@ -1317,7 +1318,7 @@ static void nbd_trip(void *opaque) LOG("discard failed"); reply.error =3D -ret; } - if (nbd_co_send_reply(req, &reply, 0) < 0) { + if (nbd_co_send_simple_reply(req, &reply, 0) < 0) { goto out; } break; @@ -1328,7 +1329,7 @@ static void nbd_trip(void *opaque) /* We must disconnect after NBD_CMD_WRITE if we did not * read the payload. */ - if (nbd_co_send_reply(req, &reply, 0) < 0 || !req->complete) { + if (nbd_co_send_simple_reply(req, &reply, 0) < 0 || !req->complete= ) { goto out; } break; --=20 2.11.0 From nobody Fri May 3 23:54:14 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.zoho.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; Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 148613832371453.02353477198483; Fri, 3 Feb 2017 08:12:03 -0800 (PST) Received: from localhost ([::1]:35530 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cZgSu-0002fR-OE for importer@patchew.org; Fri, 03 Feb 2017 11:12:00 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:36728) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cZg5o-0007oz-4w for qemu-devel@nongnu.org; Fri, 03 Feb 2017 10:48:13 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1cZg5j-00081b-2Z for qemu-devel@nongnu.org; Fri, 03 Feb 2017 10:48:08 -0500 Received: from mailhub.sw.ru ([195.214.232.25]:2837 helo=relay.sw.ru) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1cZg5i-0007xZ-J4 for qemu-devel@nongnu.org; Fri, 03 Feb 2017 10:48:03 -0500 Received: from kvm.qa.sw.ru. (msk-vpn.virtuozzo.com [195.214.232.6]) by relay.sw.ru (8.13.4/8.13.4) with ESMTP id v13Flv7i011039; Fri, 3 Feb 2017 18:47:57 +0300 (MSK) From: Vladimir Sementsov-Ogievskiy To: qemu-block@nongnu.org, qemu-devel@nongnu.org Date: Fri, 3 Feb 2017 18:47:42 +0300 Message-Id: <20170203154757.36140-4-vsementsov@virtuozzo.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20170203154757.36140-1-vsementsov@virtuozzo.com> References: <20170203154757.36140-1-vsementsov@virtuozzo.com> X-detected-operating-system: by eggs.gnu.org: OpenBSD 3.x [fuzzy] X-Received-From: 195.214.232.25 Subject: [Qemu-devel] [PATCH 03/18] nbd: Minimal structured read for server 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, famz@redhat.com, den@virtuozzo.com, armbru@redhat.com, mreitz@redhat.com, stefanha@redhat.com, pbonzini@redhat.com, jsnow@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" Minimal implementation of structured read: one data chunk + finishing none chunk. No segmentation. Minimal structured error implementation: no text message. Support DF flag, but just ignore it, as there is no segmentation any way. Signed-off-by: Vladimir Sementsov-Ogievskiy --- include/block/nbd.h | 31 +++++++++++++ nbd/nbd-internal.h | 2 + nbd/server.c | 125 ++++++++++++++++++++++++++++++++++++++++++++++++= ++-- 3 files changed, 154 insertions(+), 4 deletions(-) diff --git a/include/block/nbd.h b/include/block/nbd.h index 3c65cf8d87..58b864f145 100644 --- a/include/block/nbd.h +++ b/include/block/nbd.h @@ -70,6 +70,25 @@ struct NBDSimpleReply { }; typedef struct NBDSimpleReply NBDSimpleReply; =20 +typedef struct NBDStructuredReplyChunk { + uint32_t magic; + uint16_t flags; + uint16_t type; + uint64_t handle; + uint32_t length; +} QEMU_PACKED NBDStructuredReplyChunk; + +typedef struct NBDStructuredRead { + NBDStructuredReplyChunk h; + uint64_t offset; +} QEMU_PACKED NBDStructuredRead; + +typedef struct NBDStructuredError { + NBDStructuredReplyChunk h; + uint32_t error; + uint16_t message_length; +} QEMU_PACKED NBDStructuredError; + /* Transmission (export) flags: sent from server to client during handshak= e, but describe what will happen during transmission */ #define NBD_FLAG_HAS_FLAGS (1 << 0) /* Flags are there */ @@ -79,6 +98,7 @@ typedef struct NBDSimpleReply NBDSimpleReply; #define NBD_FLAG_ROTATIONAL (1 << 4) /* Use elevator algorithm = - rotational media */ #define NBD_FLAG_SEND_TRIM (1 << 5) /* Send TRIM (discard) */ #define NBD_FLAG_SEND_WRITE_ZEROES (1 << 6) /* Send WRITE_ZEROES */ +#define NBD_FLAG_SEND_DF (1 << 7) /* Send DF (Do not Fragmen= t) */ =20 /* New-style handshake (global) flags, sent from server to client, and control what will happen during handshake phase. */ @@ -106,6 +126,7 @@ typedef struct NBDSimpleReply NBDSimpleReply; /* Request flags, sent from client to server during transmission phase */ #define NBD_CMD_FLAG_FUA (1 << 0) /* 'force unit access' during wri= te */ #define NBD_CMD_FLAG_NO_HOLE (1 << 1) /* don't punch hole on zero run */ +#define NBD_CMD_FLAG_DF (1 << 2) /* don't fragment structured read= */ =20 /* Supported request types */ enum { @@ -130,6 +151,16 @@ enum { * aren't overflowing some other buffer. */ #define NBD_MAX_NAME_SIZE 256 =20 +/* Structured reply flags */ +#define NBD_REPLY_FLAG_DONE 1 + +/* Structured reply types */ +#define NBD_REPLY_TYPE_NONE 0 +#define NBD_REPLY_TYPE_OFFSET_DATA 1 +#define NBD_REPLY_TYPE_OFFSET_HOLE 2 +#define NBD_REPLY_TYPE_ERROR ((1 << 15) + 1) +#define NBD_REPLY_TYPE_ERROR_OFFSET ((1 << 15) + 2) + ssize_t nbd_wr_syncv(QIOChannel *ioc, struct iovec *iov, size_t niov, diff --git a/nbd/nbd-internal.h b/nbd/nbd-internal.h index 49b66b6896..489eeaf887 100644 --- a/nbd/nbd-internal.h +++ b/nbd/nbd-internal.h @@ -60,6 +60,7 @@ #define NBD_REPLY_SIZE (4 + 4 + 8) #define NBD_REQUEST_MAGIC 0x25609513 #define NBD_SIMPLE_REPLY_MAGIC 0x67446698 +#define NBD_STRUCTURED_REPLY_MAGIC 0x668e33ef #define NBD_OPTS_MAGIC 0x49484156454F5054LL #define NBD_CLIENT_MAGIC 0x0000420281861253LL #define NBD_REP_MAGIC 0x0003e889045565a9LL @@ -81,6 +82,7 @@ #define NBD_OPT_LIST (3) #define NBD_OPT_PEEK_EXPORT (4) #define NBD_OPT_STARTTLS (5) +#define NBD_OPT_STRUCTURED_REPLY (8) =20 /* NBD errors are based on errno numbers, so there is a 1:1 mapping, * but only a limited set of errno values is specified in the protocol. diff --git a/nbd/server.c b/nbd/server.c index 4cfc02123b..cb79a93c87 100644 --- a/nbd/server.c +++ b/nbd/server.c @@ -100,6 +100,8 @@ struct NBDClient { QTAILQ_ENTRY(NBDClient) next; int nb_requests; bool closing; + + bool structured_reply; }; =20 /* That's all folks */ @@ -573,6 +575,16 @@ static int nbd_negotiate_options(NBDClient *client) return ret; } break; + + case NBD_OPT_STRUCTURED_REPLY: + client->structured_reply =3D true; + ret =3D nbd_negotiate_send_rep(client->ioc, NBD_REP_ACK, + clientflags); + if (ret < 0) { + return ret; + } + break; + default: if (nbd_negotiate_drop_sync(client->ioc, length) !=3D leng= th) { return -EIO; @@ -1067,6 +1079,86 @@ static ssize_t nbd_co_send_simple_reply(NBDRequestDa= ta *req, return rc; } =20 +static void set_be_chunk(NBDStructuredReplyChunk *chunk, uint16_t flags, + uint16_t type, uint64_t handle, uint32_t length) +{ + stl_be_p(&chunk->magic, NBD_STRUCTURED_REPLY_MAGIC); + stw_be_p(&chunk->flags, flags); + stw_be_p(&chunk->type, type); + stq_be_p(&chunk->handle, handle); + stl_be_p(&chunk->length, length); +} + +static int nbd_co_send_iov(NBDClient *client, struct iovec *iov, unsigned = niov) +{ + ssize_t ret; + size_t size =3D iov_size(iov, niov); + + g_assert(qemu_in_coroutine()); + qemu_co_mutex_lock(&client->send_lock); + client->send_coroutine =3D qemu_coroutine_self(); + nbd_set_handlers(client); + + ret =3D nbd_wr_syncv(client->ioc, iov, niov, size, false); + if (ret >=3D 0 && ret !=3D size) { + ret =3D -EIO; + } + + client->send_coroutine =3D NULL; + nbd_set_handlers(client); + qemu_co_mutex_unlock(&client->send_lock); + + return ret; +} + +static inline int nbd_co_send_buf(NBDClient *client, void *buf, size_t siz= e) +{ + struct iovec iov[] =3D { + {.iov_base =3D buf, .iov_len =3D size} + }; + + return nbd_co_send_iov(client, iov, 1); +} + +static int nbd_co_send_structured_read(NBDClient *client, uint64_t handle, + uint64_t offset, void *data, size_t= size) +{ + NBDStructuredRead chunk; + + struct iovec iov[] =3D { + {.iov_base =3D &chunk, .iov_len =3D sizeof(chunk)}, + {.iov_base =3D data, .iov_len =3D size} + }; + + set_be_chunk(&chunk.h, 0, NBD_REPLY_TYPE_OFFSET_DATA, handle, + sizeof(chunk) - sizeof(chunk.h) + size); + stq_be_p(&chunk.offset, offset); + + return nbd_co_send_iov(client, iov, 2); +} + +static int nbd_co_send_structured_error(NBDClient *client, uint64_t handle, + uint32_t error) +{ + NBDStructuredError chunk; + + set_be_chunk(&chunk.h, NBD_REPLY_FLAG_DONE, NBD_REPLY_TYPE_ERROR, hand= le, + sizeof(chunk) - sizeof(chunk.h)); + stl_be_p(&chunk.error, error); + stw_be_p(&chunk.message_length, 0); + + return nbd_co_send_buf(client, &chunk, sizeof(chunk)); +} + +static int nbd_co_send_structured_none(NBDClient *client, uint64_t handle) +{ + NBDStructuredReplyChunk chunk; + + set_be_chunk(&chunk, NBD_REPLY_FLAG_DONE, NBD_REPLY_TYPE_NONE, handle,= 0); + + return nbd_co_send_buf(client, &chunk, sizeof(chunk)); +} + /* Collect a client request. Return 0 if request looks valid, -EAGAIN * to keep trying the collection, -EIO to drop connection right away, * and any other negative value to report an error to the client @@ -1147,7 +1239,8 @@ static ssize_t nbd_co_receive_request(NBDRequestData = *req, rc =3D request->type =3D=3D NBD_CMD_WRITE ? -ENOSPC : -EINVAL; goto out; } - if (request->flags & ~(NBD_CMD_FLAG_FUA | NBD_CMD_FLAG_NO_HOLE)) { + if (request->flags & ~(NBD_CMD_FLAG_FUA | NBD_CMD_FLAG_NO_HOLE | + NBD_CMD_FLAG_DF)) { LOG("unsupported flags (got 0x%x)", request->flags); rc =3D -EINVAL; goto out; @@ -1226,12 +1319,34 @@ static void nbd_trip(void *opaque) req->data, request.len); if (ret < 0) { LOG("reading from file failed"); - reply.error =3D -ret; - goto error_reply; + if (client->structured_reply) { + ret =3D nbd_co_send_structured_error(req->client, request.= handle, + -ret); + if (ret < 0) { + goto out; + } else { + break; + } + } else { + reply.error =3D -ret; + goto error_reply; + } } =20 TRACE("Read %" PRIu32" byte(s)", request.len); - if (nbd_co_send_simple_reply(req, &reply, request.len) < 0) { + if (client->structured_reply) { + ret =3D nbd_co_send_structured_read(req->client, request.handl= e, + request.from, req->data, + request.len); + if (ret < 0) { + goto out; + } + + ret =3D nbd_co_send_structured_none(req->client, request.handl= e); + } else { + ret =3D nbd_co_send_simple_reply(req, &reply, request.len); + } + if (ret < 0) { goto out; } break; @@ -1444,6 +1559,8 @@ void nbd_client_new(NBDExport *exp, client->can_read =3D true; client->close =3D close_fn; =20 + client->structured_reply =3D false; + data->client =3D client; data->co =3D qemu_coroutine_create(nbd_co_client_start, data); qemu_coroutine_enter(data->co); --=20 2.11.0 From nobody Fri May 3 23:54:14 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.zoho.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; Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1486138054461164.54547537314113; Fri, 3 Feb 2017 08:07:34 -0800 (PST) Received: from localhost ([::1]:35499 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cZgOZ-0007MX-Ka for importer@patchew.org; Fri, 03 Feb 2017 11:07:31 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:36695) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cZg5n-0007nZ-Bm for qemu-devel@nongnu.org; Fri, 03 Feb 2017 10:48:09 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1cZg5j-00081z-4U for qemu-devel@nongnu.org; Fri, 03 Feb 2017 10:48:07 -0500 Received: from mailhub.sw.ru ([195.214.232.25]:42403 helo=relay.sw.ru) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1cZg5i-0007zf-P0 for qemu-devel@nongnu.org; Fri, 03 Feb 2017 10:48:03 -0500 Received: from kvm.qa.sw.ru. (msk-vpn.virtuozzo.com [195.214.232.6]) by relay.sw.ru (8.13.4/8.13.4) with ESMTP id v13Flv7j011039; Fri, 3 Feb 2017 18:47:57 +0300 (MSK) From: Vladimir Sementsov-Ogievskiy To: qemu-block@nongnu.org, qemu-devel@nongnu.org Date: Fri, 3 Feb 2017 18:47:43 +0300 Message-Id: <20170203154757.36140-5-vsementsov@virtuozzo.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20170203154757.36140-1-vsementsov@virtuozzo.com> References: <20170203154757.36140-1-vsementsov@virtuozzo.com> X-detected-operating-system: by eggs.gnu.org: OpenBSD 3.x [fuzzy] X-Received-From: 195.214.232.25 Subject: [Qemu-devel] [PATCH 04/18] nbd/client: refactor nbd_receive_starttls 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, famz@redhat.com, den@virtuozzo.com, armbru@redhat.com, mreitz@redhat.com, stefanha@redhat.com, pbonzini@redhat.com, jsnow@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 out nbd_receive_simple_option to be reused for structured reply option. Signed-off-by: Vladimir Sementsov-Ogievskiy --- nbd/client.c | 54 +++++++++++++++++++++++++++++++++++---------------= ---- nbd/nbd-internal.h | 14 ++++++++++++++ 2 files changed, 49 insertions(+), 19 deletions(-) diff --git a/nbd/client.c b/nbd/client.c index de5c9366c7..6caf6bda6d 100644 --- a/nbd/client.c +++ b/nbd/client.c @@ -395,39 +395,55 @@ static int nbd_receive_query_exports(QIOChannel *ioc, } } =20 -static QIOChannel *nbd_receive_starttls(QIOChannel *ioc, - QCryptoTLSCreds *tlscreds, - const char *hostname, Error **errp) +static int nbd_receive_simple_option(QIOChannel *ioc, int opt, + bool abort_on_notsup, Error **errp) { nbd_opt_reply reply; - QIOChannelTLS *tioc; - struct NBDTLSHandshakeData data =3D { 0 }; =20 - TRACE("Requesting TLS from server"); - if (nbd_send_option_request(ioc, NBD_OPT_STARTTLS, 0, NULL, errp) < 0)= { - return NULL; + TRACE("Requesting '%s' option from server", nbd_opt_name(opt)); + if (nbd_send_option_request(ioc, opt, 0, NULL, errp) < 0) { + return -1; } =20 - TRACE("Getting TLS reply from server"); - if (nbd_receive_option_reply(ioc, NBD_OPT_STARTTLS, &reply, errp) < 0)= { - return NULL; + TRACE("Getting '%s' option reply from server", nbd_opt_name(opt)); + if (nbd_receive_option_reply(ioc, opt, &reply, errp) < 0) { + return -1; } =20 if (reply.type !=3D NBD_REP_ACK) { - error_setg(errp, "Server rejected request to start TLS %" PRIx32, - reply.type); - nbd_send_opt_abort(ioc); - return NULL; + error_setg(errp, "Server rejected request for '%s' option: %" PRIx= 32, + nbd_opt_name(opt), reply.type); + if (abort_on_notsup) { + nbd_send_opt_abort(ioc); + } + return -1; } =20 if (reply.length !=3D 0) { - error_setg(errp, "Start TLS response was not zero %" PRIu32, - reply.length); - nbd_send_opt_abort(ioc); + error_setg(errp, "'%s' option response was not zero %" PRIu32, + nbd_opt_name(opt), reply.length); + if (abort_on_notsup) { + nbd_send_opt_abort(ioc); + } + return -1; + } + + TRACE("%s 'option' approved", nbd_opt_name(opt)); + return 0; +} + +static QIOChannel *nbd_receive_starttls(QIOChannel *ioc, + QCryptoTLSCreds *tlscreds, + const char *hostname, Error **errp) +{ + QIOChannelTLS *tioc; + struct NBDTLSHandshakeData data =3D { 0 }; + + if (nbd_receive_simple_option(ioc, NBD_OPT_STARTTLS, true, errp) < 0) { return NULL; } =20 - TRACE("TLS request approved, setting up TLS"); + TRACE("Setting up TLS"); tioc =3D qio_channel_tls_new_client(ioc, tlscreds, hostname, errp); if (!tioc) { return NULL; diff --git a/nbd/nbd-internal.h b/nbd/nbd-internal.h index 489eeaf887..3284bfc85a 100644 --- a/nbd/nbd-internal.h +++ b/nbd/nbd-internal.h @@ -96,6 +96,20 @@ #define NBD_ENOSPC 28 #define NBD_ESHUTDOWN 108 =20 +static inline const char *nbd_opt_name(int opt) +{ + switch (opt) { + case NBD_OPT_EXPORT_NAME: return "export_name"; + case NBD_OPT_ABORT: return "abort"; + case NBD_OPT_LIST: return "list"; + case NBD_OPT_PEEK_EXPORT: return "peek_export"; + case NBD_OPT_STARTTLS: return "tls"; + case NBD_OPT_STRUCTURED_REPLY: return "structured_reply"; + } + + return ""; +} + static inline ssize_t read_sync(QIOChannel *ioc, void *buffer, size_t size) { struct iovec iov =3D { .iov_base =3D buffer, .iov_len =3D size }; --=20 2.11.0 From nobody Fri May 3 23:54:14 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.zoho.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; Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1486137284678787.483718288543; Fri, 3 Feb 2017 07:54:44 -0800 (PST) Received: from localhost ([::1]:35421 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cZgCA-0004Vq-GH for importer@patchew.org; Fri, 03 Feb 2017 10:54:42 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:36705) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cZg5n-0007nh-CK for qemu-devel@nongnu.org; Fri, 03 Feb 2017 10:48:09 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1cZg5j-00081h-3C for qemu-devel@nongnu.org; Fri, 03 Feb 2017 10:48:07 -0500 Received: from mailhub.sw.ru ([195.214.232.25]:43301 helo=relay.sw.ru) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1cZg5i-0007zE-Nh for qemu-devel@nongnu.org; Fri, 03 Feb 2017 10:48:03 -0500 Received: from kvm.qa.sw.ru. (msk-vpn.virtuozzo.com [195.214.232.6]) by relay.sw.ru (8.13.4/8.13.4) with ESMTP id v13Flv7k011039; Fri, 3 Feb 2017 18:47:57 +0300 (MSK) From: Vladimir Sementsov-Ogievskiy To: qemu-block@nongnu.org, qemu-devel@nongnu.org Date: Fri, 3 Feb 2017 18:47:44 +0300 Message-Id: <20170203154757.36140-6-vsementsov@virtuozzo.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20170203154757.36140-1-vsementsov@virtuozzo.com> References: <20170203154757.36140-1-vsementsov@virtuozzo.com> X-detected-operating-system: by eggs.gnu.org: OpenBSD 3.x [fuzzy] X-Received-From: 195.214.232.25 Subject: [Qemu-devel] [PATCH 05/18] nbd/client: fix drop_sync 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, famz@redhat.com, den@virtuozzo.com, armbru@redhat.com, mreitz@redhat.com, stefanha@redhat.com, pbonzini@redhat.com, jsnow@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" Comparison symbol is misused. It may lead to memory corruption. Signed-off-by: Vladimir Sementsov-Ogievskiy Reviewed-by: Eric Blake --- nbd/client.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nbd/client.c b/nbd/client.c index 6caf6bda6d..351731bc63 100644 --- a/nbd/client.c +++ b/nbd/client.c @@ -94,7 +94,7 @@ static ssize_t drop_sync(QIOChannel *ioc, size_t size) char small[1024]; char *buffer; =20 - buffer =3D sizeof(small) < size ? small : g_malloc(MIN(65536, size)); + buffer =3D sizeof(small) > size ? small : g_malloc(MIN(65536, size)); while (size > 0) { ssize_t count =3D read_sync(ioc, buffer, MIN(65536, size)); =20 --=20 2.11.0 From nobody Fri May 3 23:54:14 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.zoho.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; Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1486137829966829.8424087902505; Fri, 3 Feb 2017 08:03:49 -0800 (PST) Received: from localhost ([::1]:35475 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cZgKy-0003zv-8v for importer@patchew.org; Fri, 03 Feb 2017 11:03:48 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:36723) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cZg5n-0007nv-T1 for qemu-devel@nongnu.org; Fri, 03 Feb 2017 10:48:10 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1cZg5j-00081q-45 for qemu-devel@nongnu.org; Fri, 03 Feb 2017 10:48:07 -0500 Received: from mailhub.sw.ru ([195.214.232.25]:22640 helo=relay.sw.ru) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1cZg5i-0007zl-Na for qemu-devel@nongnu.org; Fri, 03 Feb 2017 10:48:03 -0500 Received: from kvm.qa.sw.ru. (msk-vpn.virtuozzo.com [195.214.232.6]) by relay.sw.ru (8.13.4/8.13.4) with ESMTP id v13Flv7l011039; Fri, 3 Feb 2017 18:47:57 +0300 (MSK) From: Vladimir Sementsov-Ogievskiy To: qemu-block@nongnu.org, qemu-devel@nongnu.org Date: Fri, 3 Feb 2017 18:47:45 +0300 Message-Id: <20170203154757.36140-7-vsementsov@virtuozzo.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20170203154757.36140-1-vsementsov@virtuozzo.com> References: <20170203154757.36140-1-vsementsov@virtuozzo.com> X-detected-operating-system: by eggs.gnu.org: OpenBSD 3.x [fuzzy] X-Received-From: 195.214.232.25 Subject: [Qemu-devel] [PATCH 06/18] nbd/client: refactor drop_sync 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, famz@redhat.com, den@virtuozzo.com, armbru@redhat.com, mreitz@redhat.com, stefanha@redhat.com, pbonzini@redhat.com, jsnow@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" Return 0 on success to simplify success checking. Signed-off-by: Vladimir Sementsov-Ogievskiy --- nbd/client.c | 35 +++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/nbd/client.c b/nbd/client.c index 351731bc63..1c274f3012 100644 --- a/nbd/client.c +++ b/nbd/client.c @@ -86,31 +86,34 @@ static QTAILQ_HEAD(, NBDExport) exports =3D QTAILQ_HEAD= _INITIALIZER(exports); =20 */ =20 -/* Discard length bytes from channel. Return -errno on failure, or - * the amount of bytes consumed. */ -static ssize_t drop_sync(QIOChannel *ioc, size_t size) +/* Discard length bytes from channel. + * Return 0 on success and -errno on fail. + */ +static int drop_sync(QIOChannel *ioc, size_t size) { - ssize_t ret =3D 0; + ssize_t ret; char small[1024]; char *buffer; =20 buffer =3D sizeof(small) > size ? small : g_malloc(MIN(65536, size)); while (size > 0) { - ssize_t count =3D read_sync(ioc, buffer, MIN(65536, size)); - - if (count <=3D 0) { - goto cleanup; + ret =3D read_sync(ioc, buffer, MIN(65536, size)); + if (ret =3D=3D 0) { + ret =3D -EIO; + } + if (ret < 0) { + break; } - assert(count <=3D size); - size -=3D count; - ret +=3D count; + + assert(ret <=3D size); + size -=3D ret; } =20 - cleanup: if (buffer !=3D small) { g_free(buffer); } - return ret; + + return ret < 0 ? ret : 0; } =20 /* Send an option request. @@ -334,7 +337,7 @@ static int nbd_receive_list(QIOChannel *ioc, const char= *want, bool *match, return -1; } if (namelen !=3D strlen(want)) { - if (drop_sync(ioc, len) !=3D len) { + if (drop_sync(ioc, len) < 0) { error_setg(errp, "failed to skip export name with wrong length= "); nbd_send_opt_abort(ioc); return -1; @@ -350,7 +353,7 @@ static int nbd_receive_list(QIOChannel *ioc, const char= *want, bool *match, } name[namelen] =3D '\0'; len -=3D namelen; - if (drop_sync(ioc, len) !=3D len) { + if (drop_sync(ioc, len) < 0) { error_setg(errp, "failed to read export description"); nbd_send_opt_abort(ioc); return -1; @@ -635,7 +638,7 @@ int nbd_receive_negotiate(QIOChannel *ioc, const char *= name, uint16_t *flags, } =20 TRACE("Size is %" PRIu64 ", export flags %" PRIx16, *size, *flags); - if (zeroes && drop_sync(ioc, 124) !=3D 124) { + if (zeroes && drop_sync(ioc, 124) < 0) { error_setg(errp, "Failed to read reserved block"); goto fail; } --=20 2.11.0 From nobody Fri May 3 23:54:14 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.zoho.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; Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1486137021782643.0420505592236; Fri, 3 Feb 2017 07:50:21 -0800 (PST) Received: from localhost ([::1]:35401 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cZg7v-0000h9-N0 for importer@patchew.org; Fri, 03 Feb 2017 10:50:19 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:36703) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cZg5n-0007ng-Cn for qemu-devel@nongnu.org; Fri, 03 Feb 2017 10:48:11 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1cZg5j-00081v-4G for qemu-devel@nongnu.org; Fri, 03 Feb 2017 10:48:07 -0500 Received: from mailhub.sw.ru ([195.214.232.25]:45806 helo=relay.sw.ru) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1cZg5i-0007yr-Ji for qemu-devel@nongnu.org; Fri, 03 Feb 2017 10:48:03 -0500 Received: from kvm.qa.sw.ru. (msk-vpn.virtuozzo.com [195.214.232.6]) by relay.sw.ru (8.13.4/8.13.4) with ESMTP id v13Flv7m011039; Fri, 3 Feb 2017 18:47:57 +0300 (MSK) From: Vladimir Sementsov-Ogievskiy To: qemu-block@nongnu.org, qemu-devel@nongnu.org Date: Fri, 3 Feb 2017 18:47:46 +0300 Message-Id: <20170203154757.36140-8-vsementsov@virtuozzo.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20170203154757.36140-1-vsementsov@virtuozzo.com> References: <20170203154757.36140-1-vsementsov@virtuozzo.com> X-detected-operating-system: by eggs.gnu.org: OpenBSD 3.x [fuzzy] X-Received-From: 195.214.232.25 Subject: [Qemu-devel] [PATCH 07/18] nbd: Minimal structured read for 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, famz@redhat.com, den@virtuozzo.com, armbru@redhat.com, mreitz@redhat.com, stefanha@redhat.com, pbonzini@redhat.com, jsnow@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" Minimal implementation: always send DF flag, to not deal with fragmented replies. Signed-off-by: Vladimir Sementsov-Ogievskiy --- block/nbd-client.c | 47 +++++++++++---- block/nbd-client.h | 2 + include/block/nbd.h | 15 +++-- nbd/client.c | 170 ++++++++++++++++++++++++++++++++++++++++++++++--= ---- qemu-nbd.c | 2 +- 5 files changed, 203 insertions(+), 33 deletions(-) diff --git a/block/nbd-client.c b/block/nbd-client.c index 3779c6c999..ff96bd1635 100644 --- a/block/nbd-client.c +++ b/block/nbd-client.c @@ -180,13 +180,20 @@ static void nbd_co_receive_reply(NBDClientSession *s, *reply =3D s->reply; if (reply->handle !=3D request->handle || !s->ioc) { + reply->simple =3D true; reply->error =3D EIO; } else { - if (qiov && reply->error =3D=3D 0) { - ret =3D nbd_wr_syncv(s->ioc, qiov->iov, qiov->niov, request->l= en, - true); - if (ret !=3D request->len) { - reply->error =3D EIO; + if (qiov) { + if ((reply->simple ? reply->error =3D=3D 0 : + reply->type =3D=3D NBD_REPLY_TYPE_OFFSET_DATA)) { + ret =3D nbd_wr_syncv(s->ioc, qiov->iov, qiov->niov, reques= t->len, + true); + if (ret !=3D request->len) { + reply->error =3D EIO; + } + } else if (!reply->simple && + reply->type =3D=3D NBD_REPLY_TYPE_OFFSET_HOLE) { + qemu_iovec_memset(qiov, 0, 0, request->len); } } =20 @@ -227,6 +234,7 @@ int nbd_client_co_preadv(BlockDriverState *bs, uint64_t= offset, .type =3D NBD_CMD_READ, .from =3D offset, .len =3D bytes, + .flags =3D client->structured_reply ? NBD_CMD_FLAG_DF : 0, }; NBDReply reply; ssize_t ret; @@ -237,12 +245,30 @@ int nbd_client_co_preadv(BlockDriverState *bs, uint64= _t offset, nbd_coroutine_start(client, &request); ret =3D nbd_co_send_request(bs, &request, NULL); if (ret < 0) { - reply.error =3D -ret; - } else { - nbd_co_receive_reply(client, &request, &reply, qiov); + goto out; } + + nbd_co_receive_reply(client, &request, &reply, qiov); + if (reply.error !=3D 0) { + ret =3D -reply.error; + } + + if (!reply.simple) { + while (!(reply.flags & NBD_REPLY_FLAG_DONE)) { + nbd_co_receive_reply(client, &request, &reply, qiov); + if (reply.error !=3D 0) { + ret =3D -reply.error; + } + if (reply.simple) { + ret =3D -EIO; + goto out; + } + } + } + +out: nbd_coroutine_end(client, &request); - return -reply.error; + return ret; } =20 int nbd_client_co_pwritev(BlockDriverState *bs, uint64_t offset, @@ -408,7 +434,8 @@ int nbd_client_init(BlockDriverState *bs, &client->nbdflags, tlscreds, hostname, &client->ioc, - &client->size, errp); + &client->size, + &client->structured_reply, errp); if (ret < 0) { logout("Failed to negotiate with the NBD server\n"); return ret; diff --git a/block/nbd-client.h b/block/nbd-client.h index f8d6006849..cba1f965bf 100644 --- a/block/nbd-client.h +++ b/block/nbd-client.h @@ -32,6 +32,8 @@ typedef struct NBDClientSession { NBDReply reply; =20 bool is_unix; + + bool structured_reply; } NBDClientSession; =20 NBDClientSession *nbd_get_client_session(BlockDriverState *bs); diff --git a/include/block/nbd.h b/include/block/nbd.h index 58b864f145..dae2e4bd03 100644 --- a/include/block/nbd.h +++ b/include/block/nbd.h @@ -57,11 +57,16 @@ struct NBDRequest { }; typedef struct NBDRequest NBDRequest; =20 -struct NBDReply { +typedef struct NBDReply { + bool simple; uint64_t handle; uint32_t error; -}; -typedef struct NBDReply NBDReply; + + uint16_t flags; + uint16_t type; + uint32_t length; + uint64_t offset; +} NBDReply; =20 struct NBDSimpleReply { /* uint32_t NBD_SIMPLE_REPLY_MAGIC */ @@ -169,10 +174,10 @@ ssize_t nbd_wr_syncv(QIOChannel *ioc, int nbd_receive_negotiate(QIOChannel *ioc, const char *name, uint16_t *fla= gs, QCryptoTLSCreds *tlscreds, const char *hostname, QIOChannel **outioc, - off_t *size, Error **errp); + off_t *size, bool *structured_reply, Error **err= p); int nbd_init(int fd, QIOChannelSocket *sioc, uint16_t flags, off_t size); ssize_t nbd_send_request(QIOChannel *ioc, NBDRequest *request); -ssize_t nbd_receive_reply(QIOChannel *ioc, NBDReply *reply); +int nbd_receive_reply(QIOChannel *ioc, NBDReply *reply); int nbd_client(int fd); int nbd_disconnect(int fd); =20 diff --git a/nbd/client.c b/nbd/client.c index 1c274f3012..9225f7e30d 100644 --- a/nbd/client.c +++ b/nbd/client.c @@ -472,11 +472,10 @@ static QIOChannel *nbd_receive_starttls(QIOChannel *i= oc, return QIO_CHANNEL(tioc); } =20 - int nbd_receive_negotiate(QIOChannel *ioc, const char *name, uint16_t *fla= gs, QCryptoTLSCreds *tlscreds, const char *hostname, QIOChannel **outioc, - off_t *size, Error **errp) + off_t *size, bool *structured_reply, Error **err= p) { char buf[256]; uint64_t magic, s; @@ -584,6 +583,12 @@ int nbd_receive_negotiate(QIOChannel *ioc, const char = *name, uint16_t *flags, if (nbd_receive_query_exports(ioc, name, errp) < 0) { goto fail; } + + if (structured_reply !=3D NULL) { + *structured_reply =3D + nbd_receive_simple_option(ioc, NBD_OPT_STRUCTURED_REPL= Y, + false, NULL) =3D=3D 0; + } } /* write the export name request */ if (nbd_send_option_request(ioc, NBD_OPT_EXPORT_NAME, -1, name, @@ -603,6 +608,14 @@ int nbd_receive_negotiate(QIOChannel *ioc, const char = *name, uint16_t *flags, goto fail; } be16_to_cpus(flags); + + if (!!structured_reply && *structured_reply && + !(*flags & NBD_CMD_FLAG_DF)) + { + error_setg(errp, "Structured reply is negotiated, " + "but DF flag is not."); + goto fail; + } } else if (magic =3D=3D NBD_CLIENT_MAGIC) { uint32_t oldflags; =20 @@ -790,20 +803,33 @@ ssize_t nbd_send_request(QIOChannel *ioc, NBDRequest = *request) return 0; } =20 -ssize_t nbd_receive_reply(QIOChannel *ioc, NBDReply *reply) +static inline int read_sync_check(QIOChannel *ioc, void *buffer, size_t si= ze) { - uint8_t buf[NBD_REPLY_SIZE]; - uint32_t magic; ssize_t ret; =20 - ret =3D read_sync(ioc, buf, sizeof(buf)); + ret =3D read_sync(ioc, buffer, size); if (ret < 0) { return ret; } - - if (ret !=3D sizeof(buf)) { + if (ret !=3D size) { LOG("read failed"); - return -EINVAL; + return -EIO; + } + + return 0; +} + +/* nbd_receive_simple_reply + * Read simple reply except magic field (which should be already read) + */ +static int nbd_receive_simple_reply(QIOChannel *ioc, NBDReply *reply) +{ + uint8_t buf[NBD_REPLY_SIZE - 4]; + ssize_t ret; + + ret =3D read_sync_check(ioc, buf, sizeof(buf)); + if (ret < 0) { + return ret; } =20 /* Reply @@ -812,9 +838,124 @@ ssize_t nbd_receive_reply(QIOChannel *ioc, NBDReply *= reply) [ 7 .. 15] handle */ =20 - magic =3D ldl_be_p(buf); - reply->error =3D ldl_be_p(buf + 4); - reply->handle =3D ldq_be_p(buf + 8); + reply->error =3D ldl_be_p(buf); + reply->handle =3D ldq_be_p(buf + 4); + + return 0; +} + +/* nbd_receive_structured_reply_chunk + * Read structured reply chunk except magic field (which should be already= read) + * Data for NBD_REPLY_TYPE_OFFSET_DATA is not read too. + * Length field of reply out parameter corresponds to unread part of reply. + */ +static int nbd_receive_structured_reply_chunk(QIOChannel *ioc, NBDReply *r= eply) +{ + NBDStructuredReplyChunk chunk; + ssize_t ret; + uint16_t message_size; + + ret =3D read_sync_check(ioc, (uint8_t *)&chunk + sizeof(chunk.magic), + sizeof(chunk) - sizeof(chunk.magic)); + if (ret < 0) { + return ret; + } + + reply->flags =3D be16_to_cpu(chunk.flags); + reply->type =3D be16_to_cpu(chunk.type); + reply->handle =3D be64_to_cpu(chunk.handle); + reply->length =3D be32_to_cpu(chunk.length); + + switch (reply->type) { + case NBD_REPLY_TYPE_NONE: + break; + case NBD_REPLY_TYPE_OFFSET_DATA: + case NBD_REPLY_TYPE_OFFSET_HOLE: + ret =3D read_sync_check(ioc, &reply->offset, sizeof(reply->offset)= ); + if (ret < 0) { + return ret; + } + be64_to_cpus(&reply->offset); + reply->length -=3D sizeof(reply->offset); + break; + case NBD_REPLY_TYPE_ERROR: + case NBD_REPLY_TYPE_ERROR_OFFSET: + ret =3D read_sync_check(ioc, &reply->error, sizeof(reply->error)); + if (ret < 0) { + return ret; + } + be32_to_cpus(&reply->error); + + ret =3D read_sync_check(ioc, &message_size, sizeof(message_size)); + if (ret < 0) { + return ret; + } + be16_to_cpus(&message_size); + + if (message_size > 0) { + /* TODO: provide error message to user */ + ret =3D drop_sync(ioc, message_size); + if (ret < 0) { + return ret; + } + } + + if (reply->type =3D=3D NBD_REPLY_TYPE_ERROR_OFFSET) { + /* drop 64bit offset */ + ret =3D drop_sync(ioc, 8); + if (ret < 0) { + return ret; + } + } + break; + default: + if (reply->type & (1 << 15)) { + /* unknown error */ + ret =3D drop_sync(ioc, reply->length); + if (ret < 0) { + return ret; + } + + reply->error =3D NBD_EINVAL; + reply->length =3D 0; + } else { + /* unknown non-error reply type */ + return -EINVAL; + } + } + + return 0; +} + +int nbd_receive_reply(QIOChannel *ioc, NBDReply *reply) +{ + uint32_t magic; + int ret; + + ret =3D read_sync_check(ioc, &magic, sizeof(magic)); + if (ret < 0) { + return ret; + } + + be32_to_cpus(&magic); + + switch (magic) { + case NBD_SIMPLE_REPLY_MAGIC: + reply->simple =3D true; + ret =3D nbd_receive_simple_reply(ioc, reply); + break; + case NBD_STRUCTURED_REPLY_MAGIC: + reply->simple =3D false; + ret =3D nbd_receive_structured_reply_chunk(ioc, reply); + break; + default: + LOG("invalid magic (got 0x%" PRIx32 ")", magic); + return -EINVAL; + } + + if (ret < 0) { + return ret; + } =20 reply->error =3D nbd_errno_to_system_errno(reply->error); =20 @@ -827,10 +968,5 @@ ssize_t nbd_receive_reply(QIOChannel *ioc, NBDReply *r= eply) ", handle =3D %" PRIu64" }", magic, reply->error, reply->handle); =20 - if (magic !=3D NBD_SIMPLE_REPLY_MAGIC) { - LOG("invalid magic (got 0x%" PRIx32 ")", magic); - return -EINVAL; - } return 0; } - diff --git a/qemu-nbd.c b/qemu-nbd.c index c734f627b4..de0099e333 100644 --- a/qemu-nbd.c +++ b/qemu-nbd.c @@ -272,7 +272,7 @@ static void *nbd_client_thread(void *arg) =20 ret =3D nbd_receive_negotiate(QIO_CHANNEL(sioc), NULL, &nbdflags, NULL, NULL, NULL, - &size, &local_error); + &size, NULL, &local_error); if (ret < 0) { if (local_error) { error_report_err(local_error); --=20 2.11.0 From nobody Fri May 3 23:54:14 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.zoho.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; Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1486137017892671.6381327044814; Fri, 3 Feb 2017 07:50:17 -0800 (PST) Received: from localhost ([::1]:35399 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cZg7p-0000dB-Kn for importer@patchew.org; Fri, 03 Feb 2017 10:50:13 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:36691) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cZg5n-0007nU-AU for qemu-devel@nongnu.org; Fri, 03 Feb 2017 10:48:08 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1cZg5i-00080s-I1 for qemu-devel@nongnu.org; Fri, 03 Feb 2017 10:48:07 -0500 Received: from mailhub.sw.ru ([195.214.232.25]:22171 helo=relay.sw.ru) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1cZg5i-0007z5-78 for qemu-devel@nongnu.org; Fri, 03 Feb 2017 10:48:02 -0500 Received: from kvm.qa.sw.ru. (msk-vpn.virtuozzo.com [195.214.232.6]) by relay.sw.ru (8.13.4/8.13.4) with ESMTP id v13Flv7n011039; Fri, 3 Feb 2017 18:47:58 +0300 (MSK) From: Vladimir Sementsov-Ogievskiy To: qemu-block@nongnu.org, qemu-devel@nongnu.org Date: Fri, 3 Feb 2017 18:47:47 +0300 Message-Id: <20170203154757.36140-9-vsementsov@virtuozzo.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20170203154757.36140-1-vsementsov@virtuozzo.com> References: <20170203154757.36140-1-vsementsov@virtuozzo.com> X-detected-operating-system: by eggs.gnu.org: OpenBSD 3.x [fuzzy] X-Received-From: 195.214.232.25 Subject: [Qemu-devel] [PATCH 08/18] hbitmap: add next_zero function 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, famz@redhat.com, den@virtuozzo.com, armbru@redhat.com, mreitz@redhat.com, stefanha@redhat.com, pbonzini@redhat.com, jsnow@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" The function searches for next zero bit. Also add interface for BdrvDirtyBitmap. Signed-off-by: Vladimir Sementsov-Ogievskiy --- block/dirty-bitmap.c | 5 +++++ include/block/dirty-bitmap.h | 2 ++ include/qemu/hbitmap.h | 8 ++++++++ util/hbitmap.c | 26 ++++++++++++++++++++++++++ 4 files changed, 41 insertions(+) diff --git a/block/dirty-bitmap.c b/block/dirty-bitmap.c index 519737c8d3..d2f23a00d9 100644 --- a/block/dirty-bitmap.c +++ b/block/dirty-bitmap.c @@ -533,3 +533,8 @@ int64_t bdrv_get_meta_dirty_count(BdrvDirtyBitmap *bitm= ap) { return hbitmap_count(bitmap->meta); } + +int64_t bdrv_dirty_bitmap_next_zero(BdrvDirtyBitmap *bitmap, uint64_t star= t) +{ + return hbitmap_next_zero(bitmap->bitmap, start); +} diff --git a/include/block/dirty-bitmap.h b/include/block/dirty-bitmap.h index 9dea14ba03..8826b74b37 100644 --- a/include/block/dirty-bitmap.h +++ b/include/block/dirty-bitmap.h @@ -72,4 +72,6 @@ void bdrv_dirty_bitmap_deserialize_zeroes(BdrvDirtyBitmap= *bitmap, bool finish); void bdrv_dirty_bitmap_deserialize_finish(BdrvDirtyBitmap *bitmap); =20 +int64_t bdrv_dirty_bitmap_next_zero(BdrvDirtyBitmap *bitmap, uint64_t star= t); + #endif diff --git a/include/qemu/hbitmap.h b/include/qemu/hbitmap.h index eb464759d5..d6fe553b12 100644 --- a/include/qemu/hbitmap.h +++ b/include/qemu/hbitmap.h @@ -257,6 +257,14 @@ void hbitmap_iter_init(HBitmapIter *hbi, const HBitmap= *hb, uint64_t first); */ unsigned long hbitmap_iter_skip_words(HBitmapIter *hbi); =20 +/* hbitmap_next_zero: + * @hb: The HBitmap to operate on + * @start: The bit to start from. + * + * Find next not dirty bit. + */ +int64_t hbitmap_next_zero(const HBitmap *hb, uint64_t start); + /* hbitmap_create_meta: * Create a "meta" hbitmap to track dirtiness of the bits in this HBitmap. * The caller owns the created bitmap and must call hbitmap_free_meta(hb) = to diff --git a/util/hbitmap.c b/util/hbitmap.c index 9f691b76bd..b850c2baf5 100644 --- a/util/hbitmap.c +++ b/util/hbitmap.c @@ -166,6 +166,32 @@ void hbitmap_iter_init(HBitmapIter *hbi, const HBitmap= *hb, uint64_t first) } } =20 +int64_t hbitmap_next_zero(const HBitmap *hb, uint64_t start) +{ + size_t pos =3D (start >> hb->granularity) >> BITS_PER_LEVEL; + unsigned long *last_lev =3D hb->levels[HBITMAP_LEVELS - 1]; + uint64_t sz =3D hb->sizes[HBITMAP_LEVELS - 1]; + unsigned long cur =3D last_lev[pos]; + unsigned start_bit_offset =3D + (start >> hb->granularity) & (BITS_PER_LONG - 1); + cur |=3D (1UL << start_bit_offset) - 1; + + if (cur =3D=3D (unsigned long)-1) { + do { + pos++; + } while (pos < sz && last_lev[pos] =3D=3D (unsigned long)-1); + + if (pos >=3D sz) { + return -1; + } + + cur =3D last_lev[pos]; + } + + return MIN((pos << BITS_PER_LEVEL) + ctol(cur), hb->size - 1) + << hb->granularity; +} + bool hbitmap_empty(const HBitmap *hb) { return hb->count =3D=3D 0; --=20 2.11.0 From nobody Fri May 3 23:54:14 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.zoho.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; Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1486137292765480.47797775419497; Fri, 3 Feb 2017 07:54:52 -0800 (PST) Received: from localhost ([::1]:35423 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cZgCI-0004cf-Mn for importer@patchew.org; Fri, 03 Feb 2017 10:54:50 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:36700) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cZg5n-0007nd-C5 for qemu-devel@nongnu.org; Fri, 03 Feb 2017 10:48:09 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1cZg5j-00082E-88 for qemu-devel@nongnu.org; Fri, 03 Feb 2017 10:48:07 -0500 Received: from mailhub.sw.ru ([195.214.232.25]:39930 helo=relay.sw.ru) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1cZg5i-0007zU-J0 for qemu-devel@nongnu.org; Fri, 03 Feb 2017 10:48:03 -0500 Received: from kvm.qa.sw.ru. (msk-vpn.virtuozzo.com [195.214.232.6]) by relay.sw.ru (8.13.4/8.13.4) with ESMTP id v13Flv7o011039; Fri, 3 Feb 2017 18:47:58 +0300 (MSK) From: Vladimir Sementsov-Ogievskiy To: qemu-block@nongnu.org, qemu-devel@nongnu.org Date: Fri, 3 Feb 2017 18:47:48 +0300 Message-Id: <20170203154757.36140-10-vsementsov@virtuozzo.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20170203154757.36140-1-vsementsov@virtuozzo.com> References: <20170203154757.36140-1-vsementsov@virtuozzo.com> X-detected-operating-system: by eggs.gnu.org: OpenBSD 3.x [fuzzy] X-Received-From: 195.214.232.25 Subject: [Qemu-devel] [PATCH 09/18] block/dirty-bitmap: add bdrv_dirty_bitmap_next() 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, famz@redhat.com, den@virtuozzo.com, armbru@redhat.com, mreitz@redhat.com, stefanha@redhat.com, pbonzini@redhat.com, jsnow@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" Signed-off-by: Vladimir Sementsov-Ogievskiy Reviewed-by: Max Reitz --- block/dirty-bitmap.c | 7 +++++++ include/block/dirty-bitmap.h | 3 +++ 2 files changed, 10 insertions(+) diff --git a/block/dirty-bitmap.c b/block/dirty-bitmap.c index d2f23a00d9..3b7db1d78c 100644 --- a/block/dirty-bitmap.c +++ b/block/dirty-bitmap.c @@ -538,3 +538,10 @@ int64_t bdrv_dirty_bitmap_next_zero(BdrvDirtyBitmap *b= itmap, uint64_t start) { return hbitmap_next_zero(bitmap->bitmap, start); } + +BdrvDirtyBitmap *bdrv_dirty_bitmap_next(BlockDriverState *bs, + BdrvDirtyBitmap *bitmap) +{ + return bitmap =3D=3D NULL ? QLIST_FIRST(&bs->dirty_bitmaps) : + QLIST_NEXT(bitmap, list); +} diff --git a/include/block/dirty-bitmap.h b/include/block/dirty-bitmap.h index 8826b74b37..ff8163ba02 100644 --- a/include/block/dirty-bitmap.h +++ b/include/block/dirty-bitmap.h @@ -74,4 +74,7 @@ void bdrv_dirty_bitmap_deserialize_finish(BdrvDirtyBitmap= *bitmap); =20 int64_t bdrv_dirty_bitmap_next_zero(BdrvDirtyBitmap *bitmap, uint64_t star= t); =20 +BdrvDirtyBitmap *bdrv_dirty_bitmap_next(BlockDriverState *bs, + BdrvDirtyBitmap *bitmap); + #endif --=20 2.11.0 From nobody Fri May 3 23:54:14 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.zoho.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; Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 148613798083515.763431878440997; Fri, 3 Feb 2017 08:06:20 -0800 (PST) Received: from localhost ([::1]:35493 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cZgNO-0006Bu-He for importer@patchew.org; Fri, 03 Feb 2017 11:06:18 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:36697) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cZg5n-0007nb-BX for qemu-devel@nongnu.org; Fri, 03 Feb 2017 10:48:09 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1cZg5j-00081U-1l for qemu-devel@nongnu.org; Fri, 03 Feb 2017 10:48:07 -0500 Received: from mailhub.sw.ru ([195.214.232.25]:43037 helo=relay.sw.ru) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1cZg5i-0007zK-Mk for qemu-devel@nongnu.org; Fri, 03 Feb 2017 10:48:02 -0500 Received: from kvm.qa.sw.ru. (msk-vpn.virtuozzo.com [195.214.232.6]) by relay.sw.ru (8.13.4/8.13.4) with ESMTP id v13Flv7p011039; Fri, 3 Feb 2017 18:47:58 +0300 (MSK) From: Vladimir Sementsov-Ogievskiy To: qemu-block@nongnu.org, qemu-devel@nongnu.org Date: Fri, 3 Feb 2017 18:47:49 +0300 Message-Id: <20170203154757.36140-11-vsementsov@virtuozzo.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20170203154757.36140-1-vsementsov@virtuozzo.com> References: <20170203154757.36140-1-vsementsov@virtuozzo.com> X-detected-operating-system: by eggs.gnu.org: OpenBSD 3.x [fuzzy] X-Received-From: 195.214.232.25 Subject: [Qemu-devel] [PATCH 10/18] block/dirty-bitmap: add bdrv_load_dirty_bitmap 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, famz@redhat.com, den@virtuozzo.com, armbru@redhat.com, mreitz@redhat.com, stefanha@redhat.com, pbonzini@redhat.com, jsnow@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" Signed-off-by: Vladimir Sementsov-Ogievskiy --- block/dirty-bitmap.c | 53 ++++++++++++++++++++++++++++++++++++++++= ++++ include/block/block_int.h | 4 ++++ include/block/dirty-bitmap.h | 3 +++ 3 files changed, 60 insertions(+) diff --git a/block/dirty-bitmap.c b/block/dirty-bitmap.c index 3b7db1d78c..394d4328d5 100644 --- a/block/dirty-bitmap.c +++ b/block/dirty-bitmap.c @@ -545,3 +545,56 @@ BdrvDirtyBitmap *bdrv_dirty_bitmap_next(BlockDriverSta= te *bs, return bitmap =3D=3D NULL ? QLIST_FIRST(&bs->dirty_bitmaps) : QLIST_NEXT(bitmap, list); } + +typedef struct BDRVLoadBitmapCo { + BlockDriverState *bs; + const char *name; + Error **errp; + BdrvDirtyBitmap *ret; + bool in_progress; +} BDRVLoadBitmapCo; + +static void bdrv_load_dity_bitmap_co_entry(void *opaque) +{ + BDRVLoadBitmapCo *lbco =3D opaque; + BlockDriver *drv =3D lbco->bs->drv; + + if (!!drv && !!drv->bdrv_dirty_bitmap_load) { + lbco->ret =3D drv->bdrv_dirty_bitmap_load(lbco->bs, lbco->name, + lbco->errp); + } else if (lbco->bs->file) { + BlockDriverState *bs =3D lbco->bs; + lbco->bs =3D lbco->bs->file->bs; + bdrv_load_dity_bitmap_co_entry(lbco); + if (lbco->ret !=3D NULL) { + QLIST_REMOVE(lbco->ret, list); + QLIST_INSERT_HEAD(&bs->dirty_bitmaps, lbco->ret, list); + } + } else { + lbco->ret =3D NULL; + } + + lbco->in_progress =3D false; +} + +BdrvDirtyBitmap *bdrv_load_dirty_bitmap(BlockDriverState *bs, const char *= name, + Error **errp) +{ + Coroutine *co; + BDRVLoadBitmapCo lbco =3D { + .bs =3D bs, + .name =3D name, + .errp =3D errp, + .in_progress =3D true + }; + + if (qemu_in_coroutine()) { + bdrv_load_dity_bitmap_co_entry(&lbco); + } else { + co =3D qemu_coroutine_create(bdrv_load_dity_bitmap_co_entry, &lbco= ); + qemu_coroutine_enter(co); + BDRV_POLL_WHILE(bs, lbco.in_progress); + } + + return lbco.ret; +} diff --git a/include/block/block_int.h b/include/block/block_int.h index 83a423c580..d3770db539 100644 --- a/include/block/block_int.h +++ b/include/block/block_int.h @@ -222,6 +222,10 @@ struct BlockDriver { int (*bdrv_get_info)(BlockDriverState *bs, BlockDriverInfo *bdi); ImageInfoSpecific *(*bdrv_get_specific_info)(BlockDriverState *bs); =20 + BdrvDirtyBitmap *(*bdrv_dirty_bitmap_load)(BlockDriverState *bs, + const char *name, + Error **errp); + int coroutine_fn (*bdrv_save_vmstate)(BlockDriverState *bs, QEMUIOVector *qiov, int64_t pos); diff --git a/include/block/dirty-bitmap.h b/include/block/dirty-bitmap.h index ff8163ba02..c0c70a8c67 100644 --- a/include/block/dirty-bitmap.h +++ b/include/block/dirty-bitmap.h @@ -77,4 +77,7 @@ int64_t bdrv_dirty_bitmap_next_zero(BdrvDirtyBitmap *bitm= ap, uint64_t start); BdrvDirtyBitmap *bdrv_dirty_bitmap_next(BlockDriverState *bs, BdrvDirtyBitmap *bitmap); =20 +BdrvDirtyBitmap *bdrv_load_dirty_bitmap(BlockDriverState *bs, const char *= name, + Error **errp); + #endif --=20 2.11.0 From nobody Fri May 3 23:54:14 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.zoho.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; Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1486139084621126.93838866336387; Fri, 3 Feb 2017 08:24:44 -0800 (PST) Received: from localhost ([::1]:35609 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cZgfB-00058t-9K for importer@patchew.org; Fri, 03 Feb 2017 11:24:41 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:36696) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cZg5n-0007na-Bo for qemu-devel@nongnu.org; Fri, 03 Feb 2017 10:48:13 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1cZg5k-00083J-52 for qemu-devel@nongnu.org; Fri, 03 Feb 2017 10:48:07 -0500 Received: from mailhub.sw.ru ([195.214.232.25]:37573 helo=relay.sw.ru) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1cZg5j-00080O-Kz for qemu-devel@nongnu.org; Fri, 03 Feb 2017 10:48:04 -0500 Received: from kvm.qa.sw.ru. (msk-vpn.virtuozzo.com [195.214.232.6]) by relay.sw.ru (8.13.4/8.13.4) with ESMTP id v13Flv7q011039; Fri, 3 Feb 2017 18:47:58 +0300 (MSK) From: Vladimir Sementsov-Ogievskiy To: qemu-block@nongnu.org, qemu-devel@nongnu.org Date: Fri, 3 Feb 2017 18:47:50 +0300 Message-Id: <20170203154757.36140-12-vsementsov@virtuozzo.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20170203154757.36140-1-vsementsov@virtuozzo.com> References: <20170203154757.36140-1-vsementsov@virtuozzo.com> X-detected-operating-system: by eggs.gnu.org: OpenBSD 3.x [fuzzy] X-Received-From: 195.214.232.25 Subject: [Qemu-devel] [PATCH 11/18] nbd: BLOCK_STATUS for bitmap export: server part 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, famz@redhat.com, den@virtuozzo.com, armbru@redhat.com, mreitz@redhat.com, stefanha@redhat.com, pbonzini@redhat.com, jsnow@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" Only one meta context type is defined: qemu-bitmap:. Maximum one query is allowed for NBD_OPT_{SET,LIST}_META_CONTEXT, NBD_REP_ERR_TOO_BIG is returned otherwise. Signed-off-by: Vladimir Sementsov-Ogievskiy --- include/block/nbd.h | 15 ++ nbd/nbd-internal.h | 6 + nbd/server.c | 445 ++++++++++++++++++++++++++++++++++++++++++++++++= ++++ 3 files changed, 466 insertions(+) diff --git a/include/block/nbd.h b/include/block/nbd.h index dae2e4bd03..516a24765c 100644 --- a/include/block/nbd.h +++ b/include/block/nbd.h @@ -94,6 +94,16 @@ typedef struct NBDStructuredError { uint16_t message_length; } QEMU_PACKED NBDStructuredError; =20 +typedef struct NBDStructuredMeta { + NBDStructuredReplyChunk h; + uint32_t context_id; +} QEMU_PACKED NBDStructuredMeta; + +typedef struct NBDExtent { + uint32_t length; + uint32_t flags; +} QEMU_PACKED NBDExtent; + /* Transmission (export) flags: sent from server to client during handshak= e, but describe what will happen during transmission */ #define NBD_FLAG_HAS_FLAGS (1 << 0) /* Flags are there */ @@ -120,6 +130,7 @@ typedef struct NBDStructuredError { =20 #define NBD_REP_ACK (1) /* Data sending finished. = */ #define NBD_REP_SERVER (2) /* Export description. */ +#define NBD_REP_META_CONTEXT (4) =20 #define NBD_REP_ERR_UNSUP NBD_REP_ERR(1) /* Unknown option */ #define NBD_REP_ERR_POLICY NBD_REP_ERR(2) /* Server denied */ @@ -127,6 +138,8 @@ typedef struct NBDStructuredError { #define NBD_REP_ERR_PLATFORM NBD_REP_ERR(4) /* Not compiled in */ #define NBD_REP_ERR_TLS_REQD NBD_REP_ERR(5) /* TLS required */ #define NBD_REP_ERR_SHUTDOWN NBD_REP_ERR(7) /* Server shutting down */ +#define NBD_REP_ERR_TOO_BIG NBD_REP_ERR(9) /* The request or the repl= y is + too large to process */ =20 /* Request flags, sent from client to server during transmission phase */ #define NBD_CMD_FLAG_FUA (1 << 0) /* 'force unit access' during wri= te */ @@ -142,6 +155,7 @@ enum { NBD_CMD_TRIM =3D 4, /* 5 reserved for failed experiment NBD_CMD_CACHE */ NBD_CMD_WRITE_ZEROES =3D 6, + NBD_CMD_BLOCK_STATUS =3D 7 }; =20 #define NBD_DEFAULT_PORT 10809 @@ -163,6 +177,7 @@ enum { #define NBD_REPLY_TYPE_NONE 0 #define NBD_REPLY_TYPE_OFFSET_DATA 1 #define NBD_REPLY_TYPE_OFFSET_HOLE 2 +#define NBD_REPLY_TYPE_BLOCK_STATUS 5 #define NBD_REPLY_TYPE_ERROR ((1 << 15) + 1) #define NBD_REPLY_TYPE_ERROR_OFFSET ((1 << 15) + 2) =20 diff --git a/nbd/nbd-internal.h b/nbd/nbd-internal.h index 3284bfc85a..fbbcf69925 100644 --- a/nbd/nbd-internal.h +++ b/nbd/nbd-internal.h @@ -83,6 +83,10 @@ #define NBD_OPT_PEEK_EXPORT (4) #define NBD_OPT_STARTTLS (5) #define NBD_OPT_STRUCTURED_REPLY (8) +#define NBD_OPT_LIST_META_CONTEXT (9) +#define NBD_OPT_SET_META_CONTEXT (10) + +#define NBD_META_NS_BITMAPS "qemu-dirty-bitmap" =20 /* NBD errors are based on errno numbers, so there is a 1:1 mapping, * but only a limited set of errno values is specified in the protocol. @@ -105,6 +109,8 @@ static inline const char *nbd_opt_name(int opt) case NBD_OPT_PEEK_EXPORT: return "peek_export"; case NBD_OPT_STARTTLS: return "tls"; case NBD_OPT_STRUCTURED_REPLY: return "structured_reply"; + case NBD_OPT_LIST_META_CONTEXT: return "list_meta_context"; + case NBD_OPT_SET_META_CONTEXT: return "set_meta_context"; } =20 return ""; diff --git a/nbd/server.c b/nbd/server.c index cb79a93c87..0b7b7230df 100644 --- a/nbd/server.c +++ b/nbd/server.c @@ -21,6 +21,8 @@ #include "qapi/error.h" #include "nbd-internal.h" =20 +#define NBD_MAX_BITMAP_EXTENTS (0x100000 / 8) /* 1 mb of extents data */ + static int system_errno_to_nbd_errno(int err) { switch (err) { @@ -102,6 +104,7 @@ struct NBDClient { bool closing; =20 bool structured_reply; + BdrvDirtyBitmap *export_bitmap; }; =20 /* That's all folks */ @@ -421,7 +424,304 @@ static QIOChannel *nbd_negotiate_handle_starttls(NBDC= lient *client, return QIO_CHANNEL(tioc); } =20 +static int nbd_negotiate_read_size_string(QIOChannel *ioc, char **str, + uint32_t max_len) +{ + uint32_t len; + + if (nbd_negotiate_read(ioc, &len, sizeof(len)) !=3D sizeof(len)) { + LOG("read failed"); + return -EIO; + } + + cpu_to_be32s(&len); + + if (max_len > 0 && len > max_len) { + LOG("Bad length received"); + return -EINVAL; + } + + *str =3D g_malloc(len + 1); + + if (nbd_negotiate_read(ioc, *str, len) !=3D len) { + LOG("read failed"); + g_free(str); + return -EIO; + } + (*str)[len] =3D '\0'; + + return sizeof(len) + len; +} + +static int nbd_negotiate_send_meta_context(QIOChannel *ioc, + const char *context, + uint32_t opt) +{ + int ret; + size_t len =3D strlen(context); + uint32_t context_id =3D cpu_to_be32(100); + + ret =3D nbd_negotiate_send_rep_len(ioc, NBD_REP_META_CONTEXT, opt, + len + sizeof(context_id)); + if (ret < 0) { + return ret; + } + + if (nbd_negotiate_write(ioc, &context_id, sizeof(context_id)) !=3D + sizeof(context_id)) + { + LOG("write failed"); + return -EIO; + } + + if (nbd_negotiate_write(ioc, context, len) !=3D len) { + LOG("write failed"); + return -EIO; + } + + return 0; +} + +static int nbd_negotiate_send_bitmap(QIOChannel *ioc, const char *bitmap_n= ame, + uint32_t opt) +{ + char *context =3D g_strdup_printf("%s:%s", NBD_META_NS_BITMAPS, bitmap= _name); + int ret =3D nbd_negotiate_send_meta_context(ioc, context, opt); + + g_free(context); + + return ret; +} + +static int nbd_negotiate_one_bitmap_query(QIOChannel *ioc, BlockDriverStat= e *bs, + uint32_t opt, const char *query, + BdrvDirtyBitmap **bitmap) +{ + BdrvDirtyBitmap *bm =3D bdrv_find_dirty_bitmap(bs, query); + if (bm !=3D NULL) { + if (bitmap !=3D NULL) { + *bitmap =3D bm; + } + return nbd_negotiate_send_bitmap(ioc, query, opt); + } + + return 0; +} + +static int nbd_negotiate_one_meta_query(QIOChannel *ioc, BlockDriverState = *bs, + uint32_t opt, BdrvDirtyBitmap **bi= tmap) +{ + int ret =3D 0, nb_read; + char *query, *colon, *namespace, *subquery; + + *bitmap =3D NULL; =20 + nb_read =3D nbd_negotiate_read_size_string(ioc, &query, 0); + if (nb_read < 0) { + return nb_read; + } + + colon =3D strchr(query, ':'); + if (colon =3D=3D NULL) { + ret =3D -EINVAL; + goto out; + } + *colon =3D '\0'; + namespace =3D query; + subquery =3D colon + 1; + + if (strcmp(namespace, NBD_META_NS_BITMAPS) =3D=3D 0) { + ret =3D nbd_negotiate_one_bitmap_query(ioc, bs, opt, subquery, bit= map); + } + +out: + g_free(query); + return ret < 0 ? ret : nb_read; +} + +/* start handle LIST_META_CONTEXT and SET_META_CONTEXT requests + * @opt should be NBD_OPT_LIST_META_CONTEXT or NBD_OPT_SET_META_C= ONTEXT + * @length related option data to read + * @nb_queries out parameter, number of queries specified by client + * @bs out parameter, bs for export, selected by client + * will be zero if some not critical error occured and error= reply + * was sent. + * + * Returns: + * Err. code < 0 on critical error + * Number of bytes read otherwise (will be equal to length on non critic= al + * error or if there no queries in request) + */ +static int nbd_negotiate_opt_meta_context_start(NBDClient *client, uint32_= t opt, + uint32_t length, + uint32_t *nb_queries, + BlockDriverState **bs) +{ + int ret; + NBDExport *exp; + char *export_name; + int nb_read =3D 0; + + if (!client->structured_reply) { + uint32_t tail =3D length - nb_read; + LOG("Structured reply is not negotiated"); + + if (nbd_negotiate_drop_sync(client->ioc, tail) !=3D tail) { + return -EIO; + } + ret =3D nbd_negotiate_send_rep_err(client->ioc, NBD_REP_ERR_INVALI= D, opt, + "Structured reply is not negotiat= ed"); + g_free(export_name); + + if (ret < 0) { + return ret; + } else { + *bs =3D NULL; + *nb_queries =3D 0; + return length; + } + } + + nb_read =3D nbd_negotiate_read_size_string(client->ioc, &export_name, + NBD_MAX_NAME_SIZE); + if (nb_read < 0) { + return nb_read; + } + + exp =3D nbd_export_find(export_name); + if (exp =3D=3D NULL) { + uint32_t tail =3D length - nb_read; + LOG("export '%s' is not found", export_name); + + if (nbd_negotiate_drop_sync(client->ioc, tail) !=3D tail) { + return -EIO; + } + ret =3D nbd_negotiate_send_rep_err(client->ioc, NBD_REP_ERR_INVALI= D, opt, + "export '%s' is not found", + export_name); + g_free(export_name); + + if (ret < 0) { + return ret; + } else { + *bs =3D NULL; + *nb_queries =3D 0; + return length; + } + } + g_free(export_name); + + *bs =3D blk_bs(exp->blk); + if (*bs =3D=3D NULL) { + LOG("export without bs"); + return -EINVAL; + } + + if (nbd_negotiate_read(client->ioc, nb_queries, + sizeof(*nb_queries)) !=3D sizeof(*nb_queries)) + { + LOG("read failed"); + return -EIO; + } + cpu_to_be32s(nb_queries); + + nb_read +=3D sizeof(*nb_queries); + + return nb_read; +} + +static int nbd_negotiate_list_meta_context(NBDClient *client, uint32_t len= gth) +{ + int ret; + BlockDriverState *bs; + uint32_t nb_queries; + int i; + int nb_read; + + nb_read =3D nbd_negotiate_opt_meta_context_start(client, + NBD_OPT_LIST_META_CONTE= XT, + length, &nb_queries, &b= s); + if (nb_read < 0) { + return nb_read; + } + if (bs =3D=3D NULL) { + /* error reply was already sent by nbd_negotiate_opt_meta_context_= start + * */ + return 0; + } + + if (nb_queries =3D=3D 0) { + BdrvDirtyBitmap *bm =3D NULL; + + if (nb_read !=3D length) { + return -EINVAL; + } + + while ((bm =3D bdrv_dirty_bitmap_next(bs, bm)) !=3D 0) { + nbd_negotiate_send_bitmap(client->ioc, bdrv_dirty_bitmap_name(= bm), + NBD_OPT_LIST_META_CONTEXT); + } + } + + for (i =3D 0; i < nb_queries; ++i) { + ret =3D nbd_negotiate_one_meta_query(client->ioc, bs, + NBD_OPT_LIST_META_CONTEXT, NULL= ); + if (ret < 0) { + return ret; + } + + nb_read +=3D ret; + } + + if (nb_read !=3D length) { + return -EINVAL; + } + + return nbd_negotiate_send_rep(client->ioc, NBD_REP_ACK, + NBD_OPT_LIST_META_CONTEXT); +} + +static int nbd_negotiate_set_meta_context(NBDClient *client, uint32_t leng= th) +{ + int ret; + BlockDriverState *bs; + uint32_t nb_queries; + int nb_read; + + nb_read =3D nbd_negotiate_opt_meta_context_start(client, + NBD_OPT_SET_META_CONTEX= T, + length, &nb_queries, &b= s); + if (nb_read < 0) { + return nb_read; + } + if (bs =3D=3D NULL) { + /* error reply was already sent by nbd_negotiate_opt_meta_context_= start + * */ + return 0; + } + + if (nb_queries =3D=3D 0) { + return nbd_negotiate_send_rep(client->ioc, NBD_REP_ACK, + NBD_OPT_SET_META_CONTEXT); + } + + if (nb_queries > 1) { + return nbd_negotiate_send_rep_err(client->ioc, NBD_REP_ERR_TOO_BIG, + NBD_OPT_SET_META_CONTEXT, + "Only one exporting context is" + "supported"); + } + + ret =3D nbd_negotiate_one_meta_query(client->ioc, bs, + NBD_OPT_SET_META_CONTEXT, + &client->export_bitmap); + if (ret < 0) { + return ret; + } + + return nbd_negotiate_send_rep(client->ioc, NBD_REP_ACK, + NBD_OPT_SET_META_CONTEXT); +} /* Process all NBD_OPT_* client option commands. * Return -errno on error, 0 on success. */ static int nbd_negotiate_options(NBDClient *client) @@ -585,6 +885,20 @@ static int nbd_negotiate_options(NBDClient *client) } break; =20 + case NBD_OPT_LIST_META_CONTEXT: + ret =3D nbd_negotiate_list_meta_context(client, length); + if (ret < 0) { + return ret; + } + break; + + case NBD_OPT_SET_META_CONTEXT: + ret =3D nbd_negotiate_set_meta_context(client, length); + if (ret < 0) { + return ret; + } + break; + default: if (nbd_negotiate_drop_sync(client->ioc, length) !=3D leng= th) { return -EIO; @@ -1159,6 +1473,124 @@ static int nbd_co_send_structured_none(NBDClient *c= lient, uint64_t handle) return nbd_co_send_buf(client, &chunk, sizeof(chunk)); } =20 +#define MAX_EXTENT_LENGTH UINT32_MAX + +static unsigned add_extents(NBDExtent *extents, unsigned nb_extents, + uint64_t length, uint32_t flags) +{ + unsigned i =3D 0; + uint32_t big_chunk =3D (MAX_EXTENT_LENGTH >> 9) << 9; + uint32_t big_chunk_be =3D cpu_to_be32(big_chunk); + uint32_t flags_be =3D cpu_to_be32(flags); + + for (i =3D 0; i < nb_extents && length > MAX_EXTENT_LENGTH; + i++, length -=3D big_chunk) + { + extents[i].length =3D big_chunk_be; + extents[i].flags =3D flags_be; + } + + if (length > 0 && i < nb_extents) { + extents[i].length =3D cpu_to_be32(length); + extents[i].flags =3D flags_be; + i++; + } + + return i; +} + +static unsigned bitmap_to_extents(BdrvDirtyBitmap *bitmap, uint64_t offset, + uint64_t length, NBDExtent *extents, + unsigned nb_extents) +{ + uint64_t begin, end; /* dirty region */ + uint64_t start_sector =3D offset >> BDRV_SECTOR_BITS; + uint64_t last_sector =3D (offset + length - 1) >> BDRV_SECTOR_BITS; + unsigned i =3D 0; + uint64_t len; + uint32_t ma =3D -1; + ma =3D (ma / bdrv_dirty_bitmap_granularity(bitmap)) * + bdrv_dirty_bitmap_granularity(bitmap); + + BdrvDirtyBitmapIter *it =3D bdrv_dirty_iter_new(bitmap, start_sector); + + assert(nb_extents > 0); + + begin =3D bdrv_dirty_iter_next(it); + if (begin =3D=3D -1) { + begin =3D last_sector + 1; + } + if (begin > start_sector) { + len =3D (begin - start_sector) << BDRV_SECTOR_BITS; + i +=3D add_extents(extents + i, nb_extents - i, len, 0); + } + + while (begin !=3D -1 && begin <=3D last_sector && i < nb_extents) { + end =3D bdrv_dirty_bitmap_next_zero(bitmap, begin + 1); + + i +=3D add_extents(extents + i, nb_extents - i, + (end - begin) << BDRV_SECTOR_BITS, 1); + + if (end > last_sector || i >=3D nb_extents) { + break; + } + + bdrv_set_dirty_iter(it, end); + begin =3D bdrv_dirty_iter_next(it); + if (begin =3D=3D -1) { + begin =3D last_sector + 1; + } + if (begin > end) { + i +=3D add_extents(extents + i, nb_extents - i, + (begin - end) << BDRV_SECTOR_BITS, 0); + } + } + + bdrv_dirty_iter_free(it); + + extents[0].length =3D + cpu_to_be32(be32_to_cpu(extents[0].length) - + (offset - (start_sector << BDRV_SECTOR_BITS))); + + return i; +} + +static int nbd_co_send_extents(NBDClient *client, uint64_t handle, + NBDExtent *extents, unsigned nb_extents, + uint32_t context_id) +{ + NBDStructuredMeta chunk; + + struct iovec iov[] =3D { + {.iov_base =3D &chunk, .iov_len =3D sizeof(chunk)}, + {.iov_base =3D extents, .iov_len =3D nb_extents * sizeof(extents[0= ])} + }; + + set_be_chunk(&chunk.h, NBD_REPLY_FLAG_DONE, NBD_REPLY_TYPE_BLOCK_STATU= S, + handle, sizeof(chunk) - sizeof(chunk.h) + iov[1].iov_len); + stl_be_p(&chunk.context_id, context_id); + + return nbd_co_send_iov(client, iov, 2); +} + +static int nbd_co_send_bitmap(NBDClient *client, uint64_t handle, + BdrvDirtyBitmap *bitmap, uint64_t offset, + uint64_t length, uint32_t context_id) +{ + int ret; + unsigned nb_extents; + NBDExtent *extents =3D g_new(NBDExtent, NBD_MAX_BITMAP_EXTENTS); + + nb_extents =3D bitmap_to_extents(bitmap, offset, length, extents, + NBD_MAX_BITMAP_EXTENTS); + + ret =3D nbd_co_send_extents(client, handle, extents, nb_extents, conte= xt_id); + + g_free(extents); + + return ret; +} + /* Collect a client request. Return 0 if request looks valid, -EAGAIN * to keep trying the collection, -EIO to drop connection right away, * and any other negative value to report an error to the client @@ -1437,6 +1869,19 @@ static void nbd_trip(void *opaque) goto out; } break; + case NBD_CMD_BLOCK_STATUS: + TRACE("Request type is BLOCK_STATUS"); + if (client->export_bitmap =3D=3D NULL) { + reply.error =3D EINVAL; + goto error_reply; + } + ret =3D nbd_co_send_bitmap(req->client, request.handle, + client->export_bitmap, request.from, + request.len, 0); + if (ret < 0) { + goto out; + } + break; default: LOG("invalid request type (%" PRIu32 ") received", request.type); reply.error =3D EINVAL; --=20 2.11.0 From nobody Fri May 3 23:54:14 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.zoho.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; Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 148613859794128.75698670079487; Fri, 3 Feb 2017 08:16:37 -0800 (PST) Received: from localhost ([::1]:35555 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cZgXL-0006ju-Vs for importer@patchew.org; Fri, 03 Feb 2017 11:16:36 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:36702) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cZg5n-0007nf-Bv for qemu-devel@nongnu.org; Fri, 03 Feb 2017 10:48:13 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1cZg5j-000829-7W for qemu-devel@nongnu.org; Fri, 03 Feb 2017 10:48:07 -0500 Received: from mailhub.sw.ru ([195.214.232.25]:48678 helo=relay.sw.ru) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1cZg5i-0007zh-O1 for qemu-devel@nongnu.org; Fri, 03 Feb 2017 10:48:03 -0500 Received: from kvm.qa.sw.ru. (msk-vpn.virtuozzo.com [195.214.232.6]) by relay.sw.ru (8.13.4/8.13.4) with ESMTP id v13Flv7r011039; Fri, 3 Feb 2017 18:47:58 +0300 (MSK) From: Vladimir Sementsov-Ogievskiy To: qemu-block@nongnu.org, qemu-devel@nongnu.org Date: Fri, 3 Feb 2017 18:47:51 +0300 Message-Id: <20170203154757.36140-13-vsementsov@virtuozzo.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20170203154757.36140-1-vsementsov@virtuozzo.com> References: <20170203154757.36140-1-vsementsov@virtuozzo.com> X-detected-operating-system: by eggs.gnu.org: OpenBSD 3.x [fuzzy] X-Received-From: 195.214.232.25 Subject: [Qemu-devel] [PATCH 12/18] nbd: BLOCK_STATUS for bitmap export: client part 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, famz@redhat.com, den@virtuozzo.com, armbru@redhat.com, mreitz@redhat.com, stefanha@redhat.com, pbonzini@redhat.com, jsnow@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" Signed-off-by: Vladimir Sementsov-Ogievskiy --- block/nbd-client.c | 146 +++++++++++++++++++++++++++++++++++++++++++++++= +++- block/nbd-client.h | 6 +++ block/nbd.c | 9 +++- include/block/nbd.h | 6 ++- nbd/client.c | 103 +++++++++++++++++++++++++++++++++++- nbd/server.c | 2 - qapi/block-core.json | 5 +- qemu-nbd.c | 2 +- 8 files changed, 270 insertions(+), 9 deletions(-) diff --git a/block/nbd-client.c b/block/nbd-client.c index ff96bd1635..c7eb21fb02 100644 --- a/block/nbd-client.c +++ b/block/nbd-client.c @@ -388,6 +388,147 @@ int nbd_client_co_pdiscard(BlockDriverState *bs, int6= 4_t offset, int count) =20 } =20 +static inline ssize_t read_sync(QIOChannel *ioc, void *buffer, size_t size) +{ + struct iovec iov =3D { .iov_base =3D buffer, .iov_len =3D size }; + /* Sockets are kept in blocking mode in the negotiation phase. After + * that, a non-readable socket simply means that another thread stole + * our request/reply. Synchronization is done with recv_coroutine, so + * that this is coroutine-safe. + */ + return nbd_wr_syncv(ioc, &iov, 1, size, true); +} + +static int nbd_client_co_cmd_block_status(BlockDriverState *bs, uint64_t o= ffset, + uint64_t bytes, NBDExtent **pext= ents, + unsigned *nb_extents) +{ + int64_t ret; + NBDReply reply; + uint32_t context_id; + int64_t nb, i; + NBDExtent *extents =3D NULL; + NBDClientSession *client =3D nbd_get_client_session(bs); + NBDRequest request =3D { + .type =3D NBD_CMD_BLOCK_STATUS, + .from =3D offset, + .len =3D bytes, + .flags =3D 0, + }; + + nbd_coroutine_start(client, &request); + + ret =3D nbd_co_send_request(bs, &request, NULL); + if (ret < 0) { + goto fail; + } + + nbd_co_receive_reply(client, &request, &reply, NULL); + if (reply.error !=3D 0) { + ret =3D -reply.error; + } + if (reply.simple) { + ret =3D -EINVAL; + goto fail; + } + if (reply.error !=3D 0) { + ret =3D -reply.error; + goto fail; + } + if (reply.type !=3D NBD_REPLY_TYPE_BLOCK_STATUS) { + ret =3D -EINVAL; + goto fail; + } + + read_sync(client->ioc, &context_id, sizeof(context_id)); + cpu_to_be32s(&context_id); + if (client->meta_data_context_id !=3D context_id) { + ret =3D -EINVAL; + goto fail; + } + + nb =3D (reply.length - sizeof(context_id)) / sizeof(NBDExtent); + extents =3D g_new(NBDExtent, nb); + if (read_sync(client->ioc, extents, nb * sizeof(NBDExtent)) !=3D + nb * sizeof(NBDExtent)) + { + ret =3D -EIO; + goto fail; + } + + if (!(reply.flags && NBD_REPLY_FLAG_DONE)) { + nbd_co_receive_reply(client, &request, &reply, NULL); + if (reply.simple) { + ret =3D -EINVAL; + goto fail; + } + if (reply.error !=3D 0) { + ret =3D -reply.error; + goto fail; + } + if (reply.type !=3D NBD_REPLY_TYPE_NONE || + !(reply.flags && NBD_REPLY_FLAG_DONE)) { + ret =3D -EINVAL; + goto fail; + } + } + + for (i =3D 0; i < nb; ++i) { + cpu_to_be32s(&extents[i].length); + cpu_to_be32s(&extents[i].flags); + } + + *pextents =3D extents; + *nb_extents =3D nb; + nbd_coroutine_end(client, &request); + return 0; + +fail: + g_free(extents); + nbd_coroutine_end(client, &request); + return ret; +} + +/* nbd_client_co_load_bitmap_part() returns end of set area, i.e. first ne= xt + * byte of unknown status (may be >=3D disk size, which means that the bit= map was + * set up to the end). + */ +int64_t nbd_client_co_load_bitmap_part(BlockDriverState *bs, uint64_t offs= et, + uint64_t bytes, BdrvDirtyBitmap *bi= tmap) +{ + int64_t ret; + uint64_t start_byte; + uint32_t nb_extents; + int64_t i, start_sector, last_sector, nr_sectors; + NBDExtent *extents =3D NULL; + + ret =3D nbd_client_co_cmd_block_status(bs, offset, bytes, &extents, + &nb_extents); + if (ret < 0) { + return ret; + } + + start_byte =3D offset; + for (i =3D 0; i < nb_extents; ++i) { + if (extents[i].flags =3D=3D 1) { + start_sector =3D start_byte >> BDRV_SECTOR_BITS; + last_sector =3D + (start_byte + extents[i].length - 1) >> BDRV_SECTOR_BITS; + nr_sectors =3D last_sector - start_sector + 1; + + bdrv_set_dirty_bitmap(bitmap, start_sector, nr_sectors); + } + + start_byte +=3D extents[i].length; + } + + g_free(extents); + + return ROUND_UP((uint64_t)start_byte, + (uint64_t)bdrv_dirty_bitmap_granularity(bitmap)); +} + + void nbd_client_detach_aio_context(BlockDriverState *bs) { aio_set_fd_handler(bdrv_get_aio_context(bs), @@ -421,6 +562,7 @@ int nbd_client_init(BlockDriverState *bs, const char *export, QCryptoTLSCreds *tlscreds, const char *hostname, + const char *bitmap_name, Error **errp) { NBDClientSession *client =3D nbd_get_client_session(bs); @@ -435,7 +577,9 @@ int nbd_client_init(BlockDriverState *bs, tlscreds, hostname, &client->ioc, &client->size, - &client->structured_reply, errp); + &client->structured_reply, + bitmap_name, + &client->bitmap_ok, errp); if (ret < 0) { logout("Failed to negotiate with the NBD server\n"); return ret; diff --git a/block/nbd-client.h b/block/nbd-client.h index cba1f965bf..e5ec89b9f6 100644 --- a/block/nbd-client.h +++ b/block/nbd-client.h @@ -34,6 +34,8 @@ typedef struct NBDClientSession { bool is_unix; =20 bool structured_reply; + bool bitmap_ok; + uint32_t meta_data_context_id; } NBDClientSession; =20 NBDClientSession *nbd_get_client_session(BlockDriverState *bs); @@ -43,6 +45,7 @@ int nbd_client_init(BlockDriverState *bs, const char *export_name, QCryptoTLSCreds *tlscreds, const char *hostname, + const char *bitmap_name, Error **errp); void nbd_client_close(BlockDriverState *bs); =20 @@ -54,9 +57,12 @@ int nbd_client_co_pwrite_zeroes(BlockDriverState *bs, in= t64_t offset, int count, BdrvRequestFlags flags); int nbd_client_co_preadv(BlockDriverState *bs, uint64_t offset, uint64_t bytes, QEMUIOVector *qiov, int flags); +int64_t nbd_client_co_load_bitmap_part(BlockDriverState *bs, uint64_t offs= et, + uint64_t bytes, BdrvDirtyBitmap *bi= tmap); =20 void nbd_client_detach_aio_context(BlockDriverState *bs); void nbd_client_attach_aio_context(BlockDriverState *bs, AioContext *new_context); =20 + #endif /* NBD_CLIENT_H */ diff --git a/block/nbd.c b/block/nbd.c index 35f24be069..63bc3f04d0 100644 --- a/block/nbd.c +++ b/block/nbd.c @@ -382,6 +382,11 @@ static QemuOptsList nbd_runtime_opts =3D { .type =3D QEMU_OPT_STRING, .help =3D "ID of the TLS credentials to use", }, + { + .name =3D "bitmap", + .type =3D QEMU_OPT_STRING, + .help =3D "Name of dirty bitmap to export", + }, }, }; =20 @@ -440,8 +445,8 @@ static int nbd_open(BlockDriverState *bs, QDict *option= s, int flags, } =20 /* NBD handshake */ - ret =3D nbd_client_init(bs, sioc, s->export, - tlscreds, hostname, errp); + ret =3D nbd_client_init(bs, sioc, s->export, tlscreds, hostname, + qemu_opt_get(opts, "bitmap"), errp); error: if (sioc) { object_unref(OBJECT(sioc)); diff --git a/include/block/nbd.h b/include/block/nbd.h index 516a24765c..08d5e51f21 100644 --- a/include/block/nbd.h +++ b/include/block/nbd.h @@ -181,6 +181,8 @@ enum { #define NBD_REPLY_TYPE_ERROR ((1 << 15) + 1) #define NBD_REPLY_TYPE_ERROR_OFFSET ((1 << 15) + 2) =20 +#define NBD_MAX_BITMAP_EXTENTS (0x100000 / 8) /* 1 mb of extents data */ + ssize_t nbd_wr_syncv(QIOChannel *ioc, struct iovec *iov, size_t niov, @@ -189,7 +191,9 @@ ssize_t nbd_wr_syncv(QIOChannel *ioc, int nbd_receive_negotiate(QIOChannel *ioc, const char *name, uint16_t *fla= gs, QCryptoTLSCreds *tlscreds, const char *hostname, QIOChannel **outioc, - off_t *size, bool *structured_reply, Error **err= p); + off_t *size, bool *structured_reply, + const char *bitmap_name, bool *bitmap_ok, + Error **errp); int nbd_init(int fd, QIOChannelSocket *sioc, uint16_t flags, off_t size); ssize_t nbd_send_request(QIOChannel *ioc, NBDRequest *request); int nbd_receive_reply(QIOChannel *ioc, NBDReply *reply); diff --git a/nbd/client.c b/nbd/client.c index 9225f7e30d..c3817b84fa 100644 --- a/nbd/client.c +++ b/nbd/client.c @@ -472,10 +472,101 @@ static QIOChannel *nbd_receive_starttls(QIOChannel *= ioc, return QIO_CHANNEL(tioc); } =20 +static int nbd_receive_query_meta_context(QIOChannel *ioc, const char *exp= ort, + const char *context, bool *ok, + Error **errp) +{ + int ret; + nbd_opt_reply reply; + size_t export_len =3D strlen(export); + size_t context_len =3D strlen(context); + size_t data_len =3D 4 + export_len + 4 + 4 + context_len; + + char *data =3D g_malloc(data_len); + char *p =3D data; + int nb_reps =3D 0; + + *ok =3D false; + stl_be_p(p, export_len); + memcpy(p +=3D 4, export, export_len); + stl_be_p(p +=3D export_len, 1); + stl_be_p(p +=3D 4, context_len); + memcpy(p +=3D 4, context, context_len); + + TRACE("Requesting set_meta_context option from server"); + ret =3D nbd_send_option_request(ioc, NBD_OPT_SET_META_CONTEXT, data_le= n, data, + errp); + if (ret < 0) { + goto out; + } + + while (true) { + uint32_t context_id; + char *context_name; + size_t len; + + ret =3D nbd_receive_option_reply(ioc, NBD_OPT_SET_META_CONTEXT, &r= eply, + errp); + if (ret < 0) { + goto out; + } + + ret =3D nbd_handle_reply_err(ioc, &reply, errp); + if (ret <=3D 0) { + goto out; + } + + if (reply.type !=3D NBD_REP_META_CONTEXT) { + break; + } + + if (read_sync(ioc, &context_id, sizeof(context_id)) !=3D + sizeof(context_id)) + { + ret =3D -EIO; + goto out; + } + + be32_to_cpus(&context_id); + + len =3D reply.length - sizeof(context_id); + context_name =3D g_malloc(len + 1); + if (read_sync(ioc, context_name, len) !=3D len) { + + ret =3D -EIO; + goto out; + } + context_name[len] =3D '\0'; + + TRACE("set meta: %u %s", context_id, context_name); + + nb_reps++; + } + + *ok =3D nb_reps =3D=3D 1 && reply.type =3D=3D NBD_REP_ACK; + +out: + g_free(data); + return ret; +} + +static int nbd_receive_query_bitmap(QIOChannel *ioc, const char *export, + const char *bitmap, bool *ok, Error **= errp) +{ + char *context =3D g_strdup_printf("%s:%s", NBD_META_NS_BITMAPS, bitmap= ); + int ret =3D nbd_receive_query_meta_context(ioc, export, context, ok, e= rrp); + + g_free(context); + + return ret; +} + int nbd_receive_negotiate(QIOChannel *ioc, const char *name, uint16_t *fla= gs, QCryptoTLSCreds *tlscreds, const char *hostname, QIOChannel **outioc, - off_t *size, bool *structured_reply, Error **err= p) + off_t *size, bool *structured_reply, + const char *bitmap_name, bool *bitmap_ok, + Error **errp) { char buf[256]; uint64_t magic, s; @@ -589,6 +680,16 @@ int nbd_receive_negotiate(QIOChannel *ioc, const char = *name, uint16_t *flags, nbd_receive_simple_option(ioc, NBD_OPT_STRUCTURED_REPL= Y, false, NULL) =3D=3D 0; } + + if (!!structured_reply && *structured_reply && !!bitmap_name) { + int ret; + assert(!!bitmap_ok); + ret =3D nbd_receive_query_bitmap(ioc, name, bitmap_name, + bitmap_ok, errp) =3D=3D 0; + if (ret < 0) { + goto fail; + } + } } /* write the export name request */ if (nbd_send_option_request(ioc, NBD_OPT_EXPORT_NAME, -1, name, diff --git a/nbd/server.c b/nbd/server.c index 0b7b7230df..c96dda4086 100644 --- a/nbd/server.c +++ b/nbd/server.c @@ -21,8 +21,6 @@ #include "qapi/error.h" #include "nbd-internal.h" =20 -#define NBD_MAX_BITMAP_EXTENTS (0x100000 / 8) /* 1 mb of extents data */ - static int system_errno_to_nbd_errno(int err) { switch (err) { diff --git a/qapi/block-core.json b/qapi/block-core.json index 6b42216960..0e15c73774 100644 --- a/qapi/block-core.json +++ b/qapi/block-core.json @@ -2331,12 +2331,15 @@ # # @tls-creds: #optional TLS credentials ID # +# @bitmap: #optional Dirty bitmap name to export (vz-7.4) +# # Since: 2.8 ## { 'struct': 'BlockdevOptionsNbd', 'data': { 'server': 'SocketAddress', '*export': 'str', - '*tls-creds': 'str' } } + '*tls-creds': 'str', + '*bitmap': 'str'} } =20 ## # @BlockdevOptionsRaw: diff --git a/qemu-nbd.c b/qemu-nbd.c index de0099e333..cf45444faf 100644 --- a/qemu-nbd.c +++ b/qemu-nbd.c @@ -272,7 +272,7 @@ static void *nbd_client_thread(void *arg) =20 ret =3D nbd_receive_negotiate(QIO_CHANNEL(sioc), NULL, &nbdflags, NULL, NULL, NULL, - &size, NULL, &local_error); + &size, NULL, NULL, NULL, &local_error); if (ret < 0) { if (local_error) { error_report_err(local_error); --=20 2.11.0 From nobody Fri May 3 23:54:14 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.zoho.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; Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1486137765242808.9134502411868; Fri, 3 Feb 2017 08:02:45 -0800 (PST) Received: from localhost ([::1]:35471 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cZgJv-00037a-6n for importer@patchew.org; Fri, 03 Feb 2017 11:02:43 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:36693) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cZg5n-0007nW-Aw for qemu-devel@nongnu.org; Fri, 03 Feb 2017 10:48:09 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1cZg5k-000836-1E for qemu-devel@nongnu.org; Fri, 03 Feb 2017 10:48:07 -0500 Received: from mailhub.sw.ru ([195.214.232.25]:7444 helo=relay.sw.ru) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1cZg5j-00080W-Mb for qemu-devel@nongnu.org; Fri, 03 Feb 2017 10:48:03 -0500 Received: from kvm.qa.sw.ru. (msk-vpn.virtuozzo.com [195.214.232.6]) by relay.sw.ru (8.13.4/8.13.4) with ESMTP id v13Flv7s011039; Fri, 3 Feb 2017 18:47:58 +0300 (MSK) From: Vladimir Sementsov-Ogievskiy To: qemu-block@nongnu.org, qemu-devel@nongnu.org Date: Fri, 3 Feb 2017 18:47:52 +0300 Message-Id: <20170203154757.36140-14-vsementsov@virtuozzo.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20170203154757.36140-1-vsementsov@virtuozzo.com> References: <20170203154757.36140-1-vsementsov@virtuozzo.com> X-detected-operating-system: by eggs.gnu.org: OpenBSD 3.x [fuzzy] X-Received-From: 195.214.232.25 Subject: [Qemu-devel] [PATCH 13/18] nbd: add nbd_dirty_bitmap_load 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, famz@redhat.com, den@virtuozzo.com, armbru@redhat.com, mreitz@redhat.com, stefanha@redhat.com, pbonzini@redhat.com, jsnow@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" Realize bdrv_dirty_bitmap_load interface. Signed-off-by: Vladimir Sementsov-Ogievskiy --- block/nbd.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/block/nbd.c b/block/nbd.c index 63bc3f04d0..b2b6fd1cf9 100644 --- a/block/nbd.c +++ b/block/nbd.c @@ -557,6 +557,35 @@ static void nbd_refresh_filename(BlockDriverState *bs,= QDict *options) bs->full_open_options =3D opts; } =20 +static BdrvDirtyBitmap *nbd_dirty_bitmap_load(BlockDriverState *bs, + const char *name, Error **er= rp) +{ + int64_t offset =3D 0, end; + uint32_t ma =3D -1; + BdrvDirtyBitmap *bitmap =3D + bdrv_create_dirty_bitmap(bs, bdrv_get_default_bitmap_granularity(b= s), + name, errp); + if (bitmap =3D=3D NULL) { + return NULL; + } + + end =3D bdrv_dirty_bitmap_size(bitmap) << BDRV_SECTOR_BITS; + + while (offset < end) { + offset =3D nbd_client_co_load_bitmap_part(bs, offset, + MIN(end - offset, ma), bit= map); + if (offset < 0) { + goto fail; + } + } + + return bitmap; + +fail: + bdrv_release_dirty_bitmap(bs, bitmap); + return NULL; +} + static BlockDriver bdrv_nbd =3D { .format_name =3D "nbd", .protocol_name =3D "nbd", @@ -574,6 +603,7 @@ static BlockDriver bdrv_nbd =3D { .bdrv_detach_aio_context =3D nbd_detach_aio_context, .bdrv_attach_aio_context =3D nbd_attach_aio_context, .bdrv_refresh_filename =3D nbd_refresh_filename, + .bdrv_dirty_bitmap_load =3D nbd_dirty_bitmap_load, }; =20 static BlockDriver bdrv_nbd_tcp =3D { @@ -593,6 +623,7 @@ static BlockDriver bdrv_nbd_tcp =3D { .bdrv_detach_aio_context =3D nbd_detach_aio_context, .bdrv_attach_aio_context =3D nbd_attach_aio_context, .bdrv_refresh_filename =3D nbd_refresh_filename, + .bdrv_dirty_bitmap_load =3D nbd_dirty_bitmap_load, }; =20 static BlockDriver bdrv_nbd_unix =3D { @@ -612,6 +643,7 @@ static BlockDriver bdrv_nbd_unix =3D { .bdrv_detach_aio_context =3D nbd_detach_aio_context, .bdrv_attach_aio_context =3D nbd_attach_aio_context, .bdrv_refresh_filename =3D nbd_refresh_filename, + .bdrv_dirty_bitmap_load =3D nbd_dirty_bitmap_load, }; =20 static void bdrv_nbd_init(void) --=20 2.11.0 From nobody Fri May 3 23:54:14 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.zoho.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; Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1486138515421837.0893202170475; Fri, 3 Feb 2017 08:15:15 -0800 (PST) Received: from localhost ([::1]:35547 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cZgW1-0005Tz-AZ for importer@patchew.org; Fri, 03 Feb 2017 11:15:13 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:36714) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cZg5n-0007nk-EJ for qemu-devel@nongnu.org; Fri, 03 Feb 2017 10:48:10 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1cZg5k-00083V-CJ for qemu-devel@nongnu.org; Fri, 03 Feb 2017 10:48:07 -0500 Received: from mailhub.sw.ru ([195.214.232.25]:12225 helo=relay.sw.ru) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1cZg5j-00080U-Pg for qemu-devel@nongnu.org; Fri, 03 Feb 2017 10:48:04 -0500 Received: from kvm.qa.sw.ru. (msk-vpn.virtuozzo.com [195.214.232.6]) by relay.sw.ru (8.13.4/8.13.4) with ESMTP id v13Flv7t011039; Fri, 3 Feb 2017 18:47:58 +0300 (MSK) From: Vladimir Sementsov-Ogievskiy To: qemu-block@nongnu.org, qemu-devel@nongnu.org Date: Fri, 3 Feb 2017 18:47:53 +0300 Message-Id: <20170203154757.36140-15-vsementsov@virtuozzo.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20170203154757.36140-1-vsementsov@virtuozzo.com> References: <20170203154757.36140-1-vsementsov@virtuozzo.com> X-detected-operating-system: by eggs.gnu.org: OpenBSD 3.x [fuzzy] X-Received-From: 195.214.232.25 Subject: [Qemu-devel] [PATCH 14/18] qmp: add x-debug-block-dirty-bitmap-sha256 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, famz@redhat.com, den@virtuozzo.com, armbru@redhat.com, mreitz@redhat.com, stefanha@redhat.com, pbonzini@redhat.com, jsnow@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" Signed-off-by: Vladimir Sementsov-Ogievskiy --- block/dirty-bitmap.c | 5 +++++ blockdev.c | 29 +++++++++++++++++++++++++++++ include/block/dirty-bitmap.h | 2 ++ include/qemu/hbitmap.h | 8 ++++++++ qapi/block-core.json | 27 +++++++++++++++++++++++++++ tests/Makefile.include | 2 +- util/hbitmap.c | 11 +++++++++++ 7 files changed, 83 insertions(+), 1 deletion(-) diff --git a/block/dirty-bitmap.c b/block/dirty-bitmap.c index 394d4328d5..a4f77dcf73 100644 --- a/block/dirty-bitmap.c +++ b/block/dirty-bitmap.c @@ -598,3 +598,8 @@ BdrvDirtyBitmap *bdrv_load_dirty_bitmap(BlockDriverStat= e *bs, const char *name, =20 return lbco.ret; } + +char *bdrv_dirty_bitmap_sha256(const BdrvDirtyBitmap *bitmap, Error **errp) +{ + return hbitmap_sha256(bitmap->bitmap, errp); +} diff --git a/blockdev.c b/blockdev.c index 245e1e1d17..1bc3fe386a 100644 --- a/blockdev.c +++ b/blockdev.c @@ -2790,6 +2790,35 @@ void qmp_block_dirty_bitmap_clear(const char *node, = const char *name, aio_context_release(aio_context); } =20 +BlockDirtyBitmapSha256 *qmp_x_debug_block_dirty_bitmap_sha256(const char *= node, + const char *= name, + Error **errp) +{ + AioContext *aio_context; + BdrvDirtyBitmap *bitmap; + BlockDriverState *bs; + BlockDirtyBitmapSha256 *ret =3D NULL; + char *sha256; + + bitmap =3D block_dirty_bitmap_lookup(node, name, &bs, &aio_context, er= rp); + if (!bitmap || !bs) { + return NULL; + } + + sha256 =3D bdrv_dirty_bitmap_sha256(bitmap, errp); + if (sha256 =3D=3D NULL) { + goto out; + } + + ret =3D g_new(BlockDirtyBitmapSha256, 1); + ret->sha256 =3D sha256; + +out: + aio_context_release(aio_context); + + return ret; +} + void hmp_drive_del(Monitor *mon, const QDict *qdict) { const char *id =3D qdict_get_str(qdict, "id"); diff --git a/include/block/dirty-bitmap.h b/include/block/dirty-bitmap.h index c0c70a8c67..0efb5591d6 100644 --- a/include/block/dirty-bitmap.h +++ b/include/block/dirty-bitmap.h @@ -80,4 +80,6 @@ BdrvDirtyBitmap *bdrv_dirty_bitmap_next(BlockDriverState = *bs, BdrvDirtyBitmap *bdrv_load_dirty_bitmap(BlockDriverState *bs, const char *= name, Error **errp); =20 +char *bdrv_dirty_bitmap_sha256(const BdrvDirtyBitmap *bitmap, Error **errp= ); + #endif diff --git a/include/qemu/hbitmap.h b/include/qemu/hbitmap.h index d6fe553b12..42685b4289 100644 --- a/include/qemu/hbitmap.h +++ b/include/qemu/hbitmap.h @@ -225,6 +225,14 @@ void hbitmap_deserialize_zeroes(HBitmap *hb, uint64_t = start, uint64_t count, void hbitmap_deserialize_finish(HBitmap *hb); =20 /** + * hbitmap_sha256: + * @bitmap: HBitmap to operate on. + * + * Returns SHA256 hash of the last level. + */ +char *hbitmap_sha256(const HBitmap *bitmap, Error **errp); + +/** * hbitmap_free: * @hb: HBitmap to operate on. * diff --git a/qapi/block-core.json b/qapi/block-core.json index 0e15c73774..b258c45595 100644 --- a/qapi/block-core.json +++ b/qapi/block-core.json @@ -1280,6 +1280,33 @@ 'data': 'BlockDirtyBitmap' } =20 ## +# @BlockDirtyBitmapSha256: +# +# SHA256 hash of dirty bitmap data +# +# @sha256: bitmap SHA256 hash +# +# Since: 2.9 +## + { 'struct': 'BlockDirtyBitmapSha256', + 'data': {'sha256': 'str'} } + +## +# @x-debug-block-dirty-bitmap-sha256: +# +# Get bitmap SHA256 +# +# Returns: BlockDirtyBitmapSha256 on success +# If @node is not a valid block device, DeviceNotFound +# If @name is not found or if hashing is failed, GenericError wit= h an +# explanation +# +# Since: 2.9 +## + { 'command': 'x-debug-block-dirty-bitmap-sha256', + 'data': 'BlockDirtyBitmap', 'returns': 'BlockDirtyBitmapSha256' } + +## # @blockdev-mirror: # # Start mirroring a block device's writes to a new destination. diff --git a/tests/Makefile.include b/tests/Makefile.include index 4841d582a1..0ee7e30a63 100644 --- a/tests/Makefile.include +++ b/tests/Makefile.include @@ -497,7 +497,7 @@ tests/test-blockjob$(EXESUF): tests/test-blockjob.o $(t= est-block-obj-y) $(test-u tests/test-blockjob-txn$(EXESUF): tests/test-blockjob-txn.o $(test-block-o= bj-y) $(test-util-obj-y) tests/test-thread-pool$(EXESUF): tests/test-thread-pool.o $(test-block-obj= -y) tests/test-iov$(EXESUF): tests/test-iov.o $(test-util-obj-y) -tests/test-hbitmap$(EXESUF): tests/test-hbitmap.o $(test-util-obj-y) +tests/test-hbitmap$(EXESUF): tests/test-hbitmap.o $(test-util-obj-y) $(tes= t-crypto-obj-y) tests/test-x86-cpuid$(EXESUF): tests/test-x86-cpuid.o tests/test-xbzrle$(EXESUF): tests/test-xbzrle.o migration/xbzrle.o page_ca= che.o $(test-util-obj-y) tests/test-cutils$(EXESUF): tests/test-cutils.o util/cutils.o diff --git a/util/hbitmap.c b/util/hbitmap.c index b850c2baf5..64078d94a1 100644 --- a/util/hbitmap.c +++ b/util/hbitmap.c @@ -13,6 +13,7 @@ #include "qemu/hbitmap.h" #include "qemu/host-utils.h" #include "trace.h" +#include "crypto/hash.h" =20 /* HBitmaps provides an array of bits. The bits are stored as usual in an * array of unsigned longs, but HBitmap is also optimized to provide fast @@ -699,3 +700,13 @@ void hbitmap_free_meta(HBitmap *hb) hbitmap_free(hb->meta); hb->meta =3D NULL; } + +char *hbitmap_sha256(const HBitmap *bitmap, Error **errp) +{ + size_t size =3D bitmap->sizes[HBITMAP_LEVELS - 1] * sizeof(unsigned lo= ng); + char *data =3D (char *)bitmap->levels[HBITMAP_LEVELS - 1]; + char *hash =3D NULL; + qcrypto_hash_digest(QCRYPTO_HASH_ALG_SHA256, data, size, &hash, errp); + + return hash; +} --=20 2.11.0 From nobody Fri May 3 23:54:14 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.zoho.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; Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1486137549009265.7953161573689; Fri, 3 Feb 2017 07:59:09 -0800 (PST) Received: from localhost ([::1]:35445 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cZgGQ-000067-VB for importer@patchew.org; Fri, 03 Feb 2017 10:59:07 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:36698) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cZg5n-0007nc-CB for qemu-devel@nongnu.org; Fri, 03 Feb 2017 10:48:09 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1cZg5j-00082k-Oj for qemu-devel@nongnu.org; Fri, 03 Feb 2017 10:48:07 -0500 Received: from mailhub.sw.ru ([195.214.232.25]:46671 helo=relay.sw.ru) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1cZg5j-000808-CE for qemu-devel@nongnu.org; Fri, 03 Feb 2017 10:48:03 -0500 Received: from kvm.qa.sw.ru. (msk-vpn.virtuozzo.com [195.214.232.6]) by relay.sw.ru (8.13.4/8.13.4) with ESMTP id v13Flv7u011039; Fri, 3 Feb 2017 18:47:58 +0300 (MSK) From: Vladimir Sementsov-Ogievskiy To: qemu-block@nongnu.org, qemu-devel@nongnu.org Date: Fri, 3 Feb 2017 18:47:54 +0300 Message-Id: <20170203154757.36140-16-vsementsov@virtuozzo.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20170203154757.36140-1-vsementsov@virtuozzo.com> References: <20170203154757.36140-1-vsementsov@virtuozzo.com> X-detected-operating-system: by eggs.gnu.org: OpenBSD 3.x [fuzzy] X-Received-From: 195.214.232.25 Subject: [Qemu-devel] [PATCH 15/18] qmp: add block-dirty-bitmap-load 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, famz@redhat.com, den@virtuozzo.com, armbru@redhat.com, mreitz@redhat.com, stefanha@redhat.com, pbonzini@redhat.com, jsnow@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" For loading dirty bitmap from nbd server. Or for underlying storages for other formats. Signed-off-by: Vladimir Sementsov-Ogievskiy --- blockdev.c | 28 ++++++++++++++++++++++++++++ qapi/block-core.json | 14 ++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/blockdev.c b/blockdev.c index 1bc3fe386a..2529943e7f 100644 --- a/blockdev.c +++ b/blockdev.c @@ -2790,6 +2790,34 @@ void qmp_block_dirty_bitmap_clear(const char *node, = const char *name, aio_context_release(aio_context); } =20 +void qmp_block_dirty_bitmap_load(const char *node, const char *name, + Error **errp) +{ + AioContext *aio_context; + BlockDriverState *bs; + + if (!node) { + error_setg(errp, "Node cannot be NULL"); + return; + } + if (!name) { + error_setg(errp, "Bitmap name cannot be NULL"); + return; + } + bs =3D bdrv_lookup_bs(node, node, NULL); + if (!bs) { + error_setg(errp, "Node '%s' not found", node); + return; + } + + aio_context =3D bdrv_get_aio_context(bs); + aio_context_acquire(aio_context); + + bdrv_load_dirty_bitmap(bs, name, errp); + + aio_context_release(aio_context); +} + BlockDirtyBitmapSha256 *qmp_x_debug_block_dirty_bitmap_sha256(const char *= node, const char *= name, Error **errp) diff --git a/qapi/block-core.json b/qapi/block-core.json index b258c45595..63777ea55b 100644 --- a/qapi/block-core.json +++ b/qapi/block-core.json @@ -1280,6 +1280,20 @@ 'data': 'BlockDirtyBitmap' } =20 ## +# @block-dirty-bitmap-load: +# +# Load a dirty bitmap from the storage (qcow2 file or nbd export) +# +# Returns: nothing on success +# If @node is not a valid block device, DeviceNotFound +# If @name is not found, GenericError with an explanation +# +# Since: vz-7.4 +## + { 'command': 'block-dirty-bitmap-load', + 'data': 'BlockDirtyBitmap' } + +## # @BlockDirtyBitmapSha256: # # SHA256 hash of dirty bitmap data --=20 2.11.0 From nobody Fri May 3 23:54:14 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.zoho.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; Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1486138811418103.75065055596326; Fri, 3 Feb 2017 08:20:11 -0800 (PST) Received: from localhost ([::1]:35575 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cZgam-0001Jg-TO for importer@patchew.org; Fri, 03 Feb 2017 11:20:08 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:36782) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cZg5p-0007pX-3x for qemu-devel@nongnu.org; Fri, 03 Feb 2017 10:48:13 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1cZg5j-00082z-VJ for qemu-devel@nongnu.org; Fri, 03 Feb 2017 10:48:09 -0500 Received: from mailhub.sw.ru ([195.214.232.25]:8881 helo=relay.sw.ru) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1cZg5j-00080P-Du for qemu-devel@nongnu.org; Fri, 03 Feb 2017 10:48:03 -0500 Received: from kvm.qa.sw.ru. (msk-vpn.virtuozzo.com [195.214.232.6]) by relay.sw.ru (8.13.4/8.13.4) with ESMTP id v13Flv7v011039; Fri, 3 Feb 2017 18:47:58 +0300 (MSK) From: Vladimir Sementsov-Ogievskiy To: qemu-block@nongnu.org, qemu-devel@nongnu.org Date: Fri, 3 Feb 2017 18:47:55 +0300 Message-Id: <20170203154757.36140-17-vsementsov@virtuozzo.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20170203154757.36140-1-vsementsov@virtuozzo.com> References: <20170203154757.36140-1-vsementsov@virtuozzo.com> X-detected-operating-system: by eggs.gnu.org: OpenBSD 3.x [fuzzy] X-Received-From: 195.214.232.25 Subject: [Qemu-devel] [PATCH 16/18] iotests: add test for nbd dirty bitmap export 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, famz@redhat.com, den@virtuozzo.com, armbru@redhat.com, mreitz@redhat.com, stefanha@redhat.com, pbonzini@redhat.com, jsnow@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" Signed-off-by: Vladimir Sementsov-Ogievskiy --- tests/qemu-iotests/180 | 133 +++++++++++++++++++++++++++++++++++++++++= ++++ tests/qemu-iotests/180.out | 5 ++ tests/qemu-iotests/group | 1 + 3 files changed, 139 insertions(+) create mode 100755 tests/qemu-iotests/180 create mode 100644 tests/qemu-iotests/180.out diff --git a/tests/qemu-iotests/180 b/tests/qemu-iotests/180 new file mode 100755 index 0000000000..e8238a064a --- /dev/null +++ b/tests/qemu-iotests/180 @@ -0,0 +1,133 @@ +#!/usr/bin/env python +# +# Test case for NBD's bitmap export +# Copyright (C) 2017 Virtuozzo. +# +# derived from io test 147, original copyright: +# Copyright (C) 2016 Red Hat, Inc. +# +# 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 os +import socket +import stat +import time +import iotests +from iotests import cachemode, imgfmt, qemu_img, qemu_nbd + +NBD_PORT =3D 10811 + +test_img =3D os.path.join(iotests.test_dir, 'test.img') +unix_socket =3D os.path.join(iotests.test_dir, 'nbd.socket') + +class NBDBlockdevAddBase(iotests.QMPTestCase): + def blockdev_add_options(self, address, export=3DNone): + options =3D { 'node-name': 'nbd-blockdev', + 'driver': 'raw', + 'file': { + 'driver': 'nbd', + 'server': address, + 'bitmap': 'mega' + } } + if export is not None: + options['file']['export'] =3D export + return options + + def client_test(self, filename, address, sha256, export=3DNone): + bao =3D self.blockdev_add_options(address, export) + result =3D self.vm.qmp('blockdev-add', **bao) + self.assert_qmp(result, 'return', {}) + + result =3D self.vm.qmp('query-named-block-nodes') + for node in result['return']: + if node['node-name'] =3D=3D 'nbd-blockdev': + if isinstance(filename, str): + self.assert_qmp(node, 'image/filename', filename) + else: + self.assert_json_filename_equal(node['image']['filenam= e'], + filename) + break + + result =3D self.vm.qmp('block-dirty-bitmap-load', + node=3D'nbd-blockdev', name=3D'mega') + self.assert_qmp(result, 'return', {}) + + result =3D self.vm.qmp('x-debug-block-dirty-bitmap-sha256', + node=3D'nbd-blockdev', name=3D'mega') + self.assert_qmp(result, 'return/sha256', sha256); + + def setUp(self): + qemu_img('create', '-f', iotests.imgfmt, test_img, '0x400000000') + self.vm =3D iotests.VM() + self.vm.launch() + + self.server =3D iotests.VM('.server') + self.server.add_drive_raw('if=3Dnone,id=3Dnbd-export,' + + 'file=3D%s,' % test_img + + 'format=3D%s,' % imgfmt + + 'cache=3D%s' % cachemode) + self.server.launch() + + def tearDown(self): + self.vm.shutdown() + self.server.shutdown() + os.remove(test_img) + + def _server_up(self, address): + result =3D self.server.qmp('nbd-server-start', addr=3Daddress) + self.assert_qmp(result, 'return', {}) + + result =3D self.server.qmp('nbd-server-add', device=3D'nbd-export') + self.assert_qmp(result, 'return', {}) + + def _server_down(self): + result =3D self.server.qmp('nbd-server-stop') + self.assert_qmp(result, 'return', {}) + + def test_export_bitmap(self): + address =3D { 'type': 'inet', + 'data': { + 'host': 'localhost', + 'port': str(NBD_PORT) + } } + + granularity =3D 65536 + regions =3D [ + { 'start': 0, 'count': 0x100000 }, + { 'start': 0x100000000, 'count': 0x200000 }, + { 'start': 0x399900000, 'count': 0x100000 } + ] + + result =3D self.server.qmp('block-dirty-bitmap-add', node=3D'nbd-e= xport', + name=3D'mega', granularity=3Dgranularity) + self.assert_qmp(result, 'return', {}); + + for r in regions: + self.server.hmp_qemu_io('nbd-export', + 'write %d %d' % (r['start'], r['count'= ])) + + result =3D self.server.qmp('x-debug-block-dirty-bitmap-sha256', + node=3D'nbd-export', name=3D'mega') + sha256 =3D result['return']['sha256'] + + self._server_up(address) + self.client_test('nbd://localhost:%i/nbd-export' % NBD_PORT, + address, sha256, 'nbd-export') + #self._server_down() + +if __name__ =3D=3D '__main__': + # Need to support image creation + iotests.main(supported_fmts=3D['vpc', 'parallels', 'qcow', 'vdi', 'qco= w2', + 'vmdk', 'raw', 'vhdx', 'qed']) diff --git a/tests/qemu-iotests/180.out b/tests/qemu-iotests/180.out new file mode 100644 index 0000000000..ae1213e6f8 --- /dev/null +++ b/tests/qemu-iotests/180.out @@ -0,0 +1,5 @@ +. +---------------------------------------------------------------------- +Ran 1 tests + +OK diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group index 866c1a032d..9d06d3f862 100644 --- a/tests/qemu-iotests/group +++ b/tests/qemu-iotests/group @@ -165,3 +165,4 @@ 170 rw auto quick 171 rw auto quick 172 auto +180 auto --=20 2.11.0 From nobody Fri May 3 23:54:14 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.zoho.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; Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1486137546245742.0976177737982; Fri, 3 Feb 2017 07:59:06 -0800 (PST) Received: from localhost ([::1]:35444 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cZgGO-0008Ux-9N for importer@patchew.org; Fri, 03 Feb 2017 10:59:04 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:36765) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cZg5o-0007pJ-Od for qemu-devel@nongnu.org; Fri, 03 Feb 2017 10:48:13 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1cZg5k-00083D-47 for qemu-devel@nongnu.org; Fri, 03 Feb 2017 10:48:08 -0500 Received: from mailhub.sw.ru ([195.214.232.25]:13024 helo=relay.sw.ru) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1cZg5j-00080M-Kd for qemu-devel@nongnu.org; Fri, 03 Feb 2017 10:48:04 -0500 Received: from kvm.qa.sw.ru. (msk-vpn.virtuozzo.com [195.214.232.6]) by relay.sw.ru (8.13.4/8.13.4) with ESMTP id v13Flv7w011039; Fri, 3 Feb 2017 18:47:58 +0300 (MSK) From: Vladimir Sementsov-Ogievskiy To: qemu-block@nongnu.org, qemu-devel@nongnu.org Date: Fri, 3 Feb 2017 18:47:56 +0300 Message-Id: <20170203154757.36140-18-vsementsov@virtuozzo.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20170203154757.36140-1-vsementsov@virtuozzo.com> References: <20170203154757.36140-1-vsementsov@virtuozzo.com> X-detected-operating-system: by eggs.gnu.org: OpenBSD 3.x [fuzzy] X-Received-From: 195.214.232.25 Subject: [Qemu-devel] [PATCH 17/18] nbd: BLOCK_STATUS for standard get_block_status function: server part 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, famz@redhat.com, den@virtuozzo.com, armbru@redhat.com, mreitz@redhat.com, stefanha@redhat.com, pbonzini@redhat.com, jsnow@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" Minimal realization: only one extent in server answer is supported. Signed-off-by: Vladimir Sementsov-Ogievskiy --- include/block/nbd.h | 3 ++ nbd/nbd-internal.h | 1 + nbd/server.c | 80 ++++++++++++++++++++++++++++++++++++++++++++++++-= ---- 3 files changed, 77 insertions(+), 7 deletions(-) diff --git a/include/block/nbd.h b/include/block/nbd.h index 08d5e51f21..69aee1eda1 100644 --- a/include/block/nbd.h +++ b/include/block/nbd.h @@ -181,6 +181,9 @@ enum { #define NBD_REPLY_TYPE_ERROR ((1 << 15) + 1) #define NBD_REPLY_TYPE_ERROR_OFFSET ((1 << 15) + 2) =20 +#define NBD_STATE_HOLE 1 +#define NBD_STATE_ZERO (1 << 1) + #define NBD_MAX_BITMAP_EXTENTS (0x100000 / 8) /* 1 mb of extents data */ =20 ssize_t nbd_wr_syncv(QIOChannel *ioc, diff --git a/nbd/nbd-internal.h b/nbd/nbd-internal.h index fbbcf69925..f89baa6049 100644 --- a/nbd/nbd-internal.h +++ b/nbd/nbd-internal.h @@ -86,6 +86,7 @@ #define NBD_OPT_LIST_META_CONTEXT (9) #define NBD_OPT_SET_META_CONTEXT (10) =20 +#define NBD_META_NS_BASE "base" #define NBD_META_NS_BITMAPS "qemu-dirty-bitmap" =20 /* NBD errors are based on errno numbers, so there is a 1:1 mapping, diff --git a/nbd/server.c b/nbd/server.c index c96dda4086..cb87481382 100644 --- a/nbd/server.c +++ b/nbd/server.c @@ -103,6 +103,7 @@ struct NBDClient { =20 bool structured_reply; BdrvDirtyBitmap *export_bitmap; + bool export_block_status; }; =20 /* That's all folks */ @@ -506,8 +507,24 @@ static int nbd_negotiate_one_bitmap_query(QIOChannel *= ioc, BlockDriverState *bs, return 0; } =20 +static int nbd_negotiate_one_base_query(QIOChannel *ioc, BlockDriverState = *bs, + uint32_t opt, const char *query, + bool *block_status) +{ + if (query[0] =3D=3D '\0' || strcmp(query, "allocation") =3D=3D 0) { + if (block_status !=3D NULL) { + *block_status =3D true; + } + + return nbd_negotiate_send_meta_context(ioc, "base:allocation", opt= ); + } + + return 0; +} + static int nbd_negotiate_one_meta_query(QIOChannel *ioc, BlockDriverState = *bs, - uint32_t opt, BdrvDirtyBitmap **bi= tmap) + uint32_t opt, BdrvDirtyBitmap **bi= tmap, + bool *block_status) { int ret =3D 0, nb_read; char *query, *colon, *namespace, *subquery; @@ -530,6 +547,9 @@ static int nbd_negotiate_one_meta_query(QIOChannel *ioc= , BlockDriverState *bs, =20 if (strcmp(namespace, NBD_META_NS_BITMAPS) =3D=3D 0) { ret =3D nbd_negotiate_one_bitmap_query(ioc, bs, opt, subquery, bit= map); + } else if (strcmp(namespace, NBD_META_NS_BASE) =3D=3D 0) { + ret =3D nbd_negotiate_one_base_query(ioc, bs, opt, subquery, + block_status); } =20 out: @@ -663,7 +683,8 @@ static int nbd_negotiate_list_meta_context(NBDClient *c= lient, uint32_t length) =20 for (i =3D 0; i < nb_queries; ++i) { ret =3D nbd_negotiate_one_meta_query(client->ioc, bs, - NBD_OPT_LIST_META_CONTEXT, NULL= ); + NBD_OPT_LIST_META_CONTEXT, NULL, + NULL); if (ret < 0) { return ret; } @@ -712,7 +733,8 @@ static int nbd_negotiate_set_meta_context(NBDClient *cl= ient, uint32_t length) =20 ret =3D nbd_negotiate_one_meta_query(client->ioc, bs, NBD_OPT_SET_META_CONTEXT, - &client->export_bitmap); + &client->export_bitmap, + &client->export_block_status); if (ret < 0) { return ret; } @@ -1497,6 +1519,30 @@ static unsigned add_extents(NBDExtent *extents, unsi= gned nb_extents, return i; } =20 +static int blockstatus_to_extent(BlockDriverState *bs, uint64_t offset, + uint64_t length, NBDExtent *extent) +{ + BlockDriverState *file; + uint64_t start_sector =3D offset >> BDRV_SECTOR_BITS; + uint64_t last_sector =3D (offset + length - 1) >> BDRV_SECTOR_BITS; + uint64_t begin =3D start_sector; + uint64_t end =3D last_sector + 1; + + int nb =3D MIN(INT_MAX, end - begin); + int64_t ret =3D bdrv_get_block_status_above(bs, NULL, begin, nb, &nb, = &file); + if (ret < 0) { + return ret; + } + + extent->flags =3D + cpu_to_be32((ret & BDRV_BLOCK_ALLOCATED ? 0 : NBD_STATE_HOLE) | + (ret & BDRV_BLOCK_ZERO ? NBD_STATE_ZERO : 0)); + extent->length =3D cpu_to_be32((nb << BDRV_SECTOR_BITS) - + (offset - (start_sector << BDRV_SECTOR_BI= TS))); + + return 0; +} + static unsigned bitmap_to_extents(BdrvDirtyBitmap *bitmap, uint64_t offset, uint64_t length, NBDExtent *extents, unsigned nb_extents) @@ -1589,6 +1635,21 @@ static int nbd_co_send_bitmap(NBDClient *client, uin= t64_t handle, return ret; } =20 +static int nbd_co_send_block_status(NBDClient *client, uint64_t handle, + BlockDriverState *bs, uint64_t offset, + uint64_t length, uint32_t context_id) +{ + int ret; + NBDExtent extent; + + ret =3D blockstatus_to_extent(bs, offset, length, &extent); + if (ret < 0) { + return nbd_co_send_structured_error(client, handle, -ret); + } + + return nbd_co_send_extents(client, handle, &extent, 1, context_id); +} + /* Collect a client request. Return 0 if request looks valid, -EAGAIN * to keep trying the collection, -EIO to drop connection right away, * and any other negative value to report an error to the client @@ -1869,13 +1930,18 @@ static void nbd_trip(void *opaque) break; case NBD_CMD_BLOCK_STATUS: TRACE("Request type is BLOCK_STATUS"); - if (client->export_bitmap =3D=3D NULL) { + if (!!client->export_bitmap) { + ret =3D nbd_co_send_bitmap(req->client, request.handle, + client->export_bitmap, request.from, + request.len, 0); + } else if (client->export_block_status) { + ret =3D nbd_co_send_block_status(req->client, request.handle, + blk_bs(exp->blk), request.from, + request.len, 0); + } else { reply.error =3D EINVAL; goto error_reply; } - ret =3D nbd_co_send_bitmap(req->client, request.handle, - client->export_bitmap, request.from, - request.len, 0); if (ret < 0) { goto out; } --=20 2.11.0 From nobody Fri May 3 23:54:14 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.zoho.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; Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1486137286698322.1752363238903; Fri, 3 Feb 2017 07:54:46 -0800 (PST) Received: from localhost ([::1]:35422 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cZgCC-0004Xk-OE for importer@patchew.org; Fri, 03 Feb 2017 10:54:44 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:36740) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cZg5o-0007p9-Dn for qemu-devel@nongnu.org; Fri, 03 Feb 2017 10:48:11 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1cZg5k-00083b-DE for qemu-devel@nongnu.org; Fri, 03 Feb 2017 10:48:08 -0500 Received: from mailhub.sw.ru ([195.214.232.25]:48742 helo=relay.sw.ru) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1cZg5j-00080Y-RA for qemu-devel@nongnu.org; Fri, 03 Feb 2017 10:48:04 -0500 Received: from kvm.qa.sw.ru. (msk-vpn.virtuozzo.com [195.214.232.6]) by relay.sw.ru (8.13.4/8.13.4) with ESMTP id v13Flv7x011039; Fri, 3 Feb 2017 18:47:59 +0300 (MSK) From: Vladimir Sementsov-Ogievskiy To: qemu-block@nongnu.org, qemu-devel@nongnu.org Date: Fri, 3 Feb 2017 18:47:57 +0300 Message-Id: <20170203154757.36140-19-vsementsov@virtuozzo.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20170203154757.36140-1-vsementsov@virtuozzo.com> References: <20170203154757.36140-1-vsementsov@virtuozzo.com> X-detected-operating-system: by eggs.gnu.org: OpenBSD 3.x [fuzzy] X-Received-From: 195.214.232.25 Subject: [Qemu-devel] [PATCH 18/18] nbd: BLOCK_STATUS for standard get_block_status function: client part 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, famz@redhat.com, den@virtuozzo.com, armbru@redhat.com, mreitz@redhat.com, stefanha@redhat.com, pbonzini@redhat.com, jsnow@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" Minimal realization: only first extent from the answer is used. Signed-off-by: Vladimir Sementsov-Ogievskiy --- block/nbd-client.c | 41 ++++++++++++++++++++++++++++++++++++++++- block/nbd-client.h | 5 +++++ block/nbd.c | 3 +++ include/block/nbd.h | 2 +- nbd/client.c | 23 ++++++++++++++++------- qemu-nbd.c | 2 +- 6 files changed, 66 insertions(+), 10 deletions(-) diff --git a/block/nbd-client.c b/block/nbd-client.c index c7eb21fb02..e419c1497c 100644 --- a/block/nbd-client.c +++ b/block/nbd-client.c @@ -528,6 +528,44 @@ int64_t nbd_client_co_load_bitmap_part(BlockDriverStat= e *bs, uint64_t offset, (uint64_t)bdrv_dirty_bitmap_granularity(bitmap)); } =20 +int64_t coroutine_fn nbd_client_co_get_block_status(BlockDriverState *bs, + int64_t sector_num, + int nb_sectors, int *p= num, + BlockDriverState **fil= e) +{ + int64_t ret; + uint32_t nb_extents; + NBDExtent *extents; + NBDClientSession *client =3D nbd_get_client_session(bs); + + if (!client->block_status_ok) { + *pnum =3D nb_sectors; + ret =3D BDRV_BLOCK_DATA | BDRV_BLOCK_ALLOCATED; + if (bs->drv->protocol_name) { + ret |=3D BDRV_BLOCK_OFFSET_VALID | (sector_num * BDRV_SECTOR_S= IZE); + } + return ret; + } + + ret =3D nbd_client_co_cmd_block_status(bs, sector_num << BDRV_SECTOR_B= ITS, + nb_sectors << BDRV_SECTOR_BITS, + &extents, &nb_extents); + if (ret < 0) { + return ret; + } + + *pnum =3D extents[0].length >> BDRV_SECTOR_BITS; + ret =3D (extents[0].flags & NBD_STATE_HOLE ? 0 : BDRV_BLOCK_ALLOCATED)= | + (extents[0].flags & NBD_STATE_ZERO ? BDRV_BLOCK_ZERO : 0); + + if ((ret & BDRV_BLOCK_ALLOCATED) && !(ret & BDRV_BLOCK_ZERO)) { + ret |=3D BDRV_BLOCK_DATA; + } + + g_free(extents); + + return ret; +} =20 void nbd_client_detach_aio_context(BlockDriverState *bs) { @@ -579,7 +617,8 @@ int nbd_client_init(BlockDriverState *bs, &client->size, &client->structured_reply, bitmap_name, - &client->bitmap_ok, errp); + &client->bitmap_ok, + &client->block_status_ok, errp); if (ret < 0) { logout("Failed to negotiate with the NBD server\n"); return ret; diff --git a/block/nbd-client.h b/block/nbd-client.h index e5ec89b9f6..9848732628 100644 --- a/block/nbd-client.h +++ b/block/nbd-client.h @@ -34,6 +34,7 @@ typedef struct NBDClientSession { bool is_unix; =20 bool structured_reply; + bool block_status_ok; bool bitmap_ok; uint32_t meta_data_context_id; } NBDClientSession; @@ -59,6 +60,10 @@ int nbd_client_co_preadv(BlockDriverState *bs, uint64_t = offset, uint64_t bytes, QEMUIOVector *qiov, int flags); int64_t nbd_client_co_load_bitmap_part(BlockDriverState *bs, uint64_t offs= et, uint64_t bytes, BdrvDirtyBitmap *bi= tmap); +int64_t coroutine_fn nbd_client_co_get_block_status(BlockDriverState *bs, + int64_t sector_num, + int nb_sectors, int *p= num, + BlockDriverState **fil= e); =20 void nbd_client_detach_aio_context(BlockDriverState *bs); void nbd_client_attach_aio_context(BlockDriverState *bs, diff --git a/block/nbd.c b/block/nbd.c index b2b6fd1cf9..b3a28f0746 100644 --- a/block/nbd.c +++ b/block/nbd.c @@ -604,6 +604,7 @@ static BlockDriver bdrv_nbd =3D { .bdrv_attach_aio_context =3D nbd_attach_aio_context, .bdrv_refresh_filename =3D nbd_refresh_filename, .bdrv_dirty_bitmap_load =3D nbd_dirty_bitmap_load, + .bdrv_co_get_block_status =3D nbd_client_co_get_block_status, }; =20 static BlockDriver bdrv_nbd_tcp =3D { @@ -624,6 +625,7 @@ static BlockDriver bdrv_nbd_tcp =3D { .bdrv_attach_aio_context =3D nbd_attach_aio_context, .bdrv_refresh_filename =3D nbd_refresh_filename, .bdrv_dirty_bitmap_load =3D nbd_dirty_bitmap_load, + .bdrv_co_get_block_status =3D nbd_client_co_get_block_status, }; =20 static BlockDriver bdrv_nbd_unix =3D { @@ -644,6 +646,7 @@ static BlockDriver bdrv_nbd_unix =3D { .bdrv_attach_aio_context =3D nbd_attach_aio_context, .bdrv_refresh_filename =3D nbd_refresh_filename, .bdrv_dirty_bitmap_load =3D nbd_dirty_bitmap_load, + .bdrv_co_get_block_status =3D nbd_client_co_get_block_status, }; =20 static void bdrv_nbd_init(void) diff --git a/include/block/nbd.h b/include/block/nbd.h index 69aee1eda1..58c1a3866b 100644 --- a/include/block/nbd.h +++ b/include/block/nbd.h @@ -196,7 +196,7 @@ int nbd_receive_negotiate(QIOChannel *ioc, const char *= name, uint16_t *flags, QIOChannel **outioc, off_t *size, bool *structured_reply, const char *bitmap_name, bool *bitmap_ok, - Error **errp); + bool *block_status_ok, Error **errp); int nbd_init(int fd, QIOChannelSocket *sioc, uint16_t flags, off_t size); ssize_t nbd_send_request(QIOChannel *ioc, NBDRequest *request); int nbd_receive_reply(QIOChannel *ioc, NBDReply *reply); diff --git a/nbd/client.c b/nbd/client.c index c3817b84fa..1b478d112c 100644 --- a/nbd/client.c +++ b/nbd/client.c @@ -563,10 +563,10 @@ static int nbd_receive_query_bitmap(QIOChannel *ioc, = const char *export, =20 int nbd_receive_negotiate(QIOChannel *ioc, const char *name, uint16_t *fla= gs, QCryptoTLSCreds *tlscreds, const char *hostname, - QIOChannel **outioc, - off_t *size, bool *structured_reply, + QIOChannel **outioc, off_t *size, + bool *structured_reply, const char *bitmap_name, bool *bitmap_ok, - Error **errp) + bool *block_status_ok, Error **errp) { char buf[256]; uint64_t magic, s; @@ -681,11 +681,19 @@ int nbd_receive_negotiate(QIOChannel *ioc, const char= *name, uint16_t *flags, false, NULL) =3D=3D 0; } =20 - if (!!structured_reply && *structured_reply && !!bitmap_name) { + if (!!structured_reply && *structured_reply) { int ret; - assert(!!bitmap_ok); - ret =3D nbd_receive_query_bitmap(ioc, name, bitmap_name, - bitmap_ok, errp) =3D=3D 0; + + if (!!bitmap_name) { + assert(!!bitmap_ok); + ret =3D nbd_receive_query_bitmap(ioc, name, bitmap_nam= e, + bitmap_ok, errp) =3D=3D= 0; + } else { + ret =3D nbd_receive_query_meta_context(ioc, name, + "base:allocation", + block_status_ok, + errp); + } if (ret < 0) { goto fail; } @@ -969,6 +977,7 @@ static int nbd_receive_structured_reply_chunk(QIOChanne= l *ioc, NBDReply *reply) =20 switch (reply->type) { case NBD_REPLY_TYPE_NONE: + case NBD_REPLY_TYPE_BLOCK_STATUS: break; case NBD_REPLY_TYPE_OFFSET_DATA: case NBD_REPLY_TYPE_OFFSET_HOLE: diff --git a/qemu-nbd.c b/qemu-nbd.c index cf45444faf..e3a4733e60 100644 --- a/qemu-nbd.c +++ b/qemu-nbd.c @@ -272,7 +272,7 @@ static void *nbd_client_thread(void *arg) =20 ret =3D nbd_receive_negotiate(QIO_CHANNEL(sioc), NULL, &nbdflags, NULL, NULL, NULL, - &size, NULL, NULL, NULL, &local_error); + &size, NULL, NULL, NULL, NULL, &local_erro= r); if (ret < 0) { if (local_error) { error_report_err(local_error); --=20 2.11.0