Commit 264ee5aa authored by Eugenio Pérez's avatar Eugenio Pérez Committed by Michael S. Tsirkin
Browse files

tools/virtio: Add --reset



Currently, it only removes and add backend, but it will reset vq
position in future commits.

Signed-off-by: default avatarEugenio Pérez <eperezma@redhat.com>
Link: https://lore.kernel.org/r/20200418102217.32327-5-eperezma@redhat.com


Signed-off-by: default avatarMichael S. Tsirkin <mst@redhat.com>
parent 7add78b2
Loading
Loading
Loading
Loading
+57 −0
Original line number Original line Diff line number Diff line
@@ -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))
+1 −0
Original line number Original line Diff line number Diff line
@@ -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
+37 −4
Original line number Original line Diff line number Diff line
@@ -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;
}
}