Commit bbc4c3f4 authored by Peter Maydell's avatar Peter Maydell
Browse files

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



Block layer patches

# gpg: Signature made Thu 29 Sep 2016 14:11:30 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:
  oslib-posix: add a configure switch to debug stack usage
  coroutine-sigaltstack: use helper for allocating stack memory
  coroutine-ucontext: use helper for allocating stack memory
  coroutine: add a macro for the coroutine stack size
  coroutine-sigaltstack: rename coroutine struct appropriately
  oslib-posix: add helpers for stack alloc and free
  block: Remove qemu_root_bds_opts
  block: Move 'discard' option to bdrv_open_common()
  block: Use 'detect-zeroes' option for 'blockdev-change-medium'
  block: Parse 'detect-zeroes' in bdrv_open_common()
  block/qapi: Move 'aio' option to file driver
  block/qapi: Use separate options type for curl driver
  block: Drop aio/cache consistency check from qmp_blockdev_add()
  block: Fix error path in qmp_blockdev_change_medium()
  block-backend: remove blk_flush_all
  qemu: use bdrv_flush_all for vm_stop et al
  block: reintroduce bdrv_flush_all

Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parents 6e11eb2d 7d992e4d
Loading
Loading
Loading
Loading
+49 −1
Original line number Diff line number Diff line
@@ -42,6 +42,7 @@
#include "qapi-event.h"
#include "qemu/cutils.h"
#include "qemu/id.h"
#include "qapi/util.h"

#ifdef CONFIG_BSD
#include <sys/ioctl.h>
@@ -764,7 +765,7 @@ static void bdrv_inherited_options(int *child_flags, QDict *child_options,
    /* Our block drivers take care to send flushes and respect unmap policy,
     * so we can default to enable both on lower layers regardless of the
     * corresponding parent options. */
    flags |= BDRV_O_UNMAP;
    qdict_set_default_str(child_options, BDRV_OPT_DISCARD, "unmap");

    /* Clear flags that only apply to the top layer */
    flags &= ~(BDRV_O_SNAPSHOT | BDRV_O_NO_BACKING | BDRV_O_COPY_ON_READ |
@@ -954,6 +955,16 @@ static QemuOptsList bdrv_runtime_opts = {
            .type = QEMU_OPT_BOOL,
            .help = "Node is opened in read-only mode",
        },
        {
            .name = "detect-zeroes",
            .type = QEMU_OPT_STRING,
            .help = "try to optimize zero writes (off, on, unmap)",
        },
        {
            .name = "discard",
            .type = QEMU_OPT_STRING,
            .help = "discard operation (ignore/off, unmap/on)",
        },
        { /* end of list */ }
    },
};
@@ -970,6 +981,8 @@ static int bdrv_open_common(BlockDriverState *bs, BdrvChild *file,
    const char *filename;
    const char *driver_name = NULL;
    const char *node_name = NULL;
    const char *discard;
    const char *detect_zeroes;
    QemuOpts *opts;
    BlockDriver *drv;
    Error *local_err = NULL;
@@ -1038,6 +1051,41 @@ static int bdrv_open_common(BlockDriverState *bs, BdrvChild *file,
        }
    }

    discard = qemu_opt_get(opts, "discard");
    if (discard != NULL) {
        if (bdrv_parse_discard_flags(discard, &bs->open_flags) != 0) {
            error_setg(errp, "Invalid discard option");
            ret = -EINVAL;
            goto fail_opts;
        }
    }

    detect_zeroes = qemu_opt_get(opts, "detect-zeroes");
    if (detect_zeroes) {
        BlockdevDetectZeroesOptions value =
            qapi_enum_parse(BlockdevDetectZeroesOptions_lookup,
                            detect_zeroes,
                            BLOCKDEV_DETECT_ZEROES_OPTIONS__MAX,
                            BLOCKDEV_DETECT_ZEROES_OPTIONS_OFF,
                            &local_err);
        if (local_err) {
            error_propagate(errp, local_err);
            ret = -EINVAL;
            goto fail_opts;
        }

        if (value == BLOCKDEV_DETECT_ZEROES_OPTIONS_UNMAP &&
            !(bs->open_flags & BDRV_O_UNMAP))
        {
            error_setg(errp, "setting detect-zeroes to unmap is not allowed "
                             "without setting discard operation to unmap");
            ret = -EINVAL;
            goto fail_opts;
        }

        bs->detect_zeroes = value;
    }

    if (filename != NULL) {
        pstrcpy(bs->filename, sizeof(bs->filename), filename);
    } else {
+4 −27
Original line number Diff line number Diff line
@@ -1592,13 +1592,12 @@ void blk_update_root_state(BlockBackend *blk)
}

/*
 * Applies the information in the root state to the given BlockDriverState. This
 * does not include the flags which have to be specified for bdrv_open(), use
 * blk_get_open_flags_from_root_state() to inquire them.
 * Returns the detect-zeroes setting to be used for bdrv_open() of a
 * BlockDriverState which is supposed to inherit the root state.
 */
void blk_apply_root_state(BlockBackend *blk, BlockDriverState *bs)
bool blk_get_detect_zeroes_from_root_state(BlockBackend *blk)
{
    bs->detect_zeroes = blk->root_state.detect_zeroes;
    return blk->root_state.detect_zeroes;
}

/*
@@ -1640,28 +1639,6 @@ int blk_commit_all(void)
    return 0;
}

int blk_flush_all(void)
{
    BlockBackend *blk = NULL;
    int result = 0;

    while ((blk = blk_all_next(blk)) != NULL) {
        AioContext *aio_context = blk_get_aio_context(blk);
        int ret;

        aio_context_acquire(aio_context);
        if (blk_is_inserted(blk)) {
            ret = blk_flush(blk);
            if (ret < 0 && !result) {
                result = ret;
            }
        }
        aio_context_release(aio_context);
    }

    return result;
}


/* throttling disk I/O limits */
void blk_set_io_limits(BlockBackend *blk, ThrottleConfig *cfg)
+25 −0
Original line number Diff line number Diff line
@@ -1619,6 +1619,31 @@ int coroutine_fn bdrv_co_pwrite_zeroes(BdrvChild *child, int64_t offset,
                           BDRV_REQ_ZERO_WRITE | flags);
}

/*
 * Flush ALL BDSes regardless of if they are reachable via a BlkBackend or not.
 */
int bdrv_flush_all(void)
{
    BdrvNextIterator it;
    BlockDriverState *bs = NULL;
    int result = 0;

    for (bs = bdrv_first(&it); bs; bs = bdrv_next(&it)) {
        AioContext *aio_context = bdrv_get_aio_context(bs);
        int ret;

        aio_context_acquire(aio_context);
        ret = bdrv_flush(bs);
        if (ret < 0 && !result) {
            result = ret;
        }
        aio_context_release(aio_context);
    }

    return result;
}


typedef struct BdrvCoGetBlockStatusData {
    BlockDriverState *bs;
    BlockDriverState *base;
+27 −17
Original line number Diff line number Diff line
@@ -143,6 +143,7 @@ typedef struct BDRVRawState {
    bool has_discard:1;
    bool has_write_zeroes:1;
    bool discard_zeroes:1;
    bool use_linux_aio:1;
    bool has_fallocate;
    bool needs_alignment;
} BDRVRawState;
@@ -367,18 +368,6 @@ static void raw_parse_flags(int bdrv_flags, int *open_flags)
    }
}

#ifdef CONFIG_LINUX_AIO
static bool raw_use_aio(int bdrv_flags)
{
    /*
     * Currently Linux do AIO only for files opened with O_DIRECT
     * specified so check NOCACHE flag too
     */
    return (bdrv_flags & (BDRV_O_NOCACHE|BDRV_O_NATIVE_AIO)) ==
                         (BDRV_O_NOCACHE|BDRV_O_NATIVE_AIO);
}
#endif

static void raw_parse_filename(const char *filename, QDict *options,
                               Error **errp)
{
@@ -399,6 +388,11 @@ static QemuOptsList raw_runtime_opts = {
            .type = QEMU_OPT_STRING,
            .help = "File name of the image",
        },
        {
            .name = "aio",
            .type = QEMU_OPT_STRING,
            .help = "host AIO implementation (threads, native)",
        },
        { /* end of list */ }
    },
};
@@ -410,6 +404,7 @@ static int raw_open_common(BlockDriverState *bs, QDict *options,
    QemuOpts *opts;
    Error *local_err = NULL;
    const char *filename = NULL;
    BlockdevAioOptions aio, aio_default;
    int fd, ret;
    struct stat st;

@@ -429,6 +424,18 @@ static int raw_open_common(BlockDriverState *bs, QDict *options,
        goto fail;
    }

    aio_default = (bdrv_flags & BDRV_O_NATIVE_AIO)
                  ? BLOCKDEV_AIO_OPTIONS_NATIVE
                  : BLOCKDEV_AIO_OPTIONS_THREADS;
    aio = qapi_enum_parse(BlockdevAioOptions_lookup, qemu_opt_get(opts, "aio"),
                          BLOCKDEV_AIO_OPTIONS__MAX, aio_default, &local_err);
    if (local_err) {
        error_propagate(errp, local_err);
        ret = -EINVAL;
        goto fail;
    }
    s->use_linux_aio = (aio == BLOCKDEV_AIO_OPTIONS_NATIVE);

    s->open_flags = open_flags;
    raw_parse_flags(bdrv_flags, &s->open_flags);

@@ -444,14 +451,15 @@ static int raw_open_common(BlockDriverState *bs, QDict *options,
    s->fd = fd;

#ifdef CONFIG_LINUX_AIO
    if (!raw_use_aio(bdrv_flags) && (bdrv_flags & BDRV_O_NATIVE_AIO)) {
     /* Currently Linux does AIO only for files opened with O_DIRECT */
    if (s->use_linux_aio && !(s->open_flags & O_DIRECT)) {
        error_setg(errp, "aio=native was specified, but it requires "
                         "cache.direct=on, which was not specified.");
        ret = -EINVAL;
        goto fail;
    }
#else
    if (bdrv_flags & BDRV_O_NATIVE_AIO) {
    if (s->use_linux_aio) {
        error_setg(errp, "aio=native was specified, but is not supported "
                         "in this build.");
        ret = -EINVAL;
@@ -1256,7 +1264,7 @@ static int coroutine_fn raw_co_prw(BlockDriverState *bs, uint64_t offset,
        if (!bdrv_qiov_is_aligned(bs, qiov)) {
            type |= QEMU_AIO_MISALIGNED;
#ifdef CONFIG_LINUX_AIO
        } else if (bs->open_flags & BDRV_O_NATIVE_AIO) {
        } else if (s->use_linux_aio) {
            LinuxAioState *aio = aio_get_linux_aio(bdrv_get_aio_context(bs));
            assert(qiov->size == bytes);
            return laio_co_submit(bs, aio, s->fd, offset, qiov, type);
@@ -1285,7 +1293,8 @@ static int coroutine_fn raw_co_pwritev(BlockDriverState *bs, uint64_t offset,
static void raw_aio_plug(BlockDriverState *bs)
{
#ifdef CONFIG_LINUX_AIO
    if (bs->open_flags & BDRV_O_NATIVE_AIO) {
    BDRVRawState *s = bs->opaque;
    if (s->use_linux_aio) {
        LinuxAioState *aio = aio_get_linux_aio(bdrv_get_aio_context(bs));
        laio_io_plug(bs, aio);
    }
@@ -1295,7 +1304,8 @@ static void raw_aio_plug(BlockDriverState *bs)
static void raw_aio_unplug(BlockDriverState *bs)
{
#ifdef CONFIG_LINUX_AIO
    if (bs->open_flags & BDRV_O_NATIVE_AIO) {
    BDRVRawState *s = bs->opaque;
    if (s->use_linux_aio) {
        LinuxAioState *aio = aio_get_linux_aio(bdrv_get_aio_context(bs));
        laio_io_unplug(bs, aio);
    }
+51 −5
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@
#include "block/thread-pool.h"
#include "qemu/iov.h"
#include "qapi/qmp/qstring.h"
#include "qapi/util.h"
#include <windows.h>
#include <winioctl.h>

@@ -252,7 +253,8 @@ static void raw_probe_alignment(BlockDriverState *bs, Error **errp)
    }
}

static void raw_parse_flags(int flags, int *access_flags, DWORD *overlapped)
static void raw_parse_flags(int flags, bool use_aio, int *access_flags,
                            DWORD *overlapped)
{
    assert(access_flags != NULL);
    assert(overlapped != NULL);
@@ -264,7 +266,7 @@ static void raw_parse_flags(int flags, int *access_flags, DWORD *overlapped)
    }

    *overlapped = FILE_ATTRIBUTE_NORMAL;
    if (flags & BDRV_O_NATIVE_AIO) {
    if (use_aio) {
        *overlapped |= FILE_FLAG_OVERLAPPED;
    }
    if (flags & BDRV_O_NOCACHE) {
@@ -292,10 +294,35 @@ static QemuOptsList raw_runtime_opts = {
            .type = QEMU_OPT_STRING,
            .help = "File name of the image",
        },
        {
            .name = "aio",
            .type = QEMU_OPT_STRING,
            .help = "host AIO implementation (threads, native)",
        },
        { /* end of list */ }
    },
};

static bool get_aio_option(QemuOpts *opts, int flags, Error **errp)
{
    BlockdevAioOptions aio, aio_default;

    aio_default = (flags & BDRV_O_NATIVE_AIO) ? BLOCKDEV_AIO_OPTIONS_NATIVE
                                              : BLOCKDEV_AIO_OPTIONS_THREADS;
    aio = qapi_enum_parse(BlockdevAioOptions_lookup, qemu_opt_get(opts, "aio"),
                          BLOCKDEV_AIO_OPTIONS__MAX, aio_default, errp);

    switch (aio) {
    case BLOCKDEV_AIO_OPTIONS_NATIVE:
        return true;
    case BLOCKDEV_AIO_OPTIONS_THREADS:
        return false;
    default:
        error_setg(errp, "Invalid AIO option");
    }
    return false;
}

static int raw_open(BlockDriverState *bs, QDict *options, int flags,
                    Error **errp)
{
@@ -305,6 +332,7 @@ static int raw_open(BlockDriverState *bs, QDict *options, int flags,
    QemuOpts *opts;
    Error *local_err = NULL;
    const char *filename;
    bool use_aio;
    int ret;

    s->type = FTYPE_FILE;
@@ -319,7 +347,14 @@ static int raw_open(BlockDriverState *bs, QDict *options, int flags,

    filename = qemu_opt_get(opts, "filename");

    raw_parse_flags(flags, &access_flags, &overlapped);
    use_aio = get_aio_option(opts, flags, &local_err);
    if (local_err) {
        error_propagate(errp, local_err);
        ret = -EINVAL;
        goto fail;
    }

    raw_parse_flags(flags, use_aio, &access_flags, &overlapped);

    if (filename[0] && filename[1] == ':') {
        snprintf(s->drive_path, sizeof(s->drive_path), "%c:\\", filename[0]);
@@ -346,7 +381,7 @@ static int raw_open(BlockDriverState *bs, QDict *options, int flags,
        goto fail;
    }

    if (flags & BDRV_O_NATIVE_AIO) {
    if (use_aio) {
        s->aio = win32_aio_init();
        if (s->aio == NULL) {
            CloseHandle(s->hfile);
@@ -647,6 +682,7 @@ static int hdev_open(BlockDriverState *bs, QDict *options, int flags,

    Error *local_err = NULL;
    const char *filename;
    bool use_aio;

    QemuOpts *opts = qemu_opts_create(&raw_runtime_opts, NULL, 0,
                                      &error_abort);
@@ -659,6 +695,16 @@ static int hdev_open(BlockDriverState *bs, QDict *options, int flags,

    filename = qemu_opt_get(opts, "filename");

    use_aio = get_aio_option(opts, flags, &local_err);
    if (!local_err && use_aio) {
        error_setg(&local_err, "AIO is not supported on Windows host devices");
    }
    if (local_err) {
        error_propagate(errp, local_err);
        ret = -EINVAL;
        goto done;
    }

    if (strstart(filename, "/dev/cdrom", NULL)) {
        if (find_cdrom(device_name, sizeof(device_name)) < 0) {
            error_setg(errp, "Could not open CD-ROM drive");
@@ -677,7 +723,7 @@ static int hdev_open(BlockDriverState *bs, QDict *options, int flags,
    }
    s->type = find_device_type(bs, filename);

    raw_parse_flags(flags, &access_flags, &overlapped);
    raw_parse_flags(flags, use_aio, &access_flags, &overlapped);

    create_flags = OPEN_EXISTING;

Loading