qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] block: bdrv_set_backing_hd(): use drained section
@ 2022-01-24 17:37 Vladimir Sementsov-Ogievskiy
  2022-01-25  9:24 ` Paolo Bonzini
  2022-01-27 14:14 ` Kevin Wolf
  0 siblings, 2 replies; 7+ messages in thread
From: Vladimir Sementsov-Ogievskiy @ 2022-01-24 17:37 UTC (permalink / raw)
  To: qemu-block; +Cc: qemu-devel, hreitz, kwolf, vsementsov, den

Graph modifications should be done in drained section. stream_prepare()
handler of block stream job call bdrv_set_backing_hd() without using
drained section and it's theoretically possible that some IO request
will interleave with graph modification and will use outdated pointers
to removed block nodes.

Some other callers use bdrv_set_backing_hd() not caring about drained
sections too. So it seems good to make a drained section exactly in
bdrv_set_backing_hd().

Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
---

Hi all!

We faced the following bug in our Rhel7-based downstream:
read request crashes because backing bs is NULL unexpectedly (honestly,
it crashes inside bdrv_is_allocated(), which is called during read and
it's a downstream-only code, but that doesn't make real sense).

In gdb I also see block-stream job in state
"refcnt = 0, status = JOB_STATUS_NULL", but it's still in jobs list.

So, I assume that backing file was disappeared exactly as final step of
block-stream job. And the problem is that this step should be done in
drained section, but seems that it isn't.

If we have a drained section, we'd wait for finish of read request
before removing the backing node.

I don't have a reproducer. I spent some time to write a test, but there
are problems that makes hard to use blkdebug's break-points: we have
drained section at block-stream start, and we do have drained section at
block-stream finish: bdrv_cor_filter_drop() called from stream_prepare()
does drained section (unlike bdrv_set_backing_hd()).

So, the fix is intuitive. I think, it's correct)

Note also, that alternative would be to make a drained section in
stream_prepare() and don't touch bdrv_set_backing_hd() function. But it
seems good to make a public graph-modification function more safe.

 block.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/block.c b/block.c
index 7b3ce415d8..b54d59d1fa 100644
--- a/block.c
+++ b/block.c
@@ -3341,6 +3341,8 @@ int bdrv_set_backing_hd(BlockDriverState *bs, BlockDriverState *backing_hd,
     int ret;
     Transaction *tran = tran_new();
 
+    bdrv_drained_begin(bs);
+
     ret = bdrv_set_backing_noperm(bs, backing_hd, tran, errp);
     if (ret < 0) {
         goto out;
@@ -3350,6 +3352,8 @@ int bdrv_set_backing_hd(BlockDriverState *bs, BlockDriverState *backing_hd,
 out:
     tran_finalize(tran, ret);
 
+    bdrv_drained_end(bs);
+
     return ret;
 }
 
-- 
2.31.1



^ permalink raw reply related	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2022-02-01 11:08 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2022-01-24 17:37 [PATCH] block: bdrv_set_backing_hd(): use drained section Vladimir Sementsov-Ogievskiy
2022-01-25  9:24 ` Paolo Bonzini
2022-01-25 10:12   ` Vladimir Sementsov-Ogievskiy
2022-01-27 14:13     ` Kevin Wolf
2022-01-28 14:12       ` Emanuele Giuseppe Esposito
2022-02-01 11:00         ` Vladimir Sementsov-Ogievskiy
2022-01-27 14:14 ` Kevin Wolf

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).