From: Kevin Wolf <kwolf@redhat.com>
To: qemu-block@nongnu.org
Cc: kwolf@redhat.com, qemu-devel@nongnu.org
Subject: [PULL 06/13] qcow2: Do not reopen data_file in invalidate_cache
Date: Wed, 4 May 2022 16:25:15 +0200 [thread overview]
Message-ID: <20220504142522.167506-7-kwolf@redhat.com> (raw)
In-Reply-To: <20220504142522.167506-1-kwolf@redhat.com>
From: Hanna Reitz <hreitz@redhat.com>
qcow2_co_invalidate_cache() closes and opens the qcow2 file, by calling
qcow2_close() and qcow2_do_open(). These two functions must thus be
usable from both a global-state and an I/O context.
As they are, they are not safe to call in an I/O context, because they
use bdrv_unref_child() and bdrv_open_child() to close/open the data_file
child, respectively, both of which are global-state functions. When
used from qcow2_co_invalidate_cache(), we do not need to close/open the
data_file child, though (we do not do this for bs->file or bs->backing
either), and so we should skip it in the qcow2_co_invalidate_cache()
path.
To do so, add a parameter to qcow2_do_open() and qcow2_close() to make
them skip handling s->data_file, and have qcow2_co_invalidate_cache()
exempt it from the memset() on the BDRVQcow2State.
(Note that the QED driver similarly closes/opens the QED image by
invoking bdrv_qed_close()+bdrv_qed_do_open(), but both functions seem
safe to use in an I/O context.)
Fixes: https://gitlab.com/qemu-project/qemu/-/issues/945
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
Message-Id: <20220427114057.36651-3-hreitz@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
block/qcow2.c | 104 ++++++++++++++++++++++++++++++--------------------
1 file changed, 62 insertions(+), 42 deletions(-)
diff --git a/block/qcow2.c b/block/qcow2.c
index b5c47931ef..4f5e6440fb 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -1296,7 +1296,8 @@ static int validate_compression_type(BDRVQcow2State *s, Error **errp)
/* Called with s->lock held. */
static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
- int flags, Error **errp)
+ int flags, bool open_data_file,
+ Error **errp)
{
ERRP_GUARD();
BDRVQcow2State *s = bs->opaque;
@@ -1614,50 +1615,52 @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
goto fail;
}
- /* Open external data file */
- s->data_file = bdrv_open_child(NULL, options, "data-file", bs,
- &child_of_bds, BDRV_CHILD_DATA,
- true, errp);
- if (*errp) {
- ret = -EINVAL;
- goto fail;
- }
+ if (open_data_file) {
+ /* Open external data file */
+ s->data_file = bdrv_open_child(NULL, options, "data-file", bs,
+ &child_of_bds, BDRV_CHILD_DATA,
+ true, errp);
+ if (*errp) {
+ ret = -EINVAL;
+ goto fail;
+ }
- if (s->incompatible_features & QCOW2_INCOMPAT_DATA_FILE) {
- if (!s->data_file && s->image_data_file) {
- s->data_file = bdrv_open_child(s->image_data_file, options,
- "data-file", bs, &child_of_bds,
- BDRV_CHILD_DATA, false, errp);
+ if (s->incompatible_features & QCOW2_INCOMPAT_DATA_FILE) {
+ if (!s->data_file && s->image_data_file) {
+ s->data_file = bdrv_open_child(s->image_data_file, options,
+ "data-file", bs, &child_of_bds,
+ BDRV_CHILD_DATA, false, errp);
+ if (!s->data_file) {
+ ret = -EINVAL;
+ goto fail;
+ }
+ }
if (!s->data_file) {
+ error_setg(errp, "'data-file' is required for this image");
ret = -EINVAL;
goto fail;
}
- }
- if (!s->data_file) {
- error_setg(errp, "'data-file' is required for this image");
- ret = -EINVAL;
- goto fail;
- }
- /* No data here */
- bs->file->role &= ~BDRV_CHILD_DATA;
+ /* No data here */
+ bs->file->role &= ~BDRV_CHILD_DATA;
- /* Must succeed because we have given up permissions if anything */
- bdrv_child_refresh_perms(bs, bs->file, &error_abort);
- } else {
- if (s->data_file) {
- error_setg(errp, "'data-file' can only be set for images with an "
- "external data file");
- ret = -EINVAL;
- goto fail;
- }
+ /* Must succeed because we have given up permissions if anything */
+ bdrv_child_refresh_perms(bs, bs->file, &error_abort);
+ } else {
+ if (s->data_file) {
+ error_setg(errp, "'data-file' can only be set for images with "
+ "an external data file");
+ ret = -EINVAL;
+ goto fail;
+ }
- s->data_file = bs->file;
+ s->data_file = bs->file;
- if (data_file_is_raw(bs)) {
- error_setg(errp, "data-file-raw requires a data file");
- ret = -EINVAL;
- goto fail;
+ if (data_file_is_raw(bs)) {
+ error_setg(errp, "data-file-raw requires a data file");
+ ret = -EINVAL;
+ goto fail;
+ }
}
}
@@ -1839,7 +1842,7 @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
fail:
g_free(s->image_data_file);
- if (has_data_file(bs)) {
+ if (open_data_file && has_data_file(bs)) {
bdrv_unref_child(bs, s->data_file);
s->data_file = NULL;
}
@@ -1876,7 +1879,8 @@ static void coroutine_fn qcow2_open_entry(void *opaque)
BDRVQcow2State *s = qoc->bs->opaque;
qemu_co_mutex_lock(&s->lock);
- qoc->ret = qcow2_do_open(qoc->bs, qoc->options, qoc->flags, qoc->errp);
+ qoc->ret = qcow2_do_open(qoc->bs, qoc->options, qoc->flags, true,
+ qoc->errp);
qemu_co_mutex_unlock(&s->lock);
}
@@ -2714,7 +2718,7 @@ static int qcow2_inactivate(BlockDriverState *bs)
return result;
}
-static void qcow2_close(BlockDriverState *bs)
+static void qcow2_do_close(BlockDriverState *bs, bool close_data_file)
{
BDRVQcow2State *s = bs->opaque;
qemu_vfree(s->l1_table);
@@ -2740,7 +2744,7 @@ static void qcow2_close(BlockDriverState *bs)
g_free(s->image_backing_file);
g_free(s->image_backing_format);
- if (has_data_file(bs)) {
+ if (close_data_file && has_data_file(bs)) {
bdrv_unref_child(bs, s->data_file);
s->data_file = NULL;
}
@@ -2749,11 +2753,17 @@ static void qcow2_close(BlockDriverState *bs)
qcow2_free_snapshots(bs);
}
+static void qcow2_close(BlockDriverState *bs)
+{
+ qcow2_do_close(bs, true);
+}
+
static void coroutine_fn qcow2_co_invalidate_cache(BlockDriverState *bs,
Error **errp)
{
ERRP_GUARD();
BDRVQcow2State *s = bs->opaque;
+ BdrvChild *data_file;
int flags = s->flags;
QCryptoBlock *crypto = NULL;
QDict *options;
@@ -2767,14 +2777,24 @@ static void coroutine_fn qcow2_co_invalidate_cache(BlockDriverState *bs,
crypto = s->crypto;
s->crypto = NULL;
- qcow2_close(bs);
+ /*
+ * Do not reopen s->data_file (i.e., have qcow2_do_close() not close it,
+ * and then prevent qcow2_do_open() from opening it), because this function
+ * runs in the I/O path and as such we must not invoke global-state
+ * functions like bdrv_unref_child() and bdrv_open_child().
+ */
+ qcow2_do_close(bs, false);
+
+ data_file = s->data_file;
memset(s, 0, sizeof(BDRVQcow2State));
+ s->data_file = data_file;
+
options = qdict_clone_shallow(bs->options);
flags &= ~BDRV_O_INACTIVE;
qemu_co_mutex_lock(&s->lock);
- ret = qcow2_do_open(bs, options, flags, errp);
+ ret = qcow2_do_open(bs, options, flags, false, errp);
qemu_co_mutex_unlock(&s->lock);
qobject_unref(options);
if (ret < 0) {
--
2.35.1
next prev parent reply other threads:[~2022-05-04 14:34 UTC|newest]
Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-05-04 14:25 [PULL 00/13] Block layer patches Kevin Wolf
2022-05-04 14:25 ` [PULL 01/13] qemu-img: properly list formats which have consistency check implemented Kevin Wolf
2022-05-04 14:25 ` [PULL 02/13] docs/vhost-user: Clarifications for VHOST_USER_ADD/REM_MEM_REG Kevin Wolf
2022-05-04 14:25 ` [PULL 03/13] libvhost-user: Fix extra vu_add/rem_mem_reg reply Kevin Wolf
2022-05-04 14:25 ` [PULL 04/13] vhost-user: Don't pass file descriptor for VHOST_USER_REM_MEM_REG Kevin Wolf
2022-05-04 14:25 ` [PULL 05/13] block: Classify bdrv_get_flags() as I/O function Kevin Wolf
2022-05-04 14:25 ` Kevin Wolf [this message]
2022-05-04 14:25 ` [PULL 07/13] Revert "main-loop: Disable GLOBAL_STATE_CODE() assertions" Kevin Wolf
2022-05-04 14:25 ` [PULL 08/13] iotests: Add regression test for issue 945 Kevin Wolf
2022-05-04 14:25 ` [PULL 09/13] block/vmdk: Fix reopening bs->file Kevin Wolf
2022-05-04 14:25 ` [PULL 10/13] iotests/reopen-file: Test reopening file child Kevin Wolf
2022-05-04 14:25 ` [PULL 11/13] coroutine-ucontext: use QEMU_DEFINE_STATIC_CO_TLS() Kevin Wolf
2022-05-13 15:27 ` Peter Maydell
2022-05-13 15:54 ` Kevin Wolf
2022-05-04 14:25 ` [PULL 12/13] coroutine: " Kevin Wolf
2022-05-04 14:25 ` [PULL 13/13] coroutine-win32: " Kevin Wolf
2022-05-05 13:09 ` [PULL 00/13] Block layer patches Richard Henderson
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20220504142522.167506-7-kwolf@redhat.com \
--to=kwolf@redhat.com \
--cc=qemu-block@nongnu.org \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).