From nobody Sun Oct 5 19:23:35 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=redhat.com Return-Path: Received: from lists.gnu.org (208.118.235.17 [208.118.235.17]) by mx.zohomail.com with SMTPS id 153055910790525.00013447806373; Mon, 2 Jul 2018 12:18:27 -0700 (PDT) Received: from localhost ([::1]:35003 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fa4L7-0002vG-2q for importer@patchew.org; Mon, 02 Jul 2018 15:18:21 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:51878) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fa4I2-000156-BO for qemu-devel@nongnu.org; Mon, 02 Jul 2018 15:15:11 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fa4I0-0006qM-S4 for qemu-devel@nongnu.org; Mon, 02 Jul 2018 15:15:10 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:60390 helo=mx1.redhat.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1fa4Hx-0006nG-B9; Mon, 02 Jul 2018 15:15:05 -0400 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.rdu2.redhat.com [10.11.54.3]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 033EC4074461; Mon, 2 Jul 2018 19:15:05 +0000 (UTC) Received: from red.redhat.com (ovpn-122-121.rdu2.redhat.com [10.10.122.121]) by smtp.corp.redhat.com (Postfix) with ESMTP id 91067111AF34; Mon, 2 Jul 2018 19:15:03 +0000 (UTC) From: Eric Blake To: qemu-devel@nongnu.org Date: Mon, 2 Jul 2018 14:14:57 -0500 Message-Id: <20180702191458.28741-2-eblake@redhat.com> In-Reply-To: <20180702191458.28741-1-eblake@redhat.com> References: <20180702191458.28741-1-eblake@redhat.com> X-Scanned-By: MIMEDefang 2.78 on 10.11.54.3 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.7]); Mon, 02 Jul 2018 19:15:05 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.7]); Mon, 02 Jul 2018 19:15:05 +0000 (UTC) for IP:'10.11.54.3' DOMAIN:'int-mx03.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'eblake@redhat.com' RCPT:'' X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.187.233.73 Subject: [Qemu-devel] [PATCH v2 1/2] nbd/client: Add x-dirty-bitmap to query bitmap from 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: Kevin Wolf , vsementsov@virtuozzo.com, qemu-block@nongnu.org, Markus Armbruster , Max Reitz , Paolo Bonzini , 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" In order to test that the NBD server is properly advertising dirty bitmaps, we need a bare minimum client that can request and read the context. Since feature freeze for 3.0 is imminent, this is the smallest workable patch, which replaces the qemu block status report with the results of the NBD server's dirty bitmap (making it very easy to use 'qemu-img map --output=3Djson' to learn where the dirty portions are). Note that the NBD protocol defines a dirty section with the same bit but opposite sense that normal "base:allocation" uses to report an allocated section; so in qemu-img map output, "data":true corresponds to clean, "data":false corresponds to dirty. A more complete solution that allows dirty bitmaps to be queried at the same time as normal block status will be required before this addition can lose the x- prefix. Until then, the fact that this replaces normal status with dirty status means actions like 'qemu-img convert' will likely misbehave due to treating dirty regions of the file as if they are unallocated. The next patch adds an iotest to exercise this new code. Signed-off-by: Eric Blake Reviewed-by: Vladimir Sementsov-Ogievskiy --- qapi/block-core.json | 7 ++++++- block/nbd-client.h | 1 + include/block/nbd.h | 1 + block/nbd-client.c | 3 +++ block/nbd.c | 10 ++++++++-- nbd/client.c | 4 ++-- 6 files changed, 21 insertions(+), 5 deletions(-) diff --git a/qapi/block-core.json b/qapi/block-core.json index 577ce5e9991..90e554ed0ff 100644 --- a/qapi/block-core.json +++ b/qapi/block-core.json @@ -3471,12 +3471,17 @@ # # @tls-creds: TLS credentials ID # +# @x-dirty-bitmap: A "qemu:dirty-bitmap:NAME" string to query in place of +# traditional "base:allocation" block status (see +# NBD_OPT_LIST_META_CONTEXT in the NBD protocol) (since 3= .0) +# # Since: 2.9 ## { 'struct': 'BlockdevOptionsNbd', 'data': { 'server': 'SocketAddress', '*export': 'str', - '*tls-creds': 'str' } } + '*tls-creds': 'str', + '*x-dirty-bitmap': 'str' } } ## # @BlockdevOptionsRaw: diff --git a/block/nbd-client.h b/block/nbd-client.h index 0ece76e5aff..cfc90550b99 100644 --- a/block/nbd-client.h +++ b/block/nbd-client.h @@ -45,6 +45,7 @@ int nbd_client_init(BlockDriverState *bs, const char *export_name, QCryptoTLSCreds *tlscreds, const char *hostname, + const char *x_dirty_bitmap, Error **errp); void nbd_client_close(BlockDriverState *bs); diff --git a/include/block/nbd.h b/include/block/nbd.h index daaeae61bf9..4638c839f51 100644 --- a/include/block/nbd.h +++ b/include/block/nbd.h @@ -259,6 +259,7 @@ static inline bool nbd_reply_type_is_error(int type) struct NBDExportInfo { /* Set by client before nbd_receive_negotiate() */ bool request_sizes; + char *x_dirty_bitmap; /* In-out fields, set by client before nbd_receive_negotiate() and * updated by server results during nbd_receive_negotiate() */ diff --git a/block/nbd-client.c b/block/nbd-client.c index 8d69eaaa32f..9686ecbd5ee 100644 --- a/block/nbd-client.c +++ b/block/nbd-client.c @@ -970,6 +970,7 @@ int nbd_client_init(BlockDriverState *bs, const char *export, QCryptoTLSCreds *tlscreds, const char *hostname, + const char *x_dirty_bitmap, Error **errp) { NBDClientSession *client =3D nbd_get_client_session(bs); @@ -982,9 +983,11 @@ int nbd_client_init(BlockDriverState *bs, client->info.request_sizes =3D true; client->info.structured_reply =3D true; client->info.base_allocation =3D true; + client->info.x_dirty_bitmap =3D g_strdup(x_dirty_bitmap); ret =3D nbd_receive_negotiate(QIO_CHANNEL(sioc), export, tlscreds, hostname, &client->ioc, &client->info, errp); + g_free(client->info.x_dirty_bitmap); if (ret < 0) { logout("Failed to negotiate with the NBD server\n"); return ret; diff --git a/block/nbd.c b/block/nbd.c index 13db4030e67..b198ad775fb 100644 --- a/block/nbd.c +++ b/block/nbd.c @@ -378,6 +378,12 @@ static QemuOptsList nbd_runtime_opts =3D { .type =3D QEMU_OPT_STRING, .help =3D "ID of the TLS credentials to use", }, + { + .name =3D "x-dirty-bitmap", + .type =3D QEMU_OPT_STRING, + .help =3D "experimental: expose named dirty bitmap in place of= " + "block status", + }, { /* end of list */ } }, }; @@ -438,8 +444,8 @@ static int nbd_open(BlockDriverState *bs, QDict *option= s, int flags, } /* 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, "x-dirty-bitmap"), errp); error: if (sioc) { object_unref(OBJECT(sioc)); diff --git a/nbd/client.c b/nbd/client.c index 232ff4f46da..40b74d9761f 100644 --- a/nbd/client.c +++ b/nbd/client.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2016-2017 Red Hat, Inc. + * Copyright (C) 2016-2018 Red Hat, Inc. * Copyright (C) 2005 Anthony Liguori * * Network Block Device Client Side @@ -831,7 +831,7 @@ int nbd_receive_negotiate(QIOChannel *ioc, const char *= name, if (info->structured_reply && base_allocation) { result =3D nbd_negotiate_simple_meta_context( - ioc, name, "base:allocation", + ioc, name, info->x_dirty_bitmap ?: "base:allocatio= n", &info->meta_base_allocation_id, errp); if (result < 0) { goto fail; --=20 2.14.4 From nobody Sun Oct 5 19:23:35 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=redhat.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1530559204876392.83721391355516; Mon, 2 Jul 2018 12:20:04 -0700 (PDT) Received: from localhost ([::1]:35009 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fa4Mk-0004c3-Ff for importer@patchew.org; Mon, 02 Jul 2018 15:20:02 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:51895) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fa4I3-00016J-FM for qemu-devel@nongnu.org; Mon, 02 Jul 2018 15:15:14 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fa4I1-0006sc-OL for qemu-devel@nongnu.org; Mon, 02 Jul 2018 15:15:11 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:45634 helo=mx1.redhat.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1fa4Hy-0006nu-5H; Mon, 02 Jul 2018 15:15:06 -0400 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.rdu2.redhat.com [10.11.54.3]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id C24A4814F0A4; Mon, 2 Jul 2018 19:15:05 +0000 (UTC) Received: from red.redhat.com (ovpn-122-121.rdu2.redhat.com [10.10.122.121]) by smtp.corp.redhat.com (Postfix) with ESMTP id 2E193111AF34; Mon, 2 Jul 2018 19:15:05 +0000 (UTC) From: Eric Blake To: qemu-devel@nongnu.org Date: Mon, 2 Jul 2018 14:14:58 -0500 Message-Id: <20180702191458.28741-3-eblake@redhat.com> In-Reply-To: <20180702191458.28741-1-eblake@redhat.com> References: <20180702191458.28741-1-eblake@redhat.com> X-Scanned-By: MIMEDefang 2.78 on 10.11.54.3 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.8]); Mon, 02 Jul 2018 19:15:05 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.8]); Mon, 02 Jul 2018 19:15:05 +0000 (UTC) for IP:'10.11.54.3' DOMAIN:'int-mx03.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'eblake@redhat.com' RCPT:'' X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.187.233.73 Subject: [Qemu-devel] [PATCH v2 2/2] iotests: New test 223 for exporting dirty bitmap over NBD 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" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Although this test is NOT a full test of image fleecing (as it intentionally uses just a single block device directly exported over NBD, rather than trying to set up a blockdev-backup job with multiple BDS involved), it DOES prove that qemu as a server is able to properly expose a dirty bitmap over NBD. When coupled with image fleecing, it is then possible for a third-party client to do an incremental backup by using qemu-img map with the x-dirty-bitmap option to learn which parts of the file are dirty (perhaps confusingly, they are the portions mapped as "data":false - which is part of the reason this is still in the x- experimental namespace), along with another normal client (perhaps 'qemu-nbd -c' to expose the server over /dev/nbd0 and then just use normal I/O on that block device) to read the dirty sections. Signed-off-by: Eric Blake Reviewed-by: John Snow Reviewed-by: Vladimir Sementsov-Ogievskiy Tested-by: John Snow --- tests/qemu-iotests/223 | 138 +++++++++++++++++++++++++++++++++++++++++= ++++ tests/qemu-iotests/223.out | 49 ++++++++++++++++ tests/qemu-iotests/group | 1 + 3 files changed, 188 insertions(+) create mode 100755 tests/qemu-iotests/223 create mode 100644 tests/qemu-iotests/223.out diff --git a/tests/qemu-iotests/223 b/tests/qemu-iotests/223 new file mode 100755 index 00000000000..b63b7a4f9e1 --- /dev/null +++ b/tests/qemu-iotests/223 @@ -0,0 +1,138 @@ +#!/bin/bash +# +# Test reading dirty bitmap over NBD +# +# Copyright (C) 2018 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 . +# + +seq=3D"$(basename $0)" +echo "QA output created by $seq" + +here=3D"$PWD" +status=3D1 # failure is the default! + +_cleanup() +{ + _cleanup_test_img + _cleanup_qemu + rm -f "$TEST_DIR/nbd" +} +trap "_cleanup; exit \$status" 0 1 2 3 15 + +# get standard environment, filters and checks +. ./common.rc +. ./common.filter +. ./common.qemu + +_supported_fmt qcow2 +_supported_proto file # uses NBD as well +_supported_os Linux + +function do_run_qemu() +{ + echo Testing: "$@" + $QEMU -nographic -qmp stdio -serial none "$@" + echo +} + +function run_qemu() +{ + do_run_qemu "$@" 2>&1 | _filter_testdir | _filter_qmp \ + | _filter_qemu | _filter_imgfmt \ + | _filter_actual_image_size +} + +echo +echo "=3D=3D=3D Create partially sparse image, then add dirty bitmap =3D= =3D=3D" +echo + +_make_test_img 4M +$QEMU_IO -c 'w -P 0x11 1M 2M' "$TEST_IMG" | _filter_qemu_io +run_qemu < >(_filter_nbd) + +silent=3D +_send_qemu_cmd $QEMU_HANDLE '{"execute":"qmp_capabilities"}' "return" +_send_qemu_cmd $QEMU_HANDLE '{"execute":"blockdev-add", + "arguments":{"driver":"qcow2", "node-name":"n", + "file":{"driver":"file", "filename":"'"$TEST_IMG"'"}}}' "return" +_send_qemu_cmd $QEMU_HANDLE '{"execute":"x-block-dirty-bitmap-disable", + "arguments":{"node":"n", "name":"b"}}' "return" +_send_qemu_cmd $QEMU_HANDLE '{"execute":"nbd-server-start", + "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" + +echo +echo "=3D=3D=3D Contrast normal status with dirty-bitmap status =3D=3D=3D" +echo + +QEMU_IO_OPTIONS=3D$QEMU_IO_OPTIONS_NO_FMT +IMG=3D"driver=3Dnbd,export=3Dn,server.type=3Dunix,server.path=3D$TEST_DIR/= nbd" +$QEMU_IO -r -c 'r -P 0 0 1m' -c 'r -P 0x11 1m 1m' \ + -c 'r -P 0x22 2m 2m' --image-opts "$IMG" | _filter_qemu_io +$QEMU_IMG map --output=3Djson --image-opts \ + "$IMG" | _filter_qemu_img_map +$QEMU_IMG map --output=3Djson --image-opts \ + "$IMG,x-dirty-bitmap=3Dqemu:dirty-bitmap:b" | _filter_qemu_img_map + +echo +echo "=3D=3D=3D End NBD server =3D=3D=3D" +echo + +_send_qemu_cmd $QEMU_HANDLE '{"execute":"nbd-server-remove", + "arguments":{"name":"n"}}' "return" +_send_qemu_cmd $QEMU_HANDLE '{"execute":"nbd-server-stop"}' "return" +_send_qemu_cmd $QEMU_HANDLE '{"execute":"quit"}' "return" + +# success, all done +echo '*** done' +rm -f $seq.full +status=3D0 diff --git a/tests/qemu-iotests/223.out b/tests/qemu-iotests/223.out new file mode 100644 index 00000000000..33021c8e6a1 --- /dev/null +++ b/tests/qemu-iotests/223.out @@ -0,0 +1,49 @@ +QA output created by 223 + +=3D=3D=3D Create partially sparse image, then add dirty bitmap =3D=3D=3D + +Formatting 'TEST_DIR/t.IMGFMT', fmt=3DIMGFMT size=3D4194304 +wrote 2097152/2097152 bytes at offset 1048576 +2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +Testing: +QMP_VERSION +{"return": {}} +{"return": {}} +{"return": {}} +{"return": {}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "SHUTDOWN", "data": {"guest": false}} + + +=3D=3D=3D Write part of the file under active bitmap =3D=3D=3D + +wrote 2097152/2097152 bytes at offset 2097152 +2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +=3D=3D=3D End dirty bitmap, and start serving image over NBD =3D=3D=3D + +{"return": {}} +{"return": {}} +{"return": {}} +{"return": {}} +{"return": {}} +{"return": {}} + +=3D=3D=3D Contrast normal status with dirty-bitmap status =3D=3D=3D + +read 1048576/1048576 bytes at offset 0 +1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 1048576/1048576 bytes at offset 1048576 +1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 2097152/2097152 bytes at offset 2097152 +2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +[{ "start": 0, "length": 1048576, "depth": 0, "zero": true, "data": false}, +{ "start": 1048576, "length": 3145728, "depth": 0, "zero": false, "data": = true}] +[{ "start": 0, "length": 2097152, "depth": 0, "zero": false, "data": true}, +{ "start": 2097152, "length": 2097152, "depth": 0, "zero": false, "data": = false}] + +=3D=3D=3D End NBD server =3D=3D=3D + +{"return": {}} +{"return": {}} +{"return": {}} +*** done diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group index eea75819d2a..a446476583e 100644 --- a/tests/qemu-iotests/group +++ b/tests/qemu-iotests/group @@ -220,3 +220,4 @@ 218 rw auto quick 219 rw auto 221 rw auto quick +223 rw auto quick --=20 2.14.4