From nobody Sun Oct 5 17:23:30 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.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 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1547007446774195.7400265216371; Tue, 8 Jan 2019 20:17:26 -0800 (PST) Received: from localhost ([127.0.0.1]:51336 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gh5Iz-0007Wl-LG for importer@patchew.org; Tue, 08 Jan 2019 23:17:25 -0500 Received: from eggs.gnu.org ([209.51.188.92]:38862) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gh5Gk-0006Hj-Rk for qemu-devel@nongnu.org; Tue, 08 Jan 2019 23:15:09 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gh5Gh-0005cO-9z for qemu-devel@nongnu.org; Tue, 08 Jan 2019 23:15:04 -0500 Received: from mx1.redhat.com ([209.132.183.28]:55382) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1gh5Gc-0005Yk-G7; Tue, 08 Jan 2019 23:14:58 -0500 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id B4A6A88E57; Wed, 9 Jan 2019 04:14:57 +0000 (UTC) Received: from blue.redhat.com (ovpn-116-216.phx2.redhat.com [10.3.116.216]) by smtp.corp.redhat.com (Postfix) with ESMTP id 15EBC7D937; Wed, 9 Jan 2019 04:14:57 +0000 (UTC) From: Eric Blake To: qemu-devel@nongnu.org Date: Tue, 8 Jan 2019 22:14:48 -0600 Message-Id: <20190109041452.31240-2-eblake@redhat.com> In-Reply-To: <20190109041452.31240-1-eblake@redhat.com> References: <20190109041452.31240-1-eblake@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.25]); Wed, 09 Jan 2019 04:14:57 +0000 (UTC) Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH 1/5] nbd: Merge nbd_export_set_name into nbd_export_new 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: Kevin Wolf , vsementsov@virtuozzo.com, jsnow@redhat.com, qemu-block@nongnu.org, Max Reitz Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Type: text/plain; charset="utf-8" The existing NBD code had a weird split where nbd_export_new() created an export but did not add it to the list of exported names until a later nbd_export_set_name() came along and grabbed a second reference on the object; later, nbd_export_close() drops the second reference. But since we never change the name of an NBD export while it is exposed, it is easier to just inline the process of setting the name as part of creating the export. Inline the contents of nbd_export_set_name() and nbd_export_set_description() into the two points in an export lifecycle where they matter, then adjust both callers to pass the name up front. Note that all callers pass a non-NULL name, (passing NULL at creation was for old style servers, but we removed support for that in commit 7f7dfe2a). Signed-off-by: Eric Blake --- include/block/nbd.h | 3 +-- blockdev-nbd.c | 5 ++--- nbd/server.c | 45 ++++++++++++++++----------------------------- qemu-nbd.c | 5 ++--- 4 files changed, 21 insertions(+), 37 deletions(-) diff --git a/include/block/nbd.h b/include/block/nbd.h index 65402d33964..2f9a2aeb73c 100644 --- a/include/block/nbd.h +++ b/include/block/nbd.h @@ -295,6 +295,7 @@ typedef struct NBDExport NBDExport; typedef struct NBDClient NBDClient; NBDExport *nbd_export_new(BlockDriverState *bs, off_t dev_offset, off_t si= ze, + const char *name, const char *description, uint16_t nbdflags, void (*close)(NBDExport *), bool writethrough, BlockBackend *on_eject_blk, Error **errp); @@ -306,8 +307,6 @@ void nbd_export_put(NBDExport *exp); BlockBackend *nbd_export_get_blockdev(NBDExport *exp); NBDExport *nbd_export_find(const char *name); -void nbd_export_set_name(NBDExport *exp, const char *name); -void nbd_export_set_description(NBDExport *exp, const char *description); void nbd_export_close_all(void); void nbd_client_new(QIOChannelSocket *sioc, diff --git a/blockdev-nbd.c b/blockdev-nbd.c index 1d170c80b82..f5edbc27d88 100644 --- a/blockdev-nbd.c +++ b/blockdev-nbd.c @@ -174,14 +174,13 @@ void qmp_nbd_server_add(const char *device, bool has_= name, const char *name, writable =3D false; } - exp =3D nbd_export_new(bs, 0, -1, writable ? 0 : NBD_FLAG_READ_ONLY, + exp =3D nbd_export_new(bs, 0, -1, name, NULL, + writable ? 0 : NBD_FLAG_READ_ONLY, NULL, false, on_eject_blk, errp); if (!exp) { return; } - nbd_export_set_name(exp, name); - /* The list of named exports has a strong reference to this export now= and * our only way of accessing it is through nbd_export_find(), so we ca= n drop * the strong reference that is @exp. */ diff --git a/nbd/server.c b/nbd/server.c index 7af0ddffb20..9cb305aa1bf 100644 --- a/nbd/server.c +++ b/nbd/server.c @@ -1456,6 +1456,7 @@ static void nbd_eject_notifier(Notifier *n, void *dat= a) } NBDExport *nbd_export_new(BlockDriverState *bs, off_t dev_offset, off_t si= ze, + const char *name, const char *description, uint16_t nbdflags, void (*close)(NBDExport *), bool writethrough, BlockBackend *on_eject_blk, Error **errp) @@ -1471,6 +1472,7 @@ NBDExport *nbd_export_new(BlockDriverState *bs, off_t= dev_offset, off_t size, * that BDRV_O_INACTIVE is cleared and the image is ready for write * access since the export could be available before migration handove= r. */ + assert(name); ctx =3D bdrv_get_aio_context(bs); aio_context_acquire(ctx); bdrv_invalidate_cache(bs, NULL); @@ -1494,6 +1496,8 @@ NBDExport *nbd_export_new(BlockDriverState *bs, off_t= dev_offset, off_t size, QTAILQ_INIT(&exp->clients); exp->blk =3D blk; exp->dev_offset =3D dev_offset; + exp->name =3D g_strdup(name); + exp->description =3D g_strdup(description); exp->nbdflags =3D nbdflags; exp->size =3D size < 0 ? blk_getlength(blk) : size; if (exp->size < 0) { @@ -1513,10 +1517,14 @@ NBDExport *nbd_export_new(BlockDriverState *bs, off= _t dev_offset, off_t size, exp->eject_notifier.notify =3D nbd_eject_notifier; blk_add_remove_bs_notifier(on_eject_blk, &exp->eject_notifier); } + QTAILQ_INSERT_TAIL(&exports, exp, next); + nbd_export_get(exp); return exp; fail: blk_unref(blk); + g_free(exp->name); + g_free(exp->description); g_free(exp); return NULL; } @@ -1533,33 +1541,6 @@ NBDExport *nbd_export_find(const char *name) return NULL; } -void nbd_export_set_name(NBDExport *exp, const char *name) -{ - if (exp->name =3D=3D name) { - return; - } - - nbd_export_get(exp); - if (exp->name !=3D NULL) { - g_free(exp->name); - exp->name =3D NULL; - QTAILQ_REMOVE(&exports, exp, next); - nbd_export_put(exp); - } - if (name !=3D NULL) { - nbd_export_get(exp); - exp->name =3D g_strdup(name); - QTAILQ_INSERT_TAIL(&exports, exp, next); - } - nbd_export_put(exp); -} - -void nbd_export_set_description(NBDExport *exp, const char *description) -{ - g_free(exp->description); - exp->description =3D g_strdup(description); -} - void nbd_export_close(NBDExport *exp) { NBDClient *client, *next; @@ -1568,8 +1549,14 @@ void nbd_export_close(NBDExport *exp) QTAILQ_FOREACH_SAFE(client, &exp->clients, next, next) { client_close(client, true); } - nbd_export_set_name(exp, NULL); - nbd_export_set_description(exp, NULL); + if (exp->name) { + nbd_export_put(exp); + g_free(exp->name); + exp->name =3D NULL; + QTAILQ_REMOVE(&exports, exp, next); + } + g_free(exp->description); + exp->description =3D NULL; nbd_export_put(exp); } diff --git a/qemu-nbd.c b/qemu-nbd.c index 2807e132396..696bd78a2e2 100644 --- a/qemu-nbd.c +++ b/qemu-nbd.c @@ -1015,10 +1015,9 @@ int main(int argc, char **argv) } } - exp =3D nbd_export_new(bs, dev_offset, fd_size, nbdflags, nbd_export_c= losed, + exp =3D nbd_export_new(bs, dev_offset, fd_size, export_name, + export_description, nbdflags, nbd_export_closed, writethrough, NULL, &error_fatal); - nbd_export_set_name(exp, export_name); - nbd_export_set_description(exp, export_description); if (device) { #if HAVE_NBD_DEVICE --=20 2.20.1 From nobody Sun Oct 5 17:23:30 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.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 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1547007608477972.5635457262257; Tue, 8 Jan 2019 20:20:08 -0800 (PST) Received: from localhost ([127.0.0.1]:51925 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gh5Lb-0000xr-D7 for importer@patchew.org; Tue, 08 Jan 2019 23:20:07 -0500 Received: from eggs.gnu.org ([209.51.188.92]:38913) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gh5Go-0006LE-SE for qemu-devel@nongnu.org; Tue, 08 Jan 2019 23:15:13 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gh5Gm-0005gO-PH for qemu-devel@nongnu.org; Tue, 08 Jan 2019 23:15:10 -0500 Received: from mx1.redhat.com ([209.132.183.28]:39464) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1gh5Gd-0005ZU-LJ; Tue, 08 Jan 2019 23:14:59 -0500 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 9912C8830F; Wed, 9 Jan 2019 04:14:58 +0000 (UTC) Received: from blue.redhat.com (ovpn-116-216.phx2.redhat.com [10.3.116.216]) by smtp.corp.redhat.com (Postfix) with ESMTP id D78587D937; Wed, 9 Jan 2019 04:14:57 +0000 (UTC) From: Eric Blake To: qemu-devel@nongnu.org Date: Tue, 8 Jan 2019 22:14:49 -0600 Message-Id: <20190109041452.31240-3-eblake@redhat.com> In-Reply-To: <20190109041452.31240-1-eblake@redhat.com> References: <20190109041452.31240-1-eblake@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.28]); Wed, 09 Jan 2019 04:14:58 +0000 (UTC) Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH 2/5] nbd: Allow bitmap export during QMP nbd-server-add 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: Kevin Wolf , vsementsov@virtuozzo.com, qemu-block@nongnu.org, Markus Armbruster , "Dr. David Alan Gilbert" , Max Reitz , jsnow@redhat.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Type: text/plain; charset="utf-8" With the experimental x-nbd-server-add-bitmap command, there was a window of time where a client could see the export but not the associated dirty bitmap, which can cause a client that planned on using the dirty bitmap to be forced to treat the entire image as dirty as a safety fallback. Furthermore, if the QMP client successfully exports a disk but then fails to add the bitmap, it has to take on the burden of removing the export. Since we don't allow changing a dirty bitmap once it is exported (whether to a different bitmap, or removing advertisement of the bitmap), it is nicer to make the bitmap tied to the export at the time the export is created, and automatically failing to export if the bitmap is not available. Since there is working libvirt demo code that uses both the bitmap export and the ability to specify an alternative name (rather than exposing the private-use bitmap that libvirt created to merge in several persistent bitmaps when doing a differential backup), the two new parameters do not need to be marked experimental. See https://www.redhat.com/archives/libvir-list/2018-October/msg01254.html, https://kvmforum2018.sched.com/event/FzuB/facilitating-incremental-backup-e= ric-blake-red-hat This patch focuses on the user interface, and reduces (but does not completely eliminate) the window where an NBD client can see the export but not the dirty bitmap. Later patches will add further cleanups now that this interface is available. Update test 223 to use the new interface. Signed-off-by: Eric Blake --- qapi/block.json | 12 +++++++++++- blockdev-nbd.c | 27 ++++++++++++++++++++++++++- hmp.c | 6 ++++-- tests/qemu-iotests/223 | 11 ++++------- tests/qemu-iotests/223.out | 2 -- 5 files changed, 45 insertions(+), 13 deletions(-) diff --git a/qapi/block.json b/qapi/block.json index 11f01f28efe..4b336303d21 100644 --- a/qapi/block.json +++ b/qapi/block.json @@ -246,6 +246,15 @@ # # @writable: Whether clients should be able to write to the device via the # NBD connection (default false). + +# @bitmap: Dirty bitmap to associate with the selected export. The export +# must be read-only, and the given bitmap is locked until the +# export is removed. (since 4.0) +# +# @bitmap-export-name: How the bitmap will be seen by nbd clients +# (default @bitmap). The NBD client must use +# NBD_OPT_SET_META_CONTEXT with "qemu:dirty-bitmap:NA= ME" +# to access the exposed bitmap. (since 4.0) # # Returns: error if the server is not running, or export with the same name # already exists. @@ -253,7 +262,8 @@ # Since: 1.3.0 ## { 'command': 'nbd-server-add', - 'data': {'device': 'str', '*name': 'str', '*writable': 'bool'} } + 'data': {'device': 'str', '*name': 'str', '*writable': 'bool', + '*bitmap': 'str', '*bitmap-export-name': 'str' } } ## # @NbdServerRemoveMode: diff --git a/blockdev-nbd.c b/blockdev-nbd.c index f5edbc27d88..cae9e802d48 100644 --- a/blockdev-nbd.c +++ b/blockdev-nbd.c @@ -140,7 +140,10 @@ void qmp_nbd_server_start(SocketAddressLegacy *addr, } void qmp_nbd_server_add(const char *device, bool has_name, const char *nam= e, - bool has_writable, bool writable, Error **errp) + bool has_writable, bool writable, + bool has_bitmap, const char *bitmap, + bool has_bitmap_export_name, + const char *bitmap_export_name, Error **errp) { BlockDriverState *bs =3D NULL; BlockBackend *on_eject_blk; @@ -160,6 +163,17 @@ void qmp_nbd_server_add(const char *device, bool has_n= ame, const char *name, return; } + if (has_bitmap_export_name && !has_bitmap) { + error_setg(errp, "Choosing bitmap export name '%s' requires a bitm= ap", + bitmap_export_name); + return; + } + if (has_bitmap && writable) { + error_setg(errp, "Cannot export bitmap '%s' on writable export", + bitmap); + return; + } + on_eject_blk =3D blk_by_name(device); bs =3D bdrv_lookup_bs(device, device, errp); @@ -185,6 +199,17 @@ void qmp_nbd_server_add(const char *device, bool has_n= ame, const char *name, * our only way of accessing it is through nbd_export_find(), so we ca= n drop * the strong reference that is @exp. */ nbd_export_put(exp); + + if (has_bitmap) { + Error *err =3D NULL; + nbd_export_bitmap(exp, bitmap, + has_bitmap_export_name ? bitmap_export_name : bi= tmap, + &err); + if (err) { + error_propagate(errp, err); + nbd_export_remove(exp, NBD_SERVER_REMOVE_MODE_HARD, NULL); + } + } } void qmp_nbd_server_remove(const char *name, diff --git a/hmp.c b/hmp.c index 80aa5ab504b..484a0000de1 100644 --- a/hmp.c +++ b/hmp.c @@ -2326,7 +2326,8 @@ void hmp_nbd_server_start(Monitor *mon, const QDict *= qdict) } qmp_nbd_server_add(info->value->device, false, NULL, - true, writable, &local_err); + true, writable, false, NULL, false, NULL, + &local_err); if (local_err !=3D NULL) { qmp_nbd_server_stop(NULL); @@ -2347,7 +2348,8 @@ void hmp_nbd_server_add(Monitor *mon, const QDict *qd= ict) bool writable =3D qdict_get_try_bool(qdict, "writable", false); Error *local_err =3D NULL; - qmp_nbd_server_add(device, !!name, name, true, writable, &local_err); + qmp_nbd_server_add(device, !!name, name, true, writable, + false, NULL, false, NULL, &local_err); hmp_handle_error(mon, &local_err); } diff --git a/tests/qemu-iotests/223 b/tests/qemu-iotests/223 index 5513dc62159..7a92c3018e2 100755 --- a/tests/qemu-iotests/223 +++ b/tests/qemu-iotests/223 @@ -120,13 +120,10 @@ _send_qemu_cmd $QEMU_HANDLE '{"execute":"nbd-server-s= tart", "arguments":{"addr":{"type":"unix", "data":{"path":"'"$TEST_DIR/nbd"'"}}}}' "return" _send_qemu_cmd $QEMU_HANDLE '{"execute":"nbd-server-add", - "arguments":{"device":"n"}}' "return" -_send_qemu_cmd $QEMU_HANDLE '{"execute":"x-nbd-server-add-bitmap", - "arguments":{"name":"n", "bitmap":"b"}}' "return" + "arguments":{"device":"n", "bitmap":"b"}}' "return" _send_qemu_cmd $QEMU_HANDLE '{"execute":"nbd-server-add", - "arguments":{"device":"n", "name":"n2"}}' "return" -_send_qemu_cmd $QEMU_HANDLE '{"execute":"x-nbd-server-add-bitmap", - "arguments":{"name":"n2", "bitmap":"b2"}}' "return" + "arguments":{"device":"n", "name":"n2", "bitmap":"b2", + "bitmap-export-name":"b3"}}' "return" echo echo "=3D=3D=3D Contrast normal status to large granularity dirty-bitmap = =3D=3D=3D" @@ -147,7 +144,7 @@ echo IMG=3D"driver=3Dnbd,export=3Dn2,server.type=3Dunix,server.path=3D$TEST_DIR= /nbd" $QEMU_IMG map --output=3Djson --image-opts \ - "$IMG,x-dirty-bitmap=3Dqemu:dirty-bitmap:b2" | _filter_qemu_img_map + "$IMG,x-dirty-bitmap=3Dqemu:dirty-bitmap:b3" | _filter_qemu_img_map echo echo "=3D=3D=3D End NBD server =3D=3D=3D" diff --git a/tests/qemu-iotests/223.out b/tests/qemu-iotests/223.out index 99ca172fbb8..0e467981bb8 100644 --- a/tests/qemu-iotests/223.out +++ b/tests/qemu-iotests/223.out @@ -31,8 +31,6 @@ wrote 2097152/2097152 bytes at offset 2097152 {"return": {}} {"return": {}} {"return": {}} -{"return": {}} -{"return": {}} =3D=3D=3D Contrast normal status to large granularity dirty-bitmap =3D=3D= =3D --=20 2.20.1 From nobody Sun Oct 5 17:23:30 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.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 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1547007587085586.529197996657; Tue, 8 Jan 2019 20:19:47 -0800 (PST) Received: from localhost ([127.0.0.1]:51859 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gh5LE-0000jb-QE for importer@patchew.org; Tue, 08 Jan 2019 23:19:44 -0500 Received: from eggs.gnu.org ([209.51.188.92]:38911) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gh5Go-0006LA-RB for qemu-devel@nongnu.org; Tue, 08 Jan 2019 23:15:12 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gh5Gm-0005gC-Om for qemu-devel@nongnu.org; Tue, 08 Jan 2019 23:15:10 -0500 Received: from mx1.redhat.com ([209.132.183.28]:39468) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1gh5Ge-0005aA-O6; Tue, 08 Jan 2019 23:15:00 -0500 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 651DE88319; Wed, 9 Jan 2019 04:14:59 +0000 (UTC) Received: from blue.redhat.com (ovpn-116-216.phx2.redhat.com [10.3.116.216]) by smtp.corp.redhat.com (Postfix) with ESMTP id BA5337D937; Wed, 9 Jan 2019 04:14:58 +0000 (UTC) From: Eric Blake To: qemu-devel@nongnu.org Date: Tue, 8 Jan 2019 22:14:50 -0600 Message-Id: <20190109041452.31240-4-eblake@redhat.com> In-Reply-To: <20190109041452.31240-1-eblake@redhat.com> References: <20190109041452.31240-1-eblake@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.28]); Wed, 09 Jan 2019 04:14:59 +0000 (UTC) Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH 3/5] nbd: Remove x-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: Kevin Wolf , vsementsov@virtuozzo.com, qemu-block@nongnu.org, Markus Armbruster , Max Reitz , jsnow@redhat.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Type: text/plain; charset="utf-8" Now that nbd-server-add can do the same functionality, we no longer need the experimental separate command. Signed-off-by: Eric Blake --- qapi/block.json | 23 ----------------------- blockdev-nbd.c | 23 ----------------------- 2 files changed, 46 deletions(-) diff --git a/qapi/block.json b/qapi/block.json index 4b336303d21..980682e69ea 100644 --- a/qapi/block.json +++ b/qapi/block.json @@ -306,29 +306,6 @@ { 'command': 'nbd-server-remove', 'data': {'name': 'str', '*mode': 'NbdServerRemoveMode'} } -## -# @x-nbd-server-add-bitmap: -# -# Expose a dirty bitmap associated with the selected export. The bitmap se= arch -# starts at the device attached to the export, and includes all backing fi= les. -# The exported bitmap is then locked until the NBD export is removed. -# -# @name: Export name. -# -# @bitmap: Bitmap name to search for. -# -# @bitmap-export-name: How the bitmap will be seen by nbd clients -# (default @bitmap) -# -# Note: the client must use NBD_OPT_SET_META_CONTEXT with a query of -# "qemu:dirty-bitmap:NAME" (where NAME matches @bitmap-export-name) to acc= ess -# the exposed bitmap. -# -# Since: 3.0 -## - { 'command': 'x-nbd-server-add-bitmap', - 'data': {'name': 'str', 'bitmap': 'str', '*bitmap-export-name': 'str'}= } - ## # @nbd-server-stop: # diff --git a/blockdev-nbd.c b/blockdev-nbd.c index cae9e802d48..faecde3b6e1 100644 --- a/blockdev-nbd.c +++ b/blockdev-nbd.c @@ -243,26 +243,3 @@ void qmp_nbd_server_stop(Error **errp) nbd_server_free(nbd_server); nbd_server =3D NULL; } - -void qmp_x_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.20.1 From nobody Sun Oct 5 17:23:30 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.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 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.gnu.org (209.51.188.17 [209.51.188.17]) by mx.zohomail.com with SMTPS id 1547007726256429.03623909805174; Tue, 8 Jan 2019 20:22:06 -0800 (PST) Received: from localhost ([127.0.0.1]:52357 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gh5NV-0002JV-3x for importer@patchew.org; Tue, 08 Jan 2019 23:22:05 -0500 Received: from eggs.gnu.org ([209.51.188.92]:39002) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gh5Gz-0006TB-K5 for qemu-devel@nongnu.org; Tue, 08 Jan 2019 23:15:22 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gh5Go-0005ij-Rq for qemu-devel@nongnu.org; Tue, 08 Jan 2019 23:15:12 -0500 Received: from mx1.redhat.com ([209.132.183.28]:41146) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1gh5Gf-0005aU-2o; Tue, 08 Jan 2019 23:15:01 -0500 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 24FBBE3E14; Wed, 9 Jan 2019 04:15:00 +0000 (UTC) Received: from blue.redhat.com (ovpn-116-216.phx2.redhat.com [10.3.116.216]) by smtp.corp.redhat.com (Postfix) with ESMTP id 8B11D7D937; Wed, 9 Jan 2019 04:14:59 +0000 (UTC) From: Eric Blake To: qemu-devel@nongnu.org Date: Tue, 8 Jan 2019 22:14:51 -0600 Message-Id: <20190109041452.31240-5-eblake@redhat.com> In-Reply-To: <20190109041452.31240-1-eblake@redhat.com> References: <20190109041452.31240-1-eblake@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.38]); Wed, 09 Jan 2019 04:15:00 +0000 (UTC) Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH 4/5] nbd: Merge nbd_export_bitmap into nbd_export_new 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: Kevin Wolf , vsementsov@virtuozzo.com, jsnow@redhat.com, qemu-block@nongnu.org, Max Reitz Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Type: text/plain; charset="utf-8" We only have one caller that wants to export a bitmap name, which it does right after creation of the export. But there is still a brief window of time where an NBD client could see the export but not the dirty bitmap, which a robust client would have to interpret as meaning the entire image should be treated as dirty. Better is to eliminate the window entirely, by inlining nbd_export_bitmap() into nbd_export_new(), and refusing to create the bitmap in the first place if the requested bitmap can't be located. This also moves the logic for determining the default bitmap export name out of blockdev-nbd into nbd_export_new(). Signed-off-by: Eric Blake --- include/block/nbd.h | 4 +-- blockdev-nbd.c | 13 +------- nbd/server.c | 76 +++++++++++++++++++++------------------------ qemu-nbd.c | 2 +- 4 files changed, 38 insertions(+), 57 deletions(-) diff --git a/include/block/nbd.h b/include/block/nbd.h index 2f9a2aeb73c..e598305ecda 100644 --- a/include/block/nbd.h +++ b/include/block/nbd.h @@ -296,6 +296,7 @@ typedef struct NBDClient NBDClient; NBDExport *nbd_export_new(BlockDriverState *bs, off_t dev_offset, off_t si= ze, const char *name, const char *description, + const char *bitmap, const char *bitmap_name, uint16_t nbdflags, void (*close)(NBDExport *), bool writethrough, BlockBackend *on_eject_blk, Error **errp); @@ -319,9 +320,6 @@ void nbd_client_put(NBDClient *client); void nbd_server_start(SocketAddress *addr, const char *tls_creds, Error **errp); -void nbd_export_bitmap(NBDExport *exp, const char *bitmap, - const char *bitmap_export_name, Error **errp); - /* nbd_read * Reads @size bytes from @ioc. Returns 0 on success. */ diff --git a/blockdev-nbd.c b/blockdev-nbd.c index faecde3b6e1..d895ee4adf5 100644 --- a/blockdev-nbd.c +++ b/blockdev-nbd.c @@ -188,7 +188,7 @@ void qmp_nbd_server_add(const char *device, bool has_na= me, const char *name, writable =3D false; } - exp =3D nbd_export_new(bs, 0, -1, name, NULL, + exp =3D nbd_export_new(bs, 0, -1, name, NULL, bitmap, bitmap_export_na= me, writable ? 0 : NBD_FLAG_READ_ONLY, NULL, false, on_eject_blk, errp); if (!exp) { @@ -199,17 +199,6 @@ void qmp_nbd_server_add(const char *device, bool has_n= ame, const char *name, * our only way of accessing it is through nbd_export_find(), so we ca= n drop * the strong reference that is @exp. */ nbd_export_put(exp); - - if (has_bitmap) { - Error *err =3D NULL; - nbd_export_bitmap(exp, bitmap, - has_bitmap_export_name ? bitmap_export_name : bi= tmap, - &err); - if (err) { - error_propagate(errp, err); - nbd_export_remove(exp, NBD_SERVER_REMOVE_MODE_HARD, NULL); - } - } } void qmp_nbd_server_remove(const char *name, diff --git a/nbd/server.c b/nbd/server.c index 9cb305aa1bf..556da68ac26 100644 --- a/nbd/server.c +++ b/nbd/server.c @@ -1457,6 +1457,7 @@ static void nbd_eject_notifier(Notifier *n, void *dat= a) NBDExport *nbd_export_new(BlockDriverState *bs, off_t dev_offset, off_t si= ze, const char *name, const char *description, + const char *bitmap, const char *bitmap_name, uint16_t nbdflags, void (*close)(NBDExport *), bool writethrough, BlockBackend *on_eject_blk, Error **errp) @@ -1507,6 +1508,40 @@ NBDExport *nbd_export_new(BlockDriverState *bs, off_= t dev_offset, off_t size, } exp->size -=3D exp->size % BDRV_SECTOR_SIZE; + if (bitmap) { + BdrvDirtyBitmap *bm =3D NULL; + BlockDriverState *bs =3D blk_bs(blk); + + 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); + goto fail; + } + + if (bdrv_dirty_bitmap_enabled(bm)) { + error_setg(errp, "Bitmap '%s' is enabled", bitmap); + goto fail; + } + + if (bdrv_dirty_bitmap_user_locked(bm)) { + error_setg(errp, "Bitmap '%s' is in use", bitmap); + goto fail; + } + + bdrv_dirty_bitmap_set_qmp_locked(bm, true); + exp->export_bitmap =3D bm; + exp->export_bitmap_context =3D g_strdup_printf("qemu:dirty-bitmap:= %s", + bitmap_name ?: bitmap= ); + } + exp->close =3D close; exp->ctx =3D blk_get_aio_context(blk); blk_add_aio_context_notifier(blk, blk_aio_attached, blk_aio_detach, ex= p); @@ -2417,44 +2452,3 @@ void nbd_client_new(QIOChannelSocket *sioc, 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_user_locked(bm)) { - error_setg(errp, "Bitmap '%s' is in use", bitmap); - return; - } - - bdrv_dirty_bitmap_set_qmp_locked(bm, true); - exp->export_bitmap =3D bm; - exp->export_bitmap_context =3D - g_strdup_printf("qemu:dirty-bitmap:%s", bitmap_export_name); -} diff --git a/qemu-nbd.c b/qemu-nbd.c index 696bd78a2e2..a6cc0f2553e 100644 --- a/qemu-nbd.c +++ b/qemu-nbd.c @@ -1015,7 +1015,7 @@ int main(int argc, char **argv) } } - exp =3D nbd_export_new(bs, dev_offset, fd_size, export_name, + exp =3D nbd_export_new(bs, dev_offset, fd_size, export_name, NULL, NUL= L, export_description, nbdflags, nbd_export_closed, writethrough, NULL, &error_fatal); --=20 2.20.1 From nobody Sun Oct 5 17:23:30 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.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 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1547007510735538.3154155811436; Tue, 8 Jan 2019 20:18:30 -0800 (PST) Received: from localhost ([127.0.0.1]:51565 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gh5K1-0008Fk-N4 for importer@patchew.org; Tue, 08 Jan 2019 23:18:29 -0500 Received: from eggs.gnu.org ([209.51.188.92]:39075) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gh5H8-0006dV-J3 for qemu-devel@nongnu.org; Tue, 08 Jan 2019 23:15:32 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gh5Gz-0005om-IZ for qemu-devel@nongnu.org; Tue, 08 Jan 2019 23:15:24 -0500 Received: from mx1.redhat.com ([209.132.183.28]:55406) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1gh5Gh-0005at-AO; Tue, 08 Jan 2019 23:15:05 -0500 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id B8F76C05B00E; Wed, 9 Jan 2019 04:15:00 +0000 (UTC) Received: from blue.redhat.com (ovpn-116-216.phx2.redhat.com [10.3.116.216]) by smtp.corp.redhat.com (Postfix) with ESMTP id 476067D937; Wed, 9 Jan 2019 04:15:00 +0000 (UTC) From: Eric Blake To: qemu-devel@nongnu.org Date: Tue, 8 Jan 2019 22:14:52 -0600 Message-Id: <20190109041452.31240-6-eblake@redhat.com> In-Reply-To: <20190109041452.31240-1-eblake@redhat.com> References: <20190109041452.31240-1-eblake@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.31]); Wed, 09 Jan 2019 04:15:00 +0000 (UTC) Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH 5/5] qemu-nbd: Add --bitmap=NAME option 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: vsementsov@virtuozzo.com, jsnow@redhat.com, qemu-block@nongnu.org Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Type: text/plain; charset="utf-8" Having to fire up qemu, then use QMP commands for nbd-server-start and nbd-server-add, just to expose a persistent dirty bitmap, is rather tedious. Make it possible to expose a dirty bitmap using just qemu-nbd (of course, for now this only works when qemu-nbd is visiting a BDS formatted as qcow2). For now, I play it safe and only allow a bitmap to be exposed on a read-only image. We may relax it in the future. Signed-off-by: Eric Blake --- qemu-nbd.texi | 5 +++++ qemu-nbd.c | 16 ++++++++++++++-- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/qemu-nbd.texi b/qemu-nbd.texi index 9a84e81eed9..1bf9d2bd8bf 100644 --- a/qemu-nbd.texi +++ b/qemu-nbd.texi @@ -45,6 +45,11 @@ auto-detecting Export the disk as read-only @item -P, --partition=3D@var{num} Only expose partition @var{num} +@item -B, --bitmap=3D@var{name} +If @var{filename} has a qcow2 persistent bitmap @var{name}, expose +that bitmap via the ``qemu:dirty-bitmap:@var{name}'' context +accessible through NBD_OPT_SET_META_CONTEXT. Requires the use of +@option{-r}. @item -s, --snapshot Use @var{filename} as an external snapshot, create a temporary file with backing_file=3D@var{filename}, redirect the write to diff --git a/qemu-nbd.c b/qemu-nbd.c index a6cc0f2553e..9781efe7a25 100644 --- a/qemu-nbd.c +++ b/qemu-nbd.c @@ -95,6 +95,7 @@ static void usage(const char *name) "Exposing part of the image:\n" " -o, --offset=3DOFFSET offset into the image\n" " -P, --partition=3DNUM only expose partition NUM\n" +" -B, --bitmap=3DNAME expose a persistent dirty bitmap\n" "\n" "General purpose options:\n" " --object type,id=3DID,... define an object such as 'secret' for provi= ding\n" @@ -509,7 +510,7 @@ int main(int argc, char **argv) off_t fd_size; QemuOpts *sn_opts =3D NULL; const char *sn_id_or_name =3D NULL; - const char *sopt =3D "hVb:o:p:rsnP:c:dvk:e:f:tl:x:T:D:"; + const char *sopt =3D "hVb:o:p:rsnP:c:dvk:e:f:tl:x:T:D:B:"; struct option lopt[] =3D { { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, 'V' }, @@ -519,6 +520,7 @@ int main(int argc, char **argv) { "offset", required_argument, NULL, 'o' }, { "read-only", no_argument, NULL, 'r' }, { "partition", required_argument, NULL, 'P' }, + { "bitmap", required_argument, NULL, 'B' }, { "connect", required_argument, NULL, 'c' }, { "disconnect", no_argument, NULL, 'd' }, { "snapshot", no_argument, NULL, 's' }, @@ -558,6 +560,7 @@ int main(int argc, char **argv) QDict *options =3D NULL; const char *export_name =3D ""; /* Default export name */ const char *export_description =3D NULL; + const char *bitmap =3D NULL; const char *tlscredsid =3D NULL; bool imageOpts =3D false; bool writethrough =3D true; @@ -695,6 +698,9 @@ int main(int argc, char **argv) exit(EXIT_FAILURE); } break; + case 'B': + bitmap =3D optarg; + break; case 'k': sockpath =3D optarg; if (sockpath[0] !=3D '/') { @@ -822,6 +828,12 @@ int main(int argc, char **argv) } } + if (bitmap && !(nbdflags & NBD_FLAG_READ_ONLY)) { + error_report("Exporting bitmap '%s' requires a readonly export", + bitmap); + exit(EXIT_FAILURE); + } + #if !HAVE_NBD_DEVICE if (disconnect || device) { error_report("Kernel /dev/nbdN support not available"); @@ -1015,7 +1027,7 @@ int main(int argc, char **argv) } } - exp =3D nbd_export_new(bs, dev_offset, fd_size, export_name, NULL, NUL= L, + exp =3D nbd_export_new(bs, dev_offset, fd_size, export_name, bitmap, N= ULL, export_description, nbdflags, nbd_export_closed, writethrough, NULL, &error_fatal); --=20 2.20.1