From nobody Sat Oct 25 21:42:57 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=virtuozzo.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1521636145499317.49756143807554; Wed, 21 Mar 2018 05:42:25 -0700 (PDT) Received: from localhost ([::1]:54636 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eyd4S-0002wF-LL for importer@patchew.org; Wed, 21 Mar 2018 08:42:24 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:54980) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eycib-00061d-3m for qemu-devel@nongnu.org; Wed, 21 Mar 2018 08:19:50 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1eyciW-0005ij-WB for qemu-devel@nongnu.org; Wed, 21 Mar 2018 08:19:49 -0400 Received: from relay.sw.ru ([185.231.240.75]:54948) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1eyciW-0005hn-NY; Wed, 21 Mar 2018 08:19:44 -0400 Received: from msk-vpn.virtuozzo.com ([195.214.232.6] helo=kvm.sw.ru) by relay.sw.ru with esmtp (Exim 4.90_1) (envelope-from ) id 1eyciT-00064u-Ai; Wed, 21 Mar 2018 15:19:41 +0300 From: Vladimir Sementsov-Ogievskiy To: qemu-devel@nongnu.org, qemu-block@nongnu.org Date: Wed, 21 Mar 2018 15:19:37 +0300 Message-Id: <20180321121940.39426-2-vsementsov@virtuozzo.com> X-Mailer: git-send-email 2.11.1 In-Reply-To: <20180321121940.39426-1-vsementsov@virtuozzo.com> References: <20180321121940.39426-1-vsementsov@virtuozzo.com> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x [fuzzy] X-Received-From: 185.231.240.75 Subject: [Qemu-devel] [PATCH 1/4] nbd/server: refactor nbd_negotiate_meta_query for several namespaces X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: kwolf@redhat.com, vsementsov@virtuozzo.com, armbru@redhat.com, mreitz@redhat.com, den@openvz.org, pbonzini@redhat.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Signed-off-by: Vladimir Sementsov-Ogievskiy --- nbd/server.c | 60 +++++++++++++++++++++++++++++++++++++++++++-------------= ---- 1 file changed, 43 insertions(+), 17 deletions(-) diff --git a/nbd/server.c b/nbd/server.c index cea158913b..b830997114 100644 --- a/nbd/server.c +++ b/nbd/server.c @@ -771,13 +771,19 @@ static int nbd_meta_base_query(NBDClient *client, NBD= ExportMetaContexts *meta, return 1; } =20 +struct { + const char *ns; + int (*func)(NBDClient *, NBDExportMetaContexts *, uint32_t, Error **); +} meta_namespace_handlers[] =3D { + /* namespaces should go in non-decreasing order by name length */ + {.ns =3D "base:", .func =3D nbd_meta_base_query}, +}; + /* nbd_negotiate_meta_query * * Parse namespace name and call corresponding function to parse body of t= he * query. * - * The only supported namespace now is 'base'. - * * The function aims not wasting time and memory to read long unknown name= space * names. * @@ -787,9 +793,12 @@ static int nbd_negotiate_meta_query(NBDClient *client, NBDExportMetaContexts *meta, Error **e= rrp) { int ret; - char query[sizeof("base:") - 1]; - size_t baselen =3D strlen("base:"); + int i; uint32_t len; + int bytes_done =3D 0; + char *query; + int nb_ns =3D sizeof(meta_namespace_handlers) / + sizeof(meta_namespace_handlers[0]); =20 ret =3D nbd_opt_read(client, &len, sizeof(len), errp); if (ret <=3D 0) { @@ -797,22 +806,39 @@ static int nbd_negotiate_meta_query(NBDClient *client, } cpu_to_be32s(&len); =20 - /* The only supported namespace for now is 'base'. So query should sta= rt - * with 'base:'. Otherwise, we can ignore it and skip the remainder. */ - if (len < baselen) { - return nbd_opt_skip(client, len, errp); - } + query =3D g_malloc(strlen(meta_namespace_handlers[nb_ns - 1].ns)); =20 - len -=3D baselen; - ret =3D nbd_opt_read(client, query, baselen, errp); - if (ret <=3D 0) { - return ret; - } - if (strncmp(query, "base:", baselen) !=3D 0) { - return nbd_opt_skip(client, len, errp); + for (i =3D 0; i < nb_ns; i++) { + const char *ns =3D meta_namespace_handlers[i].ns; + int ns_len =3D strlen(ns); + int diff_len =3D strlen(ns) - bytes_done; + + assert(diff_len >=3D 0); + + if (diff_len > 0) { + if (len < diff_len) { + ret =3D nbd_opt_skip(client, len, errp); + goto out; + } + + len -=3D diff_len; + ret =3D nbd_opt_read(client, query + bytes_done, diff_len, err= p); + if (ret <=3D 0) { + goto out; + } + } + + if (!strncmp(query, ns, ns_len)) { + ret =3D meta_namespace_handlers[i].func(client, meta, len, err= p); + goto out; + } } =20 - return nbd_meta_base_query(client, meta, len, errp); + ret =3D nbd_opt_skip(client, len, errp); + +out: + g_free(query); + return ret; } =20 /* nbd_negotiate_meta_queries --=20 2.11.1 From nobody Sat Oct 25 21:42:57 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=virtuozzo.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1521636159041422.4374151740142; Wed, 21 Mar 2018 05:42:39 -0700 (PDT) Received: from localhost ([::1]:54637 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eyd4c-00030B-1Z for importer@patchew.org; Wed, 21 Mar 2018 08:42:34 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:54981) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eycib-00061e-3y for qemu-devel@nongnu.org; Wed, 21 Mar 2018 08:19:50 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1eyciW-0005ic-VE for qemu-devel@nongnu.org; Wed, 21 Mar 2018 08:19:49 -0400 Received: from relay.sw.ru ([185.231.240.75]:54940) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1eyciW-0005hl-NH; Wed, 21 Mar 2018 08:19:44 -0400 Received: from msk-vpn.virtuozzo.com ([195.214.232.6] helo=kvm.sw.ru) by relay.sw.ru with esmtp (Exim 4.90_1) (envelope-from ) id 1eyciT-00064u-Em; Wed, 21 Mar 2018 15:19:41 +0300 From: Vladimir Sementsov-Ogievskiy To: qemu-devel@nongnu.org, qemu-block@nongnu.org Date: Wed, 21 Mar 2018 15:19:38 +0300 Message-Id: <20180321121940.39426-3-vsementsov@virtuozzo.com> X-Mailer: git-send-email 2.11.1 In-Reply-To: <20180321121940.39426-1-vsementsov@virtuozzo.com> References: <20180321121940.39426-1-vsementsov@virtuozzo.com> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x [fuzzy] X-Received-From: 185.231.240.75 Subject: [Qemu-devel] [PATCH 2/4] nbd/server: add nbd_meta_single_query helper X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: kwolf@redhat.com, vsementsov@virtuozzo.com, armbru@redhat.com, mreitz@redhat.com, den@openvz.org, pbonzini@redhat.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" The helper will be reused for bitmaps namespace. Signed-off-by: Vladimir Sementsov-Ogievskiy Reviewed-by: Eric Blake --- nbd/server.c | 41 ++++++++++++++++++++++++++++------------- 1 file changed, 28 insertions(+), 13 deletions(-) diff --git a/nbd/server.c b/nbd/server.c index b830997114..8fe53ffd4b 100644 --- a/nbd/server.c +++ b/nbd/server.c @@ -733,44 +733,59 @@ static int nbd_negotiate_send_meta_context(NBDClient = *client, return qio_channel_writev_all(client->ioc, iov, 2, errp) < 0 ? -EIO : = 0; } =20 -/* nbd_meta_base_query - * - * Handle query to 'base' namespace. For now, only base:allocation context= is - * available in it. 'len' is the amount of text remaining to be read from - * the current name, after the 'base:' portion has been stripped. +/* Read len bytes and check matching to the pattern. + * @match is set to true on empty query for _LIST_ and for query matching = the + * @pattern. @match is never set to false. * * Return -errno on I/O error, 0 if option was completely handled by * sending a reply about inconsistent lengths, or 1 on success. */ -static int nbd_meta_base_query(NBDClient *client, NBDExportMetaContexts *m= eta, - uint32_t len, Error **errp) +static int nbd_meta_single_query(NBDClient *client, const char *pattern, + uint32_t len, bool *match, Error **errp) { int ret; - char query[sizeof("allocation") - 1]; - size_t alen =3D strlen("allocation"); + char *query; =20 if (len =3D=3D 0) { if (client->opt =3D=3D NBD_OPT_LIST_META_CONTEXT) { - meta->base_allocation =3D true; + *match =3D true; } return 1; } =20 - if (len !=3D alen) { + if (len !=3D strlen(pattern)) { return nbd_opt_skip(client, len, errp); } =20 + query =3D g_malloc(len); ret =3D nbd_opt_read(client, query, len, errp); if (ret <=3D 0) { + g_free(query); return ret; } =20 - if (strncmp(query, "allocation", alen) =3D=3D 0) { - meta->base_allocation =3D true; + if (strncmp(query, pattern, len) =3D=3D 0) { + *match =3D true; } + g_free(query); =20 return 1; } =20 +/* nbd_meta_base_query + * + * Handle query to 'base' namespace. For now, only base:allocation context= is + * available in it. 'len' is the amount of text remaining to be read from + * the current name, after the 'base:' portion has been stripped. + * + * Return -errno on I/O error, 0 if option was completely handled by + * sending a reply about inconsistent lengths, or 1 on success. */ +static int nbd_meta_base_query(NBDClient *client, NBDExportMetaContexts *m= eta, + uint32_t len, Error **errp) +{ + return nbd_meta_single_query(client, "allocation", len, + &meta->base_allocation, errp); +} + struct { const char *ns; int (*func)(NBDClient *, NBDExportMetaContexts *, uint32_t, Error **); --=20 2.11.1 From nobody Sat Oct 25 21:42:57 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=virtuozzo.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1521636047185663.8046974038729; Wed, 21 Mar 2018 05:40:47 -0700 (PDT) Received: from localhost ([::1]:54585 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eyd2n-0001OY-GE for importer@patchew.org; Wed, 21 Mar 2018 08:40:41 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:54984) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eycib-00061l-4e for qemu-devel@nongnu.org; Wed, 21 Mar 2018 08:19:50 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1eyciX-0005ix-3J for qemu-devel@nongnu.org; Wed, 21 Mar 2018 08:19:49 -0400 Received: from relay.sw.ru ([185.231.240.75]:54944) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1eyciW-0005hm-NW; Wed, 21 Mar 2018 08:19:45 -0400 Received: from msk-vpn.virtuozzo.com ([195.214.232.6] helo=kvm.sw.ru) by relay.sw.ru with esmtp (Exim 4.90_1) (envelope-from ) id 1eyciT-00064u-Ij; Wed, 21 Mar 2018 15:19:41 +0300 From: Vladimir Sementsov-Ogievskiy To: qemu-devel@nongnu.org, qemu-block@nongnu.org Date: Wed, 21 Mar 2018 15:19:39 +0300 Message-Id: <20180321121940.39426-4-vsementsov@virtuozzo.com> X-Mailer: git-send-email 2.11.1 In-Reply-To: <20180321121940.39426-1-vsementsov@virtuozzo.com> References: <20180321121940.39426-1-vsementsov@virtuozzo.com> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x [fuzzy] X-Received-From: 185.231.240.75 Subject: [Qemu-devel] [PATCH 3/4] nbd/server: implement 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, vsementsov@virtuozzo.com, armbru@redhat.com, mreitz@redhat.com, den@openvz.org, pbonzini@redhat.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Signed-off-by: Vladimir Sementsov-Ogievskiy --- include/block/nbd.h | 2 + nbd/server.c | 207 ++++++++++++++++++++++++++++++++++++++++++++++++= ++-- 2 files changed, 203 insertions(+), 6 deletions(-) diff --git a/include/block/nbd.h b/include/block/nbd.h index fcdcd54502..f0b459283f 100644 --- a/include/block/nbd.h +++ b/include/block/nbd.h @@ -315,6 +315,8 @@ void nbd_client_put(NBDClient *client); void nbd_server_start(SocketAddress *addr, const char *tls_creds, Error **errp); =20 +void nbd_export_bitmap(NBDExport *exp, const char *bitmap, + const char *bitmap_export_name, Error **errp); =20 /* nbd_read * Reads @size bytes from @ioc. Returns 0 on success. diff --git a/nbd/server.c b/nbd/server.c index 8fe53ffd4b..6554919ef2 100644 --- a/nbd/server.c +++ b/nbd/server.c @@ -23,6 +23,12 @@ #include "nbd-internal.h" =20 #define NBD_META_ID_BASE_ALLOCATION 0 +#define NBD_META_ID_DIRTY_BITMAP 1 + +#define NBD_MAX_BITMAP_EXTENTS (0x100000 / 8) /* 1 mb of extents data */ +#define MAX_EXTENT_LENGTH QEMU_ALIGN_DOWN(INT32_MAX, 512) + +#define NBD_STATE_DIRTY 1 =20 static int system_errno_to_nbd_errno(int err) { @@ -80,6 +86,9 @@ struct NBDExport { =20 BlockBackend *eject_notifier_blk; Notifier eject_notifier; + + BdrvDirtyBitmap *export_bitmap; + char *export_bitmap_name; }; =20 static QTAILQ_HEAD(, NBDExport) exports =3D QTAILQ_HEAD_INITIALIZER(export= s); @@ -92,6 +101,7 @@ typedef struct NBDExportMetaContexts { bool valid; /* means that negotiation of the option finished without errors */ bool base_allocation; /* export base:allocation context (block status)= */ + bool dirty_bitmap; /* export qemu-dirty-bitmap: */ } NBDExportMetaContexts; =20 struct NBDClient { @@ -786,12 +796,32 @@ static int nbd_meta_base_query(NBDClient *client, NBD= ExportMetaContexts *meta, &meta->base_allocation, errp); } =20 +/* nbd_meta_bitmap_query + * + * Handle query to 'qemu-dirty-bitmap' namespace. + * 'len' is the amount of text remaining to be read from the current name,= after + * the 'qemu-dirty-bitmap:' portion has been stripped. + * + * Return -errno on I/O error, 0 if option was completely handled by + * sending a reply about inconsistent lengths, or 1 on success. */ +static int nbd_meta_bitmap_query(NBDClient *client, NBDExportMetaContexts = *meta, + uint32_t len, Error **errp) +{ + if (!client->exp->export_bitmap) { + return nbd_opt_skip(client, len, errp); + } + + return nbd_meta_single_query(client, client->exp->export_bitmap_name, = len, + &meta->dirty_bitmap, errp); +} + struct { const char *ns; int (*func)(NBDClient *, NBDExportMetaContexts *, uint32_t, Error **); } meta_namespace_handlers[] =3D { /* namespaces should go in non-decreasing order by name length */ {.ns =3D "base:", .func =3D nbd_meta_base_query}, + {.ns =3D "qemu-dirty-bitmap:", .func =3D nbd_meta_bitmap_query}, }; =20 /* nbd_negotiate_meta_query @@ -921,6 +951,17 @@ static int nbd_negotiate_meta_queries(NBDClient *clien= t, } } =20 + if (meta->dirty_bitmap) { + char *context =3D g_strdup_printf("qemu-dirty-bitmap:%s", + exp->export_bitmap_name); + ret =3D nbd_negotiate_send_meta_context(client, context, + NBD_META_ID_DIRTY_BITMAP, + errp); + if (ret < 0) { + return ret; + } + } + ret =3D nbd_negotiate_send_rep(client, NBD_REP_ACK, errp); if (ret =3D=3D 0) { meta->valid =3D true; @@ -1549,6 +1590,11 @@ void nbd_export_put(NBDExport *exp) exp->blk =3D NULL; } =20 + if (exp->export_bitmap) { + bdrv_dirty_bitmap_set_qmp_locked(exp->export_bitmap, false); + g_free(exp->export_bitmap_name); + } + g_free(exp); } } @@ -1790,6 +1836,9 @@ static int blockstatus_to_extent_be(BlockDriverState = *bs, uint64_t offset, } =20 /* nbd_co_send_extents + * + * NBD_REPLY_FLAG_DONE is not set, don't forget to send it. + * * @extents should be in big-endian */ static int nbd_co_send_extents(NBDClient *client, uint64_t handle, NBDExtent *extents, unsigned nb_extents, @@ -1802,7 +1851,7 @@ static int nbd_co_send_extents(NBDClient *client, uin= t64_t handle, {.iov_base =3D extents, .iov_len =3D nb_extents * sizeof(extents[0= ])} }; =20 - set_be_chunk(&chunk.h, NBD_REPLY_FLAG_DONE, NBD_REPLY_TYPE_BLOCK_STATU= S, + set_be_chunk(&chunk.h, 0, NBD_REPLY_TYPE_BLOCK_STATUS, handle, sizeof(chunk) - sizeof(chunk.h) + iov[1].iov_len); stl_be_p(&chunk.context_id, context_id); =20 @@ -1827,6 +1876,91 @@ static int nbd_co_send_block_status(NBDClient *clien= t, uint64_t handle, return nbd_co_send_extents(client, handle, &extent, 1, context_id, err= p); } =20 +/* Set several extents, describing region of given @length with given @fla= gs. + * Do not set more than @nb_extents, return number of set extents. + */ +static unsigned add_extents(NBDExtent *extents, unsigned nb_extents, + uint64_t length, uint32_t flags) +{ + unsigned i =3D 0; + uint32_t max_extent_be =3D cpu_to_be32(MAX_EXTENT_LENGTH); + uint32_t flags_be =3D cpu_to_be32(flags); + + for (i =3D 0; i < nb_extents && length > MAX_EXTENT_LENGTH; + i++, length -=3D MAX_EXTENT_LENGTH) + { + extents[i].length =3D max_extent_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 =3D offset, end; + uint64_t overall_end =3D offset + length; + unsigned i =3D 0; + BdrvDirtyBitmapIter *it; + bool dirty; + + bdrv_dirty_bitmap_lock(bitmap); + + it =3D bdrv_dirty_iter_new(bitmap); + dirty =3D bdrv_get_dirty_locked(NULL, bitmap, offset); + + while (begin < overall_end && i < nb_extents) { + if (dirty) { + end =3D bdrv_dirty_bitmap_next_zero(bitmap, begin); + } else { + bdrv_set_dirty_iter(it, begin); + end =3D bdrv_dirty_iter_next(it); + } + if (end =3D=3D -1) { + end =3D overall_end; + } + + i +=3D add_extents(extents + i, nb_extents - i, end - begin, + dirty ? NBD_STATE_DIRTY : 0); + begin =3D end; + dirty =3D !dirty; + } + + bdrv_dirty_iter_free(it); + + bdrv_dirty_bitmap_unlock(bitmap); + + return i; +} + +static int nbd_co_send_bitmap(NBDClient *client, uint64_t handle, + BdrvDirtyBitmap *bitmap, uint64_t offset, + uint64_t length, uint32_t context_id, + Error **errp) +{ + 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, + errp); + + g_free(extents); + + return ret; +} + /* nbd_co_receive_request * Collect a client request. Return 0 if request looks valid, -EIO to drop * connection right away, and any other negative value to report an error = to @@ -2040,11 +2174,32 @@ static coroutine_fn int nbd_handle_request(NBDClien= t *client, "discard failed", errp); =20 case NBD_CMD_BLOCK_STATUS: - if (client->export_meta.valid && client->export_meta.base_allocati= on) { - return nbd_co_send_block_status(client, request->handle, - blk_bs(exp->blk), request->fro= m, - request->len, - NBD_META_ID_BASE_ALLOCATION, e= rrp); + if (client->export_meta.valid && + (client->export_meta.base_allocation || + client->export_meta.dirty_bitmap)) + { + if (client->export_meta.base_allocation) { + ret =3D nbd_co_send_block_status(client, request->handle, + blk_bs(exp->blk), request->= from, + request->len, + NBD_META_ID_BASE_ALLOCATION, + errp); + if (ret < 0) { + return ret; + } + } + + if (client->export_meta.dirty_bitmap) { + ret =3D nbd_co_send_bitmap(client, request->handle, + client->exp->export_bitmap, + request->from, request->len, + NBD_META_ID_DIRTY_BITMAP, errp); + if (ret < 0) { + return ret; + } + } + + return nbd_co_send_structured_done(client, request->handle, er= rp); } else { return nbd_send_generic_reply(client, request->handle, -EINVAL, "CMD_BLOCK_STATUS not negotiated= ", @@ -2196,3 +2351,43 @@ void nbd_client_new(NBDExport *exp, co =3D qemu_coroutine_create(nbd_co_client_start, client); qemu_coroutine_enter(co); } + +void nbd_export_bitmap(NBDExport *exp, const char *bitmap, + const char *bitmap_export_name, Error **errp) +{ + BdrvDirtyBitmap *bm =3D NULL; + BlockDriverState *bs =3D blk_bs(exp->blk); + + if (exp->export_bitmap) { + error_setg(errp, "Export bitmap is already set"); + return; + } + + while (true) { + bm =3D bdrv_find_dirty_bitmap(bs, bitmap); + if (bm !=3D NULL || bs->backing =3D=3D NULL) { + break; + } + + bs =3D bs->backing->bs; + } + + if (bm =3D=3D NULL) { + error_setg(errp, "Bitmap '%s' is not found", bitmap); + return; + } + + if (bdrv_dirty_bitmap_enabled(bm)) { + error_setg(errp, "Bitmap '%s' is enabled", bitmap); + return; + } + + if (bdrv_dirty_bitmap_qmp_locked(bm)) { + error_setg(errp, "Bitmap '%s' is locked", bitmap); + return; + } + + bdrv_dirty_bitmap_set_qmp_locked(bm, true); + exp->export_bitmap =3D bm; + exp->export_bitmap_name =3D g_strdup(bitmap_export_name); +} --=20 2.11.1 From nobody Sat Oct 25 21:42:57 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=virtuozzo.com Return-Path: Received: from lists.gnu.org (208.118.235.17 [208.118.235.17]) by mx.zohomail.com with SMTPS id 1521636026358668.322300357818; Wed, 21 Mar 2018 05:40:26 -0700 (PDT) Received: from localhost ([::1]:54581 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eyd2P-00011Q-Hm for importer@patchew.org; Wed, 21 Mar 2018 08:40:17 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:54986) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eycib-00061q-4g for qemu-devel@nongnu.org; Wed, 21 Mar 2018 08:19:50 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1eyciX-0005ir-0h for qemu-devel@nongnu.org; Wed, 21 Mar 2018 08:19:49 -0400 Received: from relay.sw.ru ([185.231.240.75]:54946) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1eyciW-0005hk-NM; Wed, 21 Mar 2018 08:19:44 -0400 Received: from msk-vpn.virtuozzo.com ([195.214.232.6] helo=kvm.sw.ru) by relay.sw.ru with esmtp (Exim 4.90_1) (envelope-from ) id 1eyciT-00064u-Mb; Wed, 21 Mar 2018 15:19:41 +0300 From: Vladimir Sementsov-Ogievskiy To: qemu-devel@nongnu.org, qemu-block@nongnu.org Date: Wed, 21 Mar 2018 15:19:40 +0300 Message-Id: <20180321121940.39426-5-vsementsov@virtuozzo.com> X-Mailer: git-send-email 2.11.1 In-Reply-To: <20180321121940.39426-1-vsementsov@virtuozzo.com> References: <20180321121940.39426-1-vsementsov@virtuozzo.com> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x [fuzzy] X-Received-From: 185.231.240.75 Subject: [Qemu-devel] [PATCH 4/4] qapi: new qmp command nbd-server-add-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, vsementsov@virtuozzo.com, armbru@redhat.com, mreitz@redhat.com, den@openvz.org, pbonzini@redhat.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Signed-off-by: Vladimir Sementsov-Ogievskiy --- qapi/block.json | 27 +++++++++++++++++++++++++++ blockdev-nbd.c | 23 +++++++++++++++++++++++ 2 files changed, 50 insertions(+) diff --git a/qapi/block.json b/qapi/block.json index c694524002..4afbbcd7b7 100644 --- a/qapi/block.json +++ b/qapi/block.json @@ -269,6 +269,33 @@ 'data': {'name': 'str', '*mode': 'NbdServerRemoveMode'} } =20 ## +# @nbd-server-add-bitmap: +# +# Export dirty bitmap through selected export. Bitmaps are searched for in +# device attached to the export and in all its backings. Exported bitmap +# is locked until NBD export is removed. +# +# @name: Export name. +# +# @bitmap: Bitmap name to search. +# +# @bitmap-export-name: How the bitmap will be seen by nbd clients +# (default @bitmap) +# +# +# Returns: error on one of the following conditions: +# - the server is not running +# - export is not found +# - bitmap is not found +# - bitmap is disabled +# - bitmap is locked +# +# Since: 2.13 +## + { 'command': 'nbd-server-add-bitmap', + 'data': {'name': 'str', 'bitmap': 'str', '*bitmap-export-name': 'str'}= } + +## # @nbd-server-stop: # # Stop QEMU's embedded NBD server, and unregister all devices previously diff --git a/blockdev-nbd.c b/blockdev-nbd.c index 65a84739ed..6b0c50732c 100644 --- a/blockdev-nbd.c +++ b/blockdev-nbd.c @@ -220,3 +220,26 @@ void qmp_nbd_server_stop(Error **errp) nbd_server_free(nbd_server); nbd_server =3D NULL; } + +void qmp_nbd_server_add_bitmap(const char *name, const char *bitmap, + bool has_bitmap_export_name, + const char *bitmap_export_name, + Error **errp) +{ + NBDExport *exp; + + if (!nbd_server) { + error_setg(errp, "NBD server not running"); + return; + } + + exp =3D nbd_export_find(name); + if (exp =3D=3D NULL) { + error_setg(errp, "Export '%s' is not found", name); + return; + } + + nbd_export_bitmap(exp, bitmap, + has_bitmap_export_name ? bitmap_export_name : bitmap, + errp); +} --=20 2.11.1