tools/virtio: Add --batch option
This allow to test vhost having >1 buffers in flight Signed-off-by: Eugenio Pérez <eperezma@redhat.com> Link: https://lore.kernel.org/r/20200401183118.8334-5-eperezma@redhat.com Signed-off-by: Michael S. Tsirkin <mst@redhat.com> Link: https://lore.kernel.org/r/20200418102217.32327-3-eperezma@redhat.com Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
This commit is contained in:
committed by
Michael S. Tsirkin
parent
b3562c6087
commit
633fae33d5
@@ -1,6 +1,7 @@
|
|||||||
// SPDX-License-Identifier: GPL-2.0
|
// SPDX-License-Identifier: GPL-2.0
|
||||||
#define _GNU_SOURCE
|
#define _GNU_SOURCE
|
||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
|
#include <limits.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <poll.h>
|
#include <poll.h>
|
||||||
#include <sys/eventfd.h>
|
#include <sys/eventfd.h>
|
||||||
@@ -152,11 +153,11 @@ static void wait_for_interrupt(struct vdev_info *dev)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void run_test(struct vdev_info *dev, struct vq_info *vq,
|
static void run_test(struct vdev_info *dev, struct vq_info *vq,
|
||||||
bool delayed, int bufs)
|
bool delayed, int batch, int bufs)
|
||||||
{
|
{
|
||||||
struct scatterlist sl;
|
struct scatterlist sl;
|
||||||
long started = 0, completed = 0;
|
long started = 0, completed = 0;
|
||||||
long completed_before;
|
long completed_before, started_before;
|
||||||
int r, test = 1;
|
int r, test = 1;
|
||||||
unsigned len;
|
unsigned len;
|
||||||
long long spurious = 0;
|
long long spurious = 0;
|
||||||
@@ -165,28 +166,42 @@ static void run_test(struct vdev_info *dev, struct vq_info *vq,
|
|||||||
for (;;) {
|
for (;;) {
|
||||||
virtqueue_disable_cb(vq->vq);
|
virtqueue_disable_cb(vq->vq);
|
||||||
completed_before = completed;
|
completed_before = completed;
|
||||||
|
started_before = started;
|
||||||
do {
|
do {
|
||||||
if (started < bufs) {
|
while (started < bufs &&
|
||||||
|
(started - completed) < batch) {
|
||||||
sg_init_one(&sl, dev->buf, dev->buf_size);
|
sg_init_one(&sl, dev->buf, dev->buf_size);
|
||||||
r = virtqueue_add_outbuf(vq->vq, &sl, 1,
|
r = virtqueue_add_outbuf(vq->vq, &sl, 1,
|
||||||
dev->buf + started,
|
dev->buf + started,
|
||||||
GFP_ATOMIC);
|
GFP_ATOMIC);
|
||||||
if (likely(r == 0)) {
|
if (unlikely(r != 0)) {
|
||||||
++started;
|
if (r == -ENOSPC &&
|
||||||
if (unlikely(!virtqueue_kick(vq->vq)))
|
started > started_before)
|
||||||
|
r = 0;
|
||||||
|
else
|
||||||
r = -1;
|
r = -1;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
} else
|
|
||||||
|
++started;
|
||||||
|
|
||||||
|
if (unlikely(!virtqueue_kick(vq->vq))) {
|
||||||
|
r = -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (started >= bufs)
|
||||||
r = -1;
|
r = -1;
|
||||||
|
|
||||||
/* Flush out completed bufs if any */
|
/* Flush out completed bufs if any */
|
||||||
if (virtqueue_get_buf(vq->vq, &len)) {
|
while (virtqueue_get_buf(vq->vq, &len)) {
|
||||||
++completed;
|
++completed;
|
||||||
r = 0;
|
r = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
} while (r == 0);
|
} while (r == 0);
|
||||||
if (completed == completed_before)
|
if (completed == completed_before && started == started_before)
|
||||||
++spurious;
|
++spurious;
|
||||||
assert(completed <= bufs);
|
assert(completed <= bufs);
|
||||||
assert(started <= bufs);
|
assert(started <= bufs);
|
||||||
@@ -244,6 +259,11 @@ const struct option longopts[] = {
|
|||||||
.name = "no-delayed-interrupt",
|
.name = "no-delayed-interrupt",
|
||||||
.val = 'd',
|
.val = 'd',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
.name = "batch",
|
||||||
|
.val = 'b',
|
||||||
|
.has_arg = required_argument,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -255,6 +275,7 @@ static void help(void)
|
|||||||
" [--no-event-idx]"
|
" [--no-event-idx]"
|
||||||
" [--no-virtio-1]"
|
" [--no-virtio-1]"
|
||||||
" [--delayed-interrupt]"
|
" [--delayed-interrupt]"
|
||||||
|
" [--batch=N]"
|
||||||
"\n");
|
"\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -263,6 +284,7 @@ int main(int argc, char **argv)
|
|||||||
struct vdev_info dev;
|
struct vdev_info dev;
|
||||||
unsigned long long features = (1ULL << VIRTIO_RING_F_INDIRECT_DESC) |
|
unsigned long long features = (1ULL << VIRTIO_RING_F_INDIRECT_DESC) |
|
||||||
(1ULL << VIRTIO_RING_F_EVENT_IDX) | (1ULL << VIRTIO_F_VERSION_1);
|
(1ULL << VIRTIO_RING_F_EVENT_IDX) | (1ULL << VIRTIO_F_VERSION_1);
|
||||||
|
long batch = 1;
|
||||||
int o;
|
int o;
|
||||||
bool delayed = false;
|
bool delayed = false;
|
||||||
|
|
||||||
@@ -289,6 +311,11 @@ int main(int argc, char **argv)
|
|||||||
case 'D':
|
case 'D':
|
||||||
delayed = true;
|
delayed = true;
|
||||||
break;
|
break;
|
||||||
|
case 'b':
|
||||||
|
batch = strtol(optarg, NULL, 10);
|
||||||
|
assert(batch > 0);
|
||||||
|
assert(batch < (long)INT_MAX + 1);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
assert(0);
|
assert(0);
|
||||||
break;
|
break;
|
||||||
@@ -298,6 +325,6 @@ int main(int argc, char **argv)
|
|||||||
done:
|
done:
|
||||||
vdev_info_init(&dev, features);
|
vdev_info_init(&dev, features);
|
||||||
vq_info_add(&dev, 256);
|
vq_info_add(&dev, 256);
|
||||||
run_test(&dev, &dev.vqs[0], delayed, 0x100000);
|
run_test(&dev, &dev.vqs[0], delayed, batch, 0x100000);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user