From 38b5e4c3dc6d713eae340341ee139c12d5c1a21e Mon Sep 17 00:00:00 2001 From: Alberto Garcia Date: Thu, 15 Sep 2016 17:52:59 +0300 Subject: block: Remove bdrv_is_snapshot This is unnecessary and has been unused since 5433c24f0f9306c82ad9bcc. Signed-off-by: Alberto Garcia Reviewed-by: Kevin Wolf Reviewed-by: Eric Blake Signed-off-by: Kevin Wolf --- include/block/block.h | 1 - 1 file changed, 1 deletion(-) (limited to 'include') diff --git a/include/block/block.h b/include/block/block.h index ffecebfb3a..f374e1a725 100644 --- a/include/block/block.h +++ b/include/block/block.h @@ -414,7 +414,6 @@ void bdrv_get_full_backing_filename_from_filename(const char *backed, const char *backing, char *dest, size_t sz, Error **errp); -int bdrv_is_snapshot(BlockDriverState *bs); int path_has_protocol(const char *path); int path_is_absolute(const char *path); -- cgit v1.2.3-55-g7522 From f87a0e29a9814a7ab6ee92b238989fed6186c4f3 Mon Sep 17 00:00:00 2001 From: Alberto Garcia Date: Thu, 15 Sep 2016 17:53:02 +0300 Subject: 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: Alberto Garcia Signed-off-by: Kevin Wolf --- block.c | 38 +++++++++++++++++++++++++++++++++++--- block/vvfat.c | 3 ++- blockdev.c | 16 +++++++--------- include/block/block.h | 1 + 4 files changed, 45 insertions(+), 13 deletions(-) (limited to 'include') diff --git a/block.c b/block.c index a98b75e4df..b724adacfc 100644 --- a/block.c +++ b/block.c @@ -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); } diff --git a/block/vvfat.c b/block/vvfat.c index ba2620f3c2..ded21092ee 100644 --- a/block/vvfat.c +++ b/block/vvfat.c @@ -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 = { diff --git a/blockdev.c b/blockdev.c index 301039392c..c3f8da4700 100644 --- a/blockdev.c +++ b/blockdev.c @@ -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, diff --git a/include/block/block.h b/include/block/block.h index f374e1a725..e18233afe0 100644 --- a/include/block/block.h +++ b/include/block/block.h @@ -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 -- cgit v1.2.3-55-g7522 From 1c89e1fa2fb1414f4485a01924032ad9cdb9073d Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Tue, 20 Sep 2016 13:38:40 +0200 Subject: block: Add blk_by_dev() This finds a BlockBackend given the device model that is attached to it. Signed-off-by: Kevin Wolf Reviewed-by: Eric Blake --- block/block-backend.c | 19 +++++++++++++++++++ include/sysemu/block-backend.h | 1 + 2 files changed, 20 insertions(+) (limited to 'include') diff --git a/block/block-backend.c b/block/block-backend.c index d1349d90e5..0bd19abdfb 100644 --- a/block/block-backend.c +++ b/block/block-backend.c @@ -559,6 +559,25 @@ void *blk_get_attached_dev(BlockBackend *blk) return blk->dev; } +/* + * Return the BlockBackend which has the device model @dev attached if it + * exists, else null. + * + * @dev must not be null. + */ +BlockBackend *blk_by_dev(void *dev) +{ + BlockBackend *blk = NULL; + + assert(dev != NULL); + while ((blk = blk_all_next(blk)) != NULL) { + if (blk->dev == dev) { + return blk; + } + } + return NULL; +} + /* * Set @blk's device model callbacks to @ops. * @opaque is the opaque argument to pass to the callbacks. diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h index 4808a9621a..410eb68145 100644 --- a/include/sysemu/block-backend.h +++ b/include/sysemu/block-backend.h @@ -111,6 +111,7 @@ int blk_attach_dev(BlockBackend *blk, void *dev); void blk_attach_dev_nofail(BlockBackend *blk, void *dev); void blk_detach_dev(BlockBackend *blk, void *dev); void *blk_get_attached_dev(BlockBackend *blk); +BlockBackend *blk_by_dev(void *dev); void blk_set_dev_ops(BlockBackend *blk, const BlockDevOps *ops, void *opaque); int blk_pread_unthrottled(BlockBackend *blk, int64_t offset, uint8_t *buf, int count); -- cgit v1.2.3-55-g7522 From 9680caee0fa530726809bc72d44e127ae676e251 Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Tue, 20 Sep 2016 13:38:42 +0200 Subject: qdev-monitor: Add blk_by_qdev_id() This finds the BlockBackend attached to the device model identified by its qdev ID. Signed-off-by: Kevin Wolf Reviewed-by: Eric Blake --- include/sysemu/block-backend.h | 1 + qdev-monitor.c | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+) (limited to 'include') diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h index 410eb68145..3b29317349 100644 --- a/include/sysemu/block-backend.h +++ b/include/sysemu/block-backend.h @@ -112,6 +112,7 @@ void blk_attach_dev_nofail(BlockBackend *blk, void *dev); void blk_detach_dev(BlockBackend *blk, void *dev); void *blk_get_attached_dev(BlockBackend *blk); BlockBackend *blk_by_dev(void *dev); +BlockBackend *blk_by_qdev_id(const char *id, Error **errp); void blk_set_dev_ops(BlockBackend *blk, const BlockDevOps *ops, void *opaque); int blk_pread_unthrottled(BlockBackend *blk, int64_t offset, uint8_t *buf, int count); diff --git a/qdev-monitor.c b/qdev-monitor.c index bc0213f5e3..4f78ecb091 100644 --- a/qdev-monitor.c +++ b/qdev-monitor.c @@ -28,6 +28,7 @@ #include "qemu/config-file.h" #include "qemu/error-report.h" #include "qemu/help_option.h" +#include "sysemu/block-backend.h" /* * Aliases were a bad idea from the start. Let's keep them @@ -838,6 +839,23 @@ void qmp_device_del(const char *id, Error **errp) } } +BlockBackend *blk_by_qdev_id(const char *id, Error **errp) +{ + DeviceState *dev; + BlockBackend *blk; + + dev = find_device_state(id, errp); + if (dev == NULL) { + return NULL; + } + + blk = blk_by_dev(dev); + if (!blk) { + error_setg(errp, "Device does not have a block device backend"); + } + return blk; +} + void qdev_machine_init(void) { qdev_get_peripheral_anon(); -- cgit v1.2.3-55-g7522