From 525989a50a70ea0ffa2b1cdf56279765bb2b7de0 Mon Sep 17 00:00:00 2001 From: Alberto Garcia Date: Mon, 15 May 2017 12:34:24 +0300 Subject: stream: fix crash in stream_start() when block_job_create() fails The code that tries to reopen a BlockDriverState in stream_start() when the creation of a new block job fails crashes because it attempts to dereference a pointer that is known to be NULL. This is a regression introduced in a170a91fd3eab6155da39e740381867e, likely because the code was copied from stream_complete(). Cc: qemu-stable@nongnu.org Reported-by: Kashyap Chamarthy Signed-off-by: Alberto Garcia Tested-by: Kashyap Chamarthy Signed-off-by: Kevin Wolf --- block/stream.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'block') diff --git a/block/stream.c b/block/stream.c index 0113710845..52d329f5c6 100644 --- a/block/stream.c +++ b/block/stream.c @@ -280,6 +280,6 @@ void stream_start(const char *job_id, BlockDriverState *bs, fail: if (orig_bs_flags != bdrv_get_flags(bs)) { - bdrv_reopen(bs, s->bs_flags, NULL); + bdrv_reopen(bs, orig_bs_flags, NULL); } } -- cgit v1.2.3 From 63c8ef289087a225d445319d047501d4fe593687 Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Mon, 29 May 2017 14:08:32 +0200 Subject: mirror: Drop permissions on s->target on completion This fixes an assertion failure that was triggered by qemu-iotests 129 on some CI host, while the same test case didn't seem to fail on other hosts. Essentially the problem is that the blk_unref(s->target) in mirror_exit() doesn't necessarily mean that the BlockBackend goes away immediately. It is possible that the job completion was triggered nested in mirror_drain(), which looks like this: BlockBackend *target = s->target; blk_ref(target); blk_drain(target); blk_unref(target); In this case, the write permissions for s->target are retained until after blk_drain(), which makes removing mirror_top_bs fail for the active commit case (can't have a writable backing file in the chain without the filter driver). Explicitly dropping the permissions first means that the additional reference doesn't hurt and the job can complete successfully even if called from the nested blk_drain(). Cc: qemu-stable@nongnu.org Signed-off-by: Kevin Wolf Acked-by: Paolo Bonzini Reviewed-by: Max Reitz --- block/mirror.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'block') diff --git a/block/mirror.c b/block/mirror.c index e86f8f8ad7..e778ee0ed0 100644 --- a/block/mirror.c +++ b/block/mirror.c @@ -514,7 +514,12 @@ static void mirror_exit(BlockJob *job, void *opaque) /* Remove target parent that still uses BLK_PERM_WRITE/RESIZE before * inserting target_bs at s->to_replace, where we might not be able to get - * these permissions. */ + * these permissions. + * + * Note that blk_unref() alone doesn't necessarily drop permissions because + * we might be running nested inside mirror_drain(), which takes an extra + * reference, so use an explicit blk_set_perm() first. */ + blk_set_perm(s->target, 0, BLK_PERM_ALL, &error_abort); blk_unref(s->target); s->target = NULL; -- cgit v1.2.3 From a7a6a2bffcc4410da29427a87808272cca91e335 Mon Sep 17 00:00:00 2001 From: Alberto Garcia Date: Thu, 11 May 2017 18:03:37 +0300 Subject: qcow2: remove extra local_error variable Commit d7086422b1c1e75e320519cfe26176db6ec97a37 added a local_err variable global to the qcow2_amend_options() function, so there's no need to have this other one. Signed-off-by: Alberto Garcia Message-id: 20170511150337.21470-1-berto@igalia.com Reviewed-by: Eric Blake Signed-off-by: Max Reitz --- block/qcow2.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'block') diff --git a/block/qcow2.c b/block/qcow2.c index a8d61f0981..b3ba5daa93 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -3222,7 +3222,6 @@ static int qcow2_amend_options(BlockDriverState *bs, QemuOpts *opts, if (s->refcount_bits != refcount_bits) { int refcount_order = ctz32(refcount_bits); - Error *local_error = NULL; if (new_version < 3 && refcount_bits != 16) { error_report("Different refcount widths than 16 bits require " @@ -3234,9 +3233,9 @@ static int qcow2_amend_options(BlockDriverState *bs, QemuOpts *opts, helper_cb_info.current_operation = QCOW2_CHANGING_REFCOUNT_ORDER; ret = qcow2_change_refcount_order(bs, refcount_order, &qcow2_amend_helper_cb, - &helper_cb_info, &local_error); + &helper_cb_info, &local_err); if (ret < 0) { - error_report_err(local_error); + error_report_err(local_err); return ret; } } -- cgit v1.2.3 From bcb07dba9290407eb01971ade287ca9a332ad49d Mon Sep 17 00:00:00 2001 From: Eric Blake Date: Mon, 8 May 2017 12:13:02 -0500 Subject: block: Tweak error message related to qemu-img amend When converting a 1.1 image down to 0.10, qemu-iotests 060 forces a contrived failure where allocating a cluster used to replace a zero cluster reads unaligned data. Since it is a zero cluster rather than a data cluster being converted, changing the error message to match our earlier change in 'qcow2: Make distinction between zero cluster types obvious' is worthwhile. Suggested-by: Max Reitz Signed-off-by: Eric Blake Message-id: 20170508171302.17805-1-eblake@redhat.com [mreitz: Commit message fixes] Signed-off-by: Max Reitz --- block/qcow2-cluster.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'block') diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c index 347d94b0d2..d779ea19cf 100644 --- a/block/qcow2-cluster.c +++ b/block/qcow2-cluster.c @@ -1797,7 +1797,8 @@ static int expand_zero_clusters_in_l1(BlockDriverState *bs, uint64_t *l1_table, } if (offset_into_cluster(s, offset)) { - qcow2_signal_corruption(bs, true, -1, -1, "Data cluster offset " + qcow2_signal_corruption(bs, true, -1, -1, + "Cluster allocation offset " "%#" PRIx64 " unaligned (L2 offset: %#" PRIx64 ", L2 index: %#x)", offset, l2_offset, j); -- cgit v1.2.3 From 03c320d803fd881736b63015048498cf97d410d3 Mon Sep 17 00:00:00 2001 From: Max Reitz Date: Mon, 22 May 2017 21:52:16 +0200 Subject: block/file-*: *_parse_filename() and colons The file drivers' *_parse_filename() implementations just strip the optional protocol prefix off the filename. However, for e.g. "file:foo:bar", this would lead to "foo:bar" being stored as the BDS's filename which looks like it should be managed using the "foo" protocol. This is especially troublesome if you then try to resolve a backing filename based on "foo:bar". This issue can only occur if the stripped part is a relative filename ("file:/foo:bar" will be shortened to "/foo:bar" and having a slash before the first colon means that "/foo" is not recognized as a protocol part). Therefore, we can easily fix it by prepending "./" to such filenames. Before this patch: $ ./qemu-img create -f qcow2 backing.qcow2 64M Formatting 'backing.qcow2', fmt=qcow2 size=67108864 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 $ ./qemu-img create -f qcow2 -b backing.qcow2 file:top:image.qcow2 Formatting 'file:top:image.qcow2', fmt=qcow2 size=67108864 backing_file=backing.qcow2 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 $ ./qemu-io file:top:image.qcow2 can't open device file:top:image.qcow2: Could not open backing file: Unknown protocol 'top' After this patch: $ ./qemu-io file:top:image.qcow2 [no error] Signed-off-by: Max Reitz Message-id: 20170522195217.12991-3-mreitz@redhat.com Reviewed-by: Eric Blake Signed-off-by: Max Reitz --- block/file-posix.c | 17 +++-------------- block/file-win32.c | 12 ++---------- 2 files changed, 5 insertions(+), 24 deletions(-) (limited to 'block') diff --git a/block/file-posix.c b/block/file-posix.c index 4354d49642..de2d3a2e3c 100644 --- a/block/file-posix.c +++ b/block/file-posix.c @@ -381,12 +381,7 @@ static void raw_parse_flags(int bdrv_flags, int *open_flags) static void raw_parse_filename(const char *filename, QDict *options, Error **errp) { - /* The filename does not have to be prefixed by the protocol name, since - * "file" is the default protocol; therefore, the return value of this - * function call can be ignored. */ - strstart(filename, "file:", &filename); - - qdict_put_str(options, "filename", filename); + bdrv_parse_filename_strip_prefix(filename, "file:", options); } static QemuOptsList raw_runtime_opts = { @@ -2395,10 +2390,7 @@ static int check_hdev_writable(BDRVRawState *s) static void hdev_parse_filename(const char *filename, QDict *options, Error **errp) { - /* The prefix is optional, just as for "file". */ - strstart(filename, "host_device:", &filename); - - qdict_put_str(options, "filename", filename); + bdrv_parse_filename_strip_prefix(filename, "host_device:", options); } static bool hdev_is_sg(BlockDriverState *bs) @@ -2697,10 +2689,7 @@ static BlockDriver bdrv_host_device = { static void cdrom_parse_filename(const char *filename, QDict *options, Error **errp) { - /* The prefix is optional, just as for "file". */ - strstart(filename, "host_cdrom:", &filename); - - qdict_put_str(options, "filename", filename); + bdrv_parse_filename_strip_prefix(filename, "host_cdrom:", options); } #endif diff --git a/block/file-win32.c b/block/file-win32.c index 8f14f0bdcd..ef2910b03f 100644 --- a/block/file-win32.c +++ b/block/file-win32.c @@ -276,12 +276,7 @@ static void raw_parse_flags(int flags, bool use_aio, int *access_flags, static void raw_parse_filename(const char *filename, QDict *options, Error **errp) { - /* The filename does not have to be prefixed by the protocol name, since - * "file" is the default protocol; therefore, the return value of this - * function call can be ignored. */ - strstart(filename, "file:", &filename); - - qdict_put_str(options, "filename", filename); + bdrv_parse_filename_strip_prefix(filename, "file:", options); } static QemuOptsList raw_runtime_opts = { @@ -671,10 +666,7 @@ static int hdev_probe_device(const char *filename) static void hdev_parse_filename(const char *filename, QDict *options, Error **errp) { - /* The prefix is optional, just as for "file". */ - strstart(filename, "host_device:", &filename); - - qdict_put_str(options, "filename", filename); + bdrv_parse_filename_strip_prefix(filename, "host_device:", options); } static int hdev_open(BlockDriverState *bs, QDict *options, int flags, -- cgit v1.2.3