1
The following changes since commit 20d6c7312f1b812bb9c750f4087f69ac8485cc90:
1
The following changes since commit 887cba855bb6ff4775256f7968409281350b568c:
2
2
3
Merge remote-tracking branch 'remotes/palmer/tags/riscv-for-master-3.2-part1' into staging (2019-01-03 13:26:30 +0000)
3
configure: Fix cross-building for RISCV host (v5) (2023-07-11 17:56:09 +0100)
4
4
5
are available in the Git repository at:
5
are available in the Git repository at:
6
6
7
git://github.com/stefanha/qemu.git tags/block-pull-request
7
https://gitlab.com/stefanha/qemu.git tags/block-pull-request
8
8
9
for you to fetch changes up to 39a0408e768cd00142f5b57d27ab234282bf4df5:
9
for you to fetch changes up to 75dcb4d790bbe5327169fd72b185960ca58e2fa6:
10
10
11
dmg: don't skip zero chunk (2019-01-04 11:15:09 +0000)
11
virtio-blk: fix host notifier issues during dataplane start/stop (2023-07-12 15:20:32 -0400)
12
12
13
----------------------------------------------------------------
13
----------------------------------------------------------------
14
Pull request
14
Pull request
15
15
16
Bug fixes for the .dmg image file format.
17
18
----------------------------------------------------------------
16
----------------------------------------------------------------
19
17
20
Julio Faracco (1):
18
Stefan Hajnoczi (1):
21
dmg: Fixing wrong dmg block type value for block terminator.
19
virtio-blk: fix host notifier issues during dataplane start/stop
22
20
23
yuchenlin (3):
21
hw/block/dataplane/virtio-blk.c | 67 +++++++++++++++++++--------------
24
dmg: fix binary search
22
1 file changed, 38 insertions(+), 29 deletions(-)
25
dmg: use enumeration type instead of hard coding number
26
dmg: don't skip zero chunk
27
28
block/dmg.c | 31 ++++++++++++++++++++-----------
29
1 file changed, 20 insertions(+), 11 deletions(-)
30
23
31
--
24
--
32
2.20.1
25
2.40.1
33
34
diff view generated by jsdifflib
Deleted patch
1
From: Julio Faracco <jcfaracco@gmail.com>
2
1
3
This is a trivial patch to fix a wrong value for block terminator.
4
The old value was 0x7fffffff which is wrong. It was not affecting the
5
code because QEMU dmg block is not handling block terminator right now.
6
Neverthless, it should be fixed.
7
8
Signed-off-by: Julio Faracco <jcfaracco@gmail.com>
9
Reviewed-by: yuchenlin <yuchenlin@synology.com>
10
Message-id: 20181228145055.18039-1-jcfaracco@gmail.com
11
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
12
---
13
block/dmg.c | 2 +-
14
1 file changed, 1 insertion(+), 1 deletion(-)
15
16
diff --git a/block/dmg.c b/block/dmg.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/block/dmg.c
19
+++ b/block/dmg.c
20
@@ -XXX,XX +XXX,XX @@ enum {
21
UDBZ,
22
ULFO,
23
UDCM = 0x7ffffffe, /* Comments */
24
- UDLE /* Last Entry */
25
+ UDLE = 0xffffffff /* Last Entry */
26
};
27
28
static int dmg_probe(const uint8_t *buf, int buf_size, const char *filename)
29
--
30
2.20.1
31
32
diff view generated by jsdifflib
1
From: yuchenlin <npes87184@gmail.com>
1
The main loop thread can consume 100% CPU when using --device
2
virtio-blk-pci,iothread=<iothread>. ppoll() constantly returns but
3
reading virtqueue host notifiers fails with EAGAIN. The file descriptors
4
are stale and remain registered with the AioContext because of bugs in
5
the virtio-blk dataplane start/stop code.
2
6
3
There is a possible hang in original binary search implementation. That is
7
The problem is that the dataplane start/stop code involves drain
4
if chunk1 = 4, chunk2 = 5, chunk3 = 4, and we go else case.
8
operations, which call virtio_blk_drained_begin() and
9
virtio_blk_drained_end() at points where the host notifier is not
10
operational:
11
- In virtio_blk_data_plane_start(), blk_set_aio_context() drains after
12
vblk->dataplane_started has been set to true but the host notifier has
13
not been attached yet.
14
- In virtio_blk_data_plane_stop(), blk_drain() and blk_set_aio_context()
15
drain after the host notifier has already been detached but with
16
vblk->dataplane_started still set to true.
5
17
6
The chunk1 will be still 4, and so on.
18
I would like to simplify ->ioeventfd_start/stop() to avoid interactions
19
with drain entirely, but couldn't find a way to do that. Instead, this
20
patch accepts the fragile nature of the code and reorders it so that
21
vblk->dataplane_started is false during drain operations. This way the
22
virtio_blk_drained_begin() and virtio_blk_drained_end() calls don't
23
touch the host notifier. The result is that
24
virtio_blk_data_plane_start() and virtio_blk_data_plane_stop() have
25
complete control over the host notifier and stale file descriptors are
26
no longer left in the AioContext.
7
27
8
Signed-off-by: yuchenlin <npes87184@gmail.com>
28
This patch fixes the 100% CPU consumption in the main loop thread and
9
Message-id: 20190103114700.9686-2-npes87184@gmail.com
29
correctly moves host notifier processing to the IOThread.
30
31
Fixes: 1665d9326fd2 ("virtio-blk: implement BlockDevOps->drained_begin()")
32
Reported-by: Lukáš Doktor <ldoktor@redhat.com>
33
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
34
Tested-by: Lukas Doktor <ldoktor@redhat.com>
35
Message-id: 20230704151527.193586-1-stefanha@redhat.com
10
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
36
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
11
---
37
---
12
block/dmg.c | 10 +++++++---
38
hw/block/dataplane/virtio-blk.c | 67 +++++++++++++++++++--------------
13
1 file changed, 7 insertions(+), 3 deletions(-)
39
1 file changed, 38 insertions(+), 29 deletions(-)
14
40
15
diff --git a/block/dmg.c b/block/dmg.c
41
diff --git a/hw/block/dataplane/virtio-blk.c b/hw/block/dataplane/virtio-blk.c
16
index XXXXXXX..XXXXXXX 100644
42
index XXXXXXX..XXXXXXX 100644
17
--- a/block/dmg.c
43
--- a/hw/block/dataplane/virtio-blk.c
18
+++ b/block/dmg.c
44
+++ b/hw/block/dataplane/virtio-blk.c
19
@@ -XXX,XX +XXX,XX @@ static inline uint32_t search_chunk(BDRVDMGState *s, uint64_t sector_num)
45
@@ -XXX,XX +XXX,XX @@ int virtio_blk_data_plane_start(VirtIODevice *vdev)
20
{
46
21
/* binary search */
47
memory_region_transaction_commit();
22
uint32_t chunk1 = 0, chunk2 = s->n_chunks, chunk3;
48
23
- while (chunk1 != chunk2) {
49
- /*
24
+ while (chunk1 <= chunk2) {
50
- * These fields are visible to the IOThread so we rely on implicit barriers
25
chunk3 = (chunk1 + chunk2) / 2;
51
- * in aio_context_acquire() on the write side and aio_notify_accept() on
26
if (s->sectors[chunk3] > sector_num) {
52
- * the read side.
27
- chunk2 = chunk3;
53
- */
28
+ if (chunk3 == 0) {
54
- s->starting = false;
29
+ goto err;
55
- vblk->dataplane_started = true;
30
+ }
56
trace_virtio_blk_data_plane_start(s);
31
+ chunk2 = chunk3 - 1;
57
32
} else if (s->sectors[chunk3] + s->sectorcounts[chunk3] > sector_num) {
58
old_context = blk_get_aio_context(s->conf->conf.blk);
33
return chunk3;
59
@@ -XXX,XX +XXX,XX @@ int virtio_blk_data_plane_start(VirtIODevice *vdev)
34
} else {
60
event_notifier_set(virtio_queue_get_host_notifier(vq));
35
- chunk1 = chunk3;
36
+ chunk1 = chunk3 + 1;
37
}
38
}
61
}
39
+err:
62
40
return s->n_chunks; /* error */
63
+ /*
64
+ * These fields must be visible to the IOThread when it processes the
65
+ * virtqueue, otherwise it will think dataplane has not started yet.
66
+ *
67
+ * Make sure ->dataplane_started is false when blk_set_aio_context() is
68
+ * called above so that draining does not cause the host notifier to be
69
+ * detached/attached prematurely.
70
+ */
71
+ s->starting = false;
72
+ vblk->dataplane_started = true;
73
+ smp_wmb(); /* paired with aio_notify_accept() on the read side */
74
+
75
/* Get this show started by hooking up our callbacks */
76
if (!blk_in_drain(s->conf->conf.blk)) {
77
aio_context_acquire(s->ctx);
78
@@ -XXX,XX +XXX,XX @@ int virtio_blk_data_plane_start(VirtIODevice *vdev)
79
fail_guest_notifiers:
80
vblk->dataplane_disabled = true;
81
s->starting = false;
82
- vblk->dataplane_started = true;
83
return -ENOSYS;
41
}
84
}
42
85
86
@@ -XXX,XX +XXX,XX @@ void virtio_blk_data_plane_stop(VirtIODevice *vdev)
87
aio_wait_bh_oneshot(s->ctx, virtio_blk_data_plane_stop_bh, s);
88
}
89
90
+ /*
91
+ * Batch all the host notifiers in a single transaction to avoid
92
+ * quadratic time complexity in address_space_update_ioeventfds().
93
+ */
94
+ memory_region_transaction_begin();
95
+
96
+ for (i = 0; i < nvqs; i++) {
97
+ virtio_bus_set_host_notifier(VIRTIO_BUS(qbus), i, false);
98
+ }
99
+
100
+ /*
101
+ * The transaction expects the ioeventfds to be open when it
102
+ * commits. Do it now, before the cleanup loop.
103
+ */
104
+ memory_region_transaction_commit();
105
+
106
+ for (i = 0; i < nvqs; i++) {
107
+ virtio_bus_cleanup_host_notifier(VIRTIO_BUS(qbus), i);
108
+ }
109
+
110
+ /*
111
+ * Set ->dataplane_started to false before draining so that host notifiers
112
+ * are not detached/attached anymore.
113
+ */
114
+ vblk->dataplane_started = false;
115
+
116
aio_context_acquire(s->ctx);
117
118
/* Wait for virtio_blk_dma_restart_bh() and in flight I/O to complete */
119
@@ -XXX,XX +XXX,XX @@ void virtio_blk_data_plane_stop(VirtIODevice *vdev)
120
121
aio_context_release(s->ctx);
122
123
- /*
124
- * Batch all the host notifiers in a single transaction to avoid
125
- * quadratic time complexity in address_space_update_ioeventfds().
126
- */
127
- memory_region_transaction_begin();
128
-
129
- for (i = 0; i < nvqs; i++) {
130
- virtio_bus_set_host_notifier(VIRTIO_BUS(qbus), i, false);
131
- }
132
-
133
- /*
134
- * The transaction expects the ioeventfds to be open when it
135
- * commits. Do it now, before the cleanup loop.
136
- */
137
- memory_region_transaction_commit();
138
-
139
- for (i = 0; i < nvqs; i++) {
140
- virtio_bus_cleanup_host_notifier(VIRTIO_BUS(qbus), i);
141
- }
142
-
143
qemu_bh_cancel(s->bh);
144
notify_guest_bh(s); /* final chance to notify guest */
145
146
/* Clean up guest notifier (irq) */
147
k->set_guest_notifiers(qbus->parent, nvqs, false);
148
149
- vblk->dataplane_started = false;
150
s->stopping = false;
151
}
43
--
152
--
44
2.20.1
153
2.40.1
45
154
46
155
diff view generated by jsdifflib
Deleted patch
1
From: yuchenlin <npes87184@gmail.com>
2
1
3
Signed-off-by: yuchenlin <npes87184@gmail.com>
4
Reviewed-by: Julio Faracco <jcfaracco@gmail.com>
5
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
6
Message-id: 20190103114700.9686-3-npes87184@gmail.com
7
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
8
---
9
block/dmg.c | 4 ++--
10
1 file changed, 2 insertions(+), 2 deletions(-)
11
12
diff --git a/block/dmg.c b/block/dmg.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/block/dmg.c
15
+++ b/block/dmg.c
16
@@ -XXX,XX +XXX,XX @@ static int dmg_read_mish_block(BDRVDMGState *s, DmgHeaderState *ds,
17
18
/* all-zeroes sector (type 2) does not need to be "uncompressed" and can
19
* therefore be unbounded. */
20
- if (s->types[i] != 2 && s->sectorcounts[i] > DMG_SECTORCOUNTS_MAX) {
21
+ if (s->types[i] != UDIG && s->sectorcounts[i] > DMG_SECTORCOUNTS_MAX) {
22
error_report("sector count %" PRIu64 " for chunk %" PRIu32
23
" is larger than max (%u)",
24
s->sectorcounts[i], i, DMG_SECTORCOUNTS_MAX);
25
@@ -XXX,XX +XXX,XX @@ dmg_co_preadv(BlockDriverState *bs, uint64_t offset, uint64_t bytes,
26
/* Special case: current chunk is all zeroes. Do not perform a memcpy as
27
* s->uncompressed_chunk may be too small to cover the large all-zeroes
28
* section. dmg_read_chunk is called to find s->current_chunk */
29
- if (s->types[s->current_chunk] == 2) { /* all zeroes block entry */
30
+ if (s->types[s->current_chunk] == UDIG) { /* all zeroes block entry */
31
qemu_iovec_memset(qiov, i * 512, 0, 512);
32
continue;
33
}
34
--
35
2.20.1
36
37
diff view generated by jsdifflib
Deleted patch
1
From: yuchenlin <npes87184@gmail.com>
2
1
3
The dmg file has many tables which describe: "start from sector XXX to
4
sector XXX, the compression method is XXX and where the compressed data
5
resides on".
6
7
Each sector in the expanded file should be covered by a table. The table
8
will describe the offset of compressed data (or raw depends on the type)
9
in the dmg.
10
11
For example:
12
13
[-----------The expanded file------------]
14
[---bzip table ---]/* zeros */[---zlib---]
15
^
16
| if we want to read this sector.
17
18
we will find bzip table which contains this sector, and get the
19
compressed data offset, read it from dmg, uncompress it, finally write to
20
expanded file.
21
22
If we skip zero chunk (table), some sector cannot find the table which
23
will cause search_chunk() return s->n_chunks, dmg_read_chunk() return -1
24
and finally causing dmg_co_preadv() return EIO.
25
26
See:
27
28
[-----------The expanded file------------]
29
[---bzip table ---]/* zeros */[---zlib---]
30
^
31
| if we want to read this sector.
32
33
Oops, we cannot find the table contains it...
34
35
In the original implementation, we don't have zero table. When we try to
36
read sector inside the zero chunk. We will get EIO, and skip reading.
37
38
After this patch, we treat zero chunk the same as ignore chunk, it will
39
directly write zero and avoid some sector may not find the table.
40
41
After this patch:
42
43
[-----------The expanded file------------]
44
[---bzip table ---][--zeros--][---zlib---]
45
46
Signed-off-by: yuchenlin <npes87184@gmail.com>
47
Reviewed-by: Julio Faracco <jcfaracco@gmail.com>
48
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
49
Message-id: 20190103114700.9686-4-npes87184@gmail.com
50
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
51
---
52
block/dmg.c | 19 ++++++++++++-------
53
1 file changed, 12 insertions(+), 7 deletions(-)
54
55
diff --git a/block/dmg.c b/block/dmg.c
56
index XXXXXXX..XXXXXXX 100644
57
--- a/block/dmg.c
58
+++ b/block/dmg.c
59
@@ -XXX,XX +XXX,XX @@ static void update_max_chunk_size(BDRVDMGState *s, uint32_t chunk,
60
case UDRW: /* copy */
61
uncompressed_sectors = DIV_ROUND_UP(s->lengths[chunk], 512);
62
break;
63
- case UDIG: /* zero */
64
+ case UDZE: /* zero */
65
+ case UDIG: /* ignore */
66
/* as the all-zeroes block may be large, it is treated specially: the
67
* sector is not copied from a large buffer, a simple memset is used
68
* instead. Therefore uncompressed_sectors does not need to be set. */
69
@@ -XXX,XX +XXX,XX @@ typedef struct DmgHeaderState {
70
static bool dmg_is_known_block_type(uint32_t entry_type)
71
{
72
switch (entry_type) {
73
+ case UDZE: /* zeros */
74
case UDRW: /* uncompressed */
75
- case UDIG: /* zeroes */
76
+ case UDIG: /* ignore */
77
case UDZO: /* zlib */
78
return true;
79
case UDBZ: /* bzip2 */
80
@@ -XXX,XX +XXX,XX @@ static int dmg_read_mish_block(BDRVDMGState *s, DmgHeaderState *ds,
81
/* sector count */
82
s->sectorcounts[i] = buff_read_uint64(buffer, offset + 0x10);
83
84
- /* all-zeroes sector (type 2) does not need to be "uncompressed" and can
85
- * therefore be unbounded. */
86
- if (s->types[i] != UDIG && s->sectorcounts[i] > DMG_SECTORCOUNTS_MAX) {
87
+ /* all-zeroes sector (type UDZE and UDIG) does not need to be
88
+ * "uncompressed" and can therefore be unbounded. */
89
+ if (s->types[i] != UDZE && s->types[i] != UDIG
90
+ && s->sectorcounts[i] > DMG_SECTORCOUNTS_MAX) {
91
error_report("sector count %" PRIu64 " for chunk %" PRIu32
92
" is larger than max (%u)",
93
s->sectorcounts[i], i, DMG_SECTORCOUNTS_MAX);
94
@@ -XXX,XX +XXX,XX @@ static inline int dmg_read_chunk(BlockDriverState *bs, uint64_t sector_num)
95
return -1;
96
}
97
break;
98
- case UDIG: /* zero */
99
+ case UDZE: /* zeros */
100
+ case UDIG: /* ignore */
101
/* see dmg_read, it is treated specially. No buffer needs to be
102
* pre-filled, the zeroes can be set directly. */
103
break;
104
@@ -XXX,XX +XXX,XX @@ dmg_co_preadv(BlockDriverState *bs, uint64_t offset, uint64_t bytes,
105
/* Special case: current chunk is all zeroes. Do not perform a memcpy as
106
* s->uncompressed_chunk may be too small to cover the large all-zeroes
107
* section. dmg_read_chunk is called to find s->current_chunk */
108
- if (s->types[s->current_chunk] == UDIG) { /* all zeroes block entry */
109
+ if (s->types[s->current_chunk] == UDZE
110
+ || s->types[s->current_chunk] == UDIG) { /* all zeroes block entry */
111
qemu_iovec_memset(qiov, i * 512, 0, 512);
112
continue;
113
}
114
--
115
2.20.1
116
117
diff view generated by jsdifflib