qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Max Reitz <mreitz@redhat.com>
To: Fam Zheng <famz@redhat.com>, qemu-devel@nongnu.org
Cc: Kevin Wolf <kwolf@redhat.com>, Jeff Cody <jcody@redhat.com>,
	vsementsov@parallels.com, stefanha@redhat.com,
	John Snow <jsnow@redhat.com>
Subject: Re: [Qemu-devel] [PATCH v4 01/14] qapi: Add transaction support to block-dirty-bitmap operations
Date: Mon, 3 Aug 2015 18:49:43 +0200	[thread overview]
Message-ID: <55BF9BA7.7030309@redhat.com> (raw)
In-Reply-To: <1438238370-16212-2-git-send-email-famz@redhat.com>

On 30.07.2015 08:39, Fam Zheng wrote:
> From: John Snow <jsnow@redhat.com>
>
> This adds two qmp commands to transactions.
>
> block-dirty-bitmap-add allows you to create a bitmap simultaneously
> alongside a new full backup to accomplish a clean synchronization
> point.
>
> block-dirty-bitmap-clear allows you to reset a bitmap back to as-if
> it were new, which can also be used alongside a full backup to
> accomplish a clean synchronization point.
>
> Signed-off-by: Fam Zheng <famz@redhat.com>
> Signed-off-by: John Snow <jsnow@redhat.com>
> Reviewed-by: Max Reitz <mreitz@redhat.com>
> Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
> Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
> Signed-off-by: Fam Zheng <famz@redhat.com>
> ---
>   block.c                   |  19 +++++++-
>   blockdev.c                | 114 +++++++++++++++++++++++++++++++++++++++++++++-
>   docs/bitmaps.md           |   6 +--
>   include/block/block.h     |   1 -
>   include/block/block_int.h |   3 ++
>   qapi-schema.json          |   6 ++-
>   6 files changed, 139 insertions(+), 10 deletions(-)
>
> diff --git a/block.c b/block.c
> index d088ee0..cee68c2 100644
> --- a/block.c
> +++ b/block.c
> @@ -3566,10 +3566,25 @@ void bdrv_reset_dirty_bitmap(BdrvDirtyBitmap *bitmap,
>       hbitmap_reset(bitmap->bitmap, cur_sector, nr_sectors);
>   }
>
> -void bdrv_clear_dirty_bitmap(BdrvDirtyBitmap *bitmap)
> +void bdrv_clear_dirty_bitmap(BdrvDirtyBitmap *bitmap, HBitmap **out)
>   {
>       assert(bdrv_dirty_bitmap_enabled(bitmap));
> -    hbitmap_reset_all(bitmap->bitmap);
> +    if (!out) {
> +        hbitmap_reset_all(bitmap->bitmap);
> +    } else {
> +        HBitmap *backup = bitmap->bitmap;
> +        bitmap->bitmap = hbitmap_alloc(bitmap->size,
> +                                       hbitmap_granularity(backup));
> +        *out = backup;
> +    }
> +}
> +
> +void bdrv_undo_clear_dirty_bitmap(BdrvDirtyBitmap *bitmap, HBitmap *in)
> +{
> +    HBitmap *tmp = bitmap->bitmap;
> +    assert(bdrv_dirty_bitmap_enabled(bitmap));
> +    bitmap->bitmap = in;
> +    hbitmap_free(tmp);
>   }
>
>   void bdrv_set_dirty(BlockDriverState *bs, int64_t cur_sector,
> diff --git a/blockdev.c b/blockdev.c
> index 62a4586..b80439b 100644
> --- a/blockdev.c
> +++ b/blockdev.c
> @@ -1708,6 +1708,106 @@ static void blockdev_backup_clean(BlkTransactionState *common)
>       }
>   }
>
> +typedef struct BlockDirtyBitmapState {
> +    BlkTransactionState common;
> +    BdrvDirtyBitmap *bitmap;
> +    BlockDriverState *bs;
> +    AioContext *aio_context;
> +    HBitmap *backup;
> +    bool prepared;
> +} BlockDirtyBitmapState;
> +
> +static void block_dirty_bitmap_add_prepare(BlkTransactionState *common,
> +                                           Error **errp)
> +{
> +    Error *local_err = NULL;
> +    BlockDirtyBitmapAdd *action;
> +    BlockDirtyBitmapState *state = DO_UPCAST(BlockDirtyBitmapState,
> +                                             common, common);
> +
> +    action = common->action->block_dirty_bitmap_add;
> +    /* AIO context taken and released within qmp_block_dirty_bitmap_add */
> +    qmp_block_dirty_bitmap_add(action->node, action->name,
> +                               action->has_granularity, action->granularity,
> +                               &local_err);
> +
> +    if (!local_err) {
> +        state->prepared = true;
> +    } else {
> +        error_propagate(errp, local_err);
> +    }
> +}
> +
> +static void block_dirty_bitmap_add_abort(BlkTransactionState *common)
> +{
> +    BlockDirtyBitmapAdd *action;
> +    BlockDirtyBitmapState *state = DO_UPCAST(BlockDirtyBitmapState,
> +                                             common, common);
> +
> +    action = common->action->block_dirty_bitmap_add;
> +    /* Should not be able to fail: IF the bitmap was added via .prepare(),
> +     * then the node reference and bitmap name must have been valid.
> +     */
> +    if (state->prepared) {
> +        qmp_block_dirty_bitmap_remove(action->node, action->name, &error_abort);
> +    }
> +}
> +
> +static void block_dirty_bitmap_clear_prepare(BlkTransactionState *common,
> +                                             Error **errp)
> +{
> +    BlockDirtyBitmapState *state = DO_UPCAST(BlockDirtyBitmapState,
> +                                             common, common);
> +    BlockDirtyBitmap *action;
> +
> +    action = common->action->block_dirty_bitmap_clear;
> +    state->bitmap = block_dirty_bitmap_lookup(action->node,
> +                                              action->name,
> +                                              &state->bs,
> +                                              &state->aio_context,
> +                                              errp);
> +    if (!state->bitmap) {
> +        return;
> +    }
> +
> +    if (bdrv_dirty_bitmap_frozen(state->bitmap)) {
> +        error_setg(errp, "Cannot modify a frozen bitmap");
> +        return;
> +    } else if (!bdrv_dirty_bitmap_enabled(state->bitmap)) {
> +        error_setg(errp, "Cannot clear a disabled bitmap");
> +        return;
> +    }
> +
> +    bdrv_clear_dirty_bitmap(state->bitmap, &state->backup);
> +    /* AioContext is released in .clean() */
> +}
> +
> +static void block_dirty_bitmap_clear_abort(BlkTransactionState *common)
> +{
> +    BlockDirtyBitmapState *state = DO_UPCAST(BlockDirtyBitmapState,
> +                                             common, common);
> +
> +    bdrv_undo_clear_dirty_bitmap(state->bitmap, state->backup);
> +}
> +
> +static void block_dirty_bitmap_clear_commit(BlkTransactionState *common)
> +{
> +    BlockDirtyBitmapState *state = DO_UPCAST(BlockDirtyBitmapState,
> +                                             common, common);
> +
> +    hbitmap_free(state->backup);
> +}
> +
> +static void block_dirty_bitmap_clear_clean(BlkTransactionState *common)
> +{
> +    BlockDirtyBitmapState *state = DO_UPCAST(BlockDirtyBitmapState,
> +                                             common, common);
> +
> +    if (state->aio_context) {
> +        aio_context_release(state->aio_context);
> +    }
> +}
> +
>   static void abort_prepare(BlkTransactionState *common, Error **errp)
>   {
>       error_setg(errp, "Transaction aborted using Abort action");
> @@ -1748,6 +1848,18 @@ static const BdrvActionOps actions[] = {
>           .abort = internal_snapshot_abort,
>           .clean = internal_snapshot_clean,
>       },
> +    [TRANSACTION_ACTION_KIND_BLOCK_DIRTY_BITMAP_ADD] = {
> +        .instance_size = sizeof(BlockDirtyBitmapState),
> +        .prepare = block_dirty_bitmap_add_prepare,
> +        .abort = block_dirty_bitmap_add_abort,
> +    },
> +    [TRANSACTION_ACTION_KIND_BLOCK_DIRTY_BITMAP_CLEAR] = {
> +        .instance_size = sizeof(BlockDirtyBitmapState),
> +        .prepare = block_dirty_bitmap_clear_prepare,
> +        .commit = block_dirty_bitmap_clear_commit,
> +        .abort = block_dirty_bitmap_clear_abort,
> +        .clean = block_dirty_bitmap_clear_clean,
> +    }
>   };
>
>   /*
> @@ -2131,7 +2243,7 @@ void qmp_block_dirty_bitmap_clear(const char *node, const char *name,
>           goto out;
>       }
>
> -    bdrv_clear_dirty_bitmap(bitmap);
> +    bdrv_clear_dirty_bitmap(bitmap, NULL);
>
>    out:
>       aio_context_release(aio_context);
> diff --git a/docs/bitmaps.md b/docs/bitmaps.md
> index fa87f07..9fd8ea6 100644
> --- a/docs/bitmaps.md
> +++ b/docs/bitmaps.md
> @@ -97,11 +97,7 @@ which is included at the end of this document.
>   }
>   ```
>
> -## Transactions (Not yet implemented)
> -
> -* Transactional commands are forthcoming in a future version,
> -  and are not yet available for use. This section serves as
> -  documentation of intent for their design and usage.
> +## Transactions
>
>   ### Justification
>
> diff --git a/include/block/block.h b/include/block/block.h
> index 37916f7..b1116e9 100644
> --- a/include/block/block.h
> +++ b/include/block/block.h
> @@ -503,7 +503,6 @@ void bdrv_set_dirty_bitmap(BdrvDirtyBitmap *bitmap,
>                              int64_t cur_sector, int nr_sectors);
>   void bdrv_reset_dirty_bitmap(BdrvDirtyBitmap *bitmap,
>                                int64_t cur_sector, int nr_sectors);
> -void bdrv_clear_dirty_bitmap(BdrvDirtyBitmap *bitmap);
>   void bdrv_dirty_iter_init(BdrvDirtyBitmap *bitmap, struct HBitmapIter *hbi);
>   void bdrv_set_dirty_iter(struct HBitmapIter *hbi, int64_t offset);
>   int64_t bdrv_get_dirty_count(BdrvDirtyBitmap *bitmap);
> diff --git a/include/block/block_int.h b/include/block/block_int.h
> index 14ad4c3..281d790 100644
> --- a/include/block/block_int.h
> +++ b/include/block/block_int.h
> @@ -664,4 +664,7 @@ void blk_dev_resize_cb(BlockBackend *blk);
>
>   void bdrv_set_dirty(BlockDriverState *bs, int64_t cur_sector, int nr_sectors);
>
> +void bdrv_clear_dirty_bitmap(BdrvDirtyBitmap *bitmap, HBitmap **out);
> +void bdrv_undo_clear_dirty_bitmap(BdrvDirtyBitmap *bitmap, HBitmap *in);
> +
>   #endif /* BLOCK_INT_H */
> diff --git a/qapi-schema.json b/qapi-schema.json
> index 4342a08..83de942 100644
> --- a/qapi-schema.json
> +++ b/qapi-schema.json
> @@ -1493,6 +1493,8 @@
>   # abort since 1.6
>   # blockdev-snapshot-internal-sync since 1.7
>   # blockdev-backup since 2.3
> +# block-dirty-bitmap-add since 2.4
> +# block-dirty-bitmap-clear since 2.4

*2.5, and keep my R-b.

Max

>   ##
>   { 'union': 'TransactionAction',
>     'data': {
> @@ -1500,7 +1502,9 @@
>          'drive-backup': 'DriveBackup',
>          'blockdev-backup': 'BlockdevBackup',
>          'abort': 'Abort',
> -       'blockdev-snapshot-internal-sync': 'BlockdevSnapshotInternal'
> +       'blockdev-snapshot-internal-sync': 'BlockdevSnapshotInternal',
> +       'block-dirty-bitmap-add': 'BlockDirtyBitmapAdd',
> +       'block-dirty-bitmap-clear': 'BlockDirtyBitmap'
>      } }
>
>   ##
>

  reply	other threads:[~2015-08-03 16:49 UTC|newest]

Thread overview: 30+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-07-30  6:39 [Qemu-devel] [PATCH v4 00/14] block: incremental backup transactions using BlockJobTxn Fam Zheng
2015-07-30  6:39 ` [Qemu-devel] [PATCH v4 01/14] qapi: Add transaction support to block-dirty-bitmap operations Fam Zheng
2015-08-03 16:49   ` Max Reitz [this message]
2015-09-07  6:32     ` Fam Zheng
2015-07-30  6:39 ` [Qemu-devel] [PATCH v4 02/14] iotests: add transactional incremental backup test Fam Zheng
2015-07-30  6:39 ` [Qemu-devel] [PATCH v4 03/14] block: rename BlkTransactionState and BdrvActionOps Fam Zheng
2015-07-30  6:39 ` [Qemu-devel] [PATCH v4 04/14] backup: Extract dirty bitmap handling as a separate function Fam Zheng
2015-08-03 17:06   ` Max Reitz
2015-07-30  6:39 ` [Qemu-devel] [PATCH v4 05/14] blockjob: Introduce reference count Fam Zheng
2015-08-03 17:16   ` Max Reitz
2015-07-30  6:39 ` [Qemu-devel] [PATCH v4 06/14] blockjob: Add .commit and .abort block job actions Fam Zheng
2015-08-03 17:27   ` Max Reitz
2015-07-30  6:39 ` [Qemu-devel] [PATCH v4 07/14] blockjob: Add "completed" and "ret" in BlockJob Fam Zheng
2015-08-03 17:32   ` Max Reitz
2015-07-30  6:39 ` [Qemu-devel] [PATCH v4 08/14] blockjob: Simplify block_job_finish_sync Fam Zheng
2015-08-03 17:37   ` Max Reitz
2015-07-30  6:39 ` [Qemu-devel] [PATCH v4 09/14] block: add block job transactions Fam Zheng
2015-08-03 18:06   ` Max Reitz
2015-09-07  6:36     ` Fam Zheng
2015-07-30  6:39 ` [Qemu-devel] [PATCH v4 10/14] blockdev: make BlockJobTxn available to qmp 'transaction' Fam Zheng
2015-08-03 18:13   ` Max Reitz
2015-09-07  6:52     ` Fam Zheng
2015-07-30  6:39 ` [Qemu-devel] [PATCH v4 11/14] block/backup: support block job transactions Fam Zheng
2015-08-03 18:26   ` Max Reitz
2015-09-07  6:57     ` Fam Zheng
2015-07-30  6:39 ` [Qemu-devel] [PATCH v4 12/14] iotests: 124 - transactional failure test Fam Zheng
2015-07-30  6:39 ` [Qemu-devel] [PATCH v4 13/14] qmp-commands.hx: Update the supported 'transaction' operations Fam Zheng
2015-07-30  6:39 ` [Qemu-devel] [PATCH v4 14/14] tests: add BlockJobTxn unit test Fam Zheng
2015-08-03 18:45   ` Max Reitz
2015-09-07  7:11     ` Fam Zheng

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=55BF9BA7.7030309@redhat.com \
    --to=mreitz@redhat.com \
    --cc=famz@redhat.com \
    --cc=jcody@redhat.com \
    --cc=jsnow@redhat.com \
    --cc=kwolf@redhat.com \
    --cc=qemu-devel@nongnu.org \
    --cc=stefanha@redhat.com \
    --cc=vsementsov@parallels.com \
    /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).