Commit 76fba746 authored by Peter Maydell's avatar Peter Maydell
Browse files

Merge remote-tracking branch 'remotes/maxreitz/tags/pull-block-2017-07-11' into staging



Block layer patches

# gpg: Signature made Tue 11 Jul 2017 17:05:56 BST
# gpg:                using RSA key 0xF407DB0061D5CF40
# gpg: Good signature from "Max Reitz <mreitz@redhat.com>"
# Primary key fingerprint: 91BE B60A 30DB 3E88 57D1  1829 F407 DB00 61D5 CF40

* remotes/maxreitz/tags/pull-block-2017-07-11: (85 commits)
  iotests: Add preallocated growth test for qcow2
  iotests: Add preallocated resize test for raw
  block/qcow2: falloc/full preallocating growth
  block/qcow2: Rename "fail_block" to just "fail"
  block/qcow2: Add qcow2_refcount_area()
  block/qcow2: Metadata preallocation for truncate
  block/qcow2: Lock s->lock in preallocate()
  block/qcow2: Generalize preallocate()
  block/file-posix: Preallocation for truncate
  block/file-posix: Generalize raw_regular_truncate
  block/file-posix: Extract raw_regular_truncate()
  block/file-posix: Small fixes in raw_create()
  qemu-img: Expose PreallocMode for resizing
  block: Add PreallocMode to blk_truncate()
  block: Add PreallocMode to bdrv_truncate()
  block: Add PreallocMode to BD.bdrv_truncate()
  iotests: add test 178 for qemu-img measure
  qemu-iotests: support per-format golden output files
  qemu-img: add measure subcommand
  qcow2: add bdrv_measure() support
  ...

Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parents f0d2ead9 ced14843
Loading
Loading
Loading
Loading
+96 −87
Original line number Diff line number Diff line
@@ -2185,6 +2185,7 @@ 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));

    /* Hook up the backing file link; drop our reference, bs owns the
     * backing_hd reference now */
@@ -2573,15 +2574,7 @@ static BlockDriverState *bdrv_open_inherit(const char *filename,
        goto close_and_fail;
    }

    if (!bdrv_key_required(bs)) {
    bdrv_parent_cb_change_media(bs, true);
    } else if (!runstate_check(RUN_STATE_PRELAUNCH)
               && !runstate_check(RUN_STATE_INMIGRATE)
               && !runstate_check(RUN_STATE_PAUSED)) { /* HACK */
        error_setg(errp,
                   "Guest must be stopped for opening of encrypted image");
        goto close_and_fail;
    }

    QDECREF(options);

@@ -2989,24 +2982,45 @@ error:
void bdrv_reopen_commit(BDRVReopenState *reopen_state)
{
    BlockDriver *drv;
    BlockDriverState *bs;
    bool old_can_write, new_can_write;

    assert(reopen_state != NULL);
    drv = reopen_state->bs->drv;
    bs = reopen_state->bs;
    drv = bs->drv;
    assert(drv != NULL);

    old_can_write =
        !bdrv_is_read_only(bs) && !(bdrv_get_flags(bs) & BDRV_O_INACTIVE);

    /* If there are any driver level actions to take */
    if (drv->bdrv_reopen_commit) {
        drv->bdrv_reopen_commit(reopen_state);
    }

    /* set BDS specific flags now */
    QDECREF(reopen_state->bs->explicit_options);
    QDECREF(bs->explicit_options);

    reopen_state->bs->explicit_options   = reopen_state->explicit_options;
    reopen_state->bs->open_flags         = reopen_state->flags;
    reopen_state->bs->read_only = !(reopen_state->flags & BDRV_O_RDWR);
    bs->explicit_options   = reopen_state->explicit_options;
    bs->open_flags         = reopen_state->flags;
    bs->read_only = !(reopen_state->flags & BDRV_O_RDWR);

    bdrv_refresh_limits(reopen_state->bs, NULL);
    bdrv_refresh_limits(bs, NULL);

    new_can_write =
        !bdrv_is_read_only(bs) && !(bdrv_get_flags(bs) & BDRV_O_INACTIVE);
    if (!old_can_write && new_can_write && drv->bdrv_reopen_bitmaps_rw) {
        Error *local_err = NULL;
        if (drv->bdrv_reopen_bitmaps_rw(bs, &local_err) < 0) {
            /* This is not fatal, bitmaps just left read-only, so all following
             * writes will fail. User can remove read-only bitmaps to unblock
             * writes.
             */
            error_reportf_err(local_err,
                              "%s: Failed to make dirty bitmaps writable: ",
                              bdrv_get_node_name(bs));
        }
    }
}

/*
@@ -3040,9 +3054,6 @@ static void bdrv_close(BlockDriverState *bs)
    bdrv_flush(bs);
    bdrv_drain(bs); /* in case flush left pending I/O */

    bdrv_release_named_dirty_bitmaps(bs);
    assert(QLIST_EMPTY(&bs->dirty_bitmaps));

    if (bs->drv) {
        BdrvChild *child, *next;

@@ -3072,7 +3083,6 @@ static void bdrv_close(BlockDriverState *bs)
        bs->backing_format[0] = '\0';
        bs->total_sectors = 0;
        bs->encrypted = false;
        bs->valid_key = false;
        bs->sg = false;
        QDECREF(bs->options);
        QDECREF(bs->explicit_options);
@@ -3081,6 +3091,9 @@ static void bdrv_close(BlockDriverState *bs)
        bs->full_open_options = NULL;
    }

    bdrv_release_named_dirty_bitmaps(bs);
    assert(QLIST_EMPTY(&bs->dirty_bitmaps));

    QLIST_FOREACH_SAFE(ban, &bs->aio_notifiers, list, ban_next) {
        g_free(ban);
    }
@@ -3398,7 +3411,8 @@ exit:
/**
 * Truncate file to 'offset' bytes (needed only for file protocols)
 */
int bdrv_truncate(BdrvChild *child, int64_t offset, Error **errp)
int bdrv_truncate(BdrvChild *child, int64_t offset, PreallocMode prealloc,
                  Error **errp)
{
    BlockDriverState *bs = child->bs;
    BlockDriver *drv = bs->drv;
@@ -3421,7 +3435,7 @@ int bdrv_truncate(BdrvChild *child, int64_t offset, Error **errp)

    assert(!(bs->open_flags & BDRV_O_INACTIVE));

    ret = drv->bdrv_truncate(bs, offset, errp);
    ret = drv->bdrv_truncate(bs, offset, prealloc, errp);
    if (ret == 0) {
        ret = refresh_total_sectors(bs, offset >> BDRV_SECTOR_BITS);
        bdrv_dirty_bitmap_truncate(bs);
@@ -3450,6 +3464,41 @@ int64_t bdrv_get_allocated_file_size(BlockDriverState *bs)
    return -ENOTSUP;
}

/*
 * bdrv_measure:
 * @drv: Format driver
 * @opts: Creation options for new image
 * @in_bs: Existing image containing data for new image (may be NULL)
 * @errp: Error object
 * Returns: A #BlockMeasureInfo (free using qapi_free_BlockMeasureInfo())
 *          or NULL on error
 *
 * Calculate file size required to create a new image.
 *
 * If @in_bs is given then space for allocated clusters and zero clusters
 * from that image are included in the calculation.  If @opts contains a
 * backing file that is shared by @in_bs then backing clusters may be omitted
 * from the calculation.
 *
 * If @in_bs is NULL then the calculation includes no allocated clusters
 * unless a preallocation option is given in @opts.
 *
 * Note that @in_bs may use a different BlockDriver from @drv.
 *
 * If an error occurs the @errp pointer is set.
 */
BlockMeasureInfo *bdrv_measure(BlockDriver *drv, QemuOpts *opts,
                               BlockDriverState *in_bs, Error **errp)
{
    if (!drv->bdrv_measure) {
        error_setg(errp, "Block driver '%s' does not support size measurement",
                   drv->format_name);
        return NULL;
    }

    return drv->bdrv_measure(opts, in_bs, errp);
}

/**
 * Return number of sectors on success, -errno on error.
 */
@@ -3502,72 +3551,6 @@ bool bdrv_is_encrypted(BlockDriverState *bs)
    return bs->encrypted;
}

bool bdrv_key_required(BlockDriverState *bs)
{
    BdrvChild *backing = bs->backing;

    if (backing && backing->bs->encrypted && !backing->bs->valid_key) {
        return true;
    }
    return (bs->encrypted && !bs->valid_key);
}

int bdrv_set_key(BlockDriverState *bs, const char *key)
{
    int ret;
    if (bs->backing && bs->backing->bs->encrypted) {
        ret = bdrv_set_key(bs->backing->bs, key);
        if (ret < 0)
            return ret;
        if (!bs->encrypted)
            return 0;
    }
    if (!bs->encrypted) {
        return -EINVAL;
    } else if (!bs->drv || !bs->drv->bdrv_set_key) {
        return -ENOMEDIUM;
    }
    ret = bs->drv->bdrv_set_key(bs, key);
    if (ret < 0) {
        bs->valid_key = false;
    } else if (!bs->valid_key) {
        /* call the change callback now, we skipped it on open */
        bs->valid_key = true;
        bdrv_parent_cb_change_media(bs, true);
    }
    return ret;
}

/*
 * Provide an encryption key for @bs.
 * If @key is non-null:
 *     If @bs is not encrypted, fail.
 *     Else if the key is invalid, fail.
 *     Else set @bs's key to @key, replacing the existing key, if any.
 * If @key is null:
 *     If @bs is encrypted and still lacks a key, fail.
 *     Else do nothing.
 * On failure, store an error object through @errp if non-null.
 */
void bdrv_add_key(BlockDriverState *bs, const char *key, Error **errp)
{
    if (key) {
        if (!bdrv_is_encrypted(bs)) {
            error_setg(errp, "Node '%s' is not encrypted",
                      bdrv_get_device_or_node_name(bs));
        } else if (bdrv_set_key(bs, key) < 0) {
            error_setg(errp, QERR_INVALID_PASSWORD);
        }
    } else {
        if (bdrv_key_required(bs)) {
            error_set(errp, ERROR_CLASS_DEVICE_ENCRYPTED,
                      "'%s' (%s) is encrypted",
                      bdrv_get_device_or_node_name(bs),
                      bdrv_get_encrypted_filename(bs));
        }
    }
}

const char *bdrv_get_format_name(BlockDriverState *bs)
{
    return bs->drv ? bs->drv->format_name : NULL;
@@ -4135,6 +4118,10 @@ static int bdrv_inactivate_recurse(BlockDriverState *bs,
        }
    }

    /* At this point persistent bitmaps should be already stored by the format
     * driver */
    bdrv_release_persistent_dirty_bitmaps(bs);

    return 0;
}

@@ -4933,3 +4920,25 @@ void bdrv_del_child(BlockDriverState *parent_bs, BdrvChild *child, Error **errp)

    parent_bs->drv->bdrv_del_child(parent_bs, child, errp);
}

bool bdrv_can_store_new_dirty_bitmap(BlockDriverState *bs, const char *name,
                                     uint32_t granularity, Error **errp)
{
    BlockDriver *drv = bs->drv;

    if (!drv) {
        error_setg_errno(errp, ENOMEDIUM,
                         "Can't store persistent bitmaps to %s",
                         bdrv_get_device_or_node_name(bs));
        return false;
    }

    if (!drv->bdrv_can_store_new_dirty_bitmap) {
        error_setg_errno(errp, ENOTSUP,
                         "Can't store persistent bitmaps to %s",
                         bdrv_get_device_or_node_name(bs));
        return false;
    }

    return drv->bdrv_can_store_new_dirty_bitmap(bs, name, granularity, errp);
}
+1 −1
Original line number Diff line number Diff line
block-obj-y += raw-format.o qcow.o vdi.o vmdk.o cloop.o bochs.o vpc.o vvfat.o dmg.o
block-obj-y += qcow2.o qcow2-refcount.o qcow2-cluster.o qcow2-snapshot.o qcow2-cache.o
block-obj-y += qcow2.o qcow2-refcount.o qcow2-cluster.o qcow2-snapshot.o qcow2-cache.o qcow2-bitmap.o
block-obj-y += qed.o qed-l2-cache.o qed-table.o qed-cluster.o
block-obj-y += qed-check.o
block-obj-y += vhdx.o vhdx-endian.o vhdx-log.o
+3 −2
Original line number Diff line number Diff line
@@ -821,9 +821,10 @@ static int64_t blkdebug_getlength(BlockDriverState *bs)
    return bdrv_getlength(bs->file->bs);
}

static int blkdebug_truncate(BlockDriverState *bs, int64_t offset, Error **errp)
static int blkdebug_truncate(BlockDriverState *bs, int64_t offset,
                             PreallocMode prealloc, Error **errp)
{
    return bdrv_truncate(bs->file, offset, errp);
    return bdrv_truncate(bs->file, offset, prealloc, errp);
}

static void blkdebug_refresh_filename(BlockDriverState *bs, QDict *options)
+3 −2
Original line number Diff line number Diff line
@@ -1773,14 +1773,15 @@ int blk_pwrite_compressed(BlockBackend *blk, int64_t offset, const void *buf,
                   BDRV_REQ_WRITE_COMPRESSED);
}

int blk_truncate(BlockBackend *blk, int64_t offset, Error **errp)
int blk_truncate(BlockBackend *blk, int64_t offset, PreallocMode prealloc,
                 Error **errp)
{
    if (!blk_is_available(blk)) {
        error_setg(errp, "No medium inserted");
        return -ENOMEDIUM;
    }

    return bdrv_truncate(blk->root, offset, errp);
    return bdrv_truncate(blk->root, offset, prealloc, errp);
}

static void blk_pdiscard_entry(void *opaque)
+2 −2
Original line number Diff line number Diff line
@@ -163,7 +163,7 @@ static void coroutine_fn commit_run(void *opaque)
    }

    if (base_len < s->common.len) {
        ret = blk_truncate(s->base, s->common.len, NULL);
        ret = blk_truncate(s->base, s->common.len, PREALLOC_MODE_OFF, NULL);
        if (ret) {
            goto out;
        }
@@ -521,7 +521,7 @@ int bdrv_commit(BlockDriverState *bs)
     * grow the backing file image if possible.  If not possible,
     * we must return an error */
    if (length > backing_length) {
        ret = blk_truncate(backing, length, &local_err);
        ret = blk_truncate(backing, length, PREALLOC_MODE_OFF, &local_err);
        if (ret < 0) {
            error_report_err(local_err);
            goto ro_cleanup;
Loading