Commit 47fbad45 authored by Peter Maydell's avatar Peter Maydell
Browse files

Merge remote-tracking branch 'remotes/kevin/tags/for-upstream' into staging



Block layer patches:

- block: AioContext management, part 2
- Avoid recursive block_status call (i.e. lseek() calls) if possible
- linux-aio: Drop unused BlockAIOCB submission method
- nvme: add Get/Set Feature Timestamp support
- Fix crash on commit job start with active I/O on base node
- Fix crash in bdrv_drained_end
- Fix integer overflow in qcow2 discard

# gpg: Signature made Tue 04 Jun 2019 16:20:02 BST
# gpg:                using RSA key 7F09B272C88F2FD6
# gpg: Good signature from "Kevin Wolf <kwolf@redhat.com>" [full]
# Primary key fingerprint: DC3D EB15 9A9A F95D 3D74  56FE 7F09 B272 C88F 2FD6

* remotes/kevin/tags/for-upstream: (29 commits)
  iotests: Fix duplicated diff output on failure
  iotests: test big qcow2 shrink
  block/io: bdrv_pdiscard: support int64_t bytes parameter
  block/qcow2-refcount: add trace-point to qcow2_process_discards
  block: Remove bdrv_set_aio_context()
  test-bdrv-drain: Use bdrv_try_set_aio_context()
  iotests: Attach new devices to node in non-default iothread
  virtio-scsi-test: Test attaching new overlay with iothreads
  block: Remove wrong bdrv_set_aio_context() calls
  blockdev: Use bdrv_try_set_aio_context() for monitor commands
  block: Move node without parents to main AioContext
  test-block-iothread: BlockBackend AioContext across root node change
  test-block-iothread: Test adding parent to iothread node
  block: Adjust AioContexts when attaching nodes
  scsi-disk: Use qdev_prop_drive_iothread
  block: Add qdev_prop_drive_iothread property type
  block: Add BlockBackend.ctx
  block: Add Error to blk_set_aio_context()
  nbd-server: Call blk_set_allow_aio_context_change()
  test-block-iothread: Check filter node in test_propagate_mirror
  ...

Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parents e2a58ff4 11ba81c3
Loading
Loading
Loading
Loading
+57 −22
Original line number Diff line number Diff line
@@ -2235,6 +2235,10 @@ static void bdrv_replace_child(BdrvChild *child, BlockDriverState *new_bs)
        bdrv_get_cumulative_perm(old_bs, &perm, &shared_perm);
        bdrv_check_perm(old_bs, NULL, perm, shared_perm, NULL, &error_abort);
        bdrv_set_perm(old_bs, perm, shared_perm);

        /* When the parent requiring a non-default AioContext is removed, the
         * node moves back to the main AioContext */
        bdrv_try_set_aio_context(old_bs, qemu_get_aio_context(), NULL);
    }

    if (new_bs) {
@@ -2249,14 +2253,19 @@ static void bdrv_replace_child(BdrvChild *child, BlockDriverState *new_bs)
 *
 * On failure NULL is returned, errp is set and the reference to
 * child_bs is also dropped.
 *
 * The caller must hold the AioContext lock @child_bs, but not that of @ctx
 * (unless @child_bs is already in @ctx).
 */
BdrvChild *bdrv_root_attach_child(BlockDriverState *child_bs,
                                  const char *child_name,
                                  const BdrvChildRole *child_role,
                                  AioContext *ctx,
                                  uint64_t perm, uint64_t shared_perm,
                                  void *opaque, Error **errp)
{
    BdrvChild *child;
    Error *local_err = NULL;
    int ret;

    ret = bdrv_check_update_perm(child_bs, NULL, perm, shared_perm, NULL, errp);
@@ -2276,6 +2285,31 @@ BdrvChild *bdrv_root_attach_child(BlockDriverState *child_bs,
        .opaque         = opaque,
    };

    /* If the AioContexts don't match, first try to move the subtree of
     * child_bs into the AioContext of the new parent. If this doesn't work,
     * try moving the parent into the AioContext of child_bs instead. */
    if (bdrv_get_aio_context(child_bs) != ctx) {
        ret = bdrv_try_set_aio_context(child_bs, ctx, &local_err);
        if (ret < 0 && child_role->can_set_aio_ctx) {
            GSList *ignore = g_slist_prepend(NULL, child);;
            ctx = bdrv_get_aio_context(child_bs);
            if (child_role->can_set_aio_ctx(child, ctx, &ignore, NULL)) {
                error_free(local_err);
                ret = 0;
                g_slist_free(ignore);
                ignore = g_slist_prepend(NULL, child);;
                child_role->set_aio_ctx(child, ctx, &ignore);
            }
            g_slist_free(ignore);
        }
        if (ret < 0) {
            error_propagate(errp, local_err);
            g_free(child);
            bdrv_abort_perm_update(child_bs);
            return NULL;
        }
    }

    /* This performs the matching bdrv_set_perm() for the above check. */
    bdrv_replace_child(child, child_bs);

@@ -2289,6 +2323,9 @@ BdrvChild *bdrv_root_attach_child(BlockDriverState *child_bs,
 *
 * On failure NULL is returned, errp is set and the reference to
 * child_bs is also dropped.
 *
 * If @parent_bs and @child_bs are in different AioContexts, the caller must
 * hold the AioContext lock for @child_bs, but not for @parent_bs.
 */
BdrvChild *bdrv_attach_child(BlockDriverState *parent_bs,
                             BlockDriverState *child_bs,
@@ -2302,11 +2339,11 @@ BdrvChild *bdrv_attach_child(BlockDriverState *parent_bs,
    bdrv_get_cumulative_perm(parent_bs, &perm, &shared_perm);

    assert(parent_bs->drv);
    assert(bdrv_get_aio_context(parent_bs) == bdrv_get_aio_context(child_bs));
    bdrv_child_perm(parent_bs, child_bs, NULL, child_role, NULL,
                    perm, shared_perm, &perm, &shared_perm);

    child = bdrv_root_attach_child(child_bs, child_name, child_role,
                                   bdrv_get_aio_context(parent_bs),
                                   perm, shared_perm, parent_bs, errp);
    if (child == NULL) {
        return NULL;
@@ -2517,7 +2554,6 @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *parent_options,
        ret = -EINVAL;
        goto free_exit;
    }
    bdrv_set_aio_context(backing_hd, bdrv_get_aio_context(bs));

    if (implicit_backing) {
        bdrv_refresh_filename(backing_hd);
@@ -2884,7 +2920,7 @@ static BlockDriverState *bdrv_open_inherit(const char *filename,
            /* Not requesting BLK_PERM_CONSISTENT_READ because we're only
             * looking at the header to guess the image format. This works even
             * in cases where a guest would not see a consistent state. */
            file = blk_new(0, BLK_PERM_ALL);
            file = blk_new(bdrv_get_aio_context(file_bs), 0, BLK_PERM_ALL);
            blk_insert_bs(file, file_bs, &local_err);
            bdrv_unref(file_bs);
            if (local_err) {
@@ -4017,13 +4053,13 @@ void bdrv_replace_node(BlockDriverState *from, BlockDriverState *to,
    uint64_t perm = 0, shared = BLK_PERM_ALL;
    int ret;

    assert(!atomic_read(&from->in_flight));
    assert(!atomic_read(&to->in_flight));

    /* Make sure that @from doesn't go away until we have successfully attached
     * all of its parents to @to. */
    bdrv_ref(from);

    assert(qemu_get_current_aio_context() == qemu_get_aio_context());
    bdrv_drained_begin(from);

    /* Put all parents into @list and calculate their cumulative permissions */
    QLIST_FOREACH_SAFE(c, &from->parents, next_parent, next) {
        assert(c->bs == from);
@@ -4064,6 +4100,7 @@ void bdrv_replace_node(BlockDriverState *from, BlockDriverState *to,

out:
    g_slist_free(list);
    bdrv_drained_end(from);
    bdrv_unref(from);
}

@@ -5752,8 +5789,17 @@ static void bdrv_attach_aio_context(BlockDriverState *bs,
    bs->walking_aio_notifiers = false;
}

/* @ignore will accumulate all visited BdrvChild object. The caller is
 * responsible for freeing the list afterwards. */
/*
 * Changes the AioContext used for fd handlers, timers, and BHs by this
 * BlockDriverState and all its children and parents.
 *
 * The caller must own the AioContext lock for the old AioContext of bs, but it
 * must not own the AioContext lock for new_context (unless new_context is the
 * same as the current context of bs).
 *
 * @ignore will accumulate all visited BdrvChild object. The caller is
 * responsible for freeing the list afterwards.
 */
void bdrv_set_aio_context_ignore(BlockDriverState *bs,
                                 AioContext *new_context, GSList **ignore)
{
@@ -5776,11 +5822,10 @@ void bdrv_set_aio_context_ignore(BlockDriverState *bs,
        if (g_slist_find(*ignore, child)) {
            continue;
        }
        if (child->role->set_aio_ctx) {
        assert(child->role->set_aio_ctx);
        *ignore = g_slist_prepend(*ignore, child);
        child->role->set_aio_ctx(child, new_context, ignore);
    }
    }

    bdrv_detach_aio_context(bs);

@@ -5793,16 +5838,6 @@ void bdrv_set_aio_context_ignore(BlockDriverState *bs,
    aio_context_release(new_context);
}

/* The caller must own the AioContext lock for the old AioContext of bs, but it
 * must not own the AioContext lock for new_context (unless new_context is
 * the same as the current context of bs). */
void bdrv_set_aio_context(BlockDriverState *bs, AioContext *new_context)
{
    GSList *ignore_list = NULL;
    bdrv_set_aio_context_ignore(bs, new_context, &ignore_list);
    g_slist_free(ignore_list);
}

static bool bdrv_parent_can_set_aio_context(BdrvChild *c, AioContext *ctx,
                                            GSList **ignore, Error **errp)
{
+2 −1
Original line number Diff line number Diff line
@@ -627,7 +627,8 @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
    }

    /* The target must match the source in size, so no resize here either */
    job->target = blk_new(BLK_PERM_WRITE,
    job->target = blk_new(job->common.job.aio_context,
                          BLK_PERM_WRITE,
                          BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE |
                          BLK_PERM_WRITE_UNCHANGED | BLK_PERM_GRAPH_MOD);
    ret = blk_insert_bs(job->target, target, errp);
+32 −15
Original line number Diff line number Diff line
@@ -42,6 +42,7 @@ struct BlockBackend {
    char *name;
    int refcnt;
    BdrvChild *root;
    AioContext *ctx;
    DriveInfo *legacy_dinfo;    /* null unless created by drive_new() */
    QTAILQ_ENTRY(BlockBackend) link;         /* for block_backends */
    QTAILQ_ENTRY(BlockBackend) monitor_link; /* for monitor_block_backends */
@@ -322,12 +323,13 @@ static const BdrvChildRole child_root = {
 *
 * Return the new BlockBackend on success, null on failure.
 */
BlockBackend *blk_new(uint64_t perm, uint64_t shared_perm)
BlockBackend *blk_new(AioContext *ctx, uint64_t perm, uint64_t shared_perm)
{
    BlockBackend *blk;

    blk = g_new0(BlockBackend, 1);
    blk->refcnt = 1;
    blk->ctx = ctx;
    blk->perm = perm;
    blk->shared_perm = shared_perm;
    blk_set_enable_write_cache(blk, true);
@@ -347,6 +349,7 @@ BlockBackend *blk_new(uint64_t perm, uint64_t shared_perm)

/*
 * Creates a new BlockBackend, opens a new BlockDriverState, and connects both.
 * The new BlockBackend is in the main AioContext.
 *
 * Just as with bdrv_open(), after having called this function the reference to
 * @options belongs to the block layer (even on failure).
@@ -382,14 +385,14 @@ BlockBackend *blk_new_open(const char *filename, const char *reference,
        perm |= BLK_PERM_RESIZE;
    }

    blk = blk_new(perm, BLK_PERM_ALL);
    blk = blk_new(qemu_get_aio_context(), perm, BLK_PERM_ALL);
    bs = bdrv_open(filename, reference, options, flags, errp);
    if (!bs) {
        blk_unref(blk);
        return NULL;
    }

    blk->root = bdrv_root_attach_child(bs, "root", &child_root,
    blk->root = bdrv_root_attach_child(bs, "root", &child_root, blk->ctx,
                                       perm, BLK_PERM_ALL, blk, errp);
    if (!blk->root) {
        blk_unref(blk);
@@ -800,7 +803,7 @@ int blk_insert_bs(BlockBackend *blk, BlockDriverState *bs, Error **errp)
{
    ThrottleGroupMember *tgm = &blk->public.throttle_group_member;
    bdrv_ref(bs);
    blk->root = bdrv_root_attach_child(bs, "root", &child_root,
    blk->root = bdrv_root_attach_child(bs, "root", &child_root, blk->ctx,
                                       blk->perm, blk->shared_perm, blk, errp);
    if (blk->root == NULL) {
        return -EPERM;
@@ -1856,7 +1859,14 @@ void blk_op_unblock_all(BlockBackend *blk, Error *reason)

AioContext *blk_get_aio_context(BlockBackend *blk)
{
    return bdrv_get_aio_context(blk_bs(blk));
    BlockDriverState *bs = blk_bs(blk);

    if (bs) {
        AioContext *ctx = bdrv_get_aio_context(blk_bs(blk));
        assert(ctx == blk->ctx);
    }

    return blk->ctx;
}

static AioContext *blk_aiocb_get_aio_context(BlockAIOCB *acb)
@@ -1865,30 +1875,37 @@ static AioContext *blk_aiocb_get_aio_context(BlockAIOCB *acb)
    return blk_get_aio_context(blk_acb->blk);
}

static void blk_do_set_aio_context(BlockBackend *blk, AioContext *new_context,
                                   bool update_root_node)
static int blk_do_set_aio_context(BlockBackend *blk, AioContext *new_context,
                                  bool update_root_node, Error **errp)
{
    BlockDriverState *bs = blk_bs(blk);
    ThrottleGroupMember *tgm = &blk->public.throttle_group_member;
    int ret;

    if (bs) {
        if (update_root_node) {
            ret = bdrv_child_try_set_aio_context(bs, new_context, blk->root,
                                                 errp);
            if (ret < 0) {
                return ret;
            }
        }
        if (tgm->throttle_state) {
            bdrv_drained_begin(bs);
            throttle_group_detach_aio_context(tgm);
            throttle_group_attach_aio_context(tgm, new_context);
            bdrv_drained_end(bs);
        }
        if (update_root_node) {
            GSList *ignore = g_slist_prepend(NULL, blk->root);
            bdrv_set_aio_context_ignore(bs, new_context, &ignore);
            g_slist_free(ignore);
        }
    }

    blk->ctx = new_context;
    return 0;
}

void blk_set_aio_context(BlockBackend *blk, AioContext *new_context)
int blk_set_aio_context(BlockBackend *blk, AioContext *new_context,
                        Error **errp)
{
    blk_do_set_aio_context(blk, new_context, true);
    return blk_do_set_aio_context(blk, new_context, true, errp);
}

static bool blk_root_can_set_aio_ctx(BdrvChild *child, AioContext *ctx,
@@ -1915,7 +1932,7 @@ static void blk_root_set_aio_ctx(BdrvChild *child, AioContext *ctx,
                                 GSList **ignore)
{
    BlockBackend *blk = child->opaque;
    blk_do_set_aio_context(blk, ctx, false);
    blk_do_set_aio_context(blk, ctx, false, &error_abort);
}

void blk_add_aio_context_notifier(BlockBackend *blk,
+7 −6
Original line number Diff line number Diff line
@@ -301,7 +301,6 @@ void commit_start(const char *job_id, BlockDriverState *bs,
        commit_top_bs->implicit = true;
    }
    commit_top_bs->total_sectors = top->total_sectors;
    bdrv_set_aio_context(commit_top_bs, bdrv_get_aio_context(top));

    bdrv_append(commit_top_bs, top, &local_err);
    if (local_err) {
@@ -338,7 +337,8 @@ void commit_start(const char *job_id, BlockDriverState *bs,
        goto fail;
    }

    s->base = blk_new(BLK_PERM_CONSISTENT_READ
    s->base = blk_new(s->common.job.aio_context,
                      BLK_PERM_CONSISTENT_READ
                      | BLK_PERM_WRITE
                      | BLK_PERM_RESIZE,
                      BLK_PERM_CONSISTENT_READ
@@ -351,7 +351,7 @@ void commit_start(const char *job_id, BlockDriverState *bs,
    s->base_bs = base;

    /* Required permissions are already taken with block_job_add_bdrv() */
    s->top = blk_new(0, BLK_PERM_ALL);
    s->top = blk_new(s->common.job.aio_context, 0, BLK_PERM_ALL);
    ret = blk_insert_bs(s->top, top, errp);
    if (ret < 0) {
        goto fail;
@@ -395,6 +395,7 @@ int bdrv_commit(BlockDriverState *bs)
    BlockDriverState *backing_file_bs = NULL;
    BlockDriverState *commit_top_bs = NULL;
    BlockDriver *drv = bs->drv;
    AioContext *ctx;
    int64_t offset, length, backing_length;
    int ro;
    int64_t n;
@@ -422,8 +423,9 @@ int bdrv_commit(BlockDriverState *bs)
        }
    }

    src = blk_new(BLK_PERM_CONSISTENT_READ, BLK_PERM_ALL);
    backing = blk_new(BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL);
    ctx = bdrv_get_aio_context(bs);
    src = blk_new(ctx, BLK_PERM_CONSISTENT_READ, BLK_PERM_ALL);
    backing = blk_new(ctx, BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL);

    ret = blk_insert_bs(src, bs, &local_err);
    if (ret < 0) {
@@ -440,7 +442,6 @@ int bdrv_commit(BlockDriverState *bs)
        error_report_err(local_err);
        goto ro_cleanup;
    }
    bdrv_set_aio_context(commit_top_bs, bdrv_get_aio_context(backing_file_bs));

    bdrv_set_backing_hd(commit_top_bs, backing_file_bs, &error_abort);
    bdrv_set_backing_hd(bs, commit_top_bs, &error_abort);
+2 −1
Original line number Diff line number Diff line
@@ -257,7 +257,8 @@ static int block_crypto_co_create_generic(BlockDriverState *bs,
    QCryptoBlock *crypto = NULL;
    struct BlockCryptoCreateData data;

    blk = blk_new(BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL);
    blk = blk_new(bdrv_get_aio_context(bs),
                  BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL);

    ret = blk_insert_bs(blk, bs, errp);
    if (ret < 0) {
Loading