10.01.2019 10:13, Eric Blake wrote:
> With the experimental x-nbd-server-add-bitmap command, there was
> a window of time where an NBD 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 the exposed dirty bitmap (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, with automatic failure to export if the bitmap is not
> available.
> 
> The experimental command included an optional 'bitmap-export-name'
> field for remapping the name exposed over NBD to be different from
> the bitmap name stored on disk.  However, my libvirt demo code
> for implementing differential backups on top of persistent bitmaps
> did not need to take advantage of that feature (it is instead
> possible to create a new temporary bitmap with the desired name,
> use block-dirty-bitmap-merge to merge one or more persistent
> bitmaps into the temporary, then associate the temporary with the
> NBD export, if control is needed over the exported bitmap name).
> Hence, I'm not copying that part of the experiment over to the
> stable addition. For more details on the libvirt demo, see
> https://www.redhat.com/archives/libvir-list/2018-October/msg01254.html,
> https://kvmforum2018.sched.com/event/FzuB/facilitating-incremental-backup-eric-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 declared stable via a
> single QMP command, including removing the race window.
> 
> Update test 223 to use the new interface, including a demonstration
> that it is now easier to handle failures.
> 
> Signed-off-by: Eric Blake <ebl...@redhat.com>
> ---
>   qapi/block.json            |  7 ++++++-
>   blockdev-nbd.c             | 12 +++++++++++-
>   hmp.c                      |  5 +++--
>   tests/qemu-iotests/223     | 17 ++++++-----------
>   tests/qemu-iotests/223.out |  5 +----
>   5 files changed, 27 insertions(+), 19 deletions(-)
> 
> diff --git a/qapi/block.json b/qapi/block.json
> index 11f01f28efe..3d70420f763 100644
> --- a/qapi/block.json
> +++ b/qapi/block.json
> @@ -246,6 +246,10 @@
>   #
>   # @writable: Whether clients should be able to write to the device via the
>   #     NBD connection (default false).
> +
> +# @bitmap: Also export the dirty bitmap reachable from @device, so the
> +#          NBD client can use NBD_OPT_SET_META_CONTEXT with
> +#          "qemu:dirty-bitmap:NAME" to inspect the bitmap. (since 4.0)
>   #
>   # Returns: error if the server is not running, or export with the same name
>   #          already exists.
> @@ -253,7 +257,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' } }
> 
>   ##
>   # @NbdServerRemoveMode:
> diff --git a/blockdev-nbd.c b/blockdev-nbd.c
> index f5edbc27d88..ac7e993c35f 100644
> --- a/blockdev-nbd.c
> +++ b/blockdev-nbd.c
> @@ -140,7 +140,8 @@ void qmp_nbd_server_start(SocketAddressLegacy *addr,
>   }
> 
>   void qmp_nbd_server_add(const char *device, bool has_name, const char *name,
> -                        bool has_writable, bool writable, Error **errp)
> +                        bool has_writable, bool writable,
> +                        bool has_bitmap, const char *bitmap, Error **errp)
>   {
>       BlockDriverState *bs = NULL;
>       BlockBackend *on_eject_blk;
> @@ -185,6 +186,15 @@ void qmp_nbd_server_add(const char *device, bool 
> has_name, const char *name,
>        * our only way of accessing it is through nbd_export_find(), so we can 
> drop
>        * the strong reference that is @exp. */
>       nbd_export_put(exp);
> +
> +    if (has_bitmap) {
> +        Error *err = NULL;

Hm, I though that local_err is most popular name for it, check:

# git grep 'error_propagate(errp, err)' | wc -l
352
# git grep 'error_propagate(errp, local_err)' | wc -l
540

- hm, surprise for me, err is very popular too.. but not in block layer:

# git grep 'error_propagate(errp, err)' -- block* | wc -l
6
# git grep 'error_propagate(errp, local_err)' -- block* | wc -l
179
# git grep 'error_propagate(errp, err)' -- *nbd* block/nbd* | wc -l
0
# git grep 'error_propagate(errp, local_err)' -- *nbd* block/nbd* | wc -l
3

sorry for that very-very nitpicking, with or without s/err/local_err/:

Reviewed-by: Vladimir Sementsov-Ogievskiy <vsement...@virtuozzo.com>


> +        nbd_export_bitmap(exp, bitmap, bitmap, &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..8da5fd8760a 100644
> --- a/hmp.c
> +++ b/hmp.c
> @@ -2326,7 +2326,7 @@ 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, &local_err);
> 
>           if (local_err != NULL) {
>               qmp_nbd_server_stop(NULL);
> @@ -2347,7 +2347,8 @@ void hmp_nbd_server_add(Monitor *mon, const QDict 
> *qdict)
>       bool writable = qdict_get_try_bool(qdict, "writable", false);
>       Error *local_err = NULL;
> 
> -    qmp_nbd_server_add(device, !!name, name, true, writable, &local_err);
> +    qmp_nbd_server_add(device, !!name, name, true, writable,
> +                       false, NULL, &local_err);
>       hmp_handle_error(mon, &local_err);
>   }
> 
> diff --git a/tests/qemu-iotests/223 b/tests/qemu-iotests/223
> index f1fbb9bc1c6..1f6822f9489 100755
> --- a/tests/qemu-iotests/223
> +++ b/tests/qemu-iotests/223
> @@ -120,21 +120,16 @@ _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"
> +  "arguments":{"device":"n", "bitmap":"b"}}' "return"
>   _send_qemu_cmd $QEMU_HANDLE '{"execute":"nbd-server-add",
>     "arguments":{"device":"n"}}' "error"
> -_send_qemu_cmd $QEMU_HANDLE '{"execute":"x-nbd-server-add-bitmap",
> -  "arguments":{"name":"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"}}' "error"
> -_send_qemu_cmd $QEMU_HANDLE '{"execute":"nbd-server-remove",
> -  "arguments":{"name":"n2"}}' "return"

Aha, so, you've added this recently for this demonstration, it makes sense.

> +  "arguments":{"device":"n", "name":"n2", "bitmap":"b2"}}' "error"
>   _send_qemu_cmd $QEMU_HANDLE '{"execute":"nbd-server-add",
> -  "arguments":{"device":"n", "name":"n2", "writable":true}}' "return"
> -_send_qemu_cmd $QEMU_HANDLE '{"execute":"x-nbd-server-add-bitmap",
> -  "arguments":{"name":"n2", "bitmap":"b2"}}' "return"
> +  "arguments":{"device":"n", "name":"n2", "bitmap":"b3"}}' "error"

new error path, it demonstrates error handling with new interface too..

> +_send_qemu_cmd $QEMU_HANDLE '{"execute":"nbd-server-add",
> +  "arguments":{"device":"n", "name":"n2", "writable":true,
> +  "bitmap":"b2"}}' "return"
> 
>   echo
>   echo "=== Contrast normal status to large granularity dirty-bitmap ==="
> diff --git a/tests/qemu-iotests/223.out b/tests/qemu-iotests/223.out
> index 5ed2e322e19..7135bf59bb8 100644
> --- a/tests/qemu-iotests/223.out
> +++ b/tests/qemu-iotests/223.out
> @@ -30,11 +30,8 @@ wrote 2097152/2097152 bytes at offset 2097152
>   {"return": {}}
>   {"return": {}}
>   {"error": {"class": "GenericError", "desc": "NBD server already has export 
> named 'n'"}}
> -{"return": {}}
> -{"return": {}}
>   {"error": {"class": "GenericError", "desc": "Enabled bitmap 'b2' 
> incompatible with readonly export"}}
> -{"return": {}}
> -{"return": {}}
> +{"error": {"class": "GenericError", "desc": "Bitmap 'b3' is not found"}}
>   {"return": {}}
> 
>   === Contrast normal status to large granularity dirty-bitmap ===
> 


-- 
Best regards,
Vladimir

Reply via email to