Commit f87a0e29 authored by Alberto Garcia's avatar Alberto Garcia Committed by Kevin Wolf
Browse files

block: Add "read-only" to the options QDict



This adds the "read-only" option to the QDict. One important effect of
this change is that when a child inherits options from its parent, the
existing "read-only" mode can be preserved if it was explicitly set
previously.

This addresses scenarios like this:

   [E] <- [D] <- [C] <- [B] <- [A]

In this case, if we reopen [D] with read-only=off, and later reopen
[B], then [D] will not inherit read-only=on from its parent during the
bdrv_reopen_queue_child() stage.

The BDRV_O_RDWR flag is not removed yet, but its keep in sync with the
value of the "read-only" option.

Signed-off-by: default avatarAlberto Garcia <berto@igalia.com>
Signed-off-by: default avatarKevin Wolf <kwolf@redhat.com>
parent 9b7e8691
Loading
Loading
Loading
Loading
+35 −3
Original line number Diff line number Diff line
@@ -733,6 +733,9 @@ static void bdrv_temp_snapshot_options(int *child_flags, QDict *child_options,
    qdict_set_default_str(child_options, BDRV_OPT_CACHE_DIRECT, "off");
    qdict_set_default_str(child_options, BDRV_OPT_CACHE_NO_FLUSH, "on");

    /* Copy the read-only option from the parent */
    qdict_copy_default(child_options, parent_options, BDRV_OPT_READ_ONLY);

    /* aio=native doesn't work for cache.direct=off, so disable it for the
     * temporary snapshot */
    *child_flags &= ~BDRV_O_NATIVE_AIO;
@@ -755,6 +758,9 @@ static void bdrv_inherited_options(int *child_flags, QDict *child_options,
    qdict_copy_default(child_options, parent_options, BDRV_OPT_CACHE_DIRECT);
    qdict_copy_default(child_options, parent_options, BDRV_OPT_CACHE_NO_FLUSH);

    /* Inherit the read-only option from the parent if it's not set */
    qdict_copy_default(child_options, parent_options, BDRV_OPT_READ_ONLY);

    /* 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. */
@@ -808,7 +814,8 @@ static void bdrv_backing_options(int *child_flags, QDict *child_options,
    qdict_copy_default(child_options, parent_options, BDRV_OPT_CACHE_NO_FLUSH);

    /* backing files always opened read-only */
    flags &= ~(BDRV_O_RDWR | BDRV_O_COPY_ON_READ);
    qdict_set_default_str(child_options, BDRV_OPT_READ_ONLY, "on");
    flags &= ~BDRV_O_COPY_ON_READ;

    /* snapshot=on is handled on the top layer */
    flags &= ~(BDRV_O_SNAPSHOT | BDRV_O_TEMPORARY);
@@ -855,6 +862,14 @@ static void update_flags_from_options(int *flags, QemuOpts *opts)
    if (qemu_opt_get_bool(opts, BDRV_OPT_CACHE_DIRECT, false)) {
        *flags |= BDRV_O_NOCACHE;
    }

    *flags &= ~BDRV_O_RDWR;

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

}

static void update_options_from_flags(QDict *options, int flags)
@@ -867,6 +882,10 @@ static void update_options_from_flags(QDict *options, int flags)
        qdict_put(options, BDRV_OPT_CACHE_NO_FLUSH,
                  qbool_from_bool(flags & BDRV_O_NO_FLUSH));
    }
    if (!qdict_haskey(options, BDRV_OPT_READ_ONLY)) {
        qdict_put(options, BDRV_OPT_READ_ONLY,
                  qbool_from_bool(!(flags & BDRV_O_RDWR)));
    }
}

static void bdrv_assign_node_name(BlockDriverState *bs,
@@ -930,6 +949,11 @@ static QemuOptsList bdrv_runtime_opts = {
            .type = QEMU_OPT_BOOL,
            .help = "Ignore flush requests",
        },
        {
            .name = BDRV_OPT_READ_ONLY,
            .type = QEMU_OPT_BOOL,
            .help = "Node is opened in read-only mode",
        },
        { /* end of list */ }
    },
};
@@ -1674,14 +1698,22 @@ static BlockDriverState *bdrv_open_inherit(const char *filename,
        goto fail;
    }

    if (flags & BDRV_O_RDWR) {
        flags |= BDRV_O_ALLOW_RDWR;
    /* Set the BDRV_O_RDWR and BDRV_O_ALLOW_RDWR flags.
     * FIXME: we're parsing the QDict to avoid having to create a
     * QemuOpts just for this, but neither option is optimal. */
    if (g_strcmp0(qdict_get_try_str(options, BDRV_OPT_READ_ONLY), "on") &&
        !qdict_get_try_bool(options, BDRV_OPT_READ_ONLY, false)) {
        flags |= (BDRV_O_RDWR | BDRV_O_ALLOW_RDWR);
    } else {
        flags &= ~BDRV_O_RDWR;
    }

    if (flags & BDRV_O_SNAPSHOT) {
        snapshot_options = qdict_new();
        bdrv_temp_snapshot_options(&snapshot_flags, snapshot_options,
                                   flags, options);
        /* Let bdrv_backing_options() override "read-only" */
        qdict_del(options, BDRV_OPT_READ_ONLY);
        bdrv_backing_options(&flags, options, flags, options);
    }

+2 −1
Original line number Diff line number Diff line
@@ -2971,7 +2971,8 @@ static BlockDriver vvfat_write_target = {
static void vvfat_qcow_options(int *child_flags, QDict *child_options,
                               int parent_flags, QDict *parent_options)
{
    *child_flags = BDRV_O_RDWR | BDRV_O_NO_FLUSH;
    qdict_set_default_str(child_options, BDRV_OPT_READ_ONLY, "off");
    *child_flags = BDRV_O_NO_FLUSH;
}

static const BdrvChildRole child_vvfat_qcow = {
+7 −9
Original line number Diff line number Diff line
@@ -360,9 +360,6 @@ static void extract_common_blockdev_options(QemuOpts *opts, int *bdrv_flags,
    const char *aio;

    if (bdrv_flags) {
        if (!qemu_opt_get_bool(opts, "read-only", false)) {
            *bdrv_flags |= BDRV_O_RDWR;
        }
        if (qemu_opt_get_bool(opts, "copy-on-read", false)) {
            *bdrv_flags |= BDRV_O_COPY_ON_READ;
        }
@@ -471,7 +468,7 @@ static BlockBackend *blockdev_init(const char *file, QDict *bs_opts,
    int bdrv_flags = 0;
    int on_read_error, on_write_error;
    bool account_invalid, account_failed;
    bool writethrough;
    bool writethrough, read_only;
    BlockBackend *blk;
    BlockDriverState *bs;
    ThrottleConfig cfg;
@@ -567,6 +564,8 @@ static BlockBackend *blockdev_init(const char *file, QDict *bs_opts,
        bdrv_flags |= BDRV_O_SNAPSHOT;
    }

    read_only = qemu_opt_get_bool(opts, BDRV_OPT_READ_ONLY, false);

    /* init */
    if ((!file || !*file) && !qdict_size(bs_opts)) {
        BlockBackendRootState *blk_rs;
@@ -574,7 +573,7 @@ static BlockBackend *blockdev_init(const char *file, QDict *bs_opts,
        blk = blk_new();
        blk_rs = blk_get_root_state(blk);
        blk_rs->open_flags    = bdrv_flags;
        blk_rs->read_only     = !(bdrv_flags & BDRV_O_RDWR);
        blk_rs->read_only     = read_only;
        blk_rs->detect_zeroes = detect_zeroes;

        QDECREF(bs_opts);
@@ -588,6 +587,8 @@ static BlockBackend *blockdev_init(const char *file, QDict *bs_opts,
         * Apply the defaults here instead. */
        qdict_set_default_str(bs_opts, BDRV_OPT_CACHE_DIRECT, "off");
        qdict_set_default_str(bs_opts, BDRV_OPT_CACHE_NO_FLUSH, "off");
        qdict_set_default_str(bs_opts, BDRV_OPT_READ_ONLY,
                              read_only ? "on" : "off");
        assert((bdrv_flags & BDRV_O_CACHE_MASK) == 0);

        if (runstate_check(RUN_STATE_INMIGRATE)) {
@@ -682,6 +683,7 @@ static BlockDriverState *bds_tree_init(QDict *bs_opts, Error **errp)
     * Apply the defaults here instead. */
    qdict_set_default_str(bs_opts, BDRV_OPT_CACHE_DIRECT, "off");
    qdict_set_default_str(bs_opts, BDRV_OPT_CACHE_NO_FLUSH, "off");
    qdict_set_default_str(bs_opts, BDRV_OPT_READ_ONLY, "off");

    if (runstate_check(RUN_STATE_INMIGRATE)) {
        bdrv_flags |= BDRV_O_INACTIVE;
@@ -4158,10 +4160,6 @@ static QemuOptsList qemu_root_bds_opts = {
            .name = "aio",
            .type = QEMU_OPT_STRING,
            .help = "host AIO implementation (threads, native)",
        },{
            .name = "read-only",
            .type = QEMU_OPT_BOOL,
            .help = "open drive file as read-only",
        },{
            .name = "copy-on-read",
            .type = QEMU_OPT_BOOL,
+1 −0
Original line number Diff line number Diff line
@@ -107,6 +107,7 @@ typedef struct HDGeometry {
#define BDRV_OPT_CACHE_WB       "cache.writeback"
#define BDRV_OPT_CACHE_DIRECT   "cache.direct"
#define BDRV_OPT_CACHE_NO_FLUSH "cache.no-flush"
#define BDRV_OPT_READ_ONLY      "read-only"


#define BDRV_SECTOR_BITS   9