Blame SOURCES/kvm-nbd-Allow-bitmap-export-during-QMP-nbd-server-add.patch

383d26
From d5c834ab75d9e3e67e6f8489fef32dc4d22443a1 Mon Sep 17 00:00:00 2001
383d26
From: John Snow <jsnow@redhat.com>
383d26
Date: Wed, 27 Mar 2019 17:22:30 +0100
383d26
Subject: [PATCH 091/163] nbd: Allow bitmap export during QMP nbd-server-add
383d26
383d26
RH-Author: John Snow <jsnow@redhat.com>
383d26
Message-id: <20190327172308.31077-18-jsnow@redhat.com>
383d26
Patchwork-id: 85188
383d26
O-Subject: [RHEL-7.7 qemu-kvm-rhev PATCH 17/55] nbd: Allow bitmap export during QMP nbd-server-add
383d26
Bugzilla: 1691009
383d26
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
383d26
RH-Acked-by: Max Reitz <mreitz@redhat.com>
383d26
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
383d26
383d26
From: Eric Blake <eblake@redhat.com>
383d26
383d26
With the experimental x-nbd-server-add-bitmap command, there was
383d26
a window of time where an NBD client could see the export but not
383d26
the associated dirty bitmap, which can cause a client that planned
383d26
on using the dirty bitmap to be forced to treat the entire image
383d26
as dirty as a safety fallback.  Furthermore, if the QMP client
383d26
successfully exports a disk but then fails to add the bitmap, it
383d26
has to take on the burden of removing the export.  Since we don't
383d26
allow changing the exposed dirty bitmap (whether to a different
383d26
bitmap, or removing advertisement of the bitmap), it is nicer to
383d26
make the bitmap tied to the export at the time the export is
383d26
created, with automatic failure to export if the bitmap is not
383d26
available.
383d26
383d26
The experimental command included an optional 'bitmap-export-name'
383d26
field for remapping the name exposed over NBD to be different from
383d26
the bitmap name stored on disk.  However, my libvirt demo code
383d26
for implementing differential backups on top of persistent bitmaps
383d26
did not need to take advantage of that feature (it is instead
383d26
possible to create a new temporary bitmap with the desired name,
383d26
use block-dirty-bitmap-merge to merge one or more persistent
383d26
bitmaps into the temporary, then associate the temporary with the
383d26
NBD export, if control is needed over the exported bitmap name).
383d26
Hence, I'm not copying that part of the experiment over to the
383d26
stable addition. For more details on the libvirt demo, see
383d26
https://www.redhat.com/archives/libvir-list/2018-October/msg01254.html,
383d26
https://kvmforum2018.sched.com/event/FzuB/facilitating-incremental-backup-eric-blake-red-hat
383d26
383d26
This patch focuses on the user interface, and reduces (but does
383d26
not completely eliminate) the window where an NBD client can see
383d26
the export but not the dirty bitmap, with less work to clean up
383d26
after errors.  Later patches will add further cleanups now that
383d26
this interface is declared stable via a single QMP command,
383d26
including removing the race window.
383d26
383d26
Update test 223 to use the new interface.
383d26
383d26
Signed-off-by: Eric Blake <eblake@redhat.com>
383d26
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
383d26
Message-Id: <20190111194720.15671-6-eblake@redhat.com>
383d26
(cherry picked from commit 5fcbeb06812685a2c6d7e0e6f28f018987d08b79)
383d26
Signed-off-by: John Snow <jsnow@redhat.com>
383d26
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
383d26
---
383d26
 blockdev-nbd.c             | 12 +++++++++++-
383d26
 hmp.c                      |  5 +++--
383d26
 qapi/block.json            |  7 ++++++-
383d26
 tests/qemu-iotests/223     | 19 ++++++++-----------
383d26
 tests/qemu-iotests/223.out |  5 +----
383d26
 5 files changed, 29 insertions(+), 19 deletions(-)
383d26
383d26
diff --git a/blockdev-nbd.c b/blockdev-nbd.c
383d26
index 582ffde..ec8cf0a 100644
383d26
--- a/blockdev-nbd.c
383d26
+++ b/blockdev-nbd.c
383d26
@@ -140,7 +140,8 @@ void qmp_nbd_server_start(SocketAddressLegacy *addr,
383d26
 }
383d26
 
383d26
 void qmp_nbd_server_add(const char *device, bool has_name, const char *name,
383d26
-                        bool has_writable, bool writable, Error **errp)
383d26
+                        bool has_writable, bool writable,
383d26
+                        bool has_bitmap, const char *bitmap, Error **errp)
383d26
 {
383d26
     BlockDriverState *bs = NULL;
383d26
     BlockBackend *on_eject_blk;
383d26
@@ -185,6 +186,15 @@ void qmp_nbd_server_add(const char *device, bool has_name, const char *name,
383d26
      * our only way of accessing it is through nbd_export_find(), so we can drop
383d26
      * the strong reference that is @exp. */
383d26
     nbd_export_put(exp);
383d26
+
383d26
+    if (has_bitmap) {
383d26
+        Error *err = NULL;
383d26
+        nbd_export_bitmap(exp, bitmap, bitmap, &err;;
383d26
+        if (err) {
383d26
+            error_propagate(errp, err);
383d26
+            nbd_export_remove(exp, NBD_SERVER_REMOVE_MODE_HARD, NULL);
383d26
+        }
383d26
+    }
383d26
 }
383d26
 
383d26
 void qmp_nbd_server_remove(const char *name,
383d26
diff --git a/hmp.c b/hmp.c
383d26
index cc088da..59e52b9 100644
383d26
--- a/hmp.c
383d26
+++ b/hmp.c
383d26
@@ -2212,7 +2212,7 @@ void hmp_nbd_server_start(Monitor *mon, const QDict *qdict)
383d26
         }
383d26
 
383d26
         qmp_nbd_server_add(info->value->device, false, NULL,
383d26
-                           true, writable, &local_err);
383d26
+                           true, writable, false, NULL, &local_err);
383d26
 
383d26
         if (local_err != NULL) {
383d26
             qmp_nbd_server_stop(NULL);
383d26
@@ -2233,7 +2233,8 @@ void hmp_nbd_server_add(Monitor *mon, const QDict *qdict)
383d26
     bool writable = qdict_get_try_bool(qdict, "writable", false);
383d26
     Error *local_err = NULL;
383d26
 
383d26
-    qmp_nbd_server_add(device, !!name, name, true, writable, &local_err);
383d26
+    qmp_nbd_server_add(device, !!name, name, true, writable,
383d26
+                       false, NULL, &local_err);
383d26
     hmp_handle_error(mon, &local_err);
383d26
 }
383d26
 
383d26
diff --git a/qapi/block.json b/qapi/block.json
383d26
index ba85ceb..b04fcdc 100644
383d26
--- a/qapi/block.json
383d26
+++ b/qapi/block.json
383d26
@@ -313,6 +313,10 @@
383d26
 #
383d26
 # @writable: Whether clients should be able to write to the device via the
383d26
 #     NBD connection (default false).
383d26
+
383d26
+# @bitmap: Also export the dirty bitmap reachable from @device, so the
383d26
+#          NBD client can use NBD_OPT_SET_META_CONTEXT with
383d26
+#          "qemu:dirty-bitmap:NAME" to inspect the bitmap. (since 4.0)
383d26
 #
383d26
 # Returns: error if the server is not running, or export with the same name
383d26
 #          already exists.
383d26
@@ -320,7 +324,8 @@
383d26
 # Since: 1.3.0
383d26
 ##
383d26
 { 'command': 'nbd-server-add',
383d26
-  'data': {'device': 'str', '*name': 'str', '*writable': 'bool'} }
383d26
+  'data': {'device': 'str', '*name': 'str', '*writable': 'bool',
383d26
+           '*bitmap': 'str' } }
383d26
 
383d26
 ##
383d26
 # @NbdServerRemoveMode:
383d26
diff --git a/tests/qemu-iotests/223 b/tests/qemu-iotests/223
383d26
index f200e31..0bcc98a 100755
383d26
--- a/tests/qemu-iotests/223
383d26
+++ b/tests/qemu-iotests/223
383d26
@@ -126,23 +126,20 @@ _send_qemu_cmd $QEMU_HANDLE '{"execute":"nbd-server-start",
383d26
   "arguments":{"addr":{"type":"unix",
383d26
     "data":{"path":"'"$TEST_DIR/nbd"1'"}}}}' "error" # Attempt second server
383d26
 _send_qemu_cmd $QEMU_HANDLE '{"execute":"nbd-server-add",
383d26
-  "arguments":{"device":"n"}}' "return"
383d26
+  "arguments":{"device":"n", "bitmap":"b"}}' "return"
383d26
 _send_qemu_cmd $QEMU_HANDLE '{"execute":"nbd-server-add",
383d26
   "arguments":{"device":"nosuch"}}' "error" # Attempt to export missing node
383d26
 _send_qemu_cmd $QEMU_HANDLE '{"execute":"nbd-server-add",
383d26
   "arguments":{"device":"n"}}' "error" # Attempt to export same name twice
383d26
-_send_qemu_cmd $QEMU_HANDLE '{"execute":"x-nbd-server-add-bitmap",
383d26
-  "arguments":{"name":"n", "bitmap":"b"}}' "return"
383d26
 _send_qemu_cmd $QEMU_HANDLE '{"execute":"nbd-server-add",
383d26
-  "arguments":{"device":"n", "name":"n2"}}' "return"
383d26
-_send_qemu_cmd $QEMU_HANDLE '{"execute":"x-nbd-server-add-bitmap",
383d26
-  "arguments":{"name":"n2", "bitmap":"b2"}}' "error" # Enabled vs. read-only
383d26
-_send_qemu_cmd $QEMU_HANDLE '{"execute":"nbd-server-remove",
383d26
-  "arguments":{"name":"n2"}}' "return"
383d26
+  "arguments":{"device":"n", "name":"n2",
383d26
+  "bitmap":"b2"}}' "error" # enabled vs. read-only
383d26
+_send_qemu_cmd $QEMU_HANDLE '{"execute":"nbd-server-add",
383d26
+  "arguments":{"device":"n", "name":"n2",
383d26
+  "bitmap":"b3"}}' "error" # Missing bitmap
383d26
 _send_qemu_cmd $QEMU_HANDLE '{"execute":"nbd-server-add",
383d26
-  "arguments":{"device":"n", "name":"n2", "writable":true}}' "return"
383d26
-_send_qemu_cmd $QEMU_HANDLE '{"execute":"x-nbd-server-add-bitmap",
383d26
-  "arguments":{"name":"n2", "bitmap":"b2"}}' "return"
383d26
+  "arguments":{"device":"n", "name":"n2", "writable":true,
383d26
+  "bitmap":"b2"}}' "return"
383d26
 
383d26
 echo
383d26
 echo "=== Contrast normal status to large granularity dirty-bitmap ==="
383d26
diff --git a/tests/qemu-iotests/223.out b/tests/qemu-iotests/223.out
383d26
index 3028857..a0c2dec 100644
383d26
--- a/tests/qemu-iotests/223.out
383d26
+++ b/tests/qemu-iotests/223.out
383d26
@@ -33,11 +33,8 @@ wrote 2097152/2097152 bytes at offset 2097152
383d26
 {"return": {}}
383d26
 {"error": {"class": "GenericError", "desc": "Cannot find device=nosuch nor node_name=nosuch"}}
383d26
 {"error": {"class": "GenericError", "desc": "NBD server already has export named 'n'"}}
383d26
-{"return": {}}
383d26
-{"return": {}}
383d26
 {"error": {"class": "GenericError", "desc": "Enabled bitmap 'b2' incompatible with readonly export"}}
383d26
-{"return": {}}
383d26
-{"return": {}}
383d26
+{"error": {"class": "GenericError", "desc": "Bitmap 'b3' is not found"}}
383d26
 {"return": {}}
383d26
 
383d26
 === Contrast normal status to large granularity dirty-bitmap ===
383d26
-- 
383d26
1.8.3.1
383d26