Skip to content

Commit b50629c

Browse files
stefanhaRHkevmw
authored andcommitted
virtio: extract iothread-vq-mapping.h API
The code that builds an array of AioContext pointers indexed by the virtqueue is not specific to virtio-blk. virtio-scsi will need to do the same thing, so extract the functions. Signed-off-by: Stefan Hajnoczi <[email protected]> Reviewed-by: Kevin Wolf <[email protected]> Message-ID: <[email protected]> Tested-by: Peter Krempa <[email protected]> Signed-off-by: Kevin Wolf <[email protected]>
1 parent 2fa67a7 commit b50629c

File tree

4 files changed

+178
-141
lines changed

4 files changed

+178
-141
lines changed

hw/block/virtio-blk.c

Lines changed: 1 addition & 141 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
#endif
3434
#include "hw/virtio/virtio-bus.h"
3535
#include "migration/qemu-file-types.h"
36+
#include "hw/virtio/iothread-vq-mapping.h"
3637
#include "hw/virtio/virtio-access.h"
3738
#include "hw/virtio/virtio-blk-common.h"
3839
#include "qemu/coroutine.h"
@@ -1423,147 +1424,6 @@ static const BlockDevOps virtio_block_ops = {
14231424
.drained_end = virtio_blk_drained_end,
14241425
};
14251426

1426-
static bool
1427-
iothread_vq_mapping_validate(IOThreadVirtQueueMappingList *list, uint16_t
1428-
num_queues, Error **errp)
1429-
{
1430-
g_autofree unsigned long *vqs = bitmap_new(num_queues);
1431-
g_autoptr(GHashTable) iothreads =
1432-
g_hash_table_new(g_str_hash, g_str_equal);
1433-
1434-
for (IOThreadVirtQueueMappingList *node = list; node; node = node->next) {
1435-
const char *name = node->value->iothread;
1436-
uint16List *vq;
1437-
1438-
if (!iothread_by_id(name)) {
1439-
error_setg(errp, "IOThread \"%s\" object does not exist", name);
1440-
return false;
1441-
}
1442-
1443-
if (!g_hash_table_add(iothreads, (gpointer)name)) {
1444-
error_setg(errp,
1445-
"duplicate IOThread name \"%s\" in iothread-vq-mapping",
1446-
name);
1447-
return false;
1448-
}
1449-
1450-
if (node != list) {
1451-
if (!!node->value->vqs != !!list->value->vqs) {
1452-
error_setg(errp, "either all items in iothread-vq-mapping "
1453-
"must have vqs or none of them must have it");
1454-
return false;
1455-
}
1456-
}
1457-
1458-
for (vq = node->value->vqs; vq; vq = vq->next) {
1459-
if (vq->value >= num_queues) {
1460-
error_setg(errp, "vq index %u for IOThread \"%s\" must be "
1461-
"less than num_queues %u in iothread-vq-mapping",
1462-
vq->value, name, num_queues);
1463-
return false;
1464-
}
1465-
1466-
if (test_and_set_bit(vq->value, vqs)) {
1467-
error_setg(errp, "cannot assign vq %u to IOThread \"%s\" "
1468-
"because it is already assigned", vq->value, name);
1469-
return false;
1470-
}
1471-
}
1472-
}
1473-
1474-
if (list->value->vqs) {
1475-
for (uint16_t i = 0; i < num_queues; i++) {
1476-
if (!test_bit(i, vqs)) {
1477-
error_setg(errp,
1478-
"missing vq %u IOThread assignment in iothread-vq-mapping",
1479-
i);
1480-
return false;
1481-
}
1482-
}
1483-
}
1484-
1485-
return true;
1486-
}
1487-
1488-
/**
1489-
* iothread_vq_mapping_apply:
1490-
* @list: The mapping of virtqueues to IOThreads.
1491-
* @vq_aio_context: The array of AioContext pointers to fill in.
1492-
* @num_queues: The length of @vq_aio_context.
1493-
* @errp: If an error occurs, a pointer to the area to store the error.
1494-
*
1495-
* Fill in the AioContext for each virtqueue in the @vq_aio_context array given
1496-
* the iothread-vq-mapping parameter in @list.
1497-
*
1498-
* iothread_vq_mapping_cleanup() must be called to free IOThread object
1499-
* references after this function returns success.
1500-
*
1501-
* Returns: %true on success, %false on failure.
1502-
**/
1503-
static bool iothread_vq_mapping_apply(
1504-
IOThreadVirtQueueMappingList *list,
1505-
AioContext **vq_aio_context,
1506-
uint16_t num_queues,
1507-
Error **errp)
1508-
{
1509-
IOThreadVirtQueueMappingList *node;
1510-
size_t num_iothreads = 0;
1511-
size_t cur_iothread = 0;
1512-
1513-
if (!iothread_vq_mapping_validate(list, num_queues, errp)) {
1514-
return false;
1515-
}
1516-
1517-
for (node = list; node; node = node->next) {
1518-
num_iothreads++;
1519-
}
1520-
1521-
for (node = list; node; node = node->next) {
1522-
IOThread *iothread = iothread_by_id(node->value->iothread);
1523-
AioContext *ctx = iothread_get_aio_context(iothread);
1524-
1525-
/* Released in virtio_blk_vq_aio_context_cleanup() */
1526-
object_ref(OBJECT(iothread));
1527-
1528-
if (node->value->vqs) {
1529-
uint16List *vq;
1530-
1531-
/* Explicit vq:IOThread assignment */
1532-
for (vq = node->value->vqs; vq; vq = vq->next) {
1533-
assert(vq->value < num_queues);
1534-
vq_aio_context[vq->value] = ctx;
1535-
}
1536-
} else {
1537-
/* Round-robin vq:IOThread assignment */
1538-
for (unsigned i = cur_iothread; i < num_queues;
1539-
i += num_iothreads) {
1540-
vq_aio_context[i] = ctx;
1541-
}
1542-
}
1543-
1544-
cur_iothread++;
1545-
}
1546-
1547-
return true;
1548-
}
1549-
1550-
/**
1551-
* iothread_vq_mapping_cleanup:
1552-
* @list: The mapping of virtqueues to IOThreads.
1553-
*
1554-
* Release IOThread object references that were acquired by
1555-
* iothread_vq_mapping_apply().
1556-
*/
1557-
static void iothread_vq_mapping_cleanup(IOThreadVirtQueueMappingList *list)
1558-
{
1559-
IOThreadVirtQueueMappingList *node;
1560-
1561-
for (node = list; node; node = node->next) {
1562-
IOThread *iothread = iothread_by_id(node->value->iothread);
1563-
object_unref(OBJECT(iothread));
1564-
}
1565-
}
1566-
15671427
/* Context: BQL held */
15681428
static bool virtio_blk_vq_aio_context_init(VirtIOBlock *s, Error **errp)
15691429
{

hw/virtio/iothread-vq-mapping.c

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
/*
2+
* IOThread Virtqueue Mapping
3+
*
4+
* Copyright Red Hat, Inc
5+
*
6+
* SPDX-License-Identifier: GPL-2.0-only
7+
*/
8+
9+
#include "qemu/osdep.h"
10+
#include "system/iothread.h"
11+
#include "hw/virtio/iothread-vq-mapping.h"
12+
13+
static bool
14+
iothread_vq_mapping_validate(IOThreadVirtQueueMappingList *list, uint16_t
15+
num_queues, Error **errp)
16+
{
17+
g_autofree unsigned long *vqs = bitmap_new(num_queues);
18+
g_autoptr(GHashTable) iothreads =
19+
g_hash_table_new(g_str_hash, g_str_equal);
20+
21+
for (IOThreadVirtQueueMappingList *node = list; node; node = node->next) {
22+
const char *name = node->value->iothread;
23+
uint16List *vq;
24+
25+
if (!iothread_by_id(name)) {
26+
error_setg(errp, "IOThread \"%s\" object does not exist", name);
27+
return false;
28+
}
29+
30+
if (!g_hash_table_add(iothreads, (gpointer)name)) {
31+
error_setg(errp,
32+
"duplicate IOThread name \"%s\" in iothread-vq-mapping",
33+
name);
34+
return false;
35+
}
36+
37+
if (node != list) {
38+
if (!!node->value->vqs != !!list->value->vqs) {
39+
error_setg(errp, "either all items in iothread-vq-mapping "
40+
"must have vqs or none of them must have it");
41+
return false;
42+
}
43+
}
44+
45+
for (vq = node->value->vqs; vq; vq = vq->next) {
46+
if (vq->value >= num_queues) {
47+
error_setg(errp, "vq index %u for IOThread \"%s\" must be "
48+
"less than num_queues %u in iothread-vq-mapping",
49+
vq->value, name, num_queues);
50+
return false;
51+
}
52+
53+
if (test_and_set_bit(vq->value, vqs)) {
54+
error_setg(errp, "cannot assign vq %u to IOThread \"%s\" "
55+
"because it is already assigned", vq->value, name);
56+
return false;
57+
}
58+
}
59+
}
60+
61+
if (list->value->vqs) {
62+
for (uint16_t i = 0; i < num_queues; i++) {
63+
if (!test_bit(i, vqs)) {
64+
error_setg(errp,
65+
"missing vq %u IOThread assignment in iothread-vq-mapping",
66+
i);
67+
return false;
68+
}
69+
}
70+
}
71+
72+
return true;
73+
}
74+
75+
bool iothread_vq_mapping_apply(
76+
IOThreadVirtQueueMappingList *list,
77+
AioContext **vq_aio_context,
78+
uint16_t num_queues,
79+
Error **errp)
80+
{
81+
IOThreadVirtQueueMappingList *node;
82+
size_t num_iothreads = 0;
83+
size_t cur_iothread = 0;
84+
85+
if (!iothread_vq_mapping_validate(list, num_queues, errp)) {
86+
return false;
87+
}
88+
89+
for (node = list; node; node = node->next) {
90+
num_iothreads++;
91+
}
92+
93+
for (node = list; node; node = node->next) {
94+
IOThread *iothread = iothread_by_id(node->value->iothread);
95+
AioContext *ctx = iothread_get_aio_context(iothread);
96+
97+
/* Released in virtio_blk_vq_aio_context_cleanup() */
98+
object_ref(OBJECT(iothread));
99+
100+
if (node->value->vqs) {
101+
uint16List *vq;
102+
103+
/* Explicit vq:IOThread assignment */
104+
for (vq = node->value->vqs; vq; vq = vq->next) {
105+
assert(vq->value < num_queues);
106+
vq_aio_context[vq->value] = ctx;
107+
}
108+
} else {
109+
/* Round-robin vq:IOThread assignment */
110+
for (unsigned i = cur_iothread; i < num_queues;
111+
i += num_iothreads) {
112+
vq_aio_context[i] = ctx;
113+
}
114+
}
115+
116+
cur_iothread++;
117+
}
118+
119+
return true;
120+
}
121+
122+
void iothread_vq_mapping_cleanup(IOThreadVirtQueueMappingList *list)
123+
{
124+
IOThreadVirtQueueMappingList *node;
125+
126+
for (node = list; node; node = node->next) {
127+
IOThread *iothread = iothread_by_id(node->value->iothread);
128+
object_unref(OBJECT(iothread));
129+
}
130+
}
131+

hw/virtio/meson.build

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
system_virtio_ss = ss.source_set()
22
system_virtio_ss.add(files('virtio-bus.c'))
3+
system_virtio_ss.add(files('iothread-vq-mapping.c'))
34
system_virtio_ss.add(when: 'CONFIG_VIRTIO_PCI', if_true: files('virtio-pci.c'))
45
system_virtio_ss.add(when: 'CONFIG_VIRTIO_MMIO', if_true: files('virtio-mmio.c'))
56
system_virtio_ss.add(when: 'CONFIG_VIRTIO_CRYPTO', if_true: files('virtio-crypto.c'))
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/*
2+
* IOThread Virtqueue Mapping
3+
*
4+
* Copyright Red Hat, Inc
5+
*
6+
* SPDX-License-Identifier: GPL-2.0-only
7+
*/
8+
9+
#ifndef HW_VIRTIO_IOTHREAD_VQ_MAPPING_H
10+
#define HW_VIRTIO_IOTHREAD_VQ_MAPPING_H
11+
12+
#include "qapi/error.h"
13+
#include "qapi/qapi-types-virtio.h"
14+
15+
/**
16+
* iothread_vq_mapping_apply:
17+
* @list: The mapping of virtqueues to IOThreads.
18+
* @vq_aio_context: The array of AioContext pointers to fill in.
19+
* @num_queues: The length of @vq_aio_context.
20+
* @errp: If an error occurs, a pointer to the area to store the error.
21+
*
22+
* Fill in the AioContext for each virtqueue in the @vq_aio_context array given
23+
* the iothread-vq-mapping parameter in @list.
24+
*
25+
* iothread_vq_mapping_cleanup() must be called to free IOThread object
26+
* references after this function returns success.
27+
*
28+
* Returns: %true on success, %false on failure.
29+
**/
30+
bool iothread_vq_mapping_apply(
31+
IOThreadVirtQueueMappingList *list,
32+
AioContext **vq_aio_context,
33+
uint16_t num_queues,
34+
Error **errp);
35+
36+
/**
37+
* iothread_vq_mapping_cleanup:
38+
* @list: The mapping of virtqueues to IOThreads.
39+
*
40+
* Release IOThread object references that were acquired by
41+
* iothread_vq_mapping_apply().
42+
*/
43+
void iothread_vq_mapping_cleanup(IOThreadVirtQueueMappingList *list);
44+
45+
#endif /* HW_VIRTIO_IOTHREAD_VQ_MAPPING_H */

0 commit comments

Comments
 (0)