1
The following changes since commit 464588675455afda2899e20a0b120e4075de50c7:
1
The following changes since commit 7260438b7056469610ee166f7abe9ff8a26b8b16:
2
2
3
Merge remote-tracking branch 'remotes/sstabellini/tags/xen-20170627-tag' into staging (2017-06-29 11:45:01 +0100)
3
Merge remote-tracking branch 'remotes/palmer/tags/riscv-for-master-3.2-part2' into staging (2019-01-14 11:41:43 +0000)
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
git://github.com/stefanha/qemu.git tags/block-pull-request
8
8
9
for you to fetch changes up to c324fd0a39cee43c13f6d1fb34f74fc5e2fb007b:
9
for you to fetch changes up to fef1660132b0f25bf2d275d7f986ddcfe19a4426:
10
10
11
virtio-pci: use ioeventfd even when KVM is disabled (2017-06-30 11:03:45 +0100)
11
aio-posix: Fix concurrent aio_poll/set_fd_handler. (2019-01-14 14:09:41 +0000)
12
13
----------------------------------------------------------------
14
Pull request
15
16
No user-visible changes.
12
17
13
----------------------------------------------------------------
18
----------------------------------------------------------------
14
19
15
----------------------------------------------------------------
20
Remy Noel (2):
21
aio-posix: Unregister fd from ctx epoll when removing fd_handler.
22
aio-posix: Fix concurrent aio_poll/set_fd_handler.
16
23
17
Stefan Hajnoczi (7):
24
util/aio-posix.c | 90 +++++++++++++++++++++++++++++-------------------
18
virtio-blk: trace vdev so devices can be distinguished
25
util/aio-win32.c | 67 ++++++++++++++++-------------------
19
libqos: fix typo in virtio.h QVirtQueue->used comment
26
2 files changed, 84 insertions(+), 73 deletions(-)
20
libqos: add virtio used ring support
21
tests: fix virtio-scsi-test ISR dependence
22
tests: fix virtio-blk-test ISR dependence
23
tests: fix virtio-net-test ISR dependence
24
virtio-pci: use ioeventfd even when KVM is disabled
25
26
tests/libqos/virtio.h | 8 ++++++-
27
hw/block/virtio-blk.c | 12 ++++++----
28
hw/virtio/virtio-pci.c | 2 +-
29
tests/libqos/virtio.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++
30
tests/virtio-blk-test.c | 27 ++++++++++++++--------
31
tests/virtio-net-test.c | 6 ++---
32
tests/virtio-scsi-test.c | 2 +-
33
hw/block/trace-events | 10 ++++----
34
8 files changed, 101 insertions(+), 26 deletions(-)
35
27
36
--
28
--
37
2.9.4
29
2.20.1
38
30
39
31
diff view generated by jsdifflib
Deleted patch
1
It is hard to analyze trace logs with multiple virtio-blk devices
2
because none of the trace events include the VirtIODevice *vdev.
3
1
4
This patch adds vdev so it's clear which device a request is associated
5
with.
6
7
I considered using VirtIOBlock *s instead but VirtIODevice *vdev is more
8
general and may be correlated with generic virtio trace events like
9
virtio_set_status.
10
11
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
12
Reviewed-by: Fam Zheng <famz@redhat.com>
13
Message-id: 20170614092930.11234-1-stefanha@redhat.com
14
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
15
---
16
hw/block/virtio-blk.c | 12 +++++++-----
17
hw/block/trace-events | 10 +++++-----
18
2 files changed, 12 insertions(+), 10 deletions(-)
19
20
diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c
21
index XXXXXXX..XXXXXXX 100644
22
--- a/hw/block/virtio-blk.c
23
+++ b/hw/block/virtio-blk.c
24
@@ -XXX,XX +XXX,XX @@ static void virtio_blk_req_complete(VirtIOBlockReq *req, unsigned char status)
25
VirtIOBlock *s = req->dev;
26
VirtIODevice *vdev = VIRTIO_DEVICE(s);
27
28
- trace_virtio_blk_req_complete(req, status);
29
+ trace_virtio_blk_req_complete(vdev, req, status);
30
31
stb_p(&req->in->status, status);
32
virtqueue_push(req->vq, &req->elem, req->in_len);
33
@@ -XXX,XX +XXX,XX @@ static void virtio_blk_rw_complete(void *opaque, int ret)
34
{
35
VirtIOBlockReq *next = opaque;
36
VirtIOBlock *s = next->dev;
37
+ VirtIODevice *vdev = VIRTIO_DEVICE(s);
38
39
aio_context_acquire(blk_get_aio_context(s->conf.conf.blk));
40
while (next) {
41
VirtIOBlockReq *req = next;
42
next = req->mr_next;
43
- trace_virtio_blk_rw_complete(req, ret);
44
+ trace_virtio_blk_rw_complete(vdev, req, ret);
45
46
if (req->qiov.nalloc != -1) {
47
/* If nalloc is != 1 req->qiov is a local copy of the original
48
@@ -XXX,XX +XXX,XX @@ static inline void submit_requests(BlockBackend *blk, MultiReqBuffer *mrb,
49
mrb->reqs[i - 1]->mr_next = mrb->reqs[i];
50
}
51
52
- trace_virtio_blk_submit_multireq(mrb, start, num_reqs,
53
+ trace_virtio_blk_submit_multireq(VIRTIO_DEVICE(mrb->reqs[start]->dev),
54
+ mrb, start, num_reqs,
55
sector_num << BDRV_SECTOR_BITS,
56
qiov->size, is_write);
57
block_acct_merge_done(blk_get_stats(blk),
58
@@ -XXX,XX +XXX,XX @@ static int virtio_blk_handle_request(VirtIOBlockReq *req, MultiReqBuffer *mrb)
59
60
if (is_write) {
61
qemu_iovec_init_external(&req->qiov, iov, out_num);
62
- trace_virtio_blk_handle_write(req, req->sector_num,
63
+ trace_virtio_blk_handle_write(vdev, req, req->sector_num,
64
req->qiov.size / BDRV_SECTOR_SIZE);
65
} else {
66
qemu_iovec_init_external(&req->qiov, in_iov, in_num);
67
- trace_virtio_blk_handle_read(req, req->sector_num,
68
+ trace_virtio_blk_handle_read(vdev, req, req->sector_num,
69
req->qiov.size / BDRV_SECTOR_SIZE);
70
}
71
72
diff --git a/hw/block/trace-events b/hw/block/trace-events
73
index XXXXXXX..XXXXXXX 100644
74
--- a/hw/block/trace-events
75
+++ b/hw/block/trace-events
76
@@ -XXX,XX +XXX,XX @@
77
# See docs/tracing.txt for syntax documentation.
78
79
# hw/block/virtio-blk.c
80
-virtio_blk_req_complete(void *req, int status) "req %p status %d"
81
-virtio_blk_rw_complete(void *req, int ret) "req %p ret %d"
82
-virtio_blk_handle_write(void *req, uint64_t sector, size_t nsectors) "req %p sector %"PRIu64" nsectors %zu"
83
-virtio_blk_handle_read(void *req, uint64_t sector, size_t nsectors) "req %p sector %"PRIu64" nsectors %zu"
84
-virtio_blk_submit_multireq(void *mrb, int start, int num_reqs, uint64_t offset, size_t size, bool is_write) "mrb %p start %d num_reqs %d offset %"PRIu64" size %zu is_write %d"
85
+virtio_blk_req_complete(void *vdev, void *req, int status) "vdev %p req %p status %d"
86
+virtio_blk_rw_complete(void *vdev, void *req, int ret) "vdev %p req %p ret %d"
87
+virtio_blk_handle_write(void *vdev, void *req, uint64_t sector, size_t nsectors) "vdev %p req %p sector %"PRIu64" nsectors %zu"
88
+virtio_blk_handle_read(void *vdev, void *req, uint64_t sector, size_t nsectors) "vdev %p req %p sector %"PRIu64" nsectors %zu"
89
+virtio_blk_submit_multireq(void *vdev, void *mrb, int start, int num_reqs, uint64_t offset, size_t size, bool is_write) "vdev %p mrb %p start %d num_reqs %d offset %"PRIu64" size %zu is_write %d"
90
91
# hw/block/hd-geometry.c
92
hd_geometry_lchs_guess(void *blk, int cyls, int heads, int secs) "blk %p LCHS %d %d %d"
93
--
94
2.9.4
95
96
diff view generated by jsdifflib
Deleted patch
1
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
2
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
3
Reviewed-by: Fam Zheng <famz@redhat.com>
4
Tested-by: Eric Blake <eblake@redhat.com>
5
Tested-by: Kevin Wolf <kwolf@redhat.com>
6
Message-id: 20170628184724.21378-2-stefanha@redhat.com
7
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
8
---
9
tests/libqos/virtio.h | 2 +-
10
1 file changed, 1 insertion(+), 1 deletion(-)
11
1
12
diff --git a/tests/libqos/virtio.h b/tests/libqos/virtio.h
13
index XXXXXXX..XXXXXXX 100644
14
--- a/tests/libqos/virtio.h
15
+++ b/tests/libqos/virtio.h
16
@@ -XXX,XX +XXX,XX @@ typedef struct QVirtioDevice {
17
typedef struct QVirtQueue {
18
uint64_t desc; /* This points to an array of struct vring_desc */
19
uint64_t avail; /* This points to a struct vring_avail */
20
- uint64_t used; /* This points to a struct vring_desc */
21
+ uint64_t used; /* This points to a struct vring_used */
22
uint16_t index;
23
uint32_t size;
24
uint32_t free_head;
25
--
26
2.9.4
27
28
diff view generated by jsdifflib
1
Old kvm.ko versions only supported a tiny number of ioeventfds so
1
From: Remy Noel <remy.noel@blade-group.com>
2
virtio-pci avoids ioeventfds when kvm_has_many_ioeventfds() returns 0.
3
2
4
Do not check kvm_has_many_ioeventfds() when KVM is disabled since it
3
Cleaning the events will cause aio_epoll_update to unregister the fd.
5
always returns 0. Since commit 8c56c1a592b5092d91da8d8943c17777d6462a6f
4
Otherwise, the fd is kept registered until it is destroyed.
6
("memory: emulate ioeventfd") it has been possible to use ioeventfds in
7
qtest or TCG mode.
8
5
9
This patch makes -device virtio-blk-pci,iothread=iothread0 work even
6
Signed-off-by: Remy Noel <remy.noel@blade-group.com>
10
when KVM is disabled.
7
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
11
8
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
12
I have tested that virtio-blk-pci works under TCG both with and without
9
Message-id: 20181220152030.28035-2-remy.noel@blade-group.com
13
iothread.
14
15
This patch fixes qemu-iotests 068, which was accidentally merged early
16
despite the dependency on ioeventfd.
17
18
Cc: Michael S. Tsirkin <mst@redhat.com>
19
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
20
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
21
Reviewed-by: Fam Zheng <famz@redhat.com>
22
Tested-by: Eric Blake <eblake@redhat.com>
23
Tested-by: Kevin Wolf <kwolf@redhat.com>
24
Message-id: 20170628184724.21378-7-stefanha@redhat.com
25
Message-id: 20170615163813.7255-2-stefanha@redhat.com
26
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
10
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
27
---
11
---
28
hw/virtio/virtio-pci.c | 2 +-
12
util/aio-posix.c | 3 +++
29
1 file changed, 1 insertion(+), 1 deletion(-)
13
1 file changed, 3 insertions(+)
30
14
31
diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c
15
diff --git a/util/aio-posix.c b/util/aio-posix.c
32
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
33
--- a/hw/virtio/virtio-pci.c
17
--- a/util/aio-posix.c
34
+++ b/hw/virtio/virtio-pci.c
18
+++ b/util/aio-posix.c
35
@@ -XXX,XX +XXX,XX @@ static void virtio_pci_realize(PCIDevice *pci_dev, Error **errp)
19
@@ -XXX,XX +XXX,XX @@ void aio_set_fd_handler(AioContext *ctx,
36
bool pcie_port = pci_bus_is_express(pci_dev->bus) &&
20
QLIST_REMOVE(node, node);
37
!pci_bus_is_root(pci_dev->bus);
21
deleted = true;
38
22
}
39
- if (!kvm_has_many_ioeventfds()) {
23
+ /* Clean events in order to unregister fd from the ctx epoll. */
40
+ if (kvm_enabled() && !kvm_has_many_ioeventfds()) {
24
+ node->pfd.events = 0;
41
proxy->flags &= ~VIRTIO_PCI_FLAG_USE_IOEVENTFD;
25
+
42
}
26
poll_disable_change = -!node->io_poll;
43
27
} else {
28
poll_disable_change = !io_poll - (node && !node->io_poll);
44
--
29
--
45
2.9.4
30
2.20.1
46
31
47
32
diff view generated by jsdifflib
1
Existing tests do not touch the virtqueue used ring. Instead they poll
1
From: Remy Noel <remy.noel@blade-group.com>
2
the virtqueue ISR register and peek into their request's device-specific
2
3
status field.
3
It is possible for an io_poll callback to be concurrently executed along
4
4
with an aio_set_fd_handlers. This can cause all sorts of problems, like
5
It turns out that the virtqueue ISR register can be set to 1 more than
5
a NULL callback or a bad opaque pointer.
6
once for a single notification (see commit
6
7
83d768b5640946b7da55ce8335509df297e2c7cd "virtio: set ISR on dataplane
7
This changes set_fd_handlers so that it no longer modify existing handlers
8
notifications"). This causes problems for tests that assume a 1:1
8
entries and instead, always insert those after having proper initialisation.
9
correspondence between the ISR being 1 and request completion.
9
10
10
Tested-by: Stefan Hajnoczi <stefanha@redhat.com>
11
Peeking at device-specific status fields is also problematic if the
11
Signed-off-by: Remy Noel <remy.noel@blade-group.com>
12
device has no field that can be abused for EINPROGRESS polling
12
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
13
semantics. This is the case if all the field's values may be set by the
13
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
14
device; there's no magic constant left for polling.
14
Message-id: 20181220152030.28035-3-remy.noel@blade-group.com
15
16
It's time to process the used ring for completed requests, just like a
17
real virtio guest driver. This patch adds the necessary APIs.
18
19
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
20
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
21
Reviewed-by: Fam Zheng <famz@redhat.com>
22
Tested-by: Eric Blake <eblake@redhat.com>
23
Tested-by: Kevin Wolf <kwolf@redhat.com>
24
Message-id: 20170628184724.21378-3-stefanha@redhat.com
25
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
15
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
26
---
16
---
27
tests/libqos/virtio.h | 6 ++++++
17
util/aio-posix.c | 89 ++++++++++++++++++++++++++++--------------------
28
tests/libqos/virtio.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++
18
util/aio-win32.c | 67 ++++++++++++++++--------------------
29
2 files changed, 66 insertions(+)
19
2 files changed, 82 insertions(+), 74 deletions(-)
30
20
31
diff --git a/tests/libqos/virtio.h b/tests/libqos/virtio.h
21
diff --git a/util/aio-posix.c b/util/aio-posix.c
32
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
33
--- a/tests/libqos/virtio.h
23
--- a/util/aio-posix.c
34
+++ b/tests/libqos/virtio.h
24
+++ b/util/aio-posix.c
35
@@ -XXX,XX +XXX,XX @@ typedef struct QVirtQueue {
25
@@ -XXX,XX +XXX,XX @@ static AioHandler *find_aio_handler(AioContext *ctx, int fd)
36
uint32_t free_head;
26
return NULL;
37
uint32_t num_free;
38
uint32_t align;
39
+ uint16_t last_used_idx;
40
bool indirect;
41
bool event;
42
} QVirtQueue;
43
@@ -XXX,XX +XXX,XX @@ uint8_t qvirtio_wait_status_byte_no_isr(QVirtioDevice *d,
44
QVirtQueue *vq,
45
uint64_t addr,
46
gint64 timeout_us);
47
+void qvirtio_wait_used_elem(QVirtioDevice *d,
48
+ QVirtQueue *vq,
49
+ uint32_t desc_idx,
50
+ gint64 timeout_us);
51
void qvirtio_wait_config_isr(QVirtioDevice *d, gint64 timeout_us);
52
QVirtQueue *qvirtqueue_setup(QVirtioDevice *d,
53
QGuestAllocator *alloc, uint16_t index);
54
@@ -XXX,XX +XXX,XX @@ uint32_t qvirtqueue_add(QVirtQueue *vq, uint64_t data, uint32_t len, bool write,
55
bool next);
56
uint32_t qvirtqueue_add_indirect(QVirtQueue *vq, QVRingIndirectDesc *indirect);
57
void qvirtqueue_kick(QVirtioDevice *d, QVirtQueue *vq, uint32_t free_head);
58
+bool qvirtqueue_get_buf(QVirtQueue *vq, uint32_t *desc_idx);
59
60
void qvirtqueue_set_used_event(QVirtQueue *vq, uint16_t idx);
61
#endif
62
diff --git a/tests/libqos/virtio.c b/tests/libqos/virtio.c
63
index XXXXXXX..XXXXXXX 100644
64
--- a/tests/libqos/virtio.c
65
+++ b/tests/libqos/virtio.c
66
@@ -XXX,XX +XXX,XX @@ uint8_t qvirtio_wait_status_byte_no_isr(QVirtioDevice *d,
67
return val;
68
}
27
}
69
28
70
+/*
29
+static bool aio_remove_fd_handler(AioContext *ctx, AioHandler *node)
71
+ * qvirtio_wait_used_elem:
72
+ * @desc_idx: The next expected vq->desc[] index in the used ring
73
+ * @timeout_us: How many microseconds to wait before failing
74
+ *
75
+ * This function waits for the next completed request on the used ring.
76
+ */
77
+void qvirtio_wait_used_elem(QVirtioDevice *d,
78
+ QVirtQueue *vq,
79
+ uint32_t desc_idx,
80
+ gint64 timeout_us)
81
+{
30
+{
82
+ gint64 start_time = g_get_monotonic_time();
31
+ /* If the GSource is in the process of being destroyed then
83
+
32
+ * g_source_remove_poll() causes an assertion failure. Skip
84
+ for (;;) {
33
+ * removal in that case, because glib cleans up its state during
85
+ uint32_t got_desc_idx;
34
+ * destruction anyway.
86
+
35
+ */
87
+ clock_step(100);
36
+ if (!g_source_is_destroyed(&ctx->source)) {
88
+
37
+ g_source_remove_poll(&ctx->source, &node->pfd);
89
+ if (d->bus->get_queue_isr_status(d, vq) &&
38
+ }
90
+ qvirtqueue_get_buf(vq, &got_desc_idx)) {
39
+
91
+ g_assert_cmpint(got_desc_idx, ==, desc_idx);
40
+ /* If a read is in progress, just mark the node as deleted */
92
+ return;
41
+ if (qemu_lockcnt_count(&ctx->list_lock)) {
93
+ }
42
+ node->deleted = 1;
94
+
43
+ node->pfd.revents = 0;
95
+ g_assert(g_get_monotonic_time() - start_time <= timeout_us);
96
+ }
97
+}
98
+
99
void qvirtio_wait_config_isr(QVirtioDevice *d, gint64 timeout_us)
100
{
101
gint64 start_time = g_get_monotonic_time();
102
@@ -XXX,XX +XXX,XX @@ void qvirtqueue_kick(QVirtioDevice *d, QVirtQueue *vq, uint32_t free_head)
103
}
104
}
105
106
+/*
107
+ * qvirtqueue_get_buf:
108
+ * @desc_idx: A pointer that is filled with the vq->desc[] index, may be NULL
109
+ *
110
+ * This function gets the next used element if there is one ready.
111
+ *
112
+ * Returns: true if an element was ready, false otherwise
113
+ */
114
+bool qvirtqueue_get_buf(QVirtQueue *vq, uint32_t *desc_idx)
115
+{
116
+ uint16_t idx;
117
+
118
+ idx = readw(vq->used + offsetof(struct vring_used, idx));
119
+ if (idx == vq->last_used_idx) {
120
+ return false;
44
+ return false;
121
+ }
45
+ }
122
+
46
+ /* Otherwise, delete it for real. We can't just mark it as
123
+ if (desc_idx) {
47
+ * deleted because deleted nodes are only cleaned up while
124
+ uint64_t elem_addr;
48
+ * no one is walking the handlers list.
125
+
49
+ */
126
+ elem_addr = vq->used +
50
+ QLIST_REMOVE(node, node);
127
+ offsetof(struct vring_used, ring) +
128
+ (vq->last_used_idx % vq->size) *
129
+ sizeof(struct vring_used_elem);
130
+ *desc_idx = readl(elem_addr + offsetof(struct vring_used_elem, id));
131
+ }
132
+
133
+ vq->last_used_idx++;
134
+ return true;
51
+ return true;
135
+}
52
+}
136
+
53
+
137
void qvirtqueue_set_used_event(QVirtQueue *vq, uint16_t idx)
54
void aio_set_fd_handler(AioContext *ctx,
55
int fd,
56
bool is_external,
57
@@ -XXX,XX +XXX,XX @@ void aio_set_fd_handler(AioContext *ctx,
58
void *opaque)
138
{
59
{
139
g_assert(vq->event);
60
AioHandler *node;
61
+ AioHandler *new_node = NULL;
62
bool is_new = false;
63
bool deleted = false;
64
int poll_disable_change;
65
@@ -XXX,XX +XXX,XX @@ void aio_set_fd_handler(AioContext *ctx,
66
qemu_lockcnt_unlock(&ctx->list_lock);
67
return;
68
}
69
-
70
- /* If the GSource is in the process of being destroyed then
71
- * g_source_remove_poll() causes an assertion failure. Skip
72
- * removal in that case, because glib cleans up its state during
73
- * destruction anyway.
74
- */
75
- if (!g_source_is_destroyed(&ctx->source)) {
76
- g_source_remove_poll(&ctx->source, &node->pfd);
77
- }
78
-
79
- /* If a read is in progress, just mark the node as deleted */
80
- if (qemu_lockcnt_count(&ctx->list_lock)) {
81
- node->deleted = 1;
82
- node->pfd.revents = 0;
83
- } else {
84
- /* Otherwise, delete it for real. We can't just mark it as
85
- * deleted because deleted nodes are only cleaned up while
86
- * no one is walking the handlers list.
87
- */
88
- QLIST_REMOVE(node, node);
89
- deleted = true;
90
- }
91
/* Clean events in order to unregister fd from the ctx epoll. */
92
node->pfd.events = 0;
93
94
@@ -XXX,XX +XXX,XX @@ void aio_set_fd_handler(AioContext *ctx,
95
} else {
96
poll_disable_change = !io_poll - (node && !node->io_poll);
97
if (node == NULL) {
98
- /* Alloc and insert if it's not already there */
99
- node = g_new0(AioHandler, 1);
100
- node->pfd.fd = fd;
101
- QLIST_INSERT_HEAD_RCU(&ctx->aio_handlers, node, node);
102
-
103
- g_source_add_poll(&ctx->source, &node->pfd);
104
is_new = true;
105
}
106
+ /* Alloc and insert if it's not already there */
107
+ new_node = g_new0(AioHandler, 1);
108
109
/* Update handler with latest information */
110
- node->io_read = io_read;
111
- node->io_write = io_write;
112
- node->io_poll = io_poll;
113
- node->opaque = opaque;
114
- node->is_external = is_external;
115
+ new_node->io_read = io_read;
116
+ new_node->io_write = io_write;
117
+ new_node->io_poll = io_poll;
118
+ new_node->opaque = opaque;
119
+ new_node->is_external = is_external;
120
121
- node->pfd.events = (io_read ? G_IO_IN | G_IO_HUP | G_IO_ERR : 0);
122
- node->pfd.events |= (io_write ? G_IO_OUT | G_IO_ERR : 0);
123
+ if (is_new) {
124
+ new_node->pfd.fd = fd;
125
+ } else {
126
+ new_node->pfd = node->pfd;
127
+ }
128
+ g_source_add_poll(&ctx->source, &new_node->pfd);
129
+
130
+ new_node->pfd.events = (io_read ? G_IO_IN | G_IO_HUP | G_IO_ERR : 0);
131
+ new_node->pfd.events |= (io_write ? G_IO_OUT | G_IO_ERR : 0);
132
+
133
+ QLIST_INSERT_HEAD_RCU(&ctx->aio_handlers, new_node, node);
134
+ }
135
+ if (node) {
136
+ deleted = aio_remove_fd_handler(ctx, node);
137
}
138
139
/* No need to order poll_disable_cnt writes against other updates;
140
@@ -XXX,XX +XXX,XX @@ void aio_set_fd_handler(AioContext *ctx,
141
atomic_set(&ctx->poll_disable_cnt,
142
atomic_read(&ctx->poll_disable_cnt) + poll_disable_change);
143
144
- aio_epoll_update(ctx, node, is_new);
145
+ if (new_node) {
146
+ aio_epoll_update(ctx, new_node, is_new);
147
+ } else if (node) {
148
+ /* Unregister deleted fd_handler */
149
+ aio_epoll_update(ctx, node, false);
150
+ }
151
qemu_lockcnt_unlock(&ctx->list_lock);
152
aio_notify(ctx);
153
154
diff --git a/util/aio-win32.c b/util/aio-win32.c
155
index XXXXXXX..XXXXXXX 100644
156
--- a/util/aio-win32.c
157
+++ b/util/aio-win32.c
158
@@ -XXX,XX +XXX,XX @@ struct AioHandler {
159
QLIST_ENTRY(AioHandler) node;
160
};
161
162
+static void aio_remove_fd_handler(AioContext *ctx, AioHandler *node)
163
+{
164
+ /* If aio_poll is in progress, just mark the node as deleted */
165
+ if (qemu_lockcnt_count(&ctx->list_lock)) {
166
+ node->deleted = 1;
167
+ node->pfd.revents = 0;
168
+ } else {
169
+ /* Otherwise, delete it for real. We can't just mark it as
170
+ * deleted because deleted nodes are only cleaned up after
171
+ * releasing the list_lock.
172
+ */
173
+ QLIST_REMOVE(node, node);
174
+ g_free(node);
175
+ }
176
+}
177
+
178
void aio_set_fd_handler(AioContext *ctx,
179
int fd,
180
bool is_external,
181
@@ -XXX,XX +XXX,XX @@ void aio_set_fd_handler(AioContext *ctx,
182
void *opaque)
183
{
184
/* fd is a SOCKET in our case */
185
- AioHandler *node;
186
+ AioHandler *old_node;
187
+ AioHandler *node = NULL;
188
189
qemu_lockcnt_lock(&ctx->list_lock);
190
- QLIST_FOREACH(node, &ctx->aio_handlers, node) {
191
- if (node->pfd.fd == fd && !node->deleted) {
192
+ QLIST_FOREACH(old_node, &ctx->aio_handlers, node) {
193
+ if (old_node->pfd.fd == fd && !old_node->deleted) {
194
break;
195
}
196
}
197
198
- /* Are we deleting the fd handler? */
199
- if (!io_read && !io_write) {
200
- if (node) {
201
- /* If aio_poll is in progress, just mark the node as deleted */
202
- if (qemu_lockcnt_count(&ctx->list_lock)) {
203
- node->deleted = 1;
204
- node->pfd.revents = 0;
205
- } else {
206
- /* Otherwise, delete it for real. We can't just mark it as
207
- * deleted because deleted nodes are only cleaned up after
208
- * releasing the list_lock.
209
- */
210
- QLIST_REMOVE(node, node);
211
- g_free(node);
212
- }
213
- }
214
- } else {
215
+ if (io_read || io_write) {
216
HANDLE event;
217
long bitmask = 0;
218
219
- if (node == NULL) {
220
- /* Alloc and insert if it's not already there */
221
- node = g_new0(AioHandler, 1);
222
- node->pfd.fd = fd;
223
- QLIST_INSERT_HEAD_RCU(&ctx->aio_handlers, node, node);
224
- }
225
+ /* Alloc and insert if it's not already there */
226
+ node = g_new0(AioHandler, 1);
227
+ node->pfd.fd = fd;
228
229
node->pfd.events = 0;
230
if (node->io_read) {
231
@@ -XXX,XX +XXX,XX @@ void aio_set_fd_handler(AioContext *ctx,
232
bitmask |= FD_WRITE | FD_CONNECT;
233
}
234
235
+ QLIST_INSERT_HEAD_RCU(&ctx->aio_handlers, node, node);
236
event = event_notifier_get_handle(&ctx->notifier);
237
WSAEventSelect(node->pfd.fd, event, bitmask);
238
}
239
+ if (old_node) {
240
+ aio_remove_fd_handler(ctx, old_node);
241
+ }
242
243
qemu_lockcnt_unlock(&ctx->list_lock);
244
aio_notify(ctx);
245
@@ -XXX,XX +XXX,XX @@ void aio_set_event_notifier(AioContext *ctx,
246
if (node) {
247
g_source_remove_poll(&ctx->source, &node->pfd);
248
249
- /* aio_poll is in progress, just mark the node as deleted */
250
- if (qemu_lockcnt_count(&ctx->list_lock)) {
251
- node->deleted = 1;
252
- node->pfd.revents = 0;
253
- } else {
254
- /* Otherwise, delete it for real. We can't just mark it as
255
- * deleted because deleted nodes are only cleaned up after
256
- * releasing the list_lock.
257
- */
258
- QLIST_REMOVE(node, node);
259
- g_free(node);
260
- }
261
+ aio_remove_fd_handler(ctx, node);
262
}
263
} else {
264
if (node == NULL) {
140
--
265
--
141
2.9.4
266
2.20.1
142
267
143
268
diff view generated by jsdifflib
Deleted patch
1
Use the new used ring APIs instead of assuming ISR being set means the
2
request has completed.
3
1
4
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
5
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
6
Reviewed-by: Fam Zheng <famz@redhat.com>
7
Tested-by: Eric Blake <eblake@redhat.com>
8
Tested-by: Kevin Wolf <kwolf@redhat.com>
9
Message-id: 20170628184724.21378-4-stefanha@redhat.com
10
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
11
---
12
tests/virtio-scsi-test.c | 2 +-
13
1 file changed, 1 insertion(+), 1 deletion(-)
14
15
diff --git a/tests/virtio-scsi-test.c b/tests/virtio-scsi-test.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/tests/virtio-scsi-test.c
18
+++ b/tests/virtio-scsi-test.c
19
@@ -XXX,XX +XXX,XX @@ static uint8_t virtio_scsi_do_command(QVirtIOSCSI *vs, const uint8_t *cdb,
20
}
21
22
qvirtqueue_kick(vs->dev, vq, free_head);
23
- qvirtio_wait_queue_isr(vs->dev, vq, QVIRTIO_SCSI_TIMEOUT_US);
24
+ qvirtio_wait_used_elem(vs->dev, vq, free_head, QVIRTIO_SCSI_TIMEOUT_US);
25
26
response = readb(resp_addr +
27
offsetof(struct virtio_scsi_cmd_resp, response));
28
--
29
2.9.4
30
31
diff view generated by jsdifflib
Deleted patch
1
Use the new used ring APIs instead of assuming ISR being set means the
2
request has completed.
3
1
4
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
5
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
6
Reviewed-by: Fam Zheng <famz@redhat.com>
7
Tested-by: Eric Blake <eblake@redhat.com>
8
Tested-by: Kevin Wolf <kwolf@redhat.com>
9
Message-id: 20170628184724.21378-5-stefanha@redhat.com
10
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
11
---
12
tests/virtio-blk-test.c | 27 +++++++++++++++++----------
13
1 file changed, 17 insertions(+), 10 deletions(-)
14
15
diff --git a/tests/virtio-blk-test.c b/tests/virtio-blk-test.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/tests/virtio-blk-test.c
18
+++ b/tests/virtio-blk-test.c
19
@@ -XXX,XX +XXX,XX @@ static void test_basic(QVirtioDevice *dev, QGuestAllocator *alloc,
20
21
qvirtqueue_kick(dev, vq, free_head);
22
23
- qvirtio_wait_queue_isr(dev, vq, QVIRTIO_BLK_TIMEOUT_US);
24
+ qvirtio_wait_used_elem(dev, vq, free_head, QVIRTIO_BLK_TIMEOUT_US);
25
status = readb(req_addr + 528);
26
g_assert_cmpint(status, ==, 0);
27
28
@@ -XXX,XX +XXX,XX @@ static void test_basic(QVirtioDevice *dev, QGuestAllocator *alloc,
29
30
qvirtqueue_kick(dev, vq, free_head);
31
32
- qvirtio_wait_queue_isr(dev, vq, QVIRTIO_BLK_TIMEOUT_US);
33
+ qvirtio_wait_used_elem(dev, vq, free_head, QVIRTIO_BLK_TIMEOUT_US);
34
status = readb(req_addr + 528);
35
g_assert_cmpint(status, ==, 0);
36
37
@@ -XXX,XX +XXX,XX @@ static void test_basic(QVirtioDevice *dev, QGuestAllocator *alloc,
38
qvirtqueue_add(vq, req_addr + 528, 1, true, false);
39
qvirtqueue_kick(dev, vq, free_head);
40
41
- qvirtio_wait_queue_isr(dev, vq, QVIRTIO_BLK_TIMEOUT_US);
42
+ qvirtio_wait_used_elem(dev, vq, free_head, QVIRTIO_BLK_TIMEOUT_US);
43
status = readb(req_addr + 528);
44
g_assert_cmpint(status, ==, 0);
45
46
@@ -XXX,XX +XXX,XX @@ static void test_basic(QVirtioDevice *dev, QGuestAllocator *alloc,
47
48
qvirtqueue_kick(dev, vq, free_head);
49
50
- qvirtio_wait_queue_isr(dev, vq, QVIRTIO_BLK_TIMEOUT_US);
51
+ qvirtio_wait_used_elem(dev, vq, free_head, QVIRTIO_BLK_TIMEOUT_US);
52
status = readb(req_addr + 528);
53
g_assert_cmpint(status, ==, 0);
54
55
@@ -XXX,XX +XXX,XX @@ static void pci_indirect(void)
56
free_head = qvirtqueue_add_indirect(&vqpci->vq, indirect);
57
qvirtqueue_kick(&dev->vdev, &vqpci->vq, free_head);
58
59
- qvirtio_wait_queue_isr(&dev->vdev, &vqpci->vq,
60
+ qvirtio_wait_used_elem(&dev->vdev, &vqpci->vq, free_head,
61
QVIRTIO_BLK_TIMEOUT_US);
62
status = readb(req_addr + 528);
63
g_assert_cmpint(status, ==, 0);
64
@@ -XXX,XX +XXX,XX @@ static void pci_indirect(void)
65
free_head = qvirtqueue_add_indirect(&vqpci->vq, indirect);
66
qvirtqueue_kick(&dev->vdev, &vqpci->vq, free_head);
67
68
- qvirtio_wait_queue_isr(&dev->vdev, &vqpci->vq,
69
+ qvirtio_wait_used_elem(&dev->vdev, &vqpci->vq, free_head,
70
QVIRTIO_BLK_TIMEOUT_US);
71
status = readb(req_addr + 528);
72
g_assert_cmpint(status, ==, 0);
73
@@ -XXX,XX +XXX,XX @@ static void pci_msix(void)
74
qvirtqueue_add(&vqpci->vq, req_addr + 528, 1, true, false);
75
qvirtqueue_kick(&dev->vdev, &vqpci->vq, free_head);
76
77
- qvirtio_wait_queue_isr(&dev->vdev, &vqpci->vq,
78
+ qvirtio_wait_used_elem(&dev->vdev, &vqpci->vq, free_head,
79
QVIRTIO_BLK_TIMEOUT_US);
80
81
status = readb(req_addr + 528);
82
@@ -XXX,XX +XXX,XX @@ static void pci_msix(void)
83
qvirtqueue_kick(&dev->vdev, &vqpci->vq, free_head);
84
85
86
- qvirtio_wait_queue_isr(&dev->vdev, &vqpci->vq,
87
+ qvirtio_wait_used_elem(&dev->vdev, &vqpci->vq, free_head,
88
QVIRTIO_BLK_TIMEOUT_US);
89
90
status = readb(req_addr + 528);
91
@@ -XXX,XX +XXX,XX @@ static void pci_idx(void)
92
uint64_t capacity;
93
uint32_t features;
94
uint32_t free_head;
95
+ uint32_t write_head;
96
+ uint32_t desc_idx;
97
uint8_t status;
98
char *data;
99
100
@@ -XXX,XX +XXX,XX @@ static void pci_idx(void)
101
qvirtqueue_add(&vqpci->vq, req_addr + 528, 1, true, false);
102
qvirtqueue_kick(&dev->vdev, &vqpci->vq, free_head);
103
104
- qvirtio_wait_queue_isr(&dev->vdev, &vqpci->vq, QVIRTIO_BLK_TIMEOUT_US);
105
+ qvirtio_wait_used_elem(&dev->vdev, &vqpci->vq, free_head,
106
+ QVIRTIO_BLK_TIMEOUT_US);
107
108
/* Write request */
109
req.type = VIRTIO_BLK_T_OUT;
110
@@ -XXX,XX +XXX,XX @@ static void pci_idx(void)
111
qvirtqueue_add(&vqpci->vq, req_addr + 16, 512, false, true);
112
qvirtqueue_add(&vqpci->vq, req_addr + 528, 1, true, false);
113
qvirtqueue_kick(&dev->vdev, &vqpci->vq, free_head);
114
+ write_head = free_head;
115
116
/* No notification expected */
117
status = qvirtio_wait_status_byte_no_isr(&dev->vdev,
118
@@ -XXX,XX +XXX,XX @@ static void pci_idx(void)
119
120
qvirtqueue_kick(&dev->vdev, &vqpci->vq, free_head);
121
122
- qvirtio_wait_queue_isr(&dev->vdev, &vqpci->vq,
123
+ /* We get just one notification for both requests */
124
+ qvirtio_wait_used_elem(&dev->vdev, &vqpci->vq, write_head,
125
QVIRTIO_BLK_TIMEOUT_US);
126
+ g_assert(qvirtqueue_get_buf(&vqpci->vq, &desc_idx));
127
+ g_assert_cmpint(desc_idx, ==, free_head);
128
129
status = readb(req_addr + 528);
130
g_assert_cmpint(status, ==, 0);
131
--
132
2.9.4
133
134
diff view generated by jsdifflib
Deleted patch
1
Use the new used ring APIs instead of assuming ISR being set means the
2
request has completed.
3
1
4
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
5
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
6
Reviewed-by: Fam Zheng <famz@redhat.com>
7
Tested-by: Eric Blake <eblake@redhat.com>
8
Tested-by: Kevin Wolf <kwolf@redhat.com>
9
Message-id: 20170628184724.21378-6-stefanha@redhat.com
10
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
11
---
12
tests/virtio-net-test.c | 6 +++---
13
1 file changed, 3 insertions(+), 3 deletions(-)
14
15
diff --git a/tests/virtio-net-test.c b/tests/virtio-net-test.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/tests/virtio-net-test.c
18
+++ b/tests/virtio-net-test.c
19
@@ -XXX,XX +XXX,XX @@ static void rx_test(QVirtioDevice *dev,
20
ret = iov_send(socket, iov, 2, 0, sizeof(len) + sizeof(test));
21
g_assert_cmpint(ret, ==, sizeof(test) + sizeof(len));
22
23
- qvirtio_wait_queue_isr(dev, vq, QVIRTIO_NET_TIMEOUT_US);
24
+ qvirtio_wait_used_elem(dev, vq, free_head, QVIRTIO_NET_TIMEOUT_US);
25
memread(req_addr + VNET_HDR_SIZE, buffer, sizeof(test));
26
g_assert_cmpstr(buffer, ==, "TEST");
27
28
@@ -XXX,XX +XXX,XX @@ static void tx_test(QVirtioDevice *dev,
29
free_head = qvirtqueue_add(vq, req_addr, 64, false, false);
30
qvirtqueue_kick(dev, vq, free_head);
31
32
- qvirtio_wait_queue_isr(dev, vq, QVIRTIO_NET_TIMEOUT_US);
33
+ qvirtio_wait_used_elem(dev, vq, free_head, QVIRTIO_NET_TIMEOUT_US);
34
guest_free(alloc, req_addr);
35
36
ret = qemu_recv(socket, &len, sizeof(len), 0);
37
@@ -XXX,XX +XXX,XX @@ static void rx_stop_cont_test(QVirtioDevice *dev,
38
rsp = qmp("{ 'execute' : 'cont'}");
39
QDECREF(rsp);
40
41
- qvirtio_wait_queue_isr(dev, vq, QVIRTIO_NET_TIMEOUT_US);
42
+ qvirtio_wait_used_elem(dev, vq, free_head, QVIRTIO_NET_TIMEOUT_US);
43
memread(req_addr + VNET_HDR_SIZE, buffer, sizeof(test));
44
g_assert_cmpstr(buffer, ==, "TEST");
45
46
--
47
2.9.4
48
49
diff view generated by jsdifflib