Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Eugenio Pérez and committed by
Michael S. Tsirkin
264ee5aa 7add78b2

+95 -4
+57
drivers/vhost/test.c
··· 263 263 return 0; 264 264 } 265 265 266 + static long vhost_test_set_backend(struct vhost_test *n, unsigned index, int fd) 267 + { 268 + static void *backend; 269 + 270 + const bool enable = fd != -1; 271 + struct vhost_virtqueue *vq; 272 + int r; 273 + 274 + mutex_lock(&n->dev.mutex); 275 + r = vhost_dev_check_owner(&n->dev); 276 + if (r) 277 + goto err; 278 + 279 + if (index >= VHOST_TEST_VQ_MAX) { 280 + r = -ENOBUFS; 281 + goto err; 282 + } 283 + vq = &n->vqs[index]; 284 + mutex_lock(&vq->mutex); 285 + 286 + /* Verify that ring has been setup correctly. */ 287 + if (!vhost_vq_access_ok(vq)) { 288 + r = -EFAULT; 289 + goto err_vq; 290 + } 291 + if (!enable) { 292 + vhost_poll_stop(&vq->poll); 293 + backend = vhost_vq_get_backend(vq); 294 + vhost_vq_set_backend(vq, NULL); 295 + } else { 296 + vhost_vq_set_backend(vq, backend); 297 + r = vhost_vq_init_access(vq); 298 + if (r == 0) 299 + r = vhost_poll_start(&vq->poll, vq->kick); 300 + } 301 + 302 + mutex_unlock(&vq->mutex); 303 + 304 + if (enable) { 305 + vhost_test_flush_vq(n, index); 306 + } 307 + 308 + mutex_unlock(&n->dev.mutex); 309 + return 0; 310 + 311 + err_vq: 312 + mutex_unlock(&vq->mutex); 313 + err: 314 + mutex_unlock(&n->dev.mutex); 315 + return r; 316 + } 317 + 266 318 static long vhost_test_ioctl(struct file *f, unsigned int ioctl, 267 319 unsigned long arg) 268 320 { 321 + struct vhost_vring_file backend; 269 322 struct vhost_test *n = f->private_data; 270 323 void __user *argp = (void __user *)arg; 271 324 u64 __user *featurep = argp; ··· 330 277 if (copy_from_user(&test, argp, sizeof test)) 331 278 return -EFAULT; 332 279 return vhost_test_run(n, test); 280 + case VHOST_TEST_SET_BACKEND: 281 + if (copy_from_user(&backend, argp, sizeof backend)) 282 + return -EFAULT; 283 + return vhost_test_set_backend(n, backend.index, backend.fd); 333 284 case VHOST_GET_FEATURES: 334 285 features = VHOST_FEATURES; 335 286 if (copy_to_user(featurep, &features, sizeof features))
+1
drivers/vhost/test.h
··· 4 4 5 5 /* Start a given test on the virtio null device. 0 stops all tests. */ 6 6 #define VHOST_TEST_RUN _IOW(VHOST_VIRTIO, 0x31, int) 7 + #define VHOST_TEST_SET_BACKEND _IOW(VHOST_VIRTIO, 0x32, int) 7 8 8 9 #endif
+37 -4
tools/virtio/virtio_test.c
··· 46 46 struct vhost_memory *mem; 47 47 }; 48 48 49 + static const struct vhost_vring_file no_backend = { .fd = -1 }, 50 + backend = { .fd = 1 }; 51 + 49 52 bool vq_notify(struct virtqueue *vq) 50 53 { 51 54 struct vq_info *info = vq->priv; ··· 158 155 } 159 156 160 157 static void run_test(struct vdev_info *dev, struct vq_info *vq, 161 - bool delayed, int batch, int bufs) 158 + bool delayed, int batch, int reset_n, int bufs) 162 159 { 163 160 struct scatterlist sl; 164 - long started = 0, completed = 0; 161 + long started = 0, completed = 0, next_reset = reset_n; 165 162 long completed_before, started_before; 166 163 int r, test = 1; 167 164 unsigned len; ··· 174 171 completed_before = completed; 175 172 started_before = started; 176 173 do { 174 + const bool reset = reset_n && completed > next_reset; 177 175 if (random_batch) 178 176 batch = (random() % vq->vring.num) + 1; 179 177 ··· 204 200 if (started >= bufs) 205 201 r = -1; 206 202 203 + if (reset) { 204 + r = ioctl(dev->control, VHOST_TEST_SET_BACKEND, 205 + &no_backend); 206 + assert(!r); 207 + } 208 + 207 209 /* Flush out completed bufs if any */ 208 210 while (virtqueue_get_buf(vq->vq, &len)) { 209 211 ++completed; 210 212 r = 0; 211 213 } 212 214 215 + if (reset) { 216 + r = ioctl(dev->control, VHOST_TEST_SET_BACKEND, 217 + &backend); 218 + assert(!r); 219 + 220 + while (completed > next_reset) 221 + next_reset += completed; 222 + } 213 223 } while (r == 0); 214 224 if (completed == completed_before && started == started_before) 215 225 ++spurious; ··· 289 271 .has_arg = required_argument, 290 272 }, 291 273 { 274 + .name = "reset", 275 + .val = 'r', 276 + .has_arg = optional_argument, 277 + }, 278 + { 292 279 } 293 280 }; 294 281 ··· 305 282 " [--no-virtio-1]" 306 283 " [--delayed-interrupt]" 307 284 " [--batch=random/N]" 285 + " [--reset=N]" 308 286 "\n"); 309 287 } 310 288 ··· 314 290 struct vdev_info dev; 315 291 unsigned long long features = (1ULL << VIRTIO_RING_F_INDIRECT_DESC) | 316 292 (1ULL << VIRTIO_RING_F_EVENT_IDX) | (1ULL << VIRTIO_F_VERSION_1); 317 - long batch = 1; 293 + long batch = 1, reset = 0; 318 294 int o; 319 295 bool delayed = false; 320 296 ··· 350 326 assert(batch < (long)INT_MAX + 1); 351 327 } 352 328 break; 329 + case 'r': 330 + if (!optarg) { 331 + reset = 1; 332 + } else { 333 + reset = strtol(optarg, NULL, 10); 334 + assert(reset > 0); 335 + assert(reset < (long)INT_MAX + 1); 336 + } 337 + break; 353 338 default: 354 339 assert(0); 355 340 break; ··· 368 335 done: 369 336 vdev_info_init(&dev, features); 370 337 vq_info_add(&dev, 256); 371 - run_test(&dev, &dev.vqs[0], delayed, batch, 0x100000); 338 + run_test(&dev, &dev.vqs[0], delayed, batch, reset, 0x100000); 372 339 return 0; 373 340 }