Commit 5daf9b30 authored by Peter Maydell's avatar Peter Maydell
Browse files

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



Block layer fixes for 2.9.0-rc4

# gpg: Signature made Fri 07 Apr 2017 13:44:17 BST
# gpg:                using RSA key 0x7F09B272C88F2FD6
# gpg: Good signature from "Kevin Wolf <kwolf@redhat.com>"
# Primary key fingerprint: DC3D EB15 9A9A F95D 3D74  56FE 7F09 B272 C88F 2FD6

* remotes/kevin/tags/for-upstream:
  mirror: Fix aio context of mirror_top_bs
  block: Assert attached child node has right aio context
  block: Fix unpaired aio_disable_external in external snapshot
  block: Don't check permissions for copy on read
  qemu-img: img_create does not support image-opts, fix docs
  iotests: Add mirror tests for orphaned source
  block/mirror: Fix use-after-free
  commit: Set commit_top_bs->total_sectors
  commit: Set commit_top_bs->aio_context
  block: Ignore guest dev permissions during incoming migration

Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parents 5fe2339e 19dd29e8
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -1752,6 +1752,9 @@ static void bdrv_replace_child_noperm(BdrvChild *child,
{
    BlockDriverState *old_bs = child->bs;

    if (old_bs && new_bs) {
        assert(bdrv_get_aio_context(old_bs) == bdrv_get_aio_context(new_bs));
    }
    if (old_bs) {
        if (old_bs->quiesce_counter && child->role->drained_end) {
            child->role->drained_end(child);
@@ -1852,6 +1855,7 @@ 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));
    parent_bs->drv->bdrv_child_perm(parent_bs, NULL, child_role,
                                    perm, shared_perm, &perm, &shared_perm);

+39 −1
Original line number Diff line number Diff line
@@ -61,6 +61,7 @@ struct BlockBackend {

    uint64_t perm;
    uint64_t shared_perm;
    bool disable_perm;

    bool allow_write_beyond_eof;

@@ -578,7 +579,7 @@ int blk_set_perm(BlockBackend *blk, uint64_t perm, uint64_t shared_perm,
{
    int ret;

    if (blk->root) {
    if (blk->root && !blk->disable_perm) {
        ret = bdrv_child_try_set_perm(blk->root, perm, shared_perm, errp);
        if (ret < 0) {
            return ret;
@@ -597,15 +598,52 @@ void blk_get_perm(BlockBackend *blk, uint64_t *perm, uint64_t *shared_perm)
    *shared_perm = blk->shared_perm;
}

/*
 * Notifies the user of all BlockBackends that migration has completed. qdev
 * devices can tighten their permissions in response (specifically revoke
 * shared write permissions that we needed for storage migration).
 *
 * If an error is returned, the VM cannot be allowed to be resumed.
 */
void blk_resume_after_migration(Error **errp)
{
    BlockBackend *blk;
    Error *local_err = NULL;

    for (blk = blk_all_next(NULL); blk; blk = blk_all_next(blk)) {
        if (!blk->disable_perm) {
            continue;
        }

        blk->disable_perm = false;

        blk_set_perm(blk, blk->perm, blk->shared_perm, &local_err);
        if (local_err) {
            error_propagate(errp, local_err);
            blk->disable_perm = true;
            return;
        }
    }
}

static int blk_do_attach_dev(BlockBackend *blk, void *dev)
{
    if (blk->dev) {
        return -EBUSY;
    }

    /* While migration is still incoming, we don't need to apply the
     * permissions of guest device BlockBackends. We might still have a block
     * job or NBD server writing to the image for storage migration. */
    if (runstate_check(RUN_STATE_INMIGRATE)) {
        blk->disable_perm = true;
    }

    blk_ref(blk);
    blk->dev = dev;
    blk->legacy_dev = false;
    blk_iostatus_reset(blk);

    return 0;
}

+3 −0
Original line number Diff line number Diff line
@@ -335,6 +335,8 @@ void commit_start(const char *job_id, BlockDriverState *bs,
    if (commit_top_bs == NULL) {
        goto fail;
    }
    commit_top_bs->total_sectors = top->total_sectors;
    bdrv_set_aio_context(commit_top_bs, bdrv_get_aio_context(top));

    bdrv_set_backing_hd(commit_top_bs, top, &local_err);
    if (local_err) {
@@ -482,6 +484,7 @@ 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);
+8 −1
Original line number Diff line number Diff line
@@ -945,7 +945,14 @@ static int coroutine_fn bdrv_co_do_copy_on_readv(BdrvChild *child,
    size_t skip_bytes;
    int ret;

    assert(child->perm & (BLK_PERM_WRITE_UNCHANGED | BLK_PERM_WRITE));
    /* FIXME We cannot require callers to have write permissions when all they
     * are doing is a read request. If we did things right, write permissions
     * would be obtained anyway, but internally by the copy-on-read code. As
     * long as it is implemented here rather than in a separat filter driver,
     * the copy-on-read code doesn't have its own BdrvChild, however, for which
     * it could request permissions. Therefore we have to bypass the permission
     * system for the moment. */
    // assert(child->perm & (BLK_PERM_WRITE_UNCHANGED | BLK_PERM_WRITE));

    /* Cover entire cluster so no additional backing file I/O is required when
     * allocating cluster in the image file.
+11 −2
Original line number Diff line number Diff line
@@ -1148,9 +1148,10 @@ static void mirror_start_job(const char *job_id, BlockDriverState *bs,
        return;
    }
    mirror_top_bs->total_sectors = bs->total_sectors;
    bdrv_set_aio_context(mirror_top_bs, bdrv_get_aio_context(bs));

    /* bdrv_append takes ownership of the mirror_top_bs reference, need to keep
     * it alive until block_job_create() even if bs has no parent. */
     * it alive until block_job_create() succeeds even if bs has no parent. */
    bdrv_ref(mirror_top_bs);
    bdrv_drained_begin(bs);
    bdrv_append(mirror_top_bs, bs, &local_err);
@@ -1168,10 +1169,12 @@ static void mirror_start_job(const char *job_id, BlockDriverState *bs,
                         BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE_UNCHANGED |
                         BLK_PERM_WRITE | BLK_PERM_GRAPH_MOD, speed,
                         creation_flags, cb, opaque, errp);
    bdrv_unref(mirror_top_bs);
    if (!s) {
        goto fail;
    }
    /* The block job now has a reference to this node */
    bdrv_unref(mirror_top_bs);

    s->source = bs;
    s->mirror_top_bs = mirror_top_bs;

@@ -1242,6 +1245,10 @@ static void mirror_start_job(const char *job_id, BlockDriverState *bs,

fail:
    if (s) {
        /* Make sure this BDS does not go away until we have completed the graph
         * changes below */
        bdrv_ref(mirror_top_bs);

        g_free(s->replaces);
        blk_unref(s->target);
        block_job_unref(&s->common);
@@ -1250,6 +1257,8 @@ fail:
    bdrv_child_try_set_perm(mirror_top_bs->backing, 0, BLK_PERM_ALL,
                            &error_abort);
    bdrv_replace_node(mirror_top_bs, backing_bs(mirror_top_bs), &error_abort);

    bdrv_unref(mirror_top_bs);
}

void mirror_start(const char *job_id, BlockDriverState *bs,
Loading