Commit e2b8247a authored by Jeff Cody's avatar Jeff Cody
Browse files

block: do not set BDS read_only if copy_on_read enabled



A few block drivers will set the BDS read_only flag from their
.bdrv_open() function.  This means the bs->read_only flag could
be set after we enable copy_on_read, as the BDRV_O_COPY_ON_READ
flag check occurs prior to the call to bdrv->bdrv_open().

This adds an error return to bdrv_set_read_only(), and an error will be
return if we try to set the BDS to read_only while copy_on_read is
enabled.

This patch also changes the behavior of vvfat.  Before, vvfat could
override the drive 'readonly' flag with its own, internal 'rw' flag.

For instance, this -drive parameter would result in a writable image:

"-drive format=vvfat,dir=/tmp/vvfat,rw,if=virtio,readonly=on"

This is not correct.  Now, attempting to use the above -drive parameter
will result in an error (i.e., 'rw' is incompatible with 'readonly=on').

Signed-off-by: default avatarJeff Cody <jcody@redhat.com>
Reviewed-by: default avatarStefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: default avatarJohn Snow <jsnow@redhat.com>
Message-id: 0c5b4c1cc2c651471b131f21376dfd5ea24d2196.1491597120.git.jcody@redhat.com
parent fe5241bf
Loading
Loading
Loading
Loading
+9 −1
Original line number Diff line number Diff line
@@ -192,9 +192,17 @@ void path_combine(char *dest, int dest_size,
    }
}

void bdrv_set_read_only(BlockDriverState *bs, bool read_only)
int bdrv_set_read_only(BlockDriverState *bs, bool read_only, Error **errp)
{
    /* Do not set read_only if copy_on_read is enabled */
    if (bs->copy_on_read && read_only) {
        error_setg(errp, "Can't set node '%s' to r/o with copy-on-read enabled",
                   bdrv_get_device_or_node_name(bs));
        return -EINVAL;
    }

    bs->read_only = read_only;
    return 0;
}

void bdrv_get_full_backing_filename_from_filename(const char *backed,
+4 −1
Original line number Diff line number Diff line
@@ -110,7 +110,10 @@ static int bochs_open(BlockDriverState *bs, QDict *options, int flags,
        return -EINVAL;
    }

    bdrv_set_read_only(bs, true); /* no write support yet */
    ret = bdrv_set_read_only(bs, true, errp); /* no write support yet */
    if (ret < 0) {
        return ret;
    }

    ret = bdrv_pread(bs->file, 0, &bochs, sizeof(bochs));
    if (ret < 0) {
+4 −1
Original line number Diff line number Diff line
@@ -72,7 +72,10 @@ static int cloop_open(BlockDriverState *bs, QDict *options, int flags,
        return -EINVAL;
    }

    bdrv_set_read_only(bs, true);
    ret = bdrv_set_read_only(bs, true, errp);
    if (ret < 0) {
        return ret;
    }

    /* read header */
    ret = bdrv_pread(bs->file, 128, &s->block_size, 4);
+5 −1
Original line number Diff line number Diff line
@@ -419,8 +419,12 @@ static int dmg_open(BlockDriverState *bs, QDict *options, int flags,
        return -EINVAL;
    }

    ret = bdrv_set_read_only(bs, true, errp);
    if (ret < 0) {
        return ret;
    }

    block_module_load_one("dmg-bz2");
    bdrv_set_read_only(bs, true);

    s->n_chunks = 0;
    s->offsets = s->lengths = s->sectors = s->sectorcounts = NULL;
+10 −1
Original line number Diff line number Diff line
@@ -635,13 +635,22 @@ static int qemu_rbd_open(BlockDriverState *bs, QDict *options, int flags,
        goto failed_shutdown;
    }

    /* rbd_open is always r/w */
    r = rbd_open(s->io_ctx, s->name, &s->image, s->snap);
    if (r < 0) {
        error_setg_errno(errp, -r, "error reading header from %s", s->name);
        goto failed_open;
    }

    bdrv_set_read_only(bs, (s->snap != NULL));
    /* If we are using an rbd snapshot, we must be r/o, otherwise
     * leave as-is */
    if (s->snap != NULL) {
        r = bdrv_set_read_only(bs, true, &local_err);
        if (r < 0) {
            error_propagate(errp, local_err);
            goto failed_open;
        }
    }

    qemu_opts_del(opts);
    return 0;
Loading