Commit 44ba6010 authored by Peter Maydell's avatar Peter Maydell
Browse files

Merge remote-tracking branch 'remotes/ericb/tags/pull-nbd-2019-01-14' into staging



nbd patches for 2019-01-14

Promote bitmap/NBD interfaces to stable for use in incremental
backups. Add 'qemu-nbd --bitmap'.

- John Snow: 0/11 bitmaps: remove x- prefix from QMP api
- Philippe Mathieu-Daudé: qemu-nbd: Rename 'exp' variable clashing with math::exp() symbol
- Eric Blake: 0/8 Promote x-nbd-server-add-bitmap to stable

# gpg: Signature made Mon 14 Jan 2019 16:13:45 GMT
# gpg:                using RSA key A7A16B4A2527436A
# gpg: Good signature from "Eric Blake <eblake@redhat.com>"
# gpg:                 aka "Eric Blake (Free Software Programmer) <ebb9@byu.net>"
# gpg:                 aka "[jpeg image of size 6874]"
# Primary key fingerprint: 71C2 CC22 B1C4 6029 27D2  F3AA A7A1 6B4A 2527 436A

* remotes/ericb/tags/pull-nbd-2019-01-14:
  qemu-nbd: Add --bitmap=NAME option
  nbd: Merge nbd_export_bitmap into nbd_export_new
  nbd: Remove x-nbd-server-add-bitmap
  nbd: Allow bitmap export during QMP nbd-server-add
  nbd: Merge nbd_export_set_name into nbd_export_new
  nbd: Only require disabled bitmap for read-only exports
  nbd: Forbid nbd-server-stop when server is not running
  nbd: Add some error case testing to iotests 223
  qemu-nbd: Rename 'exp' variable clashing with math::exp() symbol
  iotests: add iotest 236 for testing bitmap merge
  iotests: implement pretty-print for log and qmp_log
  iotests: change qmp_log filters to expect QMP objects only
  iotests: remove default filters from qmp_log
  iotests: add qmp recursive sorting function
  iotests: add filter_generated_node_ids
  iotests.py: don't abort if IMGKEYSECRET is undefined
  block: remove 'x' prefix from experimental bitmap APIs
  blockdev: n-ary bitmap merge
  block/dirty-bitmap: remove assertion from restore
  blockdev: abort transactions in reverse order

Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parents b2f7c27f 636192c4
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -625,7 +625,6 @@ void bdrv_clear_dirty_bitmap(BdrvDirtyBitmap *bitmap, HBitmap **out)
void bdrv_restore_dirty_bitmap(BdrvDirtyBitmap *bitmap, HBitmap *backup)
{
    HBitmap *tmp = bitmap->bitmap;
    assert(bdrv_dirty_bitmap_enabled(bitmap));
    assert(!bdrv_dirty_bitmap_readonly(bitmap));
    bitmap->bitmap = backup;
    hbitmap_free(tmp);
+7 −25
Original line number Diff line number Diff line
@@ -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;
@@ -174,14 +175,13 @@ void qmp_nbd_server_add(const char *device, bool has_name, const char *name,
        writable = false;
    }

    exp = nbd_export_new(bs, 0, -1, writable ? 0 : NBD_FLAG_READ_ONLY,
    exp = nbd_export_new(bs, 0, -1, name, NULL, bitmap,
                         writable ? 0 : NBD_FLAG_READ_ONLY,
                         NULL, false, on_eject_blk, errp);
    if (!exp) {
        return;
    }

    nbd_export_set_name(exp, name);

    /* The list of named exports has a strong reference to this export now and
     * our only way of accessing it is through nbd_export_find(), so we can drop
     * the strong reference that is @exp. */
@@ -214,31 +214,13 @@ void qmp_nbd_server_remove(const char *name,

void qmp_nbd_server_stop(Error **errp)
{
    nbd_export_close_all();

    nbd_server_free(nbd_server);
    nbd_server = NULL;
}

void qmp_x_nbd_server_add_bitmap(const char *name, const char *bitmap,
                                 bool has_bitmap_export_name,
                                 const char *bitmap_export_name,
                                 Error **errp)
{
    NBDExport *exp;

    if (!nbd_server) {
        error_setg(errp, "NBD server not running");
        return;
    }

    exp = nbd_export_find(name);
    if (exp == NULL) {
        error_setg(errp, "Export '%s' is not found", name);
        return;
    }
    nbd_export_close_all();

    nbd_export_bitmap(exp, bitmap,
                      has_bitmap_export_name ? bitmap_export_name : bitmap,
                      errp);
    nbd_server_free(nbd_server);
    nbd_server = NULL;
}
+67 −40
Original line number Diff line number Diff line
@@ -1339,7 +1339,7 @@ struct BlkActionState {
    const BlkActionOps *ops;
    JobTxn *block_job_txn;
    TransactionProperties *txn_props;
    QSIMPLEQ_ENTRY(BlkActionState) entry;
    QTAILQ_ENTRY(BlkActionState) entry;
};

/* internal snapshot private data */
@@ -1963,7 +1963,7 @@ static void block_dirty_bitmap_add_prepare(BlkActionState *common,
                               action->has_granularity, action->granularity,
                               action->has_persistent, action->persistent,
                               action->has_autoload, action->autoload,
                               action->has_x_disabled, action->x_disabled,
                               action->has_disabled, action->disabled,
                               &local_err);

    if (!local_err) {
@@ -2048,7 +2048,7 @@ static void block_dirty_bitmap_enable_prepare(BlkActionState *common,
        return;
    }

    action = common->action->u.x_block_dirty_bitmap_enable.data;
    action = common->action->u.block_dirty_bitmap_enable.data;
    state->bitmap = block_dirty_bitmap_lookup(action->node,
                                              action->name,
                                              NULL,
@@ -2089,7 +2089,7 @@ static void block_dirty_bitmap_disable_prepare(BlkActionState *common,
        return;
    }

    action = common->action->u.x_block_dirty_bitmap_disable.data;
    action = common->action->u.block_dirty_bitmap_disable.data;
    state->bitmap = block_dirty_bitmap_lookup(action->node,
                                              action->name,
                                              NULL,
@@ -2119,33 +2119,28 @@ static void block_dirty_bitmap_disable_abort(BlkActionState *common)
    }
}

static BdrvDirtyBitmap *do_block_dirty_bitmap_merge(const char *node,
                                                    const char *target,
                                                    strList *bitmaps,
                                                    HBitmap **backup,
                                                    Error **errp);

static void block_dirty_bitmap_merge_prepare(BlkActionState *common,
                                             Error **errp)
{
    BlockDirtyBitmapMerge *action;
    BlockDirtyBitmapState *state = DO_UPCAST(BlockDirtyBitmapState,
                                             common, common);
    BdrvDirtyBitmap *merge_source;

    if (action_check_completion_mode(common, errp) < 0) {
        return;
    }

    action = common->action->u.x_block_dirty_bitmap_merge.data;
    state->bitmap = block_dirty_bitmap_lookup(action->node,
                                              action->dst_name,
                                              &state->bs,
                                              errp);
    if (!state->bitmap) {
        return;
    }

    merge_source = bdrv_find_dirty_bitmap(state->bs, action->src_name);
    if (!merge_source) {
        return;
    }
    action = common->action->u.block_dirty_bitmap_merge.data;

    bdrv_merge_dirty_bitmap(state->bitmap, merge_source, &state->backup, errp);
    state->bitmap = do_block_dirty_bitmap_merge(action->node, action->target,
                                                action->bitmaps, &state->backup,
                                                errp);
}

static void abort_prepare(BlkActionState *common, Error **errp)
@@ -2209,17 +2204,17 @@ static const BlkActionOps actions[] = {
        .commit = block_dirty_bitmap_free_backup,
        .abort = block_dirty_bitmap_restore,
    },
    [TRANSACTION_ACTION_KIND_X_BLOCK_DIRTY_BITMAP_ENABLE] = {
    [TRANSACTION_ACTION_KIND_BLOCK_DIRTY_BITMAP_ENABLE] = {
        .instance_size = sizeof(BlockDirtyBitmapState),
        .prepare = block_dirty_bitmap_enable_prepare,
        .abort = block_dirty_bitmap_enable_abort,
    },
    [TRANSACTION_ACTION_KIND_X_BLOCK_DIRTY_BITMAP_DISABLE] = {
    [TRANSACTION_ACTION_KIND_BLOCK_DIRTY_BITMAP_DISABLE] = {
        .instance_size = sizeof(BlockDirtyBitmapState),
        .prepare = block_dirty_bitmap_disable_prepare,
        .abort = block_dirty_bitmap_disable_abort,
    },
    [TRANSACTION_ACTION_KIND_X_BLOCK_DIRTY_BITMAP_MERGE] = {
    [TRANSACTION_ACTION_KIND_BLOCK_DIRTY_BITMAP_MERGE] = {
        .instance_size = sizeof(BlockDirtyBitmapState),
        .prepare = block_dirty_bitmap_merge_prepare,
        .commit = block_dirty_bitmap_free_backup,
@@ -2266,8 +2261,8 @@ void qmp_transaction(TransactionActionList *dev_list,
    BlkActionState *state, *next;
    Error *local_err = NULL;

    QSIMPLEQ_HEAD(, BlkActionState) snap_bdrv_states;
    QSIMPLEQ_INIT(&snap_bdrv_states);
    QTAILQ_HEAD(, BlkActionState) snap_bdrv_states;
    QTAILQ_INIT(&snap_bdrv_states);

    /* Does this transaction get canceled as a group on failure?
     * If not, we don't really need to make a JobTxn.
@@ -2298,7 +2293,7 @@ void qmp_transaction(TransactionActionList *dev_list,
        state->action = dev_info;
        state->block_job_txn = block_job_txn;
        state->txn_props = props;
        QSIMPLEQ_INSERT_TAIL(&snap_bdrv_states, state, entry);
        QTAILQ_INSERT_TAIL(&snap_bdrv_states, state, entry);

        state->ops->prepare(state, &local_err);
        if (local_err) {
@@ -2307,7 +2302,7 @@ void qmp_transaction(TransactionActionList *dev_list,
        }
    }

    QSIMPLEQ_FOREACH(state, &snap_bdrv_states, entry) {
    QTAILQ_FOREACH(state, &snap_bdrv_states, entry) {
        if (state->ops->commit) {
            state->ops->commit(state);
        }
@@ -2318,13 +2313,13 @@ void qmp_transaction(TransactionActionList *dev_list,

delete_and_fail:
    /* failure, and it is all-or-none; roll back all operations */
    QSIMPLEQ_FOREACH(state, &snap_bdrv_states, entry) {
    QTAILQ_FOREACH_REVERSE(state, &snap_bdrv_states, entry) {
        if (state->ops->abort) {
            state->ops->abort(state);
        }
    }
exit:
    QSIMPLEQ_FOREACH_SAFE(state, &snap_bdrv_states, entry, next) {
    QTAILQ_FOREACH_SAFE(state, &snap_bdrv_states, entry, next) {
        if (state->ops->clean) {
            state->ops->clean(state);
        }
@@ -2935,7 +2930,7 @@ void qmp_block_dirty_bitmap_clear(const char *node, const char *name,
    bdrv_clear_dirty_bitmap(bitmap, NULL);
}

void qmp_x_block_dirty_bitmap_enable(const char *node, const char *name,
void qmp_block_dirty_bitmap_enable(const char *node, const char *name,
                                   Error **errp)
{
    BlockDriverState *bs;
@@ -2956,7 +2951,7 @@ void qmp_x_block_dirty_bitmap_enable(const char *node, const char *name,
    bdrv_enable_dirty_bitmap(bitmap);
}

void qmp_x_block_dirty_bitmap_disable(const char *node, const char *name,
void qmp_block_dirty_bitmap_disable(const char *node, const char *name,
                                    Error **errp)
{
    BlockDriverState *bs;
@@ -2977,24 +2972,56 @@ void qmp_x_block_dirty_bitmap_disable(const char *node, const char *name,
    bdrv_disable_dirty_bitmap(bitmap);
}

void qmp_x_block_dirty_bitmap_merge(const char *node, const char *dst_name,
                                    const char *src_name, Error **errp)
static BdrvDirtyBitmap *do_block_dirty_bitmap_merge(const char *node,
                                                    const char *target,
                                                    strList *bitmaps,
                                                    HBitmap **backup,
                                                    Error **errp)
{
    BlockDriverState *bs;
    BdrvDirtyBitmap *dst, *src;
    BdrvDirtyBitmap *dst, *src, *anon;
    strList *lst;
    Error *local_err = NULL;

    dst = block_dirty_bitmap_lookup(node, dst_name, &bs, errp);
    dst = block_dirty_bitmap_lookup(node, target, &bs, errp);
    if (!dst) {
        return;
        return NULL;
    }

    src = bdrv_find_dirty_bitmap(bs, src_name);
    anon = bdrv_create_dirty_bitmap(bs, bdrv_dirty_bitmap_granularity(dst),
                                    NULL, errp);
    if (!anon) {
        return NULL;
    }

    for (lst = bitmaps; lst; lst = lst->next) {
        src = bdrv_find_dirty_bitmap(bs, lst->value);
        if (!src) {
        error_setg(errp, "Dirty bitmap '%s' not found", src_name);
        return;
            error_setg(errp, "Dirty bitmap '%s' not found", lst->value);
            dst = NULL;
            goto out;
        }

        bdrv_merge_dirty_bitmap(anon, src, NULL, &local_err);
        if (local_err) {
            error_propagate(errp, local_err);
            dst = NULL;
            goto out;
        }
    }

    /* Merge into dst; dst is unchanged on failure. */
    bdrv_merge_dirty_bitmap(dst, anon, backup, errp);

 out:
    bdrv_release_dirty_bitmap(bs, anon);
    return dst;
}

    bdrv_merge_dirty_bitmap(dst, src, NULL, errp);
void qmp_block_dirty_bitmap_merge(const char *node, const char *target,
                                  strList *bitmaps, Error **errp)
{
    do_block_dirty_bitmap_merge(node, target, bitmaps, NULL, errp);
}

BlockDirtyBitmapSha256 *qmp_x_debug_block_dirty_bitmap_sha256(const char *node,
+3 −2
Original line number Diff line number Diff line
@@ -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);
}

+4 −8
Original line number Diff line number Diff line
@@ -295,9 +295,10 @@ typedef struct NBDExport NBDExport;
typedef struct NBDClient NBDClient;

NBDExport *nbd_export_new(BlockDriverState *bs, off_t dev_offset, off_t size,
                          uint16_t nbdflags, void (*close)(NBDExport *),
                          bool writethrough, BlockBackend *on_eject_blk,
                          Error **errp);
                          const char *name, const char *description,
                          const char *bitmap, uint16_t nbdflags,
                          void (*close)(NBDExport *), bool writethrough,
                          BlockBackend *on_eject_blk, Error **errp);
void nbd_export_close(NBDExport *exp);
void nbd_export_remove(NBDExport *exp, NbdServerRemoveMode mode, Error **errp);
void nbd_export_get(NBDExport *exp);
@@ -306,8 +307,6 @@ void nbd_export_put(NBDExport *exp);
BlockBackend *nbd_export_get_blockdev(NBDExport *exp);

NBDExport *nbd_export_find(const char *name);
void nbd_export_set_name(NBDExport *exp, const char *name);
void nbd_export_set_description(NBDExport *exp, const char *description);
void nbd_export_close_all(void);

void nbd_client_new(QIOChannelSocket *sioc,
@@ -320,9 +319,6 @@ void nbd_client_put(NBDClient *client);
void nbd_server_start(SocketAddress *addr, const char *tls_creds,
                      Error **errp);

void nbd_export_bitmap(NBDExport *exp, const char *bitmap,
                       const char *bitmap_export_name, Error **errp);

/* nbd_read
 * Reads @size bytes from @ioc. Returns 0 on success.
 */
Loading