1
The following changes since commit 42f6c9179be4401974dd3a75ee72defd16b5092d:
1
The following changes since commit cf7ca7d5b9faca13f1f8e3ea92cfb2f741eb0c0e:
2
2
3
Merge tag 'pull-ppc-20211112' of https://github.com/legoater/qemu into staging (2021-11-12 12:28:25 +0100)
3
Merge remote-tracking branch 'remotes/stefanha-gitlab/tags/tracing-pull-request' into staging (2021-02-01 16:28:00 +0000)
4
4
5
are available in the Git repository at:
5
are available in the Git repository at:
6
6
7
git://repo.or.cz/qemu/kevin.git tags/for-upstream
7
git://repo.or.cz/qemu/kevin.git tags/for-upstream
8
8
9
for you to fetch changes up to 7461272c5f6032436ef9032c091c0118539483e4:
9
for you to fetch changes up to 26513a01741f51650f5dd716681995359794ba6f:
10
10
11
softmmu/qdev-monitor: fix use-after-free in qdev_set_id() (2021-11-15 15:49:46 +0100)
11
block: Fix VM size column width in bdrv_snapshot_dump() (2021-02-02 17:23:55 +0100)
12
12
13
----------------------------------------------------------------
13
----------------------------------------------------------------
14
Block layer patches
14
Block layer patches:
15
15
16
- Fixes to image streaming job and block layer reconfiguration to make
16
- Fix double processing of nodes in bdrv_set_aio_context()
17
iotest 030 pass again
17
- Fix potential hang in block export shutdown
18
- docs: Deprecate incorrectly typed device_add arguments
18
- block/nvme: Minor tracing improvements
19
- file-posix: Fix alignment after reopen changing O_DIRECT
19
- iotests: Some more fixups for the 'check' rewrite
20
- MAINTAINERS: Add Vladimir as co-maintainer for Block Jobs
20
21
21
----------------------------------------------------------------
22
----------------------------------------------------------------
22
Hanna Reitz (10):
23
Kevin Wolf (3):
23
stream: Traverse graph after modification
24
iotests: Revert emulator selection to old behaviour
24
block: Manipulate children list in .attach/.detach
25
iotests: Fix -makecheck output
25
block: Unite remove_empty_child and child_free
26
block: Fix VM size column width in bdrv_snapshot_dump()
26
block: Drop detached child from ignore list
27
block: Pass BdrvChild ** to replace_child_noperm
28
block: Restructure remove_file_or_backing_child()
29
transactions: Invoke clean() after everything else
30
block: Let replace_child_tran keep indirect pointer
31
block: Let replace_child_noperm free children
32
iotests/030: Unthrottle parallel jobs in reverse
33
27
34
Kevin Wolf (2):
28
Philippe Mathieu-Daudé (2):
35
docs: Deprecate incorrectly typed device_add arguments
29
block/nvme: Properly display doorbell stride length in trace event
36
file-posix: Fix alignment after reopen changing O_DIRECT
30
block/nvme: Trace NVMe spec version supported by the controller
37
31
38
Stefan Hajnoczi (1):
32
Sergio Lopez (2):
39
softmmu/qdev-monitor: fix use-after-free in qdev_set_id()
33
block: Avoid processing BDS twice in bdrv_set_aio_context_ignore()
34
block: move blk_exp_close_all() to qemu_cleanup()
40
35
41
docs/about/deprecated.rst | 14 +++
36
Vladimir Sementsov-Ogievskiy (3):
42
include/qemu/transactions.h | 3 +
37
MAINTAINERS: Add Vladimir as co-maintainer for Block Jobs
43
block.c | 233 +++++++++++++++++++++++++++++++++-----------
38
iotests/297: pylint: ignore too many statements
44
block/file-posix.c | 20 +++-
39
iotests: check: return 1 on failure
45
block/stream.c | 7 +-
40
46
softmmu/qdev-monitor.c | 2 +-
41
block.c | 35 +++++++++++++++++++++++++++--------
47
util/transactions.c | 8 +-
42
block/nvme.c | 8 +++++++-
48
tests/qemu-iotests/030 | 11 ++-
43
block/qapi.c | 4 ++--
49
tests/qemu-iotests/142 | 22 +++++
44
qemu-nbd.c | 1 +
50
tests/qemu-iotests/142.out | 15 +++
45
softmmu/runstate.c | 9 +++++++++
51
10 files changed, 269 insertions(+), 66 deletions(-)
46
storage-daemon/qemu-storage-daemon.c | 1 +
47
tests/qemu-iotests/testenv.py | 2 +-
48
tests/qemu-iotests/testrunner.py | 10 +++++++---
49
MAINTAINERS | 10 ++++++++++
50
block/trace-events | 1 +
51
tests/qemu-iotests/check | 5 ++++-
52
tests/qemu-iotests/pylintrc | 2 ++
53
12 files changed, 72 insertions(+), 16 deletions(-)
52
54
53
55
diff view generated by jsdifflib
Deleted patch
1
From: Hanna Reitz <hreitz@redhat.com>
2
1
3
bdrv_cor_filter_drop() modifies the block graph. That means that other
4
parties can also modify the block graph before it returns. Therefore,
5
we cannot assume that the result of a graph traversal we did before
6
remains valid afterwards.
7
8
We should thus fetch `base` and `unfiltered_base` afterwards instead of
9
before.
10
11
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
12
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
13
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
14
Message-Id: <20211111120829.81329-2-hreitz@redhat.com>
15
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
16
---
17
block/stream.c | 7 +++++--
18
1 file changed, 5 insertions(+), 2 deletions(-)
19
20
diff --git a/block/stream.c b/block/stream.c
21
index XXXXXXX..XXXXXXX 100644
22
--- a/block/stream.c
23
+++ b/block/stream.c
24
@@ -XXX,XX +XXX,XX @@ static int stream_prepare(Job *job)
25
{
26
StreamBlockJob *s = container_of(job, StreamBlockJob, common.job);
27
BlockDriverState *unfiltered_bs = bdrv_skip_filters(s->target_bs);
28
- BlockDriverState *base = bdrv_filter_or_cow_bs(s->above_base);
29
- BlockDriverState *unfiltered_base = bdrv_skip_filters(base);
30
+ BlockDriverState *base;
31
+ BlockDriverState *unfiltered_base;
32
Error *local_err = NULL;
33
int ret = 0;
34
35
@@ -XXX,XX +XXX,XX @@ static int stream_prepare(Job *job)
36
bdrv_cor_filter_drop(s->cor_filter_bs);
37
s->cor_filter_bs = NULL;
38
39
+ base = bdrv_filter_or_cow_bs(s->above_base);
40
+ unfiltered_base = bdrv_skip_filters(base);
41
+
42
if (bdrv_cow_child(unfiltered_bs)) {
43
const char *base_id = NULL, *base_fmt = NULL;
44
if (unfiltered_base) {
45
--
46
2.31.1
47
48
diff view generated by jsdifflib
Deleted patch
1
From: Hanna Reitz <hreitz@redhat.com>
2
1
3
The children list is specific to BDS parents. We should not modify it
4
in the general children modification code, but let BDS parents deal with
5
it in their .attach() and .detach() methods.
6
7
This also has the advantage that a BdrvChild is removed from the
8
children list before its .bs pointer can become NULL. BDS parents
9
generally assume that their children's .bs pointer is never NULL, so
10
this is actually a bug fix.
11
12
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
13
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
14
Message-Id: <20211111120829.81329-3-hreitz@redhat.com>
15
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
16
---
17
block.c | 14 +++++---------
18
1 file changed, 5 insertions(+), 9 deletions(-)
19
20
diff --git a/block.c b/block.c
21
index XXXXXXX..XXXXXXX 100644
22
--- a/block.c
23
+++ b/block.c
24
@@ -XXX,XX +XXX,XX @@ static void bdrv_child_cb_attach(BdrvChild *child)
25
{
26
BlockDriverState *bs = child->opaque;
27
28
+ QLIST_INSERT_HEAD(&bs->children, child, next);
29
+
30
if (child->role & BDRV_CHILD_COW) {
31
bdrv_backing_attach(child);
32
}
33
@@ -XXX,XX +XXX,XX @@ static void bdrv_child_cb_detach(BdrvChild *child)
34
}
35
36
bdrv_unapply_subtree_drain(child, bs);
37
+
38
+ QLIST_REMOVE(child, next);
39
}
40
41
static int bdrv_child_cb_update_filename(BdrvChild *c, BlockDriverState *base,
42
@@ -XXX,XX +XXX,XX @@ static void bdrv_child_free(void *opaque)
43
static void bdrv_remove_empty_child(BdrvChild *child)
44
{
45
assert(!child->bs);
46
- QLIST_SAFE_REMOVE(child, next);
47
+ assert(!child->next.le_prev); /* not in children list */
48
bdrv_child_free(child);
49
}
50
51
@@ -XXX,XX +XXX,XX @@ static int bdrv_attach_child_noperm(BlockDriverState *parent_bs,
52
return ret;
53
}
54
55
- QLIST_INSERT_HEAD(&parent_bs->children, *child, next);
56
- /*
57
- * child is removed in bdrv_attach_child_common_abort(), so don't care to
58
- * abort this change separately.
59
- */
60
-
61
return 0;
62
}
63
64
@@ -XXX,XX +XXX,XX @@ static void bdrv_remove_filter_or_cow_child_abort(void *opaque)
65
BdrvRemoveFilterOrCowChild *s = opaque;
66
BlockDriverState *parent_bs = s->child->opaque;
67
68
- QLIST_INSERT_HEAD(&parent_bs->children, s->child, next);
69
if (s->is_backing) {
70
parent_bs->backing = s->child;
71
} else {
72
@@ -XXX,XX +XXX,XX @@ static void bdrv_remove_file_or_backing_child(BlockDriverState *bs,
73
};
74
tran_add(tran, &bdrv_remove_filter_or_cow_child_drv, s);
75
76
- QLIST_SAFE_REMOVE(child, next);
77
if (s->is_backing) {
78
bs->backing = NULL;
79
} else {
80
--
81
2.31.1
82
83
diff view generated by jsdifflib
Deleted patch
1
From: Hanna Reitz <hreitz@redhat.com>
2
1
3
Now that bdrv_remove_empty_child() no longer removes the child from the
4
parent's children list but only checks that it is not in such a list, it
5
is only a wrapper around bdrv_child_free() that checks that the child is
6
empty and unused. That should apply to all children that we free, so
7
put those checks into bdrv_child_free() and drop
8
bdrv_remove_empty_child().
9
10
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
11
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
12
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
13
Message-Id: <20211111120829.81329-4-hreitz@redhat.com>
14
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
15
---
16
block.c | 26 +++++++++++++-------------
17
1 file changed, 13 insertions(+), 13 deletions(-)
18
19
diff --git a/block.c b/block.c
20
index XXXXXXX..XXXXXXX 100644
21
--- a/block.c
22
+++ b/block.c
23
@@ -XXX,XX +XXX,XX @@ static void bdrv_replace_child_noperm(BdrvChild *child,
24
}
25
}
26
27
-static void bdrv_child_free(void *opaque)
28
-{
29
- BdrvChild *c = opaque;
30
-
31
- g_free(c->name);
32
- g_free(c);
33
-}
34
-
35
-static void bdrv_remove_empty_child(BdrvChild *child)
36
+/**
37
+ * Free the given @child.
38
+ *
39
+ * The child must be empty (i.e. `child->bs == NULL`) and it must be
40
+ * unused (i.e. not in a children list).
41
+ */
42
+static void bdrv_child_free(BdrvChild *child)
43
{
44
assert(!child->bs);
45
assert(!child->next.le_prev); /* not in children list */
46
- bdrv_child_free(child);
47
+
48
+ g_free(child->name);
49
+ g_free(child);
50
}
51
52
typedef struct BdrvAttachChildCommonState {
53
@@ -XXX,XX +XXX,XX @@ static void bdrv_attach_child_common_abort(void *opaque)
54
}
55
56
bdrv_unref(bs);
57
- bdrv_remove_empty_child(child);
58
+ bdrv_child_free(child);
59
*s->child = NULL;
60
}
61
62
@@ -XXX,XX +XXX,XX @@ static int bdrv_attach_child_common(BlockDriverState *child_bs,
63
64
if (ret < 0) {
65
error_propagate(errp, local_err);
66
- bdrv_remove_empty_child(new_child);
67
+ bdrv_child_free(new_child);
68
return ret;
69
}
70
}
71
@@ -XXX,XX +XXX,XX @@ static void bdrv_detach_child(BdrvChild *child)
72
BlockDriverState *old_bs = child->bs;
73
74
bdrv_replace_child_noperm(child, NULL);
75
- bdrv_remove_empty_child(child);
76
+ bdrv_child_free(child);
77
78
if (old_bs) {
79
/*
80
--
81
2.31.1
82
83
diff view generated by jsdifflib
1
At the end of a reopen, we already call bdrv_refresh_limits(), which
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
should update bs->request_alignment according to the new file
3
descriptor. However, raw_probe_alignment() relies on s->needs_alignment
4
and just uses 1 if it isn't set. We neglected to update this field, so
5
starting with cache=writeback and then reopening with cache=none means
6
that we get an incorrect bs->request_alignment == 1 and unaligned
7
requests fail instead of being automatically aligned.
8
2
9
Fix this by recalculating s->needs_alignment in raw_refresh_limits()
3
I'm developing Qemu backup for several years, and finally new backup
10
before calling raw_probe_alignment().
4
architecture, including block-copy generic engine and backup-top filter
5
landed upstream, great thanks to reviewers and especially to
6
Max Reitz!
11
7
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
I also have plans of moving other block-jobs onto block-copy, so that
13
Message-Id: <20211104113109.56336-1-kwolf@redhat.com>
9
we finally have one generic block copying path, fast and well-formed.
14
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
10
15
Reviewed-by: Stefano Garzarella <sgarzare@redhat.com>
11
So, now I suggest to bring all parts of backup architecture into
12
"Block Jobs" subsystem (actually, aio_task is shared with qcow2 and
13
qemu-co-shared-resource can be reused somewhere else, but I'd keep an
14
eye on them in context of block-jobs) and add myself as co-maintainer.
15
16
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
17
Message-Id: <20210128144144.27617-1-vsementsov@virtuozzo.com>
18
Reviewed-by: Markus Armbruster <armbru@redhat.com>
19
Reviewed-by: John Snow <jsnow@redhat.com>
20
Reviewed-by: Max Reitz <mreitz@redhat.com>
16
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
21
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
17
---
22
---
18
block/file-posix.c | 20 ++++++++++++++++----
23
MAINTAINERS | 10 ++++++++++
19
tests/qemu-iotests/142 | 22 ++++++++++++++++++++++
24
1 file changed, 10 insertions(+)
20
tests/qemu-iotests/142.out | 15 +++++++++++++++
21
3 files changed, 53 insertions(+), 4 deletions(-)
22
25
23
diff --git a/block/file-posix.c b/block/file-posix.c
26
diff --git a/MAINTAINERS b/MAINTAINERS
24
index XXXXXXX..XXXXXXX 100644
27
index XXXXXXX..XXXXXXX 100644
25
--- a/block/file-posix.c
28
--- a/MAINTAINERS
26
+++ b/block/file-posix.c
29
+++ b/MAINTAINERS
27
@@ -XXX,XX +XXX,XX @@ typedef struct BDRVRawState {
30
@@ -XXX,XX +XXX,XX @@ F: scsi/*
28
int page_cache_inconsistent; /* errno from fdatasync failure */
31
29
bool has_fallocate;
32
Block Jobs
30
bool needs_alignment;
33
M: John Snow <jsnow@redhat.com>
31
+ bool force_alignment;
34
+M: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
32
bool drop_cache;
35
L: qemu-block@nongnu.org
33
bool check_cache_dropped;
36
S: Supported
34
struct {
37
F: blockjob.c
35
@@ -XXX,XX +XXX,XX @@ static bool dio_byte_aligned(int fd)
38
@@ -XXX,XX +XXX,XX @@ F: block/commit.c
36
return false;
39
F: block/stream.c
37
}
40
F: block/mirror.c
38
41
F: qapi/job.json
39
+static bool raw_needs_alignment(BlockDriverState *bs)
42
+F: block/block-copy.c
40
+{
43
+F: include/block/block-copy.c
41
+ BDRVRawState *s = bs->opaque;
44
+F: block/backup-top.h
42
+
45
+F: block/backup-top.c
43
+ if ((bs->open_flags & BDRV_O_NOCACHE) != 0 && !dio_byte_aligned(s->fd)) {
46
+F: include/block/aio_task.h
44
+ return true;
47
+F: block/aio_task.c
45
+ }
48
+F: util/qemu-co-shared-resource.c
46
+
49
+F: include/qemu/co-shared-resource.h
47
+ return s->force_alignment;
50
T: git https://gitlab.com/jsnow/qemu.git jobs
48
+}
51
+T: git https://src.openvz.org/scm/~vsementsov/qemu.git jobs
49
+
52
50
/* Check if read is allowed with given memory buffer and length.
53
Block QAPI, monitor, command line
51
*
54
M: Markus Armbruster <armbru@redhat.com>
52
* This function is used to check O_DIRECT memory buffer and request alignment.
53
@@ -XXX,XX +XXX,XX @@ static int raw_open_common(BlockDriverState *bs, QDict *options,
54
55
s->has_discard = true;
56
s->has_write_zeroes = true;
57
- if ((bs->open_flags & BDRV_O_NOCACHE) != 0 && !dio_byte_aligned(s->fd)) {
58
- s->needs_alignment = true;
59
- }
60
61
if (fstat(s->fd, &st) < 0) {
62
ret = -errno;
63
@@ -XXX,XX +XXX,XX @@ static int raw_open_common(BlockDriverState *bs, QDict *options,
64
* so QEMU makes sure all IO operations on the device are aligned
65
* to sector size, or else FreeBSD will reject them with EINVAL.
66
*/
67
- s->needs_alignment = true;
68
+ s->force_alignment = true;
69
}
70
#endif
71
+ s->needs_alignment = raw_needs_alignment(bs);
72
73
#ifdef CONFIG_XFS
74
if (platform_test_xfs_fd(s->fd)) {
75
@@ -XXX,XX +XXX,XX @@ static void raw_refresh_limits(BlockDriverState *bs, Error **errp)
76
BDRVRawState *s = bs->opaque;
77
struct stat st;
78
79
+ s->needs_alignment = raw_needs_alignment(bs);
80
raw_probe_alignment(bs, s->fd, errp);
81
+
82
bs->bl.min_mem_alignment = s->buf_align;
83
bs->bl.opt_mem_alignment = MAX(s->buf_align, qemu_real_host_page_size);
84
85
diff --git a/tests/qemu-iotests/142 b/tests/qemu-iotests/142
86
index XXXXXXX..XXXXXXX 100755
87
--- a/tests/qemu-iotests/142
88
+++ b/tests/qemu-iotests/142
89
@@ -XXX,XX +XXX,XX @@ info block backing-file"
90
91
echo "$hmp_cmds" | run_qemu -drive "$files","$ids" | grep "Cache"
92
93
+echo
94
+echo "--- Alignment after changing O_DIRECT ---"
95
+echo
96
+
97
+# Directly test the protocol level: Can unaligned requests succeed even if
98
+# O_DIRECT was only enabled through a reopen and vice versa?
99
+
100
+$QEMU_IO --cache=writeback -f file $TEST_IMG <<EOF | _filter_qemu_io
101
+read 42 42
102
+reopen -o cache.direct=on
103
+read 42 42
104
+reopen -o cache.direct=off
105
+read 42 42
106
+EOF
107
+$QEMU_IO --cache=none -f file $TEST_IMG <<EOF | _filter_qemu_io
108
+read 42 42
109
+reopen -o cache.direct=off
110
+read 42 42
111
+reopen -o cache.direct=on
112
+read 42 42
113
+EOF
114
+
115
# success, all done
116
echo "*** done"
117
rm -f $seq.full
118
diff --git a/tests/qemu-iotests/142.out b/tests/qemu-iotests/142.out
119
index XXXXXXX..XXXXXXX 100644
120
--- a/tests/qemu-iotests/142.out
121
+++ b/tests/qemu-iotests/142.out
122
@@ -XXX,XX +XXX,XX @@ cache.no-flush=on on backing-file
123
Cache mode: writeback
124
Cache mode: writeback, direct
125
Cache mode: writeback, ignore flushes
126
+
127
+--- Alignment after changing O_DIRECT ---
128
+
129
+read 42/42 bytes at offset 42
130
+42 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
131
+read 42/42 bytes at offset 42
132
+42 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
133
+read 42/42 bytes at offset 42
134
+42 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
135
+read 42/42 bytes at offset 42
136
+42 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
137
+read 42/42 bytes at offset 42
138
+42 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
139
+read 42/42 bytes at offset 42
140
+42 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
141
*** done
142
--
55
--
143
2.31.1
56
2.29.2
144
57
145
58
diff view generated by jsdifflib
1
From: Hanna Reitz <hreitz@redhat.com>
1
From: Sergio Lopez <slp@redhat.com>
2
2
3
As of a future patch, bdrv_replace_child_tran() will take a BdrvChild **
3
Some graphs may contain an indirect reference to the first BDS in the
4
pointer. Prepare for that by getting such a pointer and using it where
4
chain that can be reached while walking it bottom->up from one its
5
applicable, and (dereferenced) as a parameter for
5
children.
6
bdrv_replace_child_tran().
7
6
8
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
7
Doubling-processing of a BDS is especially problematic for the
9
Message-Id: <20211111120829.81329-7-hreitz@redhat.com>
8
aio_notifiers, as they might attempt to work on both the old and the
10
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
9
new AIO contexts.
10
11
To avoid this problem, add every child and parent to the ignore list
12
before actually processing them.
13
14
Suggested-by: Kevin Wolf <kwolf@redhat.com>
15
Signed-off-by: Sergio Lopez <slp@redhat.com>
16
Message-Id: <20210201125032.44713-2-slp@redhat.com>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
17
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
---
18
---
13
block.c | 21 ++++++++++++---------
19
block.c | 34 +++++++++++++++++++++++++++-------
14
1 file changed, 12 insertions(+), 9 deletions(-)
20
1 file changed, 27 insertions(+), 7 deletions(-)
15
21
16
diff --git a/block.c b/block.c
22
diff --git a/block.c b/block.c
17
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
18
--- a/block.c
24
--- a/block.c
19
+++ b/block.c
25
+++ b/block.c
20
@@ -XXX,XX +XXX,XX @@ static void bdrv_remove_file_or_backing_child(BlockDriverState *bs,
26
@@ -XXX,XX +XXX,XX @@ void bdrv_set_aio_context_ignore(BlockDriverState *bs,
21
BdrvChild *child,
27
AioContext *new_context, GSList **ignore)
22
Transaction *tran)
23
{
28
{
24
+ BdrvChild **childp;
29
AioContext *old_context = bdrv_get_aio_context(bs);
25
BdrvRemoveFilterOrCowChild *s;
30
- BdrvChild *child;
26
31
+ GSList *children_to_process = NULL;
27
- assert(child == bs->backing || child == bs->file);
32
+ GSList *parents_to_process = NULL;
28
-
33
+ GSList *entry;
29
if (!child) {
34
+ BdrvChild *child, *parent;
30
return;
35
36
g_assert(qemu_get_current_aio_context() == qemu_get_aio_context());
37
38
@@ -XXX,XX +XXX,XX @@ void bdrv_set_aio_context_ignore(BlockDriverState *bs,
39
continue;
40
}
41
*ignore = g_slist_prepend(*ignore, child);
42
- bdrv_set_aio_context_ignore(child->bs, new_context, ignore);
43
+ children_to_process = g_slist_prepend(children_to_process, child);
31
}
44
}
32
45
- QLIST_FOREACH(child, &bs->parents, next_parent) {
33
+ if (child == bs->backing) {
46
- if (g_slist_find(*ignore, child)) {
34
+ childp = &bs->backing;
47
+
35
+ } else if (child == bs->file) {
48
+ QLIST_FOREACH(parent, &bs->parents, next_parent) {
36
+ childp = &bs->file;
49
+ if (g_slist_find(*ignore, parent)) {
37
+ } else {
50
continue;
38
+ g_assert_not_reached();
51
}
52
- assert(child->klass->set_aio_ctx);
53
- *ignore = g_slist_prepend(*ignore, child);
54
- child->klass->set_aio_ctx(child, new_context, ignore);
55
+ *ignore = g_slist_prepend(*ignore, parent);
56
+ parents_to_process = g_slist_prepend(parents_to_process, parent);
39
+ }
57
+ }
40
+
58
+
41
if (child->bs) {
59
+ for (entry = children_to_process;
42
- bdrv_replace_child_tran(child, NULL, tran);
60
+ entry != NULL;
43
+ bdrv_replace_child_tran(*childp, NULL, tran);
61
+ entry = g_slist_next(entry)) {
62
+ child = entry->data;
63
+ bdrv_set_aio_context_ignore(child->bs, new_context, ignore);
64
+ }
65
+ g_slist_free(children_to_process);
66
+
67
+ for (entry = parents_to_process;
68
+ entry != NULL;
69
+ entry = g_slist_next(entry)) {
70
+ parent = entry->data;
71
+ assert(parent->klass->set_aio_ctx);
72
+ parent->klass->set_aio_ctx(parent, new_context, ignore);
44
}
73
}
45
74
+ g_slist_free(parents_to_process);
46
s = g_new(BdrvRemoveFilterOrCowChild, 1);
75
47
*s = (BdrvRemoveFilterOrCowChild) {
76
bdrv_detach_aio_context(bs);
48
.child = child,
77
49
- .is_backing = (child == bs->backing),
50
+ .is_backing = (childp == &bs->backing),
51
};
52
tran_add(tran, &bdrv_remove_filter_or_cow_child_drv, s);
53
54
- if (s->is_backing) {
55
- bs->backing = NULL;
56
- } else {
57
- bs->file = NULL;
58
- }
59
+ *childp = NULL;
60
}
61
62
/*
63
--
78
--
64
2.31.1
79
2.29.2
65
80
66
81
diff view generated by jsdifflib
1
From: Hanna Reitz <hreitz@redhat.com>
1
From: Sergio Lopez <slp@redhat.com>
2
2
3
bdrv_attach_child_common_abort() restores the parent's AioContext. To
3
Move blk_exp_close_all() from bdrv_close() to qemu_cleanup(), before
4
do so, the child (which was supposed to be attached, but is now detached
4
bdrv_drain_all_begin().
5
again by this abort handler) is added to the ignore list for the
6
AioContext changing functions.
7
5
8
However, since we modify a BDS's children list in the BdrvChildClass's
6
Export drivers may have coroutines yielding at some point in the block
9
.attach and .detach handlers, the child is already effectively detached
7
layer, so we need to shut them down before draining the block layer,
10
from the parent by this point. We do not need to put it into the ignore
8
as otherwise they may get stuck blk_wait_while_drained().
11
list.
12
9
13
Use this opportunity to clean up the empty line structure: Keep setting
10
RHBZ: https://bugzilla.redhat.com/show_bug.cgi?id=1900505
14
the ignore list, invoking the AioContext function, and freeing the
11
Signed-off-by: Sergio Lopez <slp@redhat.com>
15
ignore list in blocks separated by empty lines.
12
Message-Id: <20210201125032.44713-3-slp@redhat.com>
16
17
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
18
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
19
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
20
Message-Id: <20211111120829.81329-5-hreitz@redhat.com>
21
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
22
---
14
---
23
block.c | 8 +++++---
15
block.c | 1 -
24
1 file changed, 5 insertions(+), 3 deletions(-)
16
qemu-nbd.c | 1 +
17
softmmu/runstate.c | 9 +++++++++
18
storage-daemon/qemu-storage-daemon.c | 1 +
19
4 files changed, 11 insertions(+), 1 deletion(-)
25
20
26
diff --git a/block.c b/block.c
21
diff --git a/block.c b/block.c
27
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
28
--- a/block.c
23
--- a/block.c
29
+++ b/block.c
24
+++ b/block.c
30
@@ -XXX,XX +XXX,XX @@ static void bdrv_attach_child_common_abort(void *opaque)
25
@@ -XXX,XX +XXX,XX @@ static void bdrv_close(BlockDriverState *bs)
26
void bdrv_close_all(void)
27
{
28
assert(job_next(NULL) == NULL);
29
- blk_exp_close_all();
30
31
/* Drop references from requests still in flight, such as canceled block
32
* jobs whose AIO context has not been polled yet */
33
diff --git a/qemu-nbd.c b/qemu-nbd.c
34
index XXXXXXX..XXXXXXX 100644
35
--- a/qemu-nbd.c
36
+++ b/qemu-nbd.c
37
@@ -XXX,XX +XXX,XX @@ static const char *socket_activation_validate_opts(const char *device,
38
static void qemu_nbd_shutdown(void)
39
{
40
job_cancel_sync_all();
41
+ blk_exp_close_all();
42
bdrv_close_all();
43
}
44
45
diff --git a/softmmu/runstate.c b/softmmu/runstate.c
46
index XXXXXXX..XXXXXXX 100644
47
--- a/softmmu/runstate.c
48
+++ b/softmmu/runstate.c
49
@@ -XXX,XX +XXX,XX @@
50
#include "qemu/osdep.h"
51
#include "audio/audio.h"
52
#include "block/block.h"
53
+#include "block/export.h"
54
#include "chardev/char.h"
55
#include "crypto/cipher.h"
56
#include "crypto/init.h"
57
@@ -XXX,XX +XXX,XX @@ void qemu_cleanup(void)
58
*/
59
migration_shutdown();
60
61
+ /*
62
+ * Close the exports before draining the block layer. The export
63
+ * drivers may have coroutines yielding on it, so we need to clean
64
+ * them up before the drain, as otherwise they may be get stuck in
65
+ * blk_wait_while_drained().
66
+ */
67
+ blk_exp_close_all();
68
+
69
/*
70
* We must cancel all block jobs while the block layer is drained,
71
* or cancelling will be affected by throttling and thus may block
72
diff --git a/storage-daemon/qemu-storage-daemon.c b/storage-daemon/qemu-storage-daemon.c
73
index XXXXXXX..XXXXXXX 100644
74
--- a/storage-daemon/qemu-storage-daemon.c
75
+++ b/storage-daemon/qemu-storage-daemon.c
76
@@ -XXX,XX +XXX,XX @@ int main(int argc, char *argv[])
77
main_loop_wait(false);
31
}
78
}
32
79
33
if (bdrv_child_get_parent_aio_context(child) != s->old_parent_ctx) {
80
+ blk_exp_close_all();
34
- GSList *ignore = g_slist_prepend(NULL, child);
81
bdrv_drain_all_begin();
35
+ GSList *ignore;
82
bdrv_close_all();
36
37
+ /* No need to ignore `child`, because it has been detached already */
38
+ ignore = NULL;
39
child->klass->can_set_aio_ctx(child, s->old_parent_ctx, &ignore,
40
&error_abort);
41
g_slist_free(ignore);
42
- ignore = g_slist_prepend(NULL, child);
43
- child->klass->set_aio_ctx(child, s->old_parent_ctx, &ignore);
44
45
+ ignore = NULL;
46
+ child->klass->set_aio_ctx(child, s->old_parent_ctx, &ignore);
47
g_slist_free(ignore);
48
}
49
83
50
--
84
--
51
2.31.1
85
2.29.2
52
86
53
87
diff view generated by jsdifflib
1
From: Hanna Reitz <hreitz@redhat.com>
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
2
3
See the comment for why this is necessary.
3
Ignore two complains, which now lead to 297 failure on testenv.py and
4
testrunner.py.
4
5
5
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
6
Fixes: 2e5a2f57db481f18fcf70be2a36b1417370b8476
6
Message-Id: <20211111120829.81329-11-hreitz@redhat.com>
7
Fixes: d74c754c924ca34e90b7c96ce2f5609d82c0e628
8
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
9
Message-Id: <20210129161323.615027-1-vsementsov@virtuozzo.com>
10
Reviewed-by: John Snow <jsnow@redhat.com>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
---
12
---
9
tests/qemu-iotests/030 | 11 ++++++++++-
13
tests/qemu-iotests/pylintrc | 2 ++
10
1 file changed, 10 insertions(+), 1 deletion(-)
14
1 file changed, 2 insertions(+)
11
15
12
diff --git a/tests/qemu-iotests/030 b/tests/qemu-iotests/030
16
diff --git a/tests/qemu-iotests/pylintrc b/tests/qemu-iotests/pylintrc
13
index XXXXXXX..XXXXXXX 100755
17
index XXXXXXX..XXXXXXX 100644
14
--- a/tests/qemu-iotests/030
18
--- a/tests/qemu-iotests/pylintrc
15
+++ b/tests/qemu-iotests/030
19
+++ b/tests/qemu-iotests/pylintrc
16
@@ -XXX,XX +XXX,XX @@ class TestParallelOps(iotests.QMPTestCase):
20
@@ -XXX,XX +XXX,XX @@ disable=invalid-name,
17
speed=1024)
21
unsubscriptable-object,
18
self.assert_qmp(result, 'return', {})
22
# These are temporary, and should be removed:
19
23
missing-docstring,
20
- for job in pending_jobs:
24
+ too-many-return-statements,
21
+ # Do this in reverse: After unthrottling them, some jobs may finish
25
+ too-many-statements
22
+ # before we have unthrottled all of them. This will drain their
26
23
+ # subgraph, and this will make jobs above them advance (despite those
27
[FORMAT]
24
+ # jobs on top being throttled). In the worst case, all jobs below the
25
+ # top one are finished before we can unthrottle it, and this makes it
26
+ # advance so far that it completes before we can unthrottle it - which
27
+ # results in an error.
28
+ # Starting from the top (i.e. in reverse) does not have this problem:
29
+ # When a job finishes, the ones below it are not advanced.
30
+ for job in reversed(pending_jobs):
31
result = self.vm.qmp('block-job-set-speed', device=job, speed=0)
32
self.assert_qmp(result, 'return', {})
33
28
34
--
29
--
35
2.31.1
30
2.29.2
36
31
37
32
diff view generated by jsdifflib
1
While introducing a non-QemuOpts code path for device creation for JSON
1
If the qemu-system-{arch} binary for the host architecture can't be
2
-device, we noticed that QMP device_add doesn't check its input
2
found, the old 'check' implementation selected the alphabetically first
3
correctly (accepting arguments that should have been rejected), and that
3
system emulator binary that it could find. The new Python implementation
4
users may be relying on this behaviour (libvirt did until it was fixed
4
just uses the first result of glob.iglob(), which has an undefined
5
recently).
5
order.
6
6
7
Let's use a deprecation period before we fix this bug in QEMU to avoid
7
This is a problem that breaks CI because the iotests aren't actually
8
nasty surprises for users.
8
prepared to run on any emulator. They should be, so this is really a bug
9
in the failing test cases that should be fixed there, but as a quick
10
fix, let's revert to the old behaviour to let CI runs succeed again.
9
11
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
Message-Id: <20211111143530.18985-1-kwolf@redhat.com>
13
Message-Id: <20210202142802.119999-1-kwolf@redhat.com>
12
Reviewed-by: Markus Armbruster <armbru@redhat.com>
14
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
13
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
15
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
16
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
17
Reviewed-by: Eric Blake <eblake@redhat.com>
14
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
18
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
15
---
19
---
16
docs/about/deprecated.rst | 14 ++++++++++++++
20
tests/qemu-iotests/testenv.py | 2 +-
17
1 file changed, 14 insertions(+)
21
1 file changed, 1 insertion(+), 1 deletion(-)
18
22
19
diff --git a/docs/about/deprecated.rst b/docs/about/deprecated.rst
23
diff --git a/tests/qemu-iotests/testenv.py b/tests/qemu-iotests/testenv.py
20
index XXXXXXX..XXXXXXX 100644
24
index XXXXXXX..XXXXXXX 100644
21
--- a/docs/about/deprecated.rst
25
--- a/tests/qemu-iotests/testenv.py
22
+++ b/docs/about/deprecated.rst
26
+++ b/tests/qemu-iotests/testenv.py
23
@@ -XXX,XX +XXX,XX @@ options are removed in favor of using explicit ``blockdev-create`` and
27
@@ -XXX,XX +XXX,XX @@ class TestEnv(ContextManager['TestEnv']):
24
``blockdev-add`` calls. See :doc:`/interop/live-block-operations` for
28
if not os.path.exists(self.qemu_prog):
25
details.
29
pattern = root('qemu-system-*')
26
30
try:
27
+Incorrectly typed ``device_add`` arguments (since 6.2)
31
- progs = glob.iglob(pattern)
28
+''''''''''''''''''''''''''''''''''''''''''''''''''''''
32
+ progs = sorted(glob.iglob(pattern))
29
+
33
self.qemu_prog = next(p for p in progs if isxfile(p))
30
+Due to shortcomings in the internal implementation of ``device_add``, QEMU
34
except StopIteration:
31
+incorrectly accepts certain invalid arguments: Any object or list arguments are
35
sys.exit("Not found any Qemu executable binary by pattern "
32
+silently ignored. Other argument types are not checked, but an implicit
33
+conversion happens, so that e.g. string values can be assigned to integer
34
+device properties or vice versa.
35
+
36
+This is a bug in QEMU that will be fixed in the future so that previously
37
+accepted incorrect commands will return an error. Users should make sure that
38
+all arguments passed to ``device_add`` are consistent with the documented
39
+property types.
40
+
41
System accelerators
42
-------------------
43
44
--
36
--
45
2.31.1
37
2.29.2
46
38
47
39
diff view generated by jsdifflib
1
From: Hanna Reitz <hreitz@redhat.com>
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
2
3
In most of the block layer, especially when traversing down from other
3
We should indicate failure by exit code, not only output.
4
BlockDriverStates, we assume that BdrvChild.bs can never be NULL. When
5
it becomes NULL, it is expected that the corresponding BdrvChild pointer
6
also becomes NULL and the BdrvChild object is freed.
7
4
8
Therefore, once bdrv_replace_child_noperm() sets the BdrvChild.bs
5
Reported-by: Peter Maydell
9
pointer to NULL, it should also immediately set the corresponding
6
Fixes: f203080bbd9f9e5b31041b1f2afcd6040c5aaec5
10
BdrvChild pointer (like bs->file or bs->backing) to NULL.
7
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
11
8
Message-Id: <20210201085041.3079-1-vsementsov@virtuozzo.com>
12
In that context, it also makes sense for this function to free the
13
child. Sometimes we cannot do so, though, because it is called in a
14
transactional context where the caller might still want to reinstate the
15
child in the abort branch (and free it only on commit), so this behavior
16
has to remain optional.
17
18
In bdrv_replace_child_tran()'s abort handler, we now rely on the fact
19
that the BdrvChild passed to bdrv_replace_child_tran() must have had a
20
non-NULL .bs pointer initially. Make a note of that and assert it.
21
22
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
23
Message-Id: <20211111120829.81329-10-hreitz@redhat.com>
24
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
25
---
10
---
26
block.c | 102 +++++++++++++++++++++++++++++++++++++++++++-------------
11
tests/qemu-iotests/testrunner.py | 4 +++-
27
1 file changed, 79 insertions(+), 23 deletions(-)
12
tests/qemu-iotests/check | 5 ++++-
13
2 files changed, 7 insertions(+), 2 deletions(-)
28
14
29
diff --git a/block.c b/block.c
15
diff --git a/tests/qemu-iotests/testrunner.py b/tests/qemu-iotests/testrunner.py
30
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
31
--- a/block.c
17
--- a/tests/qemu-iotests/testrunner.py
32
+++ b/block.c
18
+++ b/tests/qemu-iotests/testrunner.py
33
@@ -XXX,XX +XXX,XX @@ static BlockDriverState *bdrv_open_inherit(const char *filename,
19
@@ -XXX,XX +XXX,XX @@ class TestRunner(ContextManager['TestRunner']):
34
static bool bdrv_recurse_has_child(BlockDriverState *bs,
20
35
BlockDriverState *child);
21
return res
36
22
37
+static void bdrv_child_free(BdrvChild *child);
23
- def run_tests(self, tests: List[str]) -> None:
38
static void bdrv_replace_child_noperm(BdrvChild **child,
24
+ def run_tests(self, tests: List[str]) -> bool:
39
- BlockDriverState *new_bs);
25
n_run = 0
40
+ BlockDriverState *new_bs,
26
failed = []
41
+ bool free_empty_child);
27
notrun = []
42
static void bdrv_remove_file_or_backing_child(BlockDriverState *bs,
28
@@ -XXX,XX +XXX,XX @@ class TestRunner(ContextManager['TestRunner']):
43
BdrvChild *child,
29
if failed:
44
Transaction *tran);
30
print('Failures:', ' '.join(failed))
45
@@ -XXX,XX +XXX,XX @@ typedef struct BdrvReplaceChildState {
31
print(f'Failed {len(failed)} of {n_run} iotests')
46
BdrvChild *child;
32
+ return False
47
BdrvChild **childp;
33
else:
48
BlockDriverState *old_bs;
34
print(f'Passed all {n_run} iotests')
49
+ bool free_empty_child;
35
+ return True
50
} BdrvReplaceChildState;
36
diff --git a/tests/qemu-iotests/check b/tests/qemu-iotests/check
51
37
index XXXXXXX..XXXXXXX 100755
52
static void bdrv_replace_child_commit(void *opaque)
38
--- a/tests/qemu-iotests/check
53
{
39
+++ b/tests/qemu-iotests/check
54
BdrvReplaceChildState *s = opaque;
40
@@ -XXX,XX +XXX,XX @@ if __name__ == '__main__':
55
41
else:
56
+ if (s->free_empty_child && !s->child->bs) {
42
with TestRunner(env, makecheck=args.makecheck,
57
+ bdrv_child_free(s->child);
43
color=args.color) as tr:
58
+ }
44
- tr.run_tests([os.path.join(env.source_iotests, t) for t in tests])
59
bdrv_unref(s->old_bs);
45
+ paths = [os.path.join(env.source_iotests, t) for t in tests]
60
}
46
+ ok = tr.run_tests(paths)
61
47
+ if not ok:
62
@@ -XXX,XX +XXX,XX @@ static void bdrv_replace_child_abort(void *opaque)
48
+ sys.exit(1)
63
* modify the BdrvChild * pointer we indirectly pass to it, i.e. it
64
* will not modify s->child. From that perspective, it does not matter
65
* whether we pass s->childp or &s->child.
66
- * (TODO: Right now, bdrv_replace_child_noperm() never modifies that
67
- * pointer anyway (though it will in the future), so at this point it
68
- * absolutely does not matter whether we pass s->childp or &s->child.)
69
* (2) If new_bs is not NULL, s->childp will be NULL. We then cannot use
70
* it here.
71
* (3) If new_bs is NULL, *s->childp will have been NULLed by
72
* bdrv_replace_child_tran()'s bdrv_replace_child_noperm() call, and we
73
* must not pass a NULL *s->childp here.
74
- * (TODO: In its current state, bdrv_replace_child_noperm() will not
75
- * have NULLed *s->childp, so this does not apply yet. It will in the
76
- * future.)
77
*
78
* So whether new_bs was NULL or not, we cannot pass s->childp here; and in
79
* any case, there is no reason to pass it anyway.
80
*/
81
- bdrv_replace_child_noperm(&s->child, s->old_bs);
82
+ bdrv_replace_child_noperm(&s->child, s->old_bs, true);
83
+ /*
84
+ * The child was pre-existing, so s->old_bs must be non-NULL, and
85
+ * s->child thus must not have been freed
86
+ */
87
+ assert(s->child != NULL);
88
+ if (!new_bs) {
89
+ /* As described above, *s->childp was cleared, so restore it */
90
+ assert(s->childp != NULL);
91
+ *s->childp = s->child;
92
+ }
93
bdrv_unref(new_bs);
94
}
95
96
@@ -XXX,XX +XXX,XX @@ static TransactionActionDrv bdrv_replace_child_drv = {
97
*
98
* The function doesn't update permissions, caller is responsible for this.
99
*
100
+ * (*childp)->bs must not be NULL.
101
+ *
102
* Note that if new_bs == NULL, @childp is stored in a state object attached
103
* to @tran, so that the old child can be reinstated in the abort handler.
104
* Therefore, if @new_bs can be NULL, @childp must stay valid until the
105
* transaction is committed or aborted.
106
*
107
- * (TODO: The reinstating does not happen yet, but it will once
108
- * bdrv_replace_child_noperm() NULLs *childp when new_bs is NULL.)
109
+ * If @free_empty_child is true and @new_bs is NULL, the BdrvChild is
110
+ * freed (on commit). @free_empty_child should only be false if the
111
+ * caller will free the BDrvChild themselves (which may be important
112
+ * if this is in turn called in another transactional context).
113
*/
114
static void bdrv_replace_child_tran(BdrvChild **childp,
115
BlockDriverState *new_bs,
116
- Transaction *tran)
117
+ Transaction *tran,
118
+ bool free_empty_child)
119
{
120
BdrvReplaceChildState *s = g_new(BdrvReplaceChildState, 1);
121
*s = (BdrvReplaceChildState) {
122
.child = *childp,
123
.childp = new_bs == NULL ? childp : NULL,
124
.old_bs = (*childp)->bs,
125
+ .free_empty_child = free_empty_child,
126
};
127
tran_add(tran, &bdrv_replace_child_drv, s);
128
129
+ /* The abort handler relies on this */
130
+ assert(s->old_bs != NULL);
131
+
132
if (new_bs) {
133
bdrv_ref(new_bs);
134
}
135
- bdrv_replace_child_noperm(childp, new_bs);
136
+ /*
137
+ * Pass free_empty_child=false, we will free the child (if
138
+ * necessary) in bdrv_replace_child_commit() (if our
139
+ * @free_empty_child parameter was true).
140
+ */
141
+ bdrv_replace_child_noperm(childp, new_bs, false);
142
/* old_bs reference is transparently moved from *childp to @s */
143
}
144
145
@@ -XXX,XX +XXX,XX @@ uint64_t bdrv_qapi_perm_to_blk_perm(BlockPermission qapi_perm)
146
return permissions[qapi_perm];
147
}
148
149
+/**
150
+ * Replace (*childp)->bs by @new_bs.
151
+ *
152
+ * If @new_bs is NULL, *childp will be set to NULL, too: BDS parents
153
+ * generally cannot handle a BdrvChild with .bs == NULL, so clearing
154
+ * BdrvChild.bs should generally immediately be followed by the
155
+ * BdrvChild pointer being cleared as well.
156
+ *
157
+ * If @free_empty_child is true and @new_bs is NULL, the BdrvChild is
158
+ * freed. @free_empty_child should only be false if the caller will
159
+ * free the BdrvChild themselves (this may be important in a
160
+ * transactional context, where it may only be freed on commit).
161
+ */
162
static void bdrv_replace_child_noperm(BdrvChild **childp,
163
- BlockDriverState *new_bs)
164
+ BlockDriverState *new_bs,
165
+ bool free_empty_child)
166
{
167
BdrvChild *child = *childp;
168
BlockDriverState *old_bs = child->bs;
169
@@ -XXX,XX +XXX,XX @@ static void bdrv_replace_child_noperm(BdrvChild **childp,
170
}
171
172
child->bs = new_bs;
173
+ if (!new_bs) {
174
+ *childp = NULL;
175
+ }
176
177
if (new_bs) {
178
QLIST_INSERT_HEAD(&new_bs->parents, child, next_parent);
179
@@ -XXX,XX +XXX,XX @@ static void bdrv_replace_child_noperm(BdrvChild **childp,
180
bdrv_parent_drained_end_single(child);
181
drain_saldo++;
182
}
183
+
184
+ if (free_empty_child && !child->bs) {
185
+ bdrv_child_free(child);
186
+ }
187
}
188
189
/**
190
@@ -XXX,XX +XXX,XX @@ static void bdrv_attach_child_common_abort(void *opaque)
191
BdrvChild *child = *s->child;
192
BlockDriverState *bs = child->bs;
193
194
- bdrv_replace_child_noperm(s->child, NULL);
195
+ /*
196
+ * Pass free_empty_child=false, because we still need the child
197
+ * for the AioContext operations on the parent below; those
198
+ * BdrvChildClass methods all work on a BdrvChild object, so we
199
+ * need to keep it as an empty shell (after this function, it will
200
+ * not be attached to any parent, and it will not have a .bs).
201
+ */
202
+ bdrv_replace_child_noperm(s->child, NULL, false);
203
204
if (bdrv_get_aio_context(bs) != s->old_child_ctx) {
205
bdrv_try_set_aio_context(bs, s->old_child_ctx, &error_abort);
206
@@ -XXX,XX +XXX,XX @@ static void bdrv_attach_child_common_abort(void *opaque)
207
208
bdrv_unref(bs);
209
bdrv_child_free(child);
210
- *s->child = NULL;
211
}
212
213
static TransactionActionDrv bdrv_attach_child_common_drv = {
214
@@ -XXX,XX +XXX,XX @@ static int bdrv_attach_child_common(BlockDriverState *child_bs,
215
}
216
217
bdrv_ref(child_bs);
218
- bdrv_replace_child_noperm(&new_child, child_bs);
219
+ bdrv_replace_child_noperm(&new_child, child_bs, true);
220
+ /* child_bs was non-NULL, so new_child must not have been freed */
221
+ assert(new_child != NULL);
222
223
*child = new_child;
224
225
@@ -XXX,XX +XXX,XX @@ static void bdrv_detach_child(BdrvChild **childp)
226
{
227
BlockDriverState *old_bs = (*childp)->bs;
228
229
- bdrv_replace_child_noperm(childp, NULL);
230
- bdrv_child_free(*childp);
231
+ bdrv_replace_child_noperm(childp, NULL, true);
232
233
if (old_bs) {
234
/*
235
@@ -XXX,XX +XXX,XX @@ static void bdrv_remove_file_or_backing_child(BlockDriverState *bs,
236
}
237
238
if (child->bs) {
239
- bdrv_replace_child_tran(childp, NULL, tran);
240
+ /*
241
+ * Pass free_empty_child=false, we will free the child in
242
+ * bdrv_remove_filter_or_cow_child_commit()
243
+ */
244
+ bdrv_replace_child_tran(childp, NULL, tran, false);
245
}
246
247
s = g_new(BdrvRemoveFilterOrCowChild, 1);
248
@@ -XXX,XX +XXX,XX @@ static void bdrv_remove_file_or_backing_child(BlockDriverState *bs,
249
.is_backing = (childp == &bs->backing),
250
};
251
tran_add(tran, &bdrv_remove_filter_or_cow_child_drv, s);
252
-
253
- *childp = NULL;
254
}
255
256
/*
257
@@ -XXX,XX +XXX,XX @@ static int bdrv_replace_node_noperm(BlockDriverState *from,
258
* Passing a pointer to the local variable @c is fine here, because
259
* @to is not NULL, and so &c will not be attached to the transaction.
260
*/
261
- bdrv_replace_child_tran(&c, to, tran);
262
+ bdrv_replace_child_tran(&c, to, tran, true);
263
}
264
265
return 0;
266
@@ -XXX,XX +XXX,XX @@ int bdrv_replace_child_bs(BdrvChild *child, BlockDriverState *new_bs,
267
bdrv_drained_begin(old_bs);
268
bdrv_drained_begin(new_bs);
269
270
- bdrv_replace_child_tran(&child, new_bs, tran);
271
+ bdrv_replace_child_tran(&child, new_bs, tran, true);
272
+ /* @new_bs must have been non-NULL, so @child must not have been freed */
273
+ assert(child != NULL);
274
275
found = g_hash_table_new(NULL, NULL);
276
refresh_list = bdrv_topological_dfs(refresh_list, found, old_bs);
277
--
49
--
278
2.31.1
50
2.29.2
279
51
280
52
diff view generated by jsdifflib
1
From: Hanna Reitz <hreitz@redhat.com>
1
For -makecheck, the old 'check' implementation skipped the output when
2
starting a test. It only had the condensed output at the end of a test.
2
3
3
bdrv_replace_child_noperm() modifies BdrvChild.bs, and can potentially
4
testrunner.py prints the normal output when starting a test even for
4
set it to NULL. That is dangerous, because BDS parents generally assume
5
-makecheck. This output contains '\r' at the end so that it can be
5
that their children's .bs pointer is never NULL. We therefore want to
6
overwritten with the result at the end of the test. However, for
6
let bdrv_replace_child_noperm() set the corresponding BdrvChild pointer
7
-makecheck this is shorter output in a different format, so effectively
7
to NULL, too.
8
we end up with garbled output that mixes both output forms.
8
9
9
This patch lays the foundation for it by passing a BdrvChild ** pointer
10
Revert to the old behaviour of only printing a message after the test
10
to bdrv_replace_child_noperm() so that it can later use it to NULL the
11
had completed in -makecheck mode.
11
BdrvChild pointer immediately after setting BdrvChild.bs to NULL.
12
12
13
(We will still need to undertake some intermediate steps, though.)
13
Fixes: d74c754c924ca34e90b7c96ce2f5609d82c0e628
14
14
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
15
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
15
Message-Id: <20210201161024.127921-1-kwolf@redhat.com>
16
Message-Id: <20211111120829.81329-6-hreitz@redhat.com>
17
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
16
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
18
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
17
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
19
---
18
---
20
block.c | 23 ++++++++++++-----------
19
tests/qemu-iotests/testrunner.py | 6 ++++--
21
1 file changed, 12 insertions(+), 11 deletions(-)
20
1 file changed, 4 insertions(+), 2 deletions(-)
22
21
23
diff --git a/block.c b/block.c
22
diff --git a/tests/qemu-iotests/testrunner.py b/tests/qemu-iotests/testrunner.py
24
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
25
--- a/block.c
24
--- a/tests/qemu-iotests/testrunner.py
26
+++ b/block.c
25
+++ b/tests/qemu-iotests/testrunner.py
27
@@ -XXX,XX +XXX,XX @@ static BlockDriverState *bdrv_open_inherit(const char *filename,
26
@@ -XXX,XX +XXX,XX @@ class TestRunner(ContextManager['TestRunner']):
28
static bool bdrv_recurse_has_child(BlockDriverState *bs,
27
last_el = self.last_elapsed.get(test)
29
BlockDriverState *child);
28
start = datetime.datetime.now().strftime('%H:%M:%S')
30
29
31
-static void bdrv_replace_child_noperm(BdrvChild *child,
30
- self.test_print_one_line(test=test, starttime=start, lasttime=last_el,
32
+static void bdrv_replace_child_noperm(BdrvChild **child,
31
- end='\r', test_field_width=test_field_width)
33
BlockDriverState *new_bs);
32
+ if not self.makecheck:
34
static void bdrv_remove_file_or_backing_child(BlockDriverState *bs,
33
+ self.test_print_one_line(test=test, starttime=start,
35
BdrvChild *child,
34
+ lasttime=last_el, end='\r',
36
@@ -XXX,XX +XXX,XX @@ static void bdrv_replace_child_abort(void *opaque)
35
+ test_field_width=test_field_width)
37
BlockDriverState *new_bs = s->child->bs;
36
38
37
res = self.do_run_test(test)
39
/* old_bs reference is transparently moved from @s to @s->child */
40
- bdrv_replace_child_noperm(s->child, s->old_bs);
41
+ bdrv_replace_child_noperm(&s->child, s->old_bs);
42
bdrv_unref(new_bs);
43
}
44
45
@@ -XXX,XX +XXX,XX @@ static void bdrv_replace_child_tran(BdrvChild *child, BlockDriverState *new_bs,
46
if (new_bs) {
47
bdrv_ref(new_bs);
48
}
49
- bdrv_replace_child_noperm(child, new_bs);
50
+ bdrv_replace_child_noperm(&child, new_bs);
51
/* old_bs reference is transparently moved from @child to @s */
52
}
53
54
@@ -XXX,XX +XXX,XX @@ uint64_t bdrv_qapi_perm_to_blk_perm(BlockPermission qapi_perm)
55
return permissions[qapi_perm];
56
}
57
58
-static void bdrv_replace_child_noperm(BdrvChild *child,
59
+static void bdrv_replace_child_noperm(BdrvChild **childp,
60
BlockDriverState *new_bs)
61
{
62
+ BdrvChild *child = *childp;
63
BlockDriverState *old_bs = child->bs;
64
int new_bs_quiesce_counter;
65
int drain_saldo;
66
@@ -XXX,XX +XXX,XX @@ static void bdrv_attach_child_common_abort(void *opaque)
67
BdrvChild *child = *s->child;
68
BlockDriverState *bs = child->bs;
69
70
- bdrv_replace_child_noperm(child, NULL);
71
+ bdrv_replace_child_noperm(s->child, NULL);
72
73
if (bdrv_get_aio_context(bs) != s->old_child_ctx) {
74
bdrv_try_set_aio_context(bs, s->old_child_ctx, &error_abort);
75
@@ -XXX,XX +XXX,XX @@ static int bdrv_attach_child_common(BlockDriverState *child_bs,
76
}
77
78
bdrv_ref(child_bs);
79
- bdrv_replace_child_noperm(new_child, child_bs);
80
+ bdrv_replace_child_noperm(&new_child, child_bs);
81
82
*child = new_child;
83
84
@@ -XXX,XX +XXX,XX @@ static int bdrv_attach_child_noperm(BlockDriverState *parent_bs,
85
return 0;
86
}
87
88
-static void bdrv_detach_child(BdrvChild *child)
89
+static void bdrv_detach_child(BdrvChild **childp)
90
{
91
- BlockDriverState *old_bs = child->bs;
92
+ BlockDriverState *old_bs = (*childp)->bs;
93
94
- bdrv_replace_child_noperm(child, NULL);
95
- bdrv_child_free(child);
96
+ bdrv_replace_child_noperm(childp, NULL);
97
+ bdrv_child_free(*childp);
98
99
if (old_bs) {
100
/*
101
@@ -XXX,XX +XXX,XX @@ void bdrv_root_unref_child(BdrvChild *child)
102
BlockDriverState *child_bs;
103
104
child_bs = child->bs;
105
- bdrv_detach_child(child);
106
+ bdrv_detach_child(&child);
107
bdrv_unref(child_bs);
108
}
109
38
110
--
39
--
111
2.31.1
40
2.29.2
112
41
113
42
diff view generated by jsdifflib
1
From: Stefan Hajnoczi <stefanha@redhat.com>
1
From: Philippe Mathieu-Daudé <philmd@redhat.com>
2
2
3
Reported by Coverity (CID 1465222).
3
Commit 15b2260bef3 ("block/nvme: Trace controller capabilities")
4
misunderstood the doorbell stride value from the datasheet, use
5
the correct one. The 'doorbell_scale' variable used few lines
6
later is correct.
4
7
5
Fixes: 4a1d937796de0fecd8b22d7dbebf87f38e8282fd ("softmmu/qdev-monitor: add error handling in qdev_set_id")
8
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
6
Cc: Damien Hedde <damien.hedde@greensocs.com>
9
Message-Id: <20210127212137.3482291-2-philmd@redhat.com>
7
Cc: Kevin Wolf <kwolf@redhat.com>
10
Reviewed-by: Klaus Jensen <k.jensen@samsung.com>
8
Cc: Michael S. Tsirkin <mst@redhat.com>
9
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
10
Message-Id: <20211102163342.31162-1-stefanha@redhat.com>
11
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
12
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
13
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
14
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
15
Reviewed-by: Damien Hedde <damien.hedde@greensocs.com>
16
Reviewed-by: Markus Armbruster <armbru@redhat.com>
17
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
18
---
12
---
19
softmmu/qdev-monitor.c | 2 +-
13
block/nvme.c | 2 +-
20
1 file changed, 1 insertion(+), 1 deletion(-)
14
1 file changed, 1 insertion(+), 1 deletion(-)
21
15
22
diff --git a/softmmu/qdev-monitor.c b/softmmu/qdev-monitor.c
16
diff --git a/block/nvme.c b/block/nvme.c
23
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
24
--- a/softmmu/qdev-monitor.c
18
--- a/block/nvme.c
25
+++ b/softmmu/qdev-monitor.c
19
+++ b/block/nvme.c
26
@@ -XXX,XX +XXX,XX @@ const char *qdev_set_id(DeviceState *dev, char *id, Error **errp)
20
@@ -XXX,XX +XXX,XX @@ static int nvme_init(BlockDriverState *bs, const char *device, int namespace,
27
if (prop) {
21
trace_nvme_controller_capability("Contiguous Queues Required",
28
dev->id = id;
22
NVME_CAP_CQR(cap));
29
} else {
23
trace_nvme_controller_capability("Doorbell Stride",
30
- g_free(id);
24
- 2 << (2 + NVME_CAP_DSTRD(cap)));
31
error_setg(errp, "Duplicate device ID '%s'", id);
25
+ 1 << (2 + NVME_CAP_DSTRD(cap)));
32
+ g_free(id);
26
trace_nvme_controller_capability("Subsystem Reset Supported",
33
return NULL;
27
NVME_CAP_NSSRS(cap));
34
}
28
trace_nvme_controller_capability("Memory Page Size Minimum",
35
} else {
36
--
29
--
37
2.31.1
30
2.29.2
38
31
39
32
diff view generated by jsdifflib
1
From: Hanna Reitz <hreitz@redhat.com>
1
From: Philippe Mathieu-Daudé <philmd@redhat.com>
2
2
3
As of a future commit, bdrv_replace_child_noperm() will clear the
3
NVMe controllers implement different versions of the spec,
4
indirect BdrvChild pointer passed to it if the new child BDS is NULL.
4
and different features of it. It is useful to gather this
5
bdrv_replace_child_tran() will want to let it do that, but revert this
5
information when debugging.
6
change in its abort handler. For that, we need to have it receive a
7
BdrvChild ** pointer, too, and keep it stored in the
8
BdrvReplaceChildState object that we attach to the transaction.
9
6
10
Note that we do not need to store it in the BdrvReplaceChildState when
7
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
11
new_bs is not NULL, because then there is nothing to revert. This is
8
Message-Id: <20210127212137.3482291-3-philmd@redhat.com>
12
important so that bdrv_replace_node_noperm() can pass a pointer to a
9
Reviewed-by: Klaus Jensen <k.jensen@samsung.com>
13
loop-local variable to bdrv_replace_child_tran() without worrying that
14
this pointer will outlive one loop iteration.
15
16
(Of course, for that to work, bdrv_replace_node_noperm() and in turn
17
bdrv_replace_node() and its relatives may not be called with a NULL @to
18
node. Luckily, they already are not, but now we should assert this.)
19
20
bdrv_remove_file_or_backing_child() on the other hand needs to ensure
21
that the indirect pointer it passes will stay valid for the duration of
22
the transaction. Ensure this by keeping a strong reference to the BDS
23
whose &bs->backing or &bs->file it passes to bdrv_replace_child_tran(),
24
and giving up that reference only in the transaction .clean() handler.
25
26
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
27
Message-Id: <20211111120829.81329-9-hreitz@redhat.com>
28
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
29
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
30
---
11
---
31
block.c | 83 ++++++++++++++++++++++++++++++++++++++++++++++++++-------
12
block/nvme.c | 6 ++++++
32
1 file changed, 73 insertions(+), 10 deletions(-)
13
block/trace-events | 1 +
14
2 files changed, 7 insertions(+)
33
15
34
diff --git a/block.c b/block.c
16
diff --git a/block/nvme.c b/block/nvme.c
35
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
36
--- a/block.c
18
--- a/block/nvme.c
37
+++ b/block.c
19
+++ b/block/nvme.c
38
@@ -XXX,XX +XXX,XX @@ static int bdrv_drv_set_perm(BlockDriverState *bs, uint64_t perm,
20
@@ -XXX,XX +XXX,XX @@ static int nvme_init(BlockDriverState *bs, const char *device, int namespace,
39
21
AioContext *aio_context = bdrv_get_aio_context(bs);
40
typedef struct BdrvReplaceChildState {
22
int ret;
41
BdrvChild *child;
23
uint64_t cap;
42
+ BdrvChild **childp;
24
+ uint32_t ver;
43
BlockDriverState *old_bs;
25
uint64_t timeout_ms;
44
} BdrvReplaceChildState;
26
uint64_t deadline, now;
45
27
volatile NvmeBar *regs = NULL;
46
@@ -XXX,XX +XXX,XX @@ static void bdrv_replace_child_abort(void *opaque)
28
@@ -XXX,XX +XXX,XX @@ static int nvme_init(BlockDriverState *bs, const char *device, int namespace,
47
BdrvReplaceChildState *s = opaque;
29
bs->bl.request_alignment = s->page_size;
48
BlockDriverState *new_bs = s->child->bs;
30
timeout_ms = MIN(500 * NVME_CAP_TO(cap), 30000);
49
31
50
- /* old_bs reference is transparently moved from @s to @s->child */
32
+ ver = le32_to_cpu(regs->vs);
51
+ /*
33
+ trace_nvme_controller_spec_version(extract32(ver, 16, 16),
52
+ * old_bs reference is transparently moved from @s to s->child.
34
+ extract32(ver, 8, 8),
53
+ *
35
+ extract32(ver, 0, 8));
54
+ * Pass &s->child here instead of s->childp, because:
55
+ * (1) s->old_bs must be non-NULL, so bdrv_replace_child_noperm() will not
56
+ * modify the BdrvChild * pointer we indirectly pass to it, i.e. it
57
+ * will not modify s->child. From that perspective, it does not matter
58
+ * whether we pass s->childp or &s->child.
59
+ * (TODO: Right now, bdrv_replace_child_noperm() never modifies that
60
+ * pointer anyway (though it will in the future), so at this point it
61
+ * absolutely does not matter whether we pass s->childp or &s->child.)
62
+ * (2) If new_bs is not NULL, s->childp will be NULL. We then cannot use
63
+ * it here.
64
+ * (3) If new_bs is NULL, *s->childp will have been NULLed by
65
+ * bdrv_replace_child_tran()'s bdrv_replace_child_noperm() call, and we
66
+ * must not pass a NULL *s->childp here.
67
+ * (TODO: In its current state, bdrv_replace_child_noperm() will not
68
+ * have NULLed *s->childp, so this does not apply yet. It will in the
69
+ * future.)
70
+ *
71
+ * So whether new_bs was NULL or not, we cannot pass s->childp here; and in
72
+ * any case, there is no reason to pass it anyway.
73
+ */
74
bdrv_replace_child_noperm(&s->child, s->old_bs);
75
bdrv_unref(new_bs);
76
}
77
@@ -XXX,XX +XXX,XX @@ static TransactionActionDrv bdrv_replace_child_drv = {
78
* Note: real unref of old_bs is done only on commit.
79
*
80
* The function doesn't update permissions, caller is responsible for this.
81
+ *
82
+ * Note that if new_bs == NULL, @childp is stored in a state object attached
83
+ * to @tran, so that the old child can be reinstated in the abort handler.
84
+ * Therefore, if @new_bs can be NULL, @childp must stay valid until the
85
+ * transaction is committed or aborted.
86
+ *
87
+ * (TODO: The reinstating does not happen yet, but it will once
88
+ * bdrv_replace_child_noperm() NULLs *childp when new_bs is NULL.)
89
*/
90
-static void bdrv_replace_child_tran(BdrvChild *child, BlockDriverState *new_bs,
91
+static void bdrv_replace_child_tran(BdrvChild **childp,
92
+ BlockDriverState *new_bs,
93
Transaction *tran)
94
{
95
BdrvReplaceChildState *s = g_new(BdrvReplaceChildState, 1);
96
*s = (BdrvReplaceChildState) {
97
- .child = child,
98
- .old_bs = child->bs,
99
+ .child = *childp,
100
+ .childp = new_bs == NULL ? childp : NULL,
101
+ .old_bs = (*childp)->bs,
102
};
103
tran_add(tran, &bdrv_replace_child_drv, s);
104
105
if (new_bs) {
106
bdrv_ref(new_bs);
107
}
108
- bdrv_replace_child_noperm(&child, new_bs);
109
- /* old_bs reference is transparently moved from @child to @s */
110
+ bdrv_replace_child_noperm(childp, new_bs);
111
+ /* old_bs reference is transparently moved from *childp to @s */
112
}
113
114
/*
115
@@ -XXX,XX +XXX,XX @@ static bool should_update_child(BdrvChild *c, BlockDriverState *to)
116
117
typedef struct BdrvRemoveFilterOrCowChild {
118
BdrvChild *child;
119
+ BlockDriverState *bs;
120
bool is_backing;
121
} BdrvRemoveFilterOrCowChild;
122
123
@@ -XXX,XX +XXX,XX @@ static void bdrv_remove_filter_or_cow_child_commit(void *opaque)
124
bdrv_child_free(s->child);
125
}
126
127
+static void bdrv_remove_filter_or_cow_child_clean(void *opaque)
128
+{
129
+ BdrvRemoveFilterOrCowChild *s = opaque;
130
+
36
+
131
+ /* Drop the bs reference after the transaction is done */
37
/* Reset device to get a clean state. */
132
+ bdrv_unref(s->bs);
38
regs->cc = cpu_to_le32(le32_to_cpu(regs->cc) & 0xFE);
133
+ g_free(s);
39
/* Wait for CSTS.RDY = 0. */
134
+}
40
diff --git a/block/trace-events b/block/trace-events
135
+
41
index XXXXXXX..XXXXXXX 100644
136
static TransactionActionDrv bdrv_remove_filter_or_cow_child_drv = {
42
--- a/block/trace-events
137
.abort = bdrv_remove_filter_or_cow_child_abort,
43
+++ b/block/trace-events
138
.commit = bdrv_remove_filter_or_cow_child_commit,
44
@@ -XXX,XX +XXX,XX @@ qed_aio_write_main(void *s, void *acb, int ret, uint64_t offset, size_t len) "s
139
- .clean = g_free,
45
# nvme.c
140
+ .clean = bdrv_remove_filter_or_cow_child_clean,
46
nvme_controller_capability_raw(uint64_t value) "0x%08"PRIx64
141
};
47
nvme_controller_capability(const char *desc, uint64_t value) "%s: %"PRIu64
142
48
+nvme_controller_spec_version(uint32_t mjr, uint32_t mnr, uint32_t ter) "Specification supported: %u.%u.%u"
143
/*
49
nvme_kick(void *s, unsigned q_index) "s %p q #%u"
144
@@ -XXX,XX +XXX,XX @@ static void bdrv_remove_file_or_backing_child(BlockDriverState *bs,
50
nvme_dma_flush_queue_wait(void *s) "s %p"
145
return;
51
nvme_error(int cmd_specific, int sq_head, int sqid, int cid, int status) "cmd_specific %d sq_head %d sqid %d cid %d status 0x%x"
146
}
147
148
+ /*
149
+ * Keep a reference to @bs so @childp will stay valid throughout the
150
+ * transaction (required by bdrv_replace_child_tran())
151
+ */
152
+ bdrv_ref(bs);
153
if (child == bs->backing) {
154
childp = &bs->backing;
155
} else if (child == bs->file) {
156
@@ -XXX,XX +XXX,XX @@ static void bdrv_remove_file_or_backing_child(BlockDriverState *bs,
157
}
158
159
if (child->bs) {
160
- bdrv_replace_child_tran(*childp, NULL, tran);
161
+ bdrv_replace_child_tran(childp, NULL, tran);
162
}
163
164
s = g_new(BdrvRemoveFilterOrCowChild, 1);
165
*s = (BdrvRemoveFilterOrCowChild) {
166
.child = child,
167
+ .bs = bs,
168
.is_backing = (childp == &bs->backing),
169
};
170
tran_add(tran, &bdrv_remove_filter_or_cow_child_drv, s);
171
@@ -XXX,XX +XXX,XX @@ static int bdrv_replace_node_noperm(BlockDriverState *from,
172
{
173
BdrvChild *c, *next;
174
175
+ assert(to != NULL);
176
+
177
QLIST_FOREACH_SAFE(c, &from->parents, next_parent, next) {
178
assert(c->bs == from);
179
if (!should_update_child(c, to)) {
180
@@ -XXX,XX +XXX,XX @@ static int bdrv_replace_node_noperm(BlockDriverState *from,
181
c->name, from->node_name);
182
return -EPERM;
183
}
184
- bdrv_replace_child_tran(c, to, tran);
185
+
186
+ /*
187
+ * Passing a pointer to the local variable @c is fine here, because
188
+ * @to is not NULL, and so &c will not be attached to the transaction.
189
+ */
190
+ bdrv_replace_child_tran(&c, to, tran);
191
}
192
193
return 0;
194
@@ -XXX,XX +XXX,XX @@ static int bdrv_replace_node_noperm(BlockDriverState *from,
195
*
196
* With @detach_subchain=true @to must be in a backing chain of @from. In this
197
* case backing link of the cow-parent of @to is removed.
198
+ *
199
+ * @to must not be NULL.
200
*/
201
static int bdrv_replace_node_common(BlockDriverState *from,
202
BlockDriverState *to,
203
@@ -XXX,XX +XXX,XX @@ static int bdrv_replace_node_common(BlockDriverState *from,
204
BlockDriverState *to_cow_parent = NULL;
205
int ret;
206
207
+ assert(to != NULL);
208
+
209
if (detach_subchain) {
210
assert(bdrv_chain_contains(from, to));
211
assert(from != to);
212
@@ -XXX,XX +XXX,XX @@ out:
213
return ret;
214
}
215
216
+/**
217
+ * Replace node @from by @to (where neither may be NULL).
218
+ */
219
int bdrv_replace_node(BlockDriverState *from, BlockDriverState *to,
220
Error **errp)
221
{
222
@@ -XXX,XX +XXX,XX @@ int bdrv_replace_child_bs(BdrvChild *child, BlockDriverState *new_bs,
223
bdrv_drained_begin(old_bs);
224
bdrv_drained_begin(new_bs);
225
226
- bdrv_replace_child_tran(child, new_bs, tran);
227
+ bdrv_replace_child_tran(&child, new_bs, tran);
228
229
found = g_hash_table_new(NULL, NULL);
230
refresh_list = bdrv_topological_dfs(refresh_list, found, old_bs);
231
--
52
--
232
2.31.1
53
2.29.2
233
54
234
55
diff view generated by jsdifflib
1
From: Hanna Reitz <hreitz@redhat.com>
1
size_to_str() can return a size like "4.24 MiB", with a single digit
2
integer part and two fractional digits. This is eight characters, but
3
commit b39847a5 changed the format string to only reserve seven
4
characters for the column.
2
5
3
Invoke the transaction drivers' .clean() methods only after all
6
This can result in unaligned columns, which in turn changes the output of
4
.commit() or .abort() handlers are done.
7
iotests case 267 because exceeding the column size defeats the attempt
8
to filter the size out of the output (observed with the ppc64 emulator).
9
The resulting change is only a whitespace change, but since commit
10
f203080b this is enough for iotests to consider the test failed.
5
11
6
This makes it easier to have nested transactions where the top-level
12
Taking a character away from the tag name column and adding it to the VM
7
transactions pass objects to lower transactions that the latter can
13
size column doesn't change anything in the common case (the tag name is
8
still use throughout their commit/abort phases, while the top-level
14
left justified, the VM size is right justified), but fixes this case.
9
transaction keeps a reference that is released in its .clean() method.
10
15
11
(Before this commit, that is also possible, but the top-level
16
Fixes: b39847a50553b7679d6d7fefbe6a108a17aacf8d
12
transaction would need to take care to invoke tran_add() before the
17
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
lower-level transaction does. This commit makes the ordering
18
Message-Id: <20210202155911.179865-1-kwolf@redhat.com>
14
irrelevant, which is just a bit nicer.)
19
Reviewed-by: Eric Blake <eblake@redhat.com>
15
16
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
17
Message-Id: <20211111120829.81329-8-hreitz@redhat.com>
18
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
19
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
20
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
20
---
21
---
21
include/qemu/transactions.h | 3 +++
22
block/qapi.c | 4 ++--
22
util/transactions.c | 8 ++++++--
23
1 file changed, 2 insertions(+), 2 deletions(-)
23
2 files changed, 9 insertions(+), 2 deletions(-)
24
24
25
diff --git a/include/qemu/transactions.h b/include/qemu/transactions.h
25
diff --git a/block/qapi.c b/block/qapi.c
26
index XXXXXXX..XXXXXXX 100644
26
index XXXXXXX..XXXXXXX 100644
27
--- a/include/qemu/transactions.h
27
--- a/block/qapi.c
28
+++ b/include/qemu/transactions.h
28
+++ b/block/qapi.c
29
@@ -XXX,XX +XXX,XX @@
29
@@ -XXX,XX +XXX,XX @@ void bdrv_snapshot_dump(QEMUSnapshotInfo *sn)
30
* tran_create(), call your "prepare" functions on it, and finally call
30
char *sizing = NULL;
31
* tran_abort() or tran_commit() to finalize the transaction by corresponding
31
32
* finalization actions in reverse order.
32
if (!sn) {
33
+ *
33
- qemu_printf("%-10s%-18s%7s%20s%13s%11s",
34
+ * The clean() functions registered by the drivers in a transaction are called
34
+ qemu_printf("%-10s%-17s%8s%20s%13s%11s",
35
+ * last, after all abort() or commit() functions have been called.
35
"ID", "TAG", "VM SIZE", "DATE", "VM CLOCK", "ICOUNT");
36
*/
36
} else {
37
37
ti = sn->date_sec;
38
#ifndef QEMU_TRANSACTIONS_H
38
@@ -XXX,XX +XXX,XX @@ void bdrv_snapshot_dump(QEMUSnapshotInfo *sn)
39
diff --git a/util/transactions.c b/util/transactions.c
39
snprintf(icount_buf, sizeof(icount_buf),
40
index XXXXXXX..XXXXXXX 100644
40
"%"PRId64, sn->icount);
41
--- a/util/transactions.c
42
+++ b/util/transactions.c
43
@@ -XXX,XX +XXX,XX @@ void tran_abort(Transaction *tran)
44
{
45
TransactionAction *act, *next;
46
47
- QSLIST_FOREACH_SAFE(act, &tran->actions, entry, next) {
48
+ QSLIST_FOREACH(act, &tran->actions, entry) {
49
if (act->drv->abort) {
50
act->drv->abort(act->opaque);
51
}
41
}
52
+ }
42
- qemu_printf("%-9s %-17s %7s%20s%13s%11s",
53
43
+ qemu_printf("%-9s %-16s %8s%20s%13s%11s",
54
+ QSLIST_FOREACH_SAFE(act, &tran->actions, entry, next) {
44
sn->id_str, sn->name,
55
if (act->drv->clean) {
45
sizing,
56
act->drv->clean(act->opaque);
46
date_buf,
57
}
58
@@ -XXX,XX +XXX,XX @@ void tran_commit(Transaction *tran)
59
{
60
TransactionAction *act, *next;
61
62
- QSLIST_FOREACH_SAFE(act, &tran->actions, entry, next) {
63
+ QSLIST_FOREACH(act, &tran->actions, entry) {
64
if (act->drv->commit) {
65
act->drv->commit(act->opaque);
66
}
67
+ }
68
69
+ QSLIST_FOREACH_SAFE(act, &tran->actions, entry, next) {
70
if (act->drv->clean) {
71
act->drv->clean(act->opaque);
72
}
73
--
47
--
74
2.31.1
48
2.29.2
75
49
76
50
diff view generated by jsdifflib