mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2024-12-29 09:12:07 +00:00
tools/virtio: Add --reset
Currently, it only removes and add backend, but it will reset vq position in future commits. Signed-off-by: Eugenio Pérez <eperezma@redhat.com> Link: https://lore.kernel.org/r/20200418102217.32327-5-eperezma@redhat.com Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
This commit is contained in:
parent
7add78b2a6
commit
264ee5aa81
@ -263,9 +263,62 @@ static int vhost_test_set_features(struct vhost_test *n, u64 features)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static long vhost_test_set_backend(struct vhost_test *n, unsigned index, int fd)
|
||||||
|
{
|
||||||
|
static void *backend;
|
||||||
|
|
||||||
|
const bool enable = fd != -1;
|
||||||
|
struct vhost_virtqueue *vq;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
mutex_lock(&n->dev.mutex);
|
||||||
|
r = vhost_dev_check_owner(&n->dev);
|
||||||
|
if (r)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
if (index >= VHOST_TEST_VQ_MAX) {
|
||||||
|
r = -ENOBUFS;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
vq = &n->vqs[index];
|
||||||
|
mutex_lock(&vq->mutex);
|
||||||
|
|
||||||
|
/* Verify that ring has been setup correctly. */
|
||||||
|
if (!vhost_vq_access_ok(vq)) {
|
||||||
|
r = -EFAULT;
|
||||||
|
goto err_vq;
|
||||||
|
}
|
||||||
|
if (!enable) {
|
||||||
|
vhost_poll_stop(&vq->poll);
|
||||||
|
backend = vhost_vq_get_backend(vq);
|
||||||
|
vhost_vq_set_backend(vq, NULL);
|
||||||
|
} else {
|
||||||
|
vhost_vq_set_backend(vq, backend);
|
||||||
|
r = vhost_vq_init_access(vq);
|
||||||
|
if (r == 0)
|
||||||
|
r = vhost_poll_start(&vq->poll, vq->kick);
|
||||||
|
}
|
||||||
|
|
||||||
|
mutex_unlock(&vq->mutex);
|
||||||
|
|
||||||
|
if (enable) {
|
||||||
|
vhost_test_flush_vq(n, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
mutex_unlock(&n->dev.mutex);
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
err_vq:
|
||||||
|
mutex_unlock(&vq->mutex);
|
||||||
|
err:
|
||||||
|
mutex_unlock(&n->dev.mutex);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
static long vhost_test_ioctl(struct file *f, unsigned int ioctl,
|
static long vhost_test_ioctl(struct file *f, unsigned int ioctl,
|
||||||
unsigned long arg)
|
unsigned long arg)
|
||||||
{
|
{
|
||||||
|
struct vhost_vring_file backend;
|
||||||
struct vhost_test *n = f->private_data;
|
struct vhost_test *n = f->private_data;
|
||||||
void __user *argp = (void __user *)arg;
|
void __user *argp = (void __user *)arg;
|
||||||
u64 __user *featurep = argp;
|
u64 __user *featurep = argp;
|
||||||
@ -277,6 +330,10 @@ static long vhost_test_ioctl(struct file *f, unsigned int ioctl,
|
|||||||
if (copy_from_user(&test, argp, sizeof test))
|
if (copy_from_user(&test, argp, sizeof test))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
return vhost_test_run(n, test);
|
return vhost_test_run(n, test);
|
||||||
|
case VHOST_TEST_SET_BACKEND:
|
||||||
|
if (copy_from_user(&backend, argp, sizeof backend))
|
||||||
|
return -EFAULT;
|
||||||
|
return vhost_test_set_backend(n, backend.index, backend.fd);
|
||||||
case VHOST_GET_FEATURES:
|
case VHOST_GET_FEATURES:
|
||||||
features = VHOST_FEATURES;
|
features = VHOST_FEATURES;
|
||||||
if (copy_to_user(featurep, &features, sizeof features))
|
if (copy_to_user(featurep, &features, sizeof features))
|
||||||
|
@ -4,5 +4,6 @@
|
|||||||
|
|
||||||
/* Start a given test on the virtio null device. 0 stops all tests. */
|
/* Start a given test on the virtio null device. 0 stops all tests. */
|
||||||
#define VHOST_TEST_RUN _IOW(VHOST_VIRTIO, 0x31, int)
|
#define VHOST_TEST_RUN _IOW(VHOST_VIRTIO, 0x31, int)
|
||||||
|
#define VHOST_TEST_SET_BACKEND _IOW(VHOST_VIRTIO, 0x32, int)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -46,6 +46,9 @@ struct vdev_info {
|
|||||||
struct vhost_memory *mem;
|
struct vhost_memory *mem;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const struct vhost_vring_file no_backend = { .fd = -1 },
|
||||||
|
backend = { .fd = 1 };
|
||||||
|
|
||||||
bool vq_notify(struct virtqueue *vq)
|
bool vq_notify(struct virtqueue *vq)
|
||||||
{
|
{
|
||||||
struct vq_info *info = vq->priv;
|
struct vq_info *info = vq->priv;
|
||||||
@ -155,10 +158,10 @@ 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 batch, int bufs)
|
bool delayed, int batch, int reset_n, int bufs)
|
||||||
{
|
{
|
||||||
struct scatterlist sl;
|
struct scatterlist sl;
|
||||||
long started = 0, completed = 0;
|
long started = 0, completed = 0, next_reset = reset_n;
|
||||||
long completed_before, started_before;
|
long completed_before, started_before;
|
||||||
int r, test = 1;
|
int r, test = 1;
|
||||||
unsigned len;
|
unsigned len;
|
||||||
@ -171,6 +174,7 @@ static void run_test(struct vdev_info *dev, struct vq_info *vq,
|
|||||||
completed_before = completed;
|
completed_before = completed;
|
||||||
started_before = started;
|
started_before = started;
|
||||||
do {
|
do {
|
||||||
|
const bool reset = reset_n && completed > next_reset;
|
||||||
if (random_batch)
|
if (random_batch)
|
||||||
batch = (random() % vq->vring.num) + 1;
|
batch = (random() % vq->vring.num) + 1;
|
||||||
|
|
||||||
@ -200,12 +204,26 @@ static void run_test(struct vdev_info *dev, struct vq_info *vq,
|
|||||||
if (started >= bufs)
|
if (started >= bufs)
|
||||||
r = -1;
|
r = -1;
|
||||||
|
|
||||||
|
if (reset) {
|
||||||
|
r = ioctl(dev->control, VHOST_TEST_SET_BACKEND,
|
||||||
|
&no_backend);
|
||||||
|
assert(!r);
|
||||||
|
}
|
||||||
|
|
||||||
/* Flush out completed bufs if any */
|
/* Flush out completed bufs if any */
|
||||||
while (virtqueue_get_buf(vq->vq, &len)) {
|
while (virtqueue_get_buf(vq->vq, &len)) {
|
||||||
++completed;
|
++completed;
|
||||||
r = 0;
|
r = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (reset) {
|
||||||
|
r = ioctl(dev->control, VHOST_TEST_SET_BACKEND,
|
||||||
|
&backend);
|
||||||
|
assert(!r);
|
||||||
|
|
||||||
|
while (completed > next_reset)
|
||||||
|
next_reset += completed;
|
||||||
|
}
|
||||||
} while (r == 0);
|
} while (r == 0);
|
||||||
if (completed == completed_before && started == started_before)
|
if (completed == completed_before && started == started_before)
|
||||||
++spurious;
|
++spurious;
|
||||||
@ -270,6 +288,11 @@ const struct option longopts[] = {
|
|||||||
.val = 'b',
|
.val = 'b',
|
||||||
.has_arg = required_argument,
|
.has_arg = required_argument,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
.name = "reset",
|
||||||
|
.val = 'r',
|
||||||
|
.has_arg = optional_argument,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -282,6 +305,7 @@ static void help(void)
|
|||||||
" [--no-virtio-1]"
|
" [--no-virtio-1]"
|
||||||
" [--delayed-interrupt]"
|
" [--delayed-interrupt]"
|
||||||
" [--batch=random/N]"
|
" [--batch=random/N]"
|
||||||
|
" [--reset=N]"
|
||||||
"\n");
|
"\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -290,7 +314,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;
|
long batch = 1, reset = 0;
|
||||||
int o;
|
int o;
|
||||||
bool delayed = false;
|
bool delayed = false;
|
||||||
|
|
||||||
@ -326,6 +350,15 @@ int main(int argc, char **argv)
|
|||||||
assert(batch < (long)INT_MAX + 1);
|
assert(batch < (long)INT_MAX + 1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case 'r':
|
||||||
|
if (!optarg) {
|
||||||
|
reset = 1;
|
||||||
|
} else {
|
||||||
|
reset = strtol(optarg, NULL, 10);
|
||||||
|
assert(reset > 0);
|
||||||
|
assert(reset < (long)INT_MAX + 1);
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
assert(0);
|
assert(0);
|
||||||
break;
|
break;
|
||||||
@ -335,6 +368,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, batch, 0x100000);
|
run_test(&dev, &dev.vqs[0], delayed, batch, reset, 0x100000);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user