From: Max Reitz <mreitz@redhat.com>
To: John Snow <jsnow@redhat.com>, qemu-devel@nongnu.org
Cc: Fam Zheng <famz@redhat.com>
Subject: Re: [Qemu-devel] [2.3 PATCH v7 08/10] qapi: Add transaction support to block-dirty-bitmap-{add, enable, disable}
Date: Wed, 26 Nov 2014 15:44:06 +0100 [thread overview]
Message-ID: <5475E736.1060803@redhat.com> (raw)
In-Reply-To: <1416944800-17919-9-git-send-email-jsnow@redhat.com>
On 2014-11-25 at 20:46, John Snow wrote:
> From: Fam Zheng <famz@redhat.com>
>
> This adds three qmp commands to transactions.
>
> Users can stop a dirty bitmap, start backup of it, and start another
> dirty bitmap atomically, so that the dirty bitmap is tracked
> incrementally and we don't miss any write.
>
> Signed-off-by: Fam Zheng <famz@redhat.com>
> Signed-off-by: John Snow <jsnow@redhat.com>
> ---
> blockdev.c | 147 +++++++++++++++++++++++++++++++++++++++++++------------
> qapi-schema.json | 5 +-
> 2 files changed, 119 insertions(+), 33 deletions(-)
>
> diff --git a/blockdev.c b/blockdev.c
> index adf841a..b98249b 100644
> --- a/blockdev.c
> +++ b/blockdev.c
> @@ -1497,6 +1497,106 @@ static void drive_backup_abort(BlkTransactionState *common)
> }
> }
>
> +static void block_dirty_bitmap_add_prepare(BlkTransactionState *common,
> + Error **errp)
> +{
> + BlockDirtyBitmapAdd *action;
> +
> + action = common->action->block_dirty_bitmap_add;
> + qmp_block_dirty_bitmap_add(action->device, action->name,
> + action->has_granularity, action->granularity,
> + errp);
> +}
> +
> +static void block_dirty_bitmap_add_abort(BlkTransactionState *common)
> +{
> + BlockDirtyBitmapAdd *action;
> + BdrvDirtyBitmap *bm;
> + BlockDriverState *bs;
> +
> + action = common->action->block_dirty_bitmap_add;
> + bs = bdrv_lookup_bs(action->device, NULL, NULL);
> + if (bs) {
> + bm = bdrv_find_dirty_bitmap(bs, action->name);
> + if (bm) {
> + bdrv_release_dirty_bitmap(bs, bm);
> + }
> + }
> +}
> +
> +typedef struct BlockDirtyBitmapState {
> + BlkTransactionState common;
> + BdrvDirtyBitmap *bitmap;
> +} BlockDirtyBitmapState;
> +
> +static BdrvDirtyBitmap *block_dirty_bitmap_lookup(const char *device,
> + const char *name,
> + Error **errp)
> +{
> + BlockDriverState *bs;
> + BdrvDirtyBitmap *bitmap;
> + Error *local_err = NULL;
> +
> + if (!device) {
> + error_setg(errp, "Device cannot be NULL");
> + return NULL;
> + }
> + if (!name) {
> + error_setg(errp, "Bitmap name cannot be NULL");
> + return NULL;
> + }
> +
> + bs = bdrv_lookup_bs(device, NULL, &local_err);
> + if (!bs) {
> + error_propagate(errp, local_err);
> + return NULL;
> + }
> +
> + bitmap = bdrv_find_dirty_bitmap(bs, name);
> + if (!bitmap) {
> + error_setg(errp, "Dirty bitmap not found: %s", name);
> + return NULL;
> + }
> +
> + return bitmap;
> +}
> +
> +/**
> + * Enable and Disable re-uses the same preparation.
> + */
> +static void block_dirty_bitmap_en_toggle_prepare(BlkTransactionState *common,
> + Error **errp)
> +{
> + BlockDirtyBitmapState *state = DO_UPCAST(BlockDirtyBitmapState,
> + common, common);
> + BlockDirtyBitmap *action;
> + Error *local_err = NULL;
> +
> + action = common->action->block_dirty_bitmap_enable;
common->action is a union, so this works for *disable, too (which has
the same time as *enable); but I wouldn't object a comment here that
this is indeed the case.
Or go into pedantic mode and add an assert(action ==
common->action->block_dirty_bitmap_disable).
> +
> + state->bitmap = block_dirty_bitmap_lookup(action->device,
> + action->name,
> + &local_err);
> + if (!state->bitmap) {
> + error_propagate(errp, local_err);
Again, no need for local_err or error_propagate().
Because I feel like I owe you an explanation by now why there is
local_err at all in so many places: For some functions, it is not
possible to discern whether they were successful or not just by looking
at the return value. Therefore, the only way to decide whether they
failed is by looking whether they set the Error object or not. However,
errp may be NULL, therefore in those places we cannot just look at
*errp. In those cases, we have to use a local Error object which is
passed to the function and which we then can use to determine failure or
success; on failure, it then needs to be propagated. A good example is
block_dirty_bitmap_en_toggle_prepare() itself which does not return any
value.
However, in all the places in this series where I said you could drop
the error_propagate() and local_err invoked functions which did return
error values; like here, where !state->bitmap indicates an error.
Therefore, we don't need local_err here.
> + return;
> + }
> +}
> +
> +static void block_dirty_bitmap_enable_commit(BlkTransactionState *common)
> +{
> + BlockDirtyBitmapState *state = DO_UPCAST(BlockDirtyBitmapState,
> + common, common);
> + bdrv_enable_dirty_bitmap(NULL, state->bitmap);
This does work for now, but then I'm asking myself why
bdrv_enable_dirty_bitmap() takes a BDS pointer at all. I thought maybe
in the future the BDS pointer may come in handy, but with this call
you're basically saying that the function will never need the BDS pointer.
It's better to omit the BDS pointer from bdrv_enable_dirty_bitmap(),
then. If we do notice a need for it later on, the compiler will tell us
the places where we don't pass it. Like this, if the function evaluates
the parameter in the future, it will be a runtime problem.
> +}
> +
> +static void block_dirty_bitmap_disable_commit(BlkTransactionState *common)
> +{
> + BlockDirtyBitmapState *state = DO_UPCAST(BlockDirtyBitmapState,
> + common, common);
> + bdrv_disable_dirty_bitmap(NULL, state->bitmap);
Same here, of course.
> +}
> +
> static void abort_prepare(BlkTransactionState *common, Error **errp)
> {
> error_setg(errp, "Transaction aborted using Abort action");
> @@ -1529,6 +1629,21 @@ static const BdrvActionOps actions[] = {
> .prepare = internal_snapshot_prepare,
> .abort = internal_snapshot_abort,
> },
> + [TRANSACTION_ACTION_KIND_BLOCK_DIRTY_BITMAP_ADD] = {
> + .instance_size = sizeof(BlkTransactionState),
> + .prepare = block_dirty_bitmap_add_prepare,
> + .abort = block_dirty_bitmap_add_abort,
> + },
> + [TRANSACTION_ACTION_KIND_BLOCK_DIRTY_BITMAP_ENABLE] = {
> + .instance_size = sizeof(BlockDirtyBitmapState),
> + .prepare = block_dirty_bitmap_en_toggle_prepare,
> + .commit = block_dirty_bitmap_enable_commit,
> + },
> + [TRANSACTION_ACTION_KIND_BLOCK_DIRTY_BITMAP_DISABLE] = {
> + .instance_size = sizeof(BlockDirtyBitmapState),
> + .prepare = block_dirty_bitmap_en_toggle_prepare,
> + .commit = block_dirty_bitmap_disable_commit,
> + },
> };
>
> /*
> @@ -1875,38 +1990,6 @@ void qmp_block_dirty_bitmap_remove(const char *device, const char *name,
> bdrv_release_dirty_bitmap(bs, bitmap);
> }
>
> -static BdrvDirtyBitmap *block_dirty_bitmap_lookup(const char *device,
> - const char *name,
> - Error **errp)
> -{
> - BlockDriverState *bs;
> - BdrvDirtyBitmap *bitmap;
> - Error *local_err = NULL;
> -
> - if (!device) {
> - error_setg(errp, "Device cannot be NULL");
> - return NULL;
> - }
> - if (!name) {
> - error_setg(errp, "Bitmap name cannot be NULL");
> - return NULL;
> - }
> -
> - bs = bdrv_lookup_bs(device, NULL, &local_err);
> - if (!bs) {
> - error_propagate(errp, local_err);
> - return NULL;
> - }
> -
> - bitmap = bdrv_find_dirty_bitmap(bs, name);
> - if (!bitmap) {
> - error_setg(errp, "Dirty bitmap not found: %s", name);
> - return NULL;
> - }
> -
> - return bitmap;
> -}
> -
Is it possible to move this function further up in 6 where it is
created? If so, it doesn't need to be moved in this patch (and moving
code blocks always looks a bit ugly in patches...).
Technically, the patch is fine. If it weren't for BDS issue with the
bdrv_{en,dis}able_dirty_bitmap() calls, I'd give it an R-b.
Max
next prev parent reply other threads:[~2014-11-26 14:44 UTC|newest]
Thread overview: 27+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-11-25 19:46 [Qemu-devel] [2.3 PATCH v7 00/10] block: Incremental backup series John Snow
2014-11-25 19:46 ` [Qemu-devel] [2.3 PATCH v7 01/10] qapi: Add optional field "name" to block dirty bitmap John Snow
2014-11-26 11:22 ` Max Reitz
2014-11-25 19:46 ` [Qemu-devel] [2.3 PATCH v7 02/10] qmp: Add block-dirty-bitmap-add and block-dirty-bitmap-remove John Snow
2014-11-26 12:19 ` Max Reitz
2014-11-26 15:39 ` John Snow
2014-11-26 15:53 ` Max Reitz
2014-11-27 9:16 ` Markus Armbruster
2014-11-25 19:46 ` [Qemu-devel] [2.3 PATCH v7 03/10] block: Introduce bdrv_dirty_bitmap_granularity() John Snow
2014-11-26 12:29 ` Max Reitz
2014-11-25 19:46 ` [Qemu-devel] [2.3 PATCH v7 04/10] hbitmap: Add hbitmap_copy John Snow
2014-11-26 12:32 ` Max Reitz
2014-11-25 19:46 ` [Qemu-devel] [2.3 PATCH v7 05/10] block: Add bdrv_copy_dirty_bitmap and bdrv_reset_dirty_bitmap John Snow
2014-11-26 12:43 ` Max Reitz
2014-11-26 16:01 ` Eric Blake
2014-11-27 9:05 ` Markus Armbruster
2014-11-25 19:46 ` [Qemu-devel] [2.3 PATCH v7 06/10] qmp: Add block-dirty-bitmap-enable and block-dirty-bitmap-disable John Snow
2014-11-26 12:51 ` Max Reitz
2014-11-25 19:46 ` [Qemu-devel] [2.3 PATCH v7 07/10] qmp: Add support of "dirty-bitmap" sync mode for drive-backup John Snow
2014-11-26 14:19 ` Max Reitz
2014-11-25 19:46 ` [Qemu-devel] [2.3 PATCH v7 08/10] qapi: Add transaction support to block-dirty-bitmap-{add, enable, disable} John Snow
2014-11-26 14:44 ` Max Reitz [this message]
2014-11-25 19:46 ` [Qemu-devel] [2.3 PATCH v7 09/10] qmp: Add dirty bitmap 'enabled' field in query-block John Snow
2014-11-26 14:49 ` Max Reitz
2014-11-25 19:46 ` [Qemu-devel] [2.3 PATCH v7 10/10] qemu-iotests: Add tests for drive-backup sync=dirty-bitmap John Snow
2014-11-26 14:52 ` Max Reitz
2014-11-25 19:55 ` [Qemu-devel] [2.3 PATCH v7 00/10] block: Incremental backup series John Snow
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=5475E736.1060803@redhat.com \
--to=mreitz@redhat.com \
--cc=famz@redhat.com \
--cc=jsnow@redhat.com \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).