Commit 58b1f0f2 authored by Peter Maydell's avatar Peter Maydell
Browse files

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



Block layer patches:

- qcow2: Decompression worker threads
- dmg: lzfse compression support
- file-posix: Simplify delegation to worker thread
- Don't pass flags to bdrv_reopen_queue()
- iotests: make 235 work on s390 (and others)

# gpg: Signature made Fri 14 Dec 2018 10:55:09 GMT
# gpg:                using RSA key 7F09B272C88F2FD6
# 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: (42 commits)
  block/mirror: add missing coroutine_fn annotations
  iotests: make 235 work on s390 (and others)
  block: Assert that flags are up-to-date in bdrv_reopen_prepare()
  block: Remove assertions from update_flags_from_options()
  block: Stop passing flags to bdrv_reopen_queue_child()
  block: Remove flags parameter from bdrv_reopen_queue()
  block: Clean up reopen_backing_file() in block/replication.c
  qemu-io: Put flag changes in the options QDict in reopen_f()
  block: Drop bdrv_reopen()
  block: Use bdrv_reopen_set_read_only() in the mirror driver
  block: Use bdrv_reopen_set_read_only() in external_snapshot_commit()
  block: Use bdrv_reopen_set_read_only() in qmp_change_backing_file()
  block: Use bdrv_reopen_set_read_only() in stream_start/complete()
  block: Use bdrv_reopen_set_read_only() in bdrv_commit()
  block: Use bdrv_reopen_set_read_only() in commit_start/complete()
  block: Use bdrv_reopen_set_read_only() in bdrv_backing_update_filename()
  block: Add bdrv_reopen_set_read_only()
  file-posix: Avoid aio_worker() for QEMU_AIO_IOCTL
  file-posix: Switch to .bdrv_co_ioctl
  file-posix: Remove paio_submit_co()
  ...

Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parents 3866e6be 537c3d4f
Loading
Loading
Loading
Loading
+39 −50
Original line number Diff line number Diff line
@@ -1079,11 +1079,11 @@ static int bdrv_backing_update_filename(BdrvChild *c, BlockDriverState *base,
                                        const char *filename, Error **errp)
{
    BlockDriverState *parent = c->opaque;
    int orig_flags = bdrv_get_flags(parent);
    bool read_only = bdrv_is_read_only(parent);
    int ret;

    if (!(orig_flags & BDRV_O_RDWR)) {
        ret = bdrv_reopen(parent, orig_flags | BDRV_O_RDWR, errp);
    if (read_only) {
        ret = bdrv_reopen_set_read_only(parent, false, errp);
        if (ret < 0) {
            return ret;
        }
@@ -1095,8 +1095,8 @@ static int bdrv_backing_update_filename(BdrvChild *c, BlockDriverState *base,
        error_setg_errno(errp, -ret, "Could not update backing file link");
    }

    if (!(orig_flags & BDRV_O_RDWR)) {
        bdrv_reopen(parent, orig_flags, NULL);
    if (read_only) {
        bdrv_reopen_set_read_only(parent, true, NULL);
    }

    return ret;
@@ -1139,22 +1139,18 @@ static void update_flags_from_options(int *flags, QemuOpts *opts)
{
    *flags &= ~(BDRV_O_CACHE_MASK | BDRV_O_RDWR | BDRV_O_AUTO_RDONLY);

    assert(qemu_opt_find(opts, BDRV_OPT_CACHE_NO_FLUSH));
    if (qemu_opt_get_bool_del(opts, BDRV_OPT_CACHE_NO_FLUSH, false)) {
        *flags |= BDRV_O_NO_FLUSH;
    }

    assert(qemu_opt_find(opts, BDRV_OPT_CACHE_DIRECT));
    if (qemu_opt_get_bool_del(opts, BDRV_OPT_CACHE_DIRECT, false)) {
        *flags |= BDRV_O_NOCACHE;
    }

    assert(qemu_opt_find(opts, BDRV_OPT_READ_ONLY));
    if (!qemu_opt_get_bool_del(opts, BDRV_OPT_READ_ONLY, false)) {
        *flags |= BDRV_O_RDWR;
    }

    assert(qemu_opt_find(opts, BDRV_OPT_AUTO_READ_ONLY));
    if (qemu_opt_get_bool_del(opts, BDRV_OPT_AUTO_READ_ONLY, false)) {
        *flags |= BDRV_O_AUTO_RDONLY;
    }
@@ -2931,7 +2927,6 @@ BlockDriverState *bdrv_open(const char *filename, const char *reference,
static BlockReopenQueue *bdrv_reopen_queue_child(BlockReopenQueue *bs_queue,
                                                 BlockDriverState *bs,
                                                 QDict *options,
                                                 int flags,
                                                 const BdrvChildRole *role,
                                                 QDict *parent_options,
                                                 int parent_flags)
@@ -2940,7 +2935,9 @@ static BlockReopenQueue *bdrv_reopen_queue_child(BlockReopenQueue *bs_queue,

    BlockReopenQueueEntry *bs_entry;
    BdrvChild *child;
    QDict *old_options, *explicit_options;
    QDict *old_options, *explicit_options, *options_copy;
    int flags;
    QemuOpts *opts;

    /* Make sure that the caller remembered to use a drained section. This is
     * important to avoid graph changes between the recursive queuing here and
@@ -2966,22 +2963,11 @@ static BlockReopenQueue *bdrv_reopen_queue_child(BlockReopenQueue *bs_queue,
    /*
     * Precedence of options:
     * 1. Explicitly passed in options (highest)
     * 2. Set in flags (only for top level)
     * 3. Retained from explicitly set options of bs
     * 4. Inherited from parent node
     * 5. Retained from effective options of bs
     * 2. Retained from explicitly set options of bs
     * 3. Inherited from parent node
     * 4. Retained from effective options of bs
     */

    if (!parent_options) {
        /*
         * Any setting represented by flags is always updated. If the
         * corresponding QDict option is set, it takes precedence. Otherwise
         * the flag is translated into a QDict option. The old setting of bs is
         * not considered.
         */
        update_options_from_flags(options, flags);
    }

    /* Old explicitly set values (don't overwrite by inherited value) */
    if (bs_entry) {
        old_options = qdict_clone_shallow(bs_entry->state.explicit_options);
@@ -2995,16 +2981,10 @@ static BlockReopenQueue *bdrv_reopen_queue_child(BlockReopenQueue *bs_queue,

    /* Inherit from parent node */
    if (parent_options) {
        QemuOpts *opts;
        QDict *options_copy;
        assert(!flags);
        flags = 0;
        role->inherit_options(&flags, options, parent_flags, parent_options);
        options_copy = qdict_clone_shallow(options);
        opts = qemu_opts_create(&bdrv_runtime_opts, NULL, 0, &error_abort);
        qemu_opts_absorb_qdict(opts, options_copy, NULL);
        update_flags_from_options(&flags, opts);
        qemu_opts_del(opts);
        qobject_unref(options_copy);
    } else {
        flags = bdrv_get_flags(bs);
    }

    /* Old values are used for options that aren't set yet */
@@ -3012,6 +2992,14 @@ static BlockReopenQueue *bdrv_reopen_queue_child(BlockReopenQueue *bs_queue,
    bdrv_join_options(bs, options, old_options);
    qobject_unref(old_options);

    /* We have the final set of options so let's update the flags */
    options_copy = qdict_clone_shallow(options);
    opts = qemu_opts_create(&bdrv_runtime_opts, NULL, 0, &error_abort);
    qemu_opts_absorb_qdict(opts, options_copy, NULL);
    update_flags_from_options(&flags, opts);
    qemu_opts_del(opts);
    qobject_unref(options_copy);

    /* bdrv_open_inherit() sets and clears some additional flags internally */
    flags &= ~BDRV_O_PROTOCOL;
    if (flags & BDRV_O_RDWR) {
@@ -3051,7 +3039,7 @@ static BlockReopenQueue *bdrv_reopen_queue_child(BlockReopenQueue *bs_queue,
        qdict_extract_subqdict(options, &new_child_options, child_key_dot);
        g_free(child_key_dot);

        bdrv_reopen_queue_child(bs_queue, child->bs, new_child_options, 0,
        bdrv_reopen_queue_child(bs_queue, child->bs, new_child_options,
                                child->role, options, flags);
    }

@@ -3060,10 +3048,9 @@ static BlockReopenQueue *bdrv_reopen_queue_child(BlockReopenQueue *bs_queue,

BlockReopenQueue *bdrv_reopen_queue(BlockReopenQueue *bs_queue,
                                    BlockDriverState *bs,
                                    QDict *options, int flags)
                                    QDict *options)
{
    return bdrv_reopen_queue_child(bs_queue, bs, options, flags,
                                   NULL, NULL, 0);
    return bdrv_reopen_queue_child(bs_queue, bs, options, NULL, NULL, 0);
}

/*
@@ -3125,22 +3112,18 @@ cleanup:
    return ret;
}


/* Reopen a single BlockDriverState with the specified flags. */
int bdrv_reopen(BlockDriverState *bs, int bdrv_flags, Error **errp)
int bdrv_reopen_set_read_only(BlockDriverState *bs, bool read_only,
                              Error **errp)
{
    int ret = -1;
    Error *local_err = NULL;
    int ret;
    BlockReopenQueue *queue;
    QDict *opts = qdict_new();

    bdrv_subtree_drained_begin(bs);

    queue = bdrv_reopen_queue(NULL, bs, NULL, bdrv_flags);
    ret = bdrv_reopen_multiple(bdrv_get_aio_context(bs), queue, &local_err);
    if (local_err != NULL) {
        error_propagate(errp, local_err);
    }
    qdict_put_bool(opts, BDRV_OPT_READ_ONLY, read_only);

    bdrv_subtree_drained_begin(bs);
    queue = bdrv_reopen_queue(NULL, bs, opts);
    ret = bdrv_reopen_multiple(bdrv_get_aio_context(bs), queue, errp);
    bdrv_subtree_drained_end(bs);

    return ret;
@@ -3214,6 +3197,7 @@ int bdrv_reopen_prepare(BDRVReopenState *reopen_state, BlockReopenQueue *queue,
                        Error **errp)
{
    int ret = -1;
    int old_flags;
    Error *local_err = NULL;
    BlockDriver *drv;
    QemuOpts *opts;
@@ -3240,7 +3224,12 @@ int bdrv_reopen_prepare(BDRVReopenState *reopen_state, BlockReopenQueue *queue,
        goto error;
    }

    /* This was already called in bdrv_reopen_queue_child() so the flags
     * are up-to-date. This time we simply want to remove the options from
     * QemuOpts in order to indicate that they have been processed. */
    old_flags = reopen_state->flags;
    update_flags_from_options(&reopen_state->flags, opts);
    assert(old_flags == reopen_state->flags);

    discard = qemu_opt_get_del(opts, BDRV_OPT_DISCARD);
    if (discard != NULL) {
+2 −0
Original line number Diff line number Diff line
@@ -57,6 +57,8 @@ ssh.o-libs := $(LIBSSH2_LIBS)
block-obj-dmg-bz2-$(CONFIG_BZIP2) += dmg-bz2.o
block-obj-$(if $(CONFIG_DMG),m,n) += $(block-obj-dmg-bz2-y)
dmg-bz2.o-libs     := $(BZIP2_LIBS)
block-obj-$(if $(CONFIG_LZFSE),m,n) += dmg-lzfse.o
dmg-lzfse.o-libs   := $(LZFSE_LIBS)
qcow.o-libs        := -lz
linux-aio.o-libs   := -laio
parallels.o-cflags := $(LIBXML2_CFLAGS)
+7 −31
Original line number Diff line number Diff line
@@ -28,6 +28,13 @@

#define BACKUP_CLUSTER_SIZE_DEFAULT (1 << 16)

typedef struct CowRequest {
    int64_t start_byte;
    int64_t end_byte;
    QLIST_ENTRY(CowRequest) list;
    CoQueue wait_queue; /* coroutines blocked on this request */
} CowRequest;

typedef struct BackupBlockJob {
    BlockJob common;
    BlockBackend *target;
@@ -322,37 +329,6 @@ void backup_do_checkpoint(BlockJob *job, Error **errp)
    hbitmap_set(backup_job->copy_bitmap, 0, len);
}

void backup_wait_for_overlapping_requests(BlockJob *job, int64_t offset,
                                          uint64_t bytes)
{
    BackupBlockJob *backup_job = container_of(job, BackupBlockJob, common);
    int64_t start, end;

    assert(block_job_driver(job) == &backup_job_driver);

    start = QEMU_ALIGN_DOWN(offset, backup_job->cluster_size);
    end = QEMU_ALIGN_UP(offset + bytes, backup_job->cluster_size);
    wait_for_overlapping_requests(backup_job, start, end);
}

void backup_cow_request_begin(CowRequest *req, BlockJob *job,
                              int64_t offset, uint64_t bytes)
{
    BackupBlockJob *backup_job = container_of(job, BackupBlockJob, common);
    int64_t start, end;

    assert(block_job_driver(job) == &backup_job_driver);

    start = QEMU_ALIGN_DOWN(offset, backup_job->cluster_size);
    end = QEMU_ALIGN_UP(offset + bytes, backup_job->cluster_size);
    cow_request_begin(req, backup_job, start, end);
}

void backup_cow_request_end(CowRequest *req)
{
    cow_request_end(req);
}

static void backup_drain(BlockJob *job)
{
    BackupBlockJob *s = container_of(job, BackupBlockJob, common);
+9 −14
Original line number Diff line number Diff line
@@ -38,7 +38,7 @@ typedef struct CommitBlockJob {
    BlockBackend *base;
    BlockDriverState *base_bs;
    BlockdevOnError on_error;
    int base_flags;
    bool base_read_only;
    char *backing_file_str;
} CommitBlockJob;

@@ -124,8 +124,8 @@ static void commit_clean(Job *job)
    /* restore base open flags here if appropriate (e.g., change the base back
     * to r/o). These reopens do not need to be atomic, since we won't abort
     * even on failure here */
    if (s->base_flags != bdrv_get_flags(s->base_bs)) {
        bdrv_reopen(s->base_bs, s->base_flags, NULL);
    if (s->base_read_only) {
        bdrv_reopen_set_read_only(s->base_bs, true, NULL);
    }

    g_free(s->backing_file_str);
@@ -264,7 +264,6 @@ void commit_start(const char *job_id, BlockDriverState *bs,
                  const char *filter_node_name, Error **errp)
{
    CommitBlockJob *s;
    int orig_base_flags;
    BlockDriverState *iter;
    BlockDriverState *commit_top_bs = NULL;
    Error *local_err = NULL;
@@ -283,11 +282,9 @@ void commit_start(const char *job_id, BlockDriverState *bs,
    }

    /* convert base to r/w, if necessary */
    orig_base_flags = bdrv_get_flags(base);
    if (!(orig_base_flags & BDRV_O_RDWR)) {
        bdrv_reopen(base, orig_base_flags | BDRV_O_RDWR, &local_err);
        if (local_err != NULL) {
            error_propagate(errp, local_err);
    s->base_read_only = bdrv_is_read_only(base);
    if (s->base_read_only) {
        if (bdrv_reopen_set_read_only(base, false, errp) != 0) {
            goto fail;
        }
    }
@@ -363,7 +360,6 @@ void commit_start(const char *job_id, BlockDriverState *bs,
        goto fail;
    }

    s->base_flags = orig_base_flags;
    s->backing_file_str = g_strdup(backing_file_str);
    s->on_error = on_error;

@@ -395,7 +391,7 @@ int bdrv_commit(BlockDriverState *bs)
    BlockDriverState *commit_top_bs = NULL;
    BlockDriver *drv = bs->drv;
    int64_t offset, length, backing_length;
    int ro, open_flags;
    int ro;
    int64_t n;
    int ret = 0;
    uint8_t *buf = NULL;
@@ -414,10 +410,9 @@ int bdrv_commit(BlockDriverState *bs)
    }

    ro = bs->backing->bs->read_only;
    open_flags =  bs->backing->bs->open_flags;

    if (ro) {
        if (bdrv_reopen(bs->backing->bs, open_flags | BDRV_O_RDWR, NULL)) {
        if (bdrv_reopen_set_read_only(bs->backing->bs, false, NULL)) {
            return -EACCES;
        }
    }
@@ -527,7 +522,7 @@ ro_cleanup:

    if (ro) {
        /* ignoring error return here */
        bdrv_reopen(bs->backing->bs, open_flags & ~BDRV_O_RDWR, NULL);
        bdrv_reopen_set_read_only(bs->backing->bs, true, NULL);
    }

    return ret;

block/dmg-lzfse.c

0 → 100644
+49 −0
Original line number Diff line number Diff line
/*
 * DMG lzfse uncompression
 *
 * Copyright (c) 2018 Julio Cesar Faracco
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
#include "qemu/osdep.h"
#include "qemu-common.h"
#include "dmg.h"
#include <lzfse.h>

static int dmg_uncompress_lzfse_do(char *next_in, unsigned int avail_in,
                                   char *next_out, unsigned int avail_out)
{
    size_t out_size = lzfse_decode_buffer((uint8_t *) next_out, avail_out,
                                          (uint8_t *) next_in, avail_in,
                                          NULL);

    /* We need to decode the single chunk only. */
    /* So, out_size == avail_out is not an error here. */
    if (out_size > 0) {
        return out_size;
    }
    return -1;
}

__attribute__((constructor))
static void dmg_lzfse_init(void)
{
    assert(!dmg_uncompress_lzfse);
    dmg_uncompress_lzfse = dmg_uncompress_lzfse_do;
}
Loading