1
The following changes since commit 464588675455afda2899e20a0b120e4075de50c7:
1
The following changes since commit 6cb4f6db4f4367faa33da85b15f75bbbd2bed2a6:
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/cleber/tags/python-next-pull-request' into staging (2019-03-07 16:16:02 +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 6ca206204fa773c8626d59caf2a5676d6cc35f52:
10
10
11
virtio-pci: use ioeventfd even when KVM is disabled (2017-06-30 11:03:45 +0100)
11
iothread: document about why we need explicit aio_poll() (2019-03-08 10:20:57 +0000)
12
13
----------------------------------------------------------------
14
Pull request
12
15
13
----------------------------------------------------------------
16
----------------------------------------------------------------
14
17
15
----------------------------------------------------------------
18
Anastasiia Rusakova (1):
19
hw/block/virtio-blk: Clean req->dev repetitions
16
20
17
Stefan Hajnoczi (7):
21
Peter Xu (5):
18
virtio-blk: trace vdev so devices can be distinguished
22
iothread: replace init_done_cond with a semaphore
19
libqos: fix typo in virtio.h QVirtQueue->used comment
23
iothread: create the gcontext unconditionally
20
libqos: add virtio used ring support
24
iothread: create main loop unconditionally
21
tests: fix virtio-scsi-test ISR dependence
25
iothread: push gcontext earlier in the thread_fn
22
tests: fix virtio-blk-test ISR dependence
26
iothread: document about why we need explicit aio_poll()
23
tests: fix virtio-net-test ISR dependence
24
virtio-pci: use ioeventfd even when KVM is disabled
25
27
26
tests/libqos/virtio.h | 8 ++++++-
28
Stefan Hajnoczi (1):
27
hw/block/virtio-blk.c | 12 ++++++----
29
MAINTAINERS: add missing support status fields
28
hw/virtio/virtio-pci.c | 2 +-
30
29
tests/libqos/virtio.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++
31
MAINTAINERS | 3 ++
30
tests/virtio-blk-test.c | 27 ++++++++++++++--------
32
include/sysemu/iothread.h | 5 +--
31
tests/virtio-net-test.c | 6 ++---
33
hw/block/virtio-blk.c | 16 ++++---
32
tests/virtio-scsi-test.c | 2 +-
34
iothread.c | 90 +++++++++++++++++++--------------------
33
hw/block/trace-events | 10 ++++----
35
4 files changed, 57 insertions(+), 57 deletions(-)
34
8 files changed, 101 insertions(+), 26 deletions(-)
35
36
36
--
37
--
37
2.9.4
38
2.20.1
38
39
39
40
diff view generated by jsdifflib
1
Old kvm.ko versions only supported a tiny number of ioeventfds so
1
This patch adds the "S:" line for areas of the codebase that currently
2
virtio-pci avoids ioeventfds when kvm_has_many_ioeventfds() returns 0.
2
lack a support status field.
3
3
4
Do not check kvm_has_many_ioeventfds() when KVM is disabled since it
4
Note that there are a few more areas that are more abstract and do not
5
always returns 0. Since commit 8c56c1a592b5092d91da8d8943c17777d6462a6f
5
correspond to a specific set of files. They have not been modified.
6
("memory: emulate ioeventfd") it has been possible to use ioeventfds in
7
qtest or TCG mode.
8
6
9
This patch makes -device virtio-blk-pci,iothread=iothread0 work even
7
Cc: Alex Bennée <alex.bennee@linaro.org>
10
when KVM is disabled.
11
12
I have tested that virtio-blk-pci works under TCG both with and without
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>
8
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
20
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
9
Reviewed-by: Thomas Huth <thuth@redhat.com>
21
Reviewed-by: Fam Zheng <famz@redhat.com>
10
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
22
Tested-by: Eric Blake <eblake@redhat.com>
11
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
23
Tested-by: Kevin Wolf <kwolf@redhat.com>
12
Message-id: 20190301163518.20702-1-stefanha@redhat.com
24
Message-id: 20170628184724.21378-7-stefanha@redhat.com
13
Message-Id: <20190301163518.20702-1-stefanha@redhat.com>
25
Message-id: 20170615163813.7255-2-stefanha@redhat.com
26
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
14
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
27
---
15
---
28
hw/virtio/virtio-pci.c | 2 +-
16
MAINTAINERS | 3 +++
29
1 file changed, 1 insertion(+), 1 deletion(-)
17
1 file changed, 3 insertions(+)
30
18
31
diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c
19
diff --git a/MAINTAINERS b/MAINTAINERS
32
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
33
--- a/hw/virtio/virtio-pci.c
21
--- a/MAINTAINERS
34
+++ b/hw/virtio/virtio-pci.c
22
+++ b/MAINTAINERS
35
@@ -XXX,XX +XXX,XX @@ static void virtio_pci_realize(PCIDevice *pci_dev, Error **errp)
23
@@ -XXX,XX +XXX,XX @@ F: include/hw/tricore/
36
bool pcie_port = pci_bus_is_express(pci_dev->bus) &&
24
37
!pci_bus_is_root(pci_dev->bus);
25
Multiarch Linux User Tests
38
26
M: Alex Bennée <alex.bennee@linaro.org>
39
- if (!kvm_has_many_ioeventfds()) {
27
+S: Maintained
40
+ if (kvm_enabled() && !kvm_has_many_ioeventfds()) {
28
F: tests/tcg/multiarch/
41
proxy->flags &= ~VIRTIO_PCI_FLAG_USE_IOEVENTFD;
29
42
}
30
Guest CPU Cores (KVM):
43
31
@@ -XXX,XX +XXX,XX @@ F: qemu.sasl
32
Coroutines
33
M: Stefan Hajnoczi <stefanha@redhat.com>
34
M: Kevin Wolf <kwolf@redhat.com>
35
+S: Maintained
36
F: util/*coroutine*
37
F: include/qemu/coroutine*
38
F: tests/test-coroutine.c
39
@@ -XXX,XX +XXX,XX @@ F: .gitlab-ci.yml
40
Guest Test Compilation Support
41
M: Alex Bennée <alex.bennee@linaro.org>
42
R: Philippe Mathieu-Daudé <f4bug@amsat.org>
43
+S: Maintained
44
F: tests/tcg/Makefile
45
F: tests/tcg/Makefile.include
46
L: qemu-devel@nongnu.org
44
--
47
--
45
2.9.4
48
2.20.1
46
49
47
50
diff view generated by jsdifflib
1
It is hard to analyze trace logs with multiple virtio-blk devices
1
From: Anastasiia Rusakova <arusakova917@gmail.com>
2
because none of the trace events include the VirtIODevice *vdev.
3
2
4
This patch adds vdev so it's clear which device a request is associated
3
Some functions sometimes uses req->dev even though a local variable
5
with.
4
VirtIOBlock* s = req->dev has already been defined.
5
Updated places to use s everywhere in the file.
6
6
7
I considered using VirtIOBlock *s instead but VirtIODevice *vdev is more
7
Signed-off-by: Anastasiia Rusakova <arusakova917@gmail.com>
8
general and may be correlated with generic virtio trace events like
8
Message-id: 20190307161925.4158-1-rusakova.nastasia@icloud.com
9
virtio_set_status.
9
Message-Id: <20190307161925.4158-1-rusakova.nastasia@icloud.com>
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>
10
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
15
---
11
---
16
hw/block/virtio-blk.c | 12 +++++++-----
12
hw/block/virtio-blk.c | 16 +++++++++-------
17
hw/block/trace-events | 10 +++++-----
13
1 file changed, 9 insertions(+), 7 deletions(-)
18
2 files changed, 12 insertions(+), 10 deletions(-)
19
14
20
diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c
15
diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c
21
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
22
--- a/hw/block/virtio-blk.c
17
--- a/hw/block/virtio-blk.c
23
+++ b/hw/block/virtio-blk.c
18
+++ 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)
19
@@ -XXX,XX +XXX,XX @@ static void virtio_blk_rw_complete(void *opaque, int ret)
20
}
21
22
if (ret) {
23
- int p = virtio_ldl_p(VIRTIO_DEVICE(req->dev), &req->out.type);
24
+ int p = virtio_ldl_p(VIRTIO_DEVICE(s), &req->out.type);
25
bool is_read = !(p & VIRTIO_BLK_T_OUT);
26
/* Note that memory may be dirtied on read failure. If the
27
* virtio request is not completed here, as is the case for
28
@@ -XXX,XX +XXX,XX @@ static void virtio_blk_rw_complete(void *opaque, int ret)
29
}
30
31
virtio_blk_req_complete(req, VIRTIO_BLK_S_OK);
32
- block_acct_done(blk_get_stats(req->dev->blk), &req->acct);
33
+ block_acct_done(blk_get_stats(s->blk), &req->acct);
34
virtio_blk_free_request(req);
35
}
36
aio_context_release(blk_get_aio_context(s->conf.conf.blk));
37
@@ -XXX,XX +XXX,XX @@ static int virtio_blk_handle_scsi_req(VirtIOBlockReq *req)
34
{
38
{
35
VirtIOBlockReq *next = opaque;
39
int status = VIRTIO_BLK_S_OK;
36
VirtIOBlock *s = next->dev;
40
struct virtio_scsi_inhdr *scsi = NULL;
37
+ VirtIODevice *vdev = VIRTIO_DEVICE(s);
41
- VirtIODevice *vdev = VIRTIO_DEVICE(req->dev);
38
42
- VirtQueueElement *elem = &req->elem;
39
aio_context_acquire(blk_get_aio_context(s->conf.conf.blk));
43
VirtIOBlock *blk = req->dev;
40
while (next) {
44
+ VirtIODevice *vdev = VIRTIO_DEVICE(blk);
41
VirtIOBlockReq *req = next;
45
+ VirtQueueElement *elem = &req->elem;
42
next = req->mr_next;
46
43
- trace_virtio_blk_rw_complete(req, ret);
47
#ifdef __linux__
44
+ trace_virtio_blk_rw_complete(vdev, req, ret);
48
int i;
45
49
@@ -XXX,XX +XXX,XX @@ static void virtio_blk_submit_multireq(BlockBackend *blk, MultiReqBuffer *mrb)
46
if (req->qiov.nalloc != -1) {
50
47
/* If nalloc is != 1 req->qiov is a local copy of the original
51
static void virtio_blk_handle_flush(VirtIOBlockReq *req, MultiReqBuffer *mrb)
48
@@ -XXX,XX +XXX,XX @@ static inline void submit_requests(BlockBackend *blk, MultiReqBuffer *mrb,
52
{
49
mrb->reqs[i - 1]->mr_next = mrb->reqs[i];
53
- block_acct_start(blk_get_stats(req->dev->blk), &req->acct, 0,
50
}
54
+ VirtIOBlock *s = req->dev;
51
55
+
52
- trace_virtio_blk_submit_multireq(mrb, start, num_reqs,
56
+ block_acct_start(blk_get_stats(s->blk), &req->acct, 0,
53
+ trace_virtio_blk_submit_multireq(VIRTIO_DEVICE(mrb->reqs[start]->dev),
57
BLOCK_ACCT_FLUSH);
54
+ mrb, start, num_reqs,
58
55
sector_num << BDRV_SECTOR_BITS,
59
/*
56
qiov->size, is_write);
60
* Make sure all outstanding writes are posted to the backing device.
57
block_acct_merge_done(blk_get_stats(blk),
61
*/
58
@@ -XXX,XX +XXX,XX @@ static int virtio_blk_handle_request(VirtIOBlockReq *req, MultiReqBuffer *mrb)
62
if (mrb->is_write && mrb->num_reqs > 0) {
59
63
- virtio_blk_submit_multireq(req->dev->blk, mrb);
60
if (is_write) {
64
+ virtio_blk_submit_multireq(s->blk, mrb);
61
qemu_iovec_init_external(&req->qiov, iov, out_num);
65
}
62
- trace_virtio_blk_handle_write(req, req->sector_num,
66
- blk_aio_flush(req->dev->blk, virtio_blk_flush_complete, req);
63
+ trace_virtio_blk_handle_write(vdev, req, req->sector_num,
67
+ blk_aio_flush(s->blk, virtio_blk_flush_complete, req);
64
req->qiov.size / BDRV_SECTOR_SIZE);
68
}
65
} else {
69
66
qemu_iovec_init_external(&req->qiov, in_iov, in_num);
70
static bool virtio_blk_sect_range_ok(VirtIOBlock *dev,
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
--
71
--
94
2.9.4
72
2.20.1
95
73
96
74
diff view generated by jsdifflib
1
Use the new used ring APIs instead of assuming ISR being set means the
1
From: Peter Xu <peterx@redhat.com>
2
request has completed.
3
2
4
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
3
Only sending an init-done message using lock+cond seems an overkill to
5
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
4
me. Replacing it with a simpler semaphore.
6
Reviewed-by: Fam Zheng <famz@redhat.com>
5
7
Tested-by: Eric Blake <eblake@redhat.com>
6
Meanwhile, init the semaphore unconditionally, then we can destroy it
8
Tested-by: Kevin Wolf <kwolf@redhat.com>
7
unconditionally too in finalize which seems cleaner.
9
Message-id: 20170628184724.21378-6-stefanha@redhat.com
8
9
Signed-off-by: Peter Xu <peterx@redhat.com>
10
Message-id: 20190306115532.23025-2-peterx@redhat.com
11
Message-Id: <20190306115532.23025-2-peterx@redhat.com>
10
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
12
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
11
---
13
---
12
tests/virtio-net-test.c | 6 +++---
14
include/sysemu/iothread.h | 3 +--
13
1 file changed, 3 insertions(+), 3 deletions(-)
15
iothread.c | 17 ++++-------------
16
2 files changed, 5 insertions(+), 15 deletions(-)
14
17
15
diff --git a/tests/virtio-net-test.c b/tests/virtio-net-test.c
18
diff --git a/include/sysemu/iothread.h b/include/sysemu/iothread.h
16
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
17
--- a/tests/virtio-net-test.c
20
--- a/include/sysemu/iothread.h
18
+++ b/tests/virtio-net-test.c
21
+++ b/include/sysemu/iothread.h
19
@@ -XXX,XX +XXX,XX @@ static void rx_test(QVirtioDevice *dev,
22
@@ -XXX,XX +XXX,XX @@ typedef struct {
20
ret = iov_send(socket, iov, 2, 0, sizeof(len) + sizeof(test));
23
GMainContext *worker_context;
21
g_assert_cmpint(ret, ==, sizeof(test) + sizeof(len));
24
GMainLoop *main_loop;
22
25
GOnce once;
23
- qvirtio_wait_queue_isr(dev, vq, QVIRTIO_NET_TIMEOUT_US);
26
- QemuMutex init_done_lock;
24
+ qvirtio_wait_used_elem(dev, vq, free_head, QVIRTIO_NET_TIMEOUT_US);
27
- QemuCond init_done_cond; /* is thread initialization done? */
25
memread(req_addr + VNET_HDR_SIZE, buffer, sizeof(test));
28
+ QemuSemaphore init_done_sem; /* is thread init done? */
26
g_assert_cmpstr(buffer, ==, "TEST");
29
bool stopping; /* has iothread_stop() been called? */
27
30
bool running; /* should iothread_run() continue? */
28
@@ -XXX,XX +XXX,XX @@ static void tx_test(QVirtioDevice *dev,
31
int thread_id;
29
free_head = qvirtqueue_add(vq, req_addr, 64, false, false);
32
diff --git a/iothread.c b/iothread.c
30
qvirtqueue_kick(dev, vq, free_head);
33
index XXXXXXX..XXXXXXX 100644
31
34
--- a/iothread.c
32
- qvirtio_wait_queue_isr(dev, vq, QVIRTIO_NET_TIMEOUT_US);
35
+++ b/iothread.c
33
+ qvirtio_wait_used_elem(dev, vq, free_head, QVIRTIO_NET_TIMEOUT_US);
36
@@ -XXX,XX +XXX,XX @@ static void *iothread_run(void *opaque)
34
guest_free(alloc, req_addr);
37
rcu_register_thread();
35
38
36
ret = qemu_recv(socket, &len, sizeof(len), 0);
39
my_iothread = iothread;
37
@@ -XXX,XX +XXX,XX @@ static void rx_stop_cont_test(QVirtioDevice *dev,
40
- qemu_mutex_lock(&iothread->init_done_lock);
38
rsp = qmp("{ 'execute' : 'cont'}");
41
iothread->thread_id = qemu_get_thread_id();
39
QDECREF(rsp);
42
- qemu_cond_signal(&iothread->init_done_cond);
40
43
- qemu_mutex_unlock(&iothread->init_done_lock);
41
- qvirtio_wait_queue_isr(dev, vq, QVIRTIO_NET_TIMEOUT_US);
44
+ qemu_sem_post(&iothread->init_done_sem);
42
+ qvirtio_wait_used_elem(dev, vq, free_head, QVIRTIO_NET_TIMEOUT_US);
45
43
memread(req_addr + VNET_HDR_SIZE, buffer, sizeof(test));
46
while (iothread->running) {
44
g_assert_cmpstr(buffer, ==, "TEST");
47
aio_poll(iothread->ctx, true);
45
48
@@ -XXX,XX +XXX,XX @@ static void iothread_instance_init(Object *obj)
49
50
iothread->poll_max_ns = IOTHREAD_POLL_MAX_NS_DEFAULT;
51
iothread->thread_id = -1;
52
+ qemu_sem_init(&iothread->init_done_sem, 0);
53
}
54
55
static void iothread_instance_finalize(Object *obj)
56
@@ -XXX,XX +XXX,XX @@ static void iothread_instance_finalize(Object *obj)
57
58
iothread_stop(iothread);
59
60
- if (iothread->thread_id != -1) {
61
- qemu_cond_destroy(&iothread->init_done_cond);
62
- qemu_mutex_destroy(&iothread->init_done_lock);
63
- }
64
/*
65
* Before glib2 2.33.10, there is a glib2 bug that GSource context
66
* pointer may not be cleared even if the context has already been
67
@@ -XXX,XX +XXX,XX @@ static void iothread_instance_finalize(Object *obj)
68
g_main_context_unref(iothread->worker_context);
69
iothread->worker_context = NULL;
70
}
71
+ qemu_sem_destroy(&iothread->init_done_sem);
72
}
73
74
static void iothread_complete(UserCreatable *obj, Error **errp)
75
@@ -XXX,XX +XXX,XX @@ static void iothread_complete(UserCreatable *obj, Error **errp)
76
return;
77
}
78
79
- qemu_mutex_init(&iothread->init_done_lock);
80
- qemu_cond_init(&iothread->init_done_cond);
81
iothread->once = (GOnce) G_ONCE_INIT;
82
83
/* This assumes we are called from a thread with useful CPU affinity for us
84
@@ -XXX,XX +XXX,XX @@ static void iothread_complete(UserCreatable *obj, Error **errp)
85
g_free(name);
86
87
/* Wait for initialization to complete */
88
- qemu_mutex_lock(&iothread->init_done_lock);
89
while (iothread->thread_id == -1) {
90
- qemu_cond_wait(&iothread->init_done_cond,
91
- &iothread->init_done_lock);
92
+ qemu_sem_wait(&iothread->init_done_sem);
93
}
94
- qemu_mutex_unlock(&iothread->init_done_lock);
95
}
96
97
typedef struct {
46
--
98
--
47
2.9.4
99
2.20.1
48
100
49
101
diff view generated by jsdifflib
1
Existing tests do not touch the virtqueue used ring. Instead they poll
1
From: Peter Xu <peterx@redhat.com>
2
the virtqueue ISR register and peek into their request's device-specific
3
status field.
4
2
5
It turns out that the virtqueue ISR register can be set to 1 more than
3
In existing code we create the gcontext dynamically at the first
6
once for a single notification (see commit
4
access of the gcontext from caller. That can bring some complexity
7
83d768b5640946b7da55ce8335509df297e2c7cd "virtio: set ISR on dataplane
5
and potential races during using iothread. Since the context itself
8
notifications"). This causes problems for tests that assume a 1:1
6
is not that big a resource, and we won't have millions of iothread,
9
correspondence between the ISR being 1 and request completion.
7
let's simply create the gcontext unconditionally.
10
8
11
Peeking at device-specific status fields is also problematic if the
9
This will also be a preparation work further to move the thread
12
device has no field that can be abused for EINPROGRESS polling
10
context push operation earlier than before (now it's only pushed right
13
semantics. This is the case if all the field's values may be set by the
11
before we want to start running the gmainloop).
14
device; there's no magic constant left for polling.
15
12
16
It's time to process the used ring for completed requests, just like a
13
Removing the g_once since it's not necessary, while introducing a new
17
real virtio guest driver. This patch adds the necessary APIs.
14
run_gcontext boolean to show whether we want to run the gcontext.
18
15
19
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
16
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
20
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
17
Signed-off-by: Peter Xu <peterx@redhat.com>
21
Reviewed-by: Fam Zheng <famz@redhat.com>
18
Message-id: 20190306115532.23025-3-peterx@redhat.com
22
Tested-by: Eric Blake <eblake@redhat.com>
19
Message-Id: <20190306115532.23025-3-peterx@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>
20
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
26
---
21
---
27
tests/libqos/virtio.h | 6 ++++++
22
include/sysemu/iothread.h | 2 +-
28
tests/libqos/virtio.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++
23
iothread.c | 43 +++++++++++++++++++--------------------
29
2 files changed, 66 insertions(+)
24
2 files changed, 22 insertions(+), 23 deletions(-)
30
25
31
diff --git a/tests/libqos/virtio.h b/tests/libqos/virtio.h
26
diff --git a/include/sysemu/iothread.h b/include/sysemu/iothread.h
32
index XXXXXXX..XXXXXXX 100644
27
index XXXXXXX..XXXXXXX 100644
33
--- a/tests/libqos/virtio.h
28
--- a/include/sysemu/iothread.h
34
+++ b/tests/libqos/virtio.h
29
+++ b/include/sysemu/iothread.h
35
@@ -XXX,XX +XXX,XX @@ typedef struct QVirtQueue {
30
@@ -XXX,XX +XXX,XX @@ typedef struct {
36
uint32_t free_head;
31
37
uint32_t num_free;
32
QemuThread thread;
38
uint32_t align;
33
AioContext *ctx;
39
+ uint16_t last_used_idx;
34
+ bool run_gcontext; /* whether we should run gcontext */
40
bool indirect;
35
GMainContext *worker_context;
41
bool event;
36
GMainLoop *main_loop;
42
} QVirtQueue;
37
- GOnce once;
43
@@ -XXX,XX +XXX,XX @@ uint8_t qvirtio_wait_status_byte_no_isr(QVirtioDevice *d,
38
QemuSemaphore init_done_sem; /* is thread init done? */
44
QVirtQueue *vq,
39
bool stopping; /* has iothread_stop() been called? */
45
uint64_t addr,
40
bool running; /* should iothread_run() continue? */
46
gint64 timeout_us);
41
diff --git a/iothread.c b/iothread.c
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
42
index XXXXXXX..XXXXXXX 100644
64
--- a/tests/libqos/virtio.c
43
--- a/iothread.c
65
+++ b/tests/libqos/virtio.c
44
+++ b/iothread.c
66
@@ -XXX,XX +XXX,XX @@ uint8_t qvirtio_wait_status_byte_no_isr(QVirtioDevice *d,
45
@@ -XXX,XX +XXX,XX @@ static void *iothread_run(void *opaque)
67
return val;
46
* We must check the running state again in case it was
47
* changed in previous aio_poll()
48
*/
49
- if (iothread->running && atomic_read(&iothread->worker_context)) {
50
+ if (iothread->running && atomic_read(&iothread->run_gcontext)) {
51
GMainLoop *loop;
52
53
g_main_context_push_thread_default(iothread->worker_context);
54
@@ -XXX,XX +XXX,XX @@ static void iothread_instance_init(Object *obj)
55
iothread->poll_max_ns = IOTHREAD_POLL_MAX_NS_DEFAULT;
56
iothread->thread_id = -1;
57
qemu_sem_init(&iothread->init_done_sem, 0);
58
+ /* By default, we don't run gcontext */
59
+ atomic_set(&iothread->run_gcontext, 0);
68
}
60
}
69
61
70
+/*
62
static void iothread_instance_finalize(Object *obj)
71
+ * qvirtio_wait_used_elem:
63
@@ -XXX,XX +XXX,XX @@ static void iothread_instance_finalize(Object *obj)
72
+ * @desc_idx: The next expected vq->desc[] index in the used ring
64
qemu_sem_destroy(&iothread->init_done_sem);
73
+ * @timeout_us: How many microseconds to wait before failing
65
}
74
+ *
66
75
+ * This function waits for the next completed request on the used ring.
67
+static void iothread_init_gcontext(IOThread *iothread)
76
+ */
77
+void qvirtio_wait_used_elem(QVirtioDevice *d,
78
+ QVirtQueue *vq,
79
+ uint32_t desc_idx,
80
+ gint64 timeout_us)
81
+{
68
+{
82
+ gint64 start_time = g_get_monotonic_time();
69
+ GSource *source;
83
+
70
+
84
+ for (;;) {
71
+ iothread->worker_context = g_main_context_new();
85
+ uint32_t got_desc_idx;
72
+ source = aio_get_g_source(iothread_get_aio_context(iothread));
86
+
73
+ g_source_attach(source, iothread->worker_context);
87
+ clock_step(100);
74
+ g_source_unref(source);
88
+
89
+ if (d->bus->get_queue_isr_status(d, vq) &&
90
+ qvirtqueue_get_buf(vq, &got_desc_idx)) {
91
+ g_assert_cmpint(got_desc_idx, ==, desc_idx);
92
+ return;
93
+ }
94
+
95
+ g_assert(g_get_monotonic_time() - start_time <= timeout_us);
96
+ }
97
+}
75
+}
98
+
76
+
99
void qvirtio_wait_config_isr(QVirtioDevice *d, gint64 timeout_us)
77
static void iothread_complete(UserCreatable *obj, Error **errp)
100
{
78
{
101
gint64 start_time = g_get_monotonic_time();
79
Error *local_error = NULL;
102
@@ -XXX,XX +XXX,XX @@ void qvirtqueue_kick(QVirtioDevice *d, QVirtQueue *vq, uint32_t free_head)
80
@@ -XXX,XX +XXX,XX @@ static void iothread_complete(UserCreatable *obj, Error **errp)
81
return;
103
}
82
}
83
84
+ /*
85
+ * Init one GMainContext for the iothread unconditionally, even if
86
+ * it's not used
87
+ */
88
+ iothread_init_gcontext(iothread);
89
+
90
aio_context_set_poll_params(iothread->ctx,
91
iothread->poll_max_ns,
92
iothread->poll_grow,
93
@@ -XXX,XX +XXX,XX @@ static void iothread_complete(UserCreatable *obj, Error **errp)
94
return;
95
}
96
97
- iothread->once = (GOnce) G_ONCE_INIT;
98
-
99
/* This assumes we are called from a thread with useful CPU affinity for us
100
* to inherit.
101
*/
102
@@ -XXX,XX +XXX,XX @@ IOThreadInfoList *qmp_query_iothreads(Error **errp)
103
return head;
104
}
104
}
105
105
106
+/*
106
-static gpointer iothread_g_main_context_init(gpointer opaque)
107
+ * qvirtqueue_get_buf:
107
-{
108
+ * @desc_idx: A pointer that is filled with the vq->desc[] index, may be NULL
108
- AioContext *ctx;
109
+ *
109
- IOThread *iothread = opaque;
110
+ * This function gets the next used element if there is one ready.
110
- GSource *source;
111
+ *
111
-
112
+ * Returns: true if an element was ready, false otherwise
112
- iothread->worker_context = g_main_context_new();
113
+ */
113
-
114
+bool qvirtqueue_get_buf(QVirtQueue *vq, uint32_t *desc_idx)
114
- ctx = iothread_get_aio_context(iothread);
115
+{
115
- source = aio_get_g_source(ctx);
116
+ uint16_t idx;
116
- g_source_attach(source, iothread->worker_context);
117
+
117
- g_source_unref(source);
118
+ idx = readw(vq->used + offsetof(struct vring_used, idx));
118
-
119
+ if (idx == vq->last_used_idx) {
119
- aio_notify(iothread->ctx);
120
+ return false;
120
- return NULL;
121
+ }
121
-}
122
+
122
-
123
+ if (desc_idx) {
123
GMainContext *iothread_get_g_main_context(IOThread *iothread)
124
+ uint64_t elem_addr;
125
+
126
+ elem_addr = vq->used +
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;
135
+}
136
+
137
void qvirtqueue_set_used_event(QVirtQueue *vq, uint16_t idx)
138
{
124
{
139
g_assert(vq->event);
125
- g_once(&iothread->once, iothread_g_main_context_init, iothread);
126
-
127
+ atomic_set(&iothread->run_gcontext, 1);
128
+ aio_notify(iothread->ctx);
129
return iothread->worker_context;
130
}
131
140
--
132
--
141
2.9.4
133
2.20.1
142
134
143
135
diff view generated by jsdifflib
1
Use the new used ring APIs instead of assuming ISR being set means the
1
From: Peter Xu <peterx@redhat.com>
2
request has completed.
3
2
4
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
3
Since we've have the gcontext always there, create the main loop
5
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
4
altogether. The iothread_run() is even cleaner.
6
Reviewed-by: Fam Zheng <famz@redhat.com>
5
7
Tested-by: Eric Blake <eblake@redhat.com>
6
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
8
Tested-by: Kevin Wolf <kwolf@redhat.com>
7
Signed-off-by: Peter Xu <peterx@redhat.com>
9
Message-id: 20170628184724.21378-5-stefanha@redhat.com
8
Message-id: 20190306115532.23025-4-peterx@redhat.com
9
Message-Id: <20190306115532.23025-4-peterx@redhat.com>
10
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
10
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
11
---
11
---
12
tests/virtio-blk-test.c | 27 +++++++++++++++++----------
12
iothread.c | 12 +++---------
13
1 file changed, 17 insertions(+), 10 deletions(-)
13
1 file changed, 3 insertions(+), 9 deletions(-)
14
14
15
diff --git a/tests/virtio-blk-test.c b/tests/virtio-blk-test.c
15
diff --git a/iothread.c b/iothread.c
16
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
17
--- a/tests/virtio-blk-test.c
17
--- a/iothread.c
18
+++ b/tests/virtio-blk-test.c
18
+++ b/iothread.c
19
@@ -XXX,XX +XXX,XX @@ static void test_basic(QVirtioDevice *dev, QGuestAllocator *alloc,
19
@@ -XXX,XX +XXX,XX @@ static void *iothread_run(void *opaque)
20
20
* changed in previous aio_poll()
21
qvirtqueue_kick(dev, vq, free_head);
21
*/
22
22
if (iothread->running && atomic_read(&iothread->run_gcontext)) {
23
- qvirtio_wait_queue_isr(dev, vq, QVIRTIO_BLK_TIMEOUT_US);
23
- GMainLoop *loop;
24
+ qvirtio_wait_used_elem(dev, vq, free_head, QVIRTIO_BLK_TIMEOUT_US);
24
-
25
status = readb(req_addr + 528);
25
g_main_context_push_thread_default(iothread->worker_context);
26
g_assert_cmpint(status, ==, 0);
26
- iothread->main_loop =
27
27
- g_main_loop_new(iothread->worker_context, TRUE);
28
@@ -XXX,XX +XXX,XX @@ static void test_basic(QVirtioDevice *dev, QGuestAllocator *alloc,
28
- loop = iothread->main_loop;
29
29
-
30
qvirtqueue_kick(dev, vq, free_head);
30
g_main_loop_run(iothread->main_loop);
31
31
- iothread->main_loop = NULL;
32
- qvirtio_wait_queue_isr(dev, vq, QVIRTIO_BLK_TIMEOUT_US);
32
- g_main_loop_unref(loop);
33
+ qvirtio_wait_used_elem(dev, vq, free_head, QVIRTIO_BLK_TIMEOUT_US);
33
-
34
status = readb(req_addr + 528);
34
g_main_context_pop_thread_default(iothread->worker_context);
35
g_assert_cmpint(status, ==, 0);
35
}
36
36
}
37
@@ -XXX,XX +XXX,XX @@ static void test_basic(QVirtioDevice *dev, QGuestAllocator *alloc,
37
@@ -XXX,XX +XXX,XX @@ static void iothread_instance_finalize(Object *obj)
38
qvirtqueue_add(vq, req_addr + 528, 1, true, false);
38
if (iothread->worker_context) {
39
qvirtqueue_kick(dev, vq, free_head);
39
g_main_context_unref(iothread->worker_context);
40
40
iothread->worker_context = NULL;
41
- qvirtio_wait_queue_isr(dev, vq, QVIRTIO_BLK_TIMEOUT_US);
41
+ g_main_loop_unref(iothread->main_loop);
42
+ qvirtio_wait_used_elem(dev, vq, free_head, QVIRTIO_BLK_TIMEOUT_US);
42
+ iothread->main_loop = NULL;
43
status = readb(req_addr + 528);
43
}
44
g_assert_cmpint(status, ==, 0);
44
qemu_sem_destroy(&iothread->init_done_sem);
45
45
}
46
@@ -XXX,XX +XXX,XX @@ static void test_basic(QVirtioDevice *dev, QGuestAllocator *alloc,
46
@@ -XXX,XX +XXX,XX @@ static void iothread_init_gcontext(IOThread *iothread)
47
47
source = aio_get_g_source(iothread_get_aio_context(iothread));
48
qvirtqueue_kick(dev, vq, free_head);
48
g_source_attach(source, iothread->worker_context);
49
49
g_source_unref(source);
50
- qvirtio_wait_queue_isr(dev, vq, QVIRTIO_BLK_TIMEOUT_US);
50
+ iothread->main_loop = g_main_loop_new(iothread->worker_context, TRUE);
51
+ qvirtio_wait_used_elem(dev, vq, free_head, QVIRTIO_BLK_TIMEOUT_US);
51
}
52
status = readb(req_addr + 528);
52
53
g_assert_cmpint(status, ==, 0);
53
static void iothread_complete(UserCreatable *obj, Error **errp)
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
--
54
--
132
2.9.4
55
2.20.1
133
56
134
57
diff view generated by jsdifflib
1
Use the new used ring APIs instead of assuming ISR being set means the
1
From: Peter Xu <peterx@redhat.com>
2
request has completed.
2
3
We were pushing the context until right before running the gmainloop.
4
Now since we have everything unconditionally, we can move this
5
earlier.
6
7
One benefit is that now it's done even before init_done_sem, so as
8
long as the iothread user calls iothread_create() and completes, we
9
know that the thread stack is ready.
10
11
Signed-off-by: Peter Xu <peterx@redhat.com>
12
Message-id: 20190306115532.23025-5-peterx@redhat.com
13
Message-Id: <20190306115532.23025-5-peterx@redhat.com>
14
15
[Tweaked comment wording as discussed with Peter Xu.
16
--Stefan]
3
17
4
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
18
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
---
19
---
12
tests/virtio-scsi-test.c | 2 +-
20
iothread.c | 9 ++++++---
13
1 file changed, 1 insertion(+), 1 deletion(-)
21
1 file changed, 6 insertions(+), 3 deletions(-)
14
22
15
diff --git a/tests/virtio-scsi-test.c b/tests/virtio-scsi-test.c
23
diff --git a/iothread.c b/iothread.c
16
index XXXXXXX..XXXXXXX 100644
24
index XXXXXXX..XXXXXXX 100644
17
--- a/tests/virtio-scsi-test.c
25
--- a/iothread.c
18
+++ b/tests/virtio-scsi-test.c
26
+++ b/iothread.c
19
@@ -XXX,XX +XXX,XX @@ static uint8_t virtio_scsi_do_command(QVirtIOSCSI *vs, const uint8_t *cdb,
27
@@ -XXX,XX +XXX,XX @@ static void *iothread_run(void *opaque)
28
IOThread *iothread = opaque;
29
30
rcu_register_thread();
31
-
32
+ /*
33
+ * g_main_context_push_thread_default() must be called before anything
34
+ * in this new thread uses glib.
35
+ */
36
+ g_main_context_push_thread_default(iothread->worker_context);
37
my_iothread = iothread;
38
iothread->thread_id = qemu_get_thread_id();
39
qemu_sem_post(&iothread->init_done_sem);
40
@@ -XXX,XX +XXX,XX @@ static void *iothread_run(void *opaque)
41
* changed in previous aio_poll()
42
*/
43
if (iothread->running && atomic_read(&iothread->run_gcontext)) {
44
- g_main_context_push_thread_default(iothread->worker_context);
45
g_main_loop_run(iothread->main_loop);
46
- g_main_context_pop_thread_default(iothread->worker_context);
47
}
20
}
48
}
21
49
22
qvirtqueue_kick(vs->dev, vq, free_head);
50
+ g_main_context_pop_thread_default(iothread->worker_context);
23
- qvirtio_wait_queue_isr(vs->dev, vq, QVIRTIO_SCSI_TIMEOUT_US);
51
rcu_unregister_thread();
24
+ qvirtio_wait_used_elem(vs->dev, vq, free_head, QVIRTIO_SCSI_TIMEOUT_US);
52
return NULL;
25
53
}
26
response = readb(resp_addr +
27
offsetof(struct virtio_scsi_cmd_resp, response));
28
--
54
--
29
2.9.4
55
2.20.1
30
56
31
57
diff view generated by jsdifflib
1
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
1
From: Peter Xu <peterx@redhat.com>
2
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
2
3
Reviewed-by: Fam Zheng <famz@redhat.com>
3
After consulting Paolo I know why we'd better keep the explicit
4
Tested-by: Eric Blake <eblake@redhat.com>
4
aio_poll() in iothread_run(). Document it directly into the code so
5
Tested-by: Kevin Wolf <kwolf@redhat.com>
5
that future readers will know the answer from day one.
6
Message-id: 20170628184724.21378-2-stefanha@redhat.com
6
7
Signed-off-by: Peter Xu <peterx@redhat.com>
8
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
9
Message-id: 20190306115532.23025-6-peterx@redhat.com
10
Message-Id: <20190306115532.23025-6-peterx@redhat.com>
7
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
11
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
8
---
12
---
9
tests/libqos/virtio.h | 2 +-
13
iothread.c | 9 +++++++++
10
1 file changed, 1 insertion(+), 1 deletion(-)
14
1 file changed, 9 insertions(+)
11
15
12
diff --git a/tests/libqos/virtio.h b/tests/libqos/virtio.h
16
diff --git a/iothread.c b/iothread.c
13
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
14
--- a/tests/libqos/virtio.h
18
--- a/iothread.c
15
+++ b/tests/libqos/virtio.h
19
+++ b/iothread.c
16
@@ -XXX,XX +XXX,XX @@ typedef struct QVirtioDevice {
20
@@ -XXX,XX +XXX,XX @@ static void *iothread_run(void *opaque)
17
typedef struct QVirtQueue {
21
qemu_sem_post(&iothread->init_done_sem);
18
uint64_t desc; /* This points to an array of struct vring_desc */
22
19
uint64_t avail; /* This points to a struct vring_avail */
23
while (iothread->running) {
20
- uint64_t used; /* This points to a struct vring_desc */
24
+ /*
21
+ uint64_t used; /* This points to a struct vring_used */
25
+ * Note: from functional-wise the g_main_loop_run() below can
22
uint16_t index;
26
+ * already cover the aio_poll() events, but we can't run the
23
uint32_t size;
27
+ * main loop unconditionally because explicit aio_poll() here
24
uint32_t free_head;
28
+ * is faster than g_main_loop_run() when we do not need the
29
+ * gcontext at all (e.g., pure block layer iothreads). In
30
+ * other words, when we want to run the gcontext with the
31
+ * iothread we need to pay some performance for functionality.
32
+ */
33
aio_poll(iothread->ctx, true);
34
35
/*
25
--
36
--
26
2.9.4
37
2.20.1
27
38
28
39
diff view generated by jsdifflib