1 /*
2  * QTest testcase for Vhost-user Block Device
3  *
4  * Based on tests/qtest//virtio-blk-test.c
5 
6  * Copyright (c) 2014 SUSE LINUX Products GmbH
7  * Copyright (c) 2014 Marc Marí
8  * Copyright (c) 2020 Coiby Xu
9  *
10  * This work is licensed under the terms of the GNU GPL, version 2 or later.
11  * See the COPYING file in the top-level directory.
12  */
13 
14 #include "qemu/osdep.h"
15 #include "libqtest-single.h"
16 #include "qemu/bswap.h"
17 #include "qemu/module.h"
18 #include "standard-headers/linux/virtio_blk.h"
19 #include "standard-headers/linux/virtio_pci.h"
20 #include "libqos/qgraph.h"
21 #include "libqos/vhost-user-blk.h"
22 #include "libqos/libqos-pc.h"
23 
24 #define TEST_IMAGE_SIZE         (64 * 1024 * 1024)
25 #define QVIRTIO_BLK_TIMEOUT_US  (30 * 1000 * 1000)
26 #define PCI_SLOT_HP             0x06
27 
28 typedef struct {
29     pid_t pid;
30 } QemuStorageDaemonState;
31 
32 typedef struct QVirtioBlkReq {
33     uint32_t type;
34     uint32_t ioprio;
35     uint64_t sector;
36     char *data;
37     uint8_t status;
38 } QVirtioBlkReq;
39 
40 #ifdef HOST_WORDS_BIGENDIAN
41 static const bool host_is_big_endian = true;
42 #else
43 static const bool host_is_big_endian; /* false */
44 #endif
45 
46 static inline void virtio_blk_fix_request(QVirtioDevice *d, QVirtioBlkReq *req)
47 {
48     if (qvirtio_is_big_endian(d) != host_is_big_endian) {
49         req->type = bswap32(req->type);
50         req->ioprio = bswap32(req->ioprio);
51         req->sector = bswap64(req->sector);
52     }
53 }
54 
55 static inline void virtio_blk_fix_dwz_hdr(QVirtioDevice *d,
56     struct virtio_blk_discard_write_zeroes *dwz_hdr)
57 {
58     if (qvirtio_is_big_endian(d) != host_is_big_endian) {
59         dwz_hdr->sector = bswap64(dwz_hdr->sector);
60         dwz_hdr->num_sectors = bswap32(dwz_hdr->num_sectors);
61         dwz_hdr->flags = bswap32(dwz_hdr->flags);
62     }
63 }
64 
65 static uint64_t virtio_blk_request(QGuestAllocator *alloc, QVirtioDevice *d,
66                                    QVirtioBlkReq *req, uint64_t data_size)
67 {
68     uint64_t addr;
69     uint8_t status = 0xFF;
70     QTestState *qts = global_qtest;
71 
72     switch (req->type) {
73     case VIRTIO_BLK_T_IN:
74     case VIRTIO_BLK_T_OUT:
75         g_assert_cmpuint(data_size % 512, ==, 0);
76         break;
77     case VIRTIO_BLK_T_DISCARD:
78     case VIRTIO_BLK_T_WRITE_ZEROES:
79         g_assert_cmpuint(data_size %
80                          sizeof(struct virtio_blk_discard_write_zeroes), ==, 0);
81         break;
82     default:
83         g_assert_cmpuint(data_size, ==, 0);
84     }
85 
86     addr = guest_alloc(alloc, sizeof(*req) + data_size);
87 
88     virtio_blk_fix_request(d, req);
89 
90     qtest_memwrite(qts, addr, req, 16);
91     qtest_memwrite(qts, addr + 16, req->data, data_size);
92     qtest_memwrite(qts, addr + 16 + data_size, &status, sizeof(status));
93 
94     return addr;
95 }
96 
97 static void test_invalid_discard_write_zeroes(QVirtioDevice *dev,
98                                               QGuestAllocator *alloc,
99                                               QTestState *qts,
100                                               QVirtQueue *vq,
101                                               uint32_t type)
102 {
103     QVirtioBlkReq req;
104     struct virtio_blk_discard_write_zeroes dwz_hdr;
105     struct virtio_blk_discard_write_zeroes dwz_hdr2[2];
106     uint64_t req_addr;
107     uint32_t free_head;
108     uint8_t status;
109 
110     /* More than one dwz is not supported */
111     req.type = type;
112     req.data = (char *) dwz_hdr2;
113     dwz_hdr2[0].sector = 0;
114     dwz_hdr2[0].num_sectors = 1;
115     dwz_hdr2[0].flags = 0;
116     dwz_hdr2[1].sector = 1;
117     dwz_hdr2[1].num_sectors = 1;
118     dwz_hdr2[1].flags = 0;
119 
120     virtio_blk_fix_dwz_hdr(dev, &dwz_hdr2[0]);
121     virtio_blk_fix_dwz_hdr(dev, &dwz_hdr2[1]);
122 
123     req_addr = virtio_blk_request(alloc, dev, &req, sizeof(dwz_hdr2));
124 
125     free_head = qvirtqueue_add(qts, vq, req_addr, 16, false, true);
126     qvirtqueue_add(qts, vq, req_addr + 16, sizeof(dwz_hdr2), false, true);
127     qvirtqueue_add(qts, vq, req_addr + 16 + sizeof(dwz_hdr2), 1, true,
128                    false);
129 
130     qvirtqueue_kick(qts, dev, vq, free_head);
131 
132     qvirtio_wait_used_elem(qts, dev, vq, free_head, NULL,
133                            QVIRTIO_BLK_TIMEOUT_US);
134     status = readb(req_addr + 16 + sizeof(dwz_hdr2));
135     g_assert_cmpint(status, ==, VIRTIO_BLK_S_UNSUPP);
136 
137     guest_free(alloc, req_addr);
138 
139     /* num_sectors must be less than config->max_write_zeroes_sectors */
140     req.type = type;
141     req.data = (char *) &dwz_hdr;
142     dwz_hdr.sector = 0;
143     dwz_hdr.num_sectors = 0xffffffff;
144     dwz_hdr.flags = 0;
145 
146     virtio_blk_fix_dwz_hdr(dev, &dwz_hdr);
147 
148     req_addr = virtio_blk_request(alloc, dev, &req, sizeof(dwz_hdr));
149 
150     free_head = qvirtqueue_add(qts, vq, req_addr, 16, false, true);
151     qvirtqueue_add(qts, vq, req_addr + 16, sizeof(dwz_hdr), false, true);
152     qvirtqueue_add(qts, vq, req_addr + 16 + sizeof(dwz_hdr), 1, true,
153                    false);
154 
155     qvirtqueue_kick(qts, dev, vq, free_head);
156 
157     qvirtio_wait_used_elem(qts, dev, vq, free_head, NULL,
158                            QVIRTIO_BLK_TIMEOUT_US);
159     status = readb(req_addr + 16 + sizeof(dwz_hdr));
160     g_assert_cmpint(status, ==, VIRTIO_BLK_S_IOERR);
161 
162     guest_free(alloc, req_addr);
163 
164     /* sector must be less than the device capacity */
165     req.type = type;
166     req.data = (char *) &dwz_hdr;
167     dwz_hdr.sector = TEST_IMAGE_SIZE / 512 + 1;
168     dwz_hdr.num_sectors = 1;
169     dwz_hdr.flags = 0;
170 
171     virtio_blk_fix_dwz_hdr(dev, &dwz_hdr);
172 
173     req_addr = virtio_blk_request(alloc, dev, &req, sizeof(dwz_hdr));
174 
175     free_head = qvirtqueue_add(qts, vq, req_addr, 16, false, true);
176     qvirtqueue_add(qts, vq, req_addr + 16, sizeof(dwz_hdr), false, true);
177     qvirtqueue_add(qts, vq, req_addr + 16 + sizeof(dwz_hdr), 1, true,
178                    false);
179 
180     qvirtqueue_kick(qts, dev, vq, free_head);
181 
182     qvirtio_wait_used_elem(qts, dev, vq, free_head, NULL,
183                            QVIRTIO_BLK_TIMEOUT_US);
184     status = readb(req_addr + 16 + sizeof(dwz_hdr));
185     g_assert_cmpint(status, ==, VIRTIO_BLK_S_IOERR);
186 
187     guest_free(alloc, req_addr);
188 
189     /* reserved flag bits must be zero */
190     req.type = type;
191     req.data = (char *) &dwz_hdr;
192     dwz_hdr.sector = 0;
193     dwz_hdr.num_sectors = 1;
194     dwz_hdr.flags = ~VIRTIO_BLK_WRITE_ZEROES_FLAG_UNMAP;
195 
196     virtio_blk_fix_dwz_hdr(dev, &dwz_hdr);
197 
198     req_addr = virtio_blk_request(alloc, dev, &req, sizeof(dwz_hdr));
199 
200     free_head = qvirtqueue_add(qts, vq, req_addr, 16, false, true);
201     qvirtqueue_add(qts, vq, req_addr + 16, sizeof(dwz_hdr), false, true);
202     qvirtqueue_add(qts, vq, req_addr + 16 + sizeof(dwz_hdr), 1, true,
203                    false);
204 
205     qvirtqueue_kick(qts, dev, vq, free_head);
206 
207     qvirtio_wait_used_elem(qts, dev, vq, free_head, NULL,
208                            QVIRTIO_BLK_TIMEOUT_US);
209     status = readb(req_addr + 16 + sizeof(dwz_hdr));
210     g_assert_cmpint(status, ==, VIRTIO_BLK_S_UNSUPP);
211 
212     guest_free(alloc, req_addr);
213 }
214 
215 /* Returns the request virtqueue so the caller can perform further tests */
216 static QVirtQueue *test_basic(QVirtioDevice *dev, QGuestAllocator *alloc)
217 {
218     QVirtioBlkReq req;
219     uint64_t req_addr;
220     uint64_t capacity;
221     uint64_t features;
222     uint32_t free_head;
223     uint8_t status;
224     char *data;
225     QTestState *qts = global_qtest;
226     QVirtQueue *vq;
227 
228     features = qvirtio_get_features(dev);
229     features = features & ~(QVIRTIO_F_BAD_FEATURE |
230                     (1u << VIRTIO_RING_F_INDIRECT_DESC) |
231                     (1u << VIRTIO_RING_F_EVENT_IDX) |
232                     (1u << VIRTIO_BLK_F_SCSI));
233     qvirtio_set_features(dev, features);
234 
235     capacity = qvirtio_config_readq(dev, 0);
236     g_assert_cmpint(capacity, ==, TEST_IMAGE_SIZE / 512);
237 
238     vq = qvirtqueue_setup(dev, alloc, 0);
239 
240     qvirtio_set_driver_ok(dev);
241 
242     /* Write and read with 3 descriptor layout */
243     /* Write request */
244     req.type = VIRTIO_BLK_T_OUT;
245     req.ioprio = 1;
246     req.sector = 0;
247     req.data = g_malloc0(512);
248     strcpy(req.data, "TEST");
249 
250     req_addr = virtio_blk_request(alloc, dev, &req, 512);
251 
252     g_free(req.data);
253 
254     free_head = qvirtqueue_add(qts, vq, req_addr, 16, false, true);
255     qvirtqueue_add(qts, vq, req_addr + 16, 512, false, true);
256     qvirtqueue_add(qts, vq, req_addr + 528, 1, true, false);
257 
258     qvirtqueue_kick(qts, dev, vq, free_head);
259 
260     qvirtio_wait_used_elem(qts, dev, vq, free_head, NULL,
261                            QVIRTIO_BLK_TIMEOUT_US);
262     status = readb(req_addr + 528);
263     g_assert_cmpint(status, ==, 0);
264 
265     guest_free(alloc, req_addr);
266 
267     /* Read request */
268     req.type = VIRTIO_BLK_T_IN;
269     req.ioprio = 1;
270     req.sector = 0;
271     req.data = g_malloc0(512);
272 
273     req_addr = virtio_blk_request(alloc, dev, &req, 512);
274 
275     g_free(req.data);
276 
277     free_head = qvirtqueue_add(qts, vq, req_addr, 16, false, true);
278     qvirtqueue_add(qts, vq, req_addr + 16, 512, true, true);
279     qvirtqueue_add(qts, vq, req_addr + 528, 1, true, false);
280 
281     qvirtqueue_kick(qts, dev, vq, free_head);
282 
283     qvirtio_wait_used_elem(qts, dev, vq, free_head, NULL,
284                            QVIRTIO_BLK_TIMEOUT_US);
285     status = readb(req_addr + 528);
286     g_assert_cmpint(status, ==, 0);
287 
288     data = g_malloc0(512);
289     qtest_memread(qts, req_addr + 16, data, 512);
290     g_assert_cmpstr(data, ==, "TEST");
291     g_free(data);
292 
293     guest_free(alloc, req_addr);
294 
295     if (features & (1u << VIRTIO_BLK_F_WRITE_ZEROES)) {
296         struct virtio_blk_discard_write_zeroes dwz_hdr;
297         void *expected;
298 
299         /*
300          * WRITE_ZEROES request on the same sector of previous test where
301          * we wrote "TEST".
302          */
303         req.type = VIRTIO_BLK_T_WRITE_ZEROES;
304         req.data = (char *) &dwz_hdr;
305         dwz_hdr.sector = 0;
306         dwz_hdr.num_sectors = 1;
307         dwz_hdr.flags = 0;
308 
309         virtio_blk_fix_dwz_hdr(dev, &dwz_hdr);
310 
311         req_addr = virtio_blk_request(alloc, dev, &req, sizeof(dwz_hdr));
312 
313         free_head = qvirtqueue_add(qts, vq, req_addr, 16, false, true);
314         qvirtqueue_add(qts, vq, req_addr + 16, sizeof(dwz_hdr), false, true);
315         qvirtqueue_add(qts, vq, req_addr + 16 + sizeof(dwz_hdr), 1, true,
316                        false);
317 
318         qvirtqueue_kick(qts, dev, vq, free_head);
319 
320         qvirtio_wait_used_elem(qts, dev, vq, free_head, NULL,
321                                QVIRTIO_BLK_TIMEOUT_US);
322         status = readb(req_addr + 16 + sizeof(dwz_hdr));
323         g_assert_cmpint(status, ==, 0);
324 
325         guest_free(alloc, req_addr);
326 
327         /* Read request to check if the sector contains all zeroes */
328         req.type = VIRTIO_BLK_T_IN;
329         req.ioprio = 1;
330         req.sector = 0;
331         req.data = g_malloc0(512);
332 
333         req_addr = virtio_blk_request(alloc, dev, &req, 512);
334 
335         g_free(req.data);
336 
337         free_head = qvirtqueue_add(qts, vq, req_addr, 16, false, true);
338         qvirtqueue_add(qts, vq, req_addr + 16, 512, true, true);
339         qvirtqueue_add(qts, vq, req_addr + 528, 1, true, false);
340 
341         qvirtqueue_kick(qts, dev, vq, free_head);
342 
343         qvirtio_wait_used_elem(qts, dev, vq, free_head, NULL,
344                                QVIRTIO_BLK_TIMEOUT_US);
345         status = readb(req_addr + 528);
346         g_assert_cmpint(status, ==, 0);
347 
348         data = g_malloc(512);
349         expected = g_malloc0(512);
350         qtest_memread(qts, req_addr + 16, data, 512);
351         g_assert_cmpmem(data, 512, expected, 512);
352         g_free(expected);
353         g_free(data);
354 
355         guest_free(alloc, req_addr);
356 
357         test_invalid_discard_write_zeroes(dev, alloc, qts, vq,
358                                           VIRTIO_BLK_T_WRITE_ZEROES);
359     }
360 
361     if (features & (1u << VIRTIO_BLK_F_DISCARD)) {
362         struct virtio_blk_discard_write_zeroes dwz_hdr;
363 
364         req.type = VIRTIO_BLK_T_DISCARD;
365         req.data = (char *) &dwz_hdr;
366         dwz_hdr.sector = 0;
367         dwz_hdr.num_sectors = 1;
368         dwz_hdr.flags = 0;
369 
370         virtio_blk_fix_dwz_hdr(dev, &dwz_hdr);
371 
372         req_addr = virtio_blk_request(alloc, dev, &req, sizeof(dwz_hdr));
373 
374         free_head = qvirtqueue_add(qts, vq, req_addr, 16, false, true);
375         qvirtqueue_add(qts, vq, req_addr + 16, sizeof(dwz_hdr), false, true);
376         qvirtqueue_add(qts, vq, req_addr + 16 + sizeof(dwz_hdr),
377                        1, true, false);
378 
379         qvirtqueue_kick(qts, dev, vq, free_head);
380 
381         qvirtio_wait_used_elem(qts, dev, vq, free_head, NULL,
382                                QVIRTIO_BLK_TIMEOUT_US);
383         status = readb(req_addr + 16 + sizeof(dwz_hdr));
384         g_assert_cmpint(status, ==, 0);
385 
386         guest_free(alloc, req_addr);
387 
388         test_invalid_discard_write_zeroes(dev, alloc, qts, vq,
389                                           VIRTIO_BLK_T_DISCARD);
390     }
391 
392     if (features & (1u << VIRTIO_F_ANY_LAYOUT)) {
393         /* Write and read with 2 descriptor layout */
394         /* Write request */
395         req.type = VIRTIO_BLK_T_OUT;
396         req.ioprio = 1;
397         req.sector = 1;
398         req.data = g_malloc0(512);
399         strcpy(req.data, "TEST");
400 
401         req_addr = virtio_blk_request(alloc, dev, &req, 512);
402 
403         g_free(req.data);
404 
405         free_head = qvirtqueue_add(qts, vq, req_addr, 528, false, true);
406         qvirtqueue_add(qts, vq, req_addr + 528, 1, true, false);
407         qvirtqueue_kick(qts, dev, vq, free_head);
408 
409         qvirtio_wait_used_elem(qts, dev, vq, free_head, NULL,
410                                QVIRTIO_BLK_TIMEOUT_US);
411         status = readb(req_addr + 528);
412         g_assert_cmpint(status, ==, 0);
413 
414         guest_free(alloc, req_addr);
415 
416         /* Read request */
417         req.type = VIRTIO_BLK_T_IN;
418         req.ioprio = 1;
419         req.sector = 1;
420         req.data = g_malloc0(512);
421 
422         req_addr = virtio_blk_request(alloc, dev, &req, 512);
423 
424         g_free(req.data);
425 
426         free_head = qvirtqueue_add(qts, vq, req_addr, 16, false, true);
427         qvirtqueue_add(qts, vq, req_addr + 16, 513, true, false);
428 
429         qvirtqueue_kick(qts, dev, vq, free_head);
430 
431         qvirtio_wait_used_elem(qts, dev, vq, free_head, NULL,
432                                QVIRTIO_BLK_TIMEOUT_US);
433         status = readb(req_addr + 528);
434         g_assert_cmpint(status, ==, 0);
435 
436         data = g_malloc0(512);
437         qtest_memread(qts, req_addr + 16, data, 512);
438         g_assert_cmpstr(data, ==, "TEST");
439         g_free(data);
440 
441         guest_free(alloc, req_addr);
442     }
443 
444     return vq;
445 }
446 
447 static void basic(void *obj, void *data, QGuestAllocator *t_alloc)
448 {
449     QVhostUserBlk *blk_if = obj;
450     QVirtQueue *vq;
451 
452     vq = test_basic(blk_if->vdev, t_alloc);
453     qvirtqueue_cleanup(blk_if->vdev->bus, vq, t_alloc);
454 
455 }
456 
457 static void indirect(void *obj, void *u_data, QGuestAllocator *t_alloc)
458 {
459     QVirtQueue *vq;
460     QVhostUserBlk *blk_if = obj;
461     QVirtioDevice *dev = blk_if->vdev;
462     QVirtioBlkReq req;
463     QVRingIndirectDesc *indirect;
464     uint64_t req_addr;
465     uint64_t capacity;
466     uint64_t features;
467     uint32_t free_head;
468     uint8_t status;
469     char *data;
470     QTestState *qts = global_qtest;
471 
472     features = qvirtio_get_features(dev);
473     g_assert_cmphex(features & (1u << VIRTIO_RING_F_INDIRECT_DESC), !=, 0);
474     features = features & ~(QVIRTIO_F_BAD_FEATURE |
475                             (1u << VIRTIO_RING_F_EVENT_IDX) |
476                             (1u << VIRTIO_BLK_F_SCSI));
477     qvirtio_set_features(dev, features);
478 
479     capacity = qvirtio_config_readq(dev, 0);
480     g_assert_cmpint(capacity, ==, TEST_IMAGE_SIZE / 512);
481 
482     vq = qvirtqueue_setup(dev, t_alloc, 0);
483     qvirtio_set_driver_ok(dev);
484 
485     /* Write request */
486     req.type = VIRTIO_BLK_T_OUT;
487     req.ioprio = 1;
488     req.sector = 0;
489     req.data = g_malloc0(512);
490     strcpy(req.data, "TEST");
491 
492     req_addr = virtio_blk_request(t_alloc, dev, &req, 512);
493 
494     g_free(req.data);
495 
496     indirect = qvring_indirect_desc_setup(qts, dev, t_alloc, 2);
497     qvring_indirect_desc_add(dev, qts, indirect, req_addr, 528, false);
498     qvring_indirect_desc_add(dev, qts, indirect, req_addr + 528, 1, true);
499     free_head = qvirtqueue_add_indirect(qts, vq, indirect);
500     qvirtqueue_kick(qts, dev, vq, free_head);
501 
502     qvirtio_wait_used_elem(qts, dev, vq, free_head, NULL,
503                            QVIRTIO_BLK_TIMEOUT_US);
504     status = readb(req_addr + 528);
505     g_assert_cmpint(status, ==, 0);
506 
507     g_free(indirect);
508     guest_free(t_alloc, req_addr);
509 
510     /* Read request */
511     req.type = VIRTIO_BLK_T_IN;
512     req.ioprio = 1;
513     req.sector = 0;
514     req.data = g_malloc0(512);
515     strcpy(req.data, "TEST");
516 
517     req_addr = virtio_blk_request(t_alloc, dev, &req, 512);
518 
519     g_free(req.data);
520 
521     indirect = qvring_indirect_desc_setup(qts, dev, t_alloc, 2);
522     qvring_indirect_desc_add(dev, qts, indirect, req_addr, 16, false);
523     qvring_indirect_desc_add(dev, qts, indirect, req_addr + 16, 513, true);
524     free_head = qvirtqueue_add_indirect(qts, vq, indirect);
525     qvirtqueue_kick(qts, dev, vq, free_head);
526 
527     qvirtio_wait_used_elem(qts, dev, vq, free_head, NULL,
528                            QVIRTIO_BLK_TIMEOUT_US);
529     status = readb(req_addr + 528);
530     g_assert_cmpint(status, ==, 0);
531 
532     data = g_malloc0(512);
533     qtest_memread(qts, req_addr + 16, data, 512);
534     g_assert_cmpstr(data, ==, "TEST");
535     g_free(data);
536 
537     g_free(indirect);
538     guest_free(t_alloc, req_addr);
539     qvirtqueue_cleanup(dev->bus, vq, t_alloc);
540 }
541 
542 static void idx(void *obj, void *u_data, QGuestAllocator *t_alloc)
543 {
544     QVirtQueue *vq;
545     QVhostUserBlkPCI *blk = obj;
546     QVirtioPCIDevice *pdev = &blk->pci_vdev;
547     QVirtioDevice *dev = &pdev->vdev;
548     QVirtioBlkReq req;
549     uint64_t req_addr;
550     uint64_t capacity;
551     uint64_t features;
552     uint32_t free_head;
553     uint32_t write_head;
554     uint32_t desc_idx;
555     uint8_t status;
556     char *data;
557     QOSGraphObject *blk_object = obj;
558     QPCIDevice *pci_dev = blk_object->get_driver(blk_object, "pci-device");
559     QTestState *qts = global_qtest;
560 
561     if (qpci_check_buggy_msi(pci_dev)) {
562         return;
563     }
564 
565     qpci_msix_enable(pdev->pdev);
566     qvirtio_pci_set_msix_configuration_vector(pdev, t_alloc, 0);
567 
568     features = qvirtio_get_features(dev);
569     features = features & ~(QVIRTIO_F_BAD_FEATURE |
570                             (1u << VIRTIO_RING_F_INDIRECT_DESC) |
571                             (1u << VIRTIO_F_NOTIFY_ON_EMPTY) |
572                             (1u << VIRTIO_BLK_F_SCSI));
573     qvirtio_set_features(dev, features);
574 
575     capacity = qvirtio_config_readq(dev, 0);
576     g_assert_cmpint(capacity, ==, TEST_IMAGE_SIZE / 512);
577 
578     vq = qvirtqueue_setup(dev, t_alloc, 0);
579     qvirtqueue_pci_msix_setup(pdev, (QVirtQueuePCI *)vq, t_alloc, 1);
580 
581     qvirtio_set_driver_ok(dev);
582 
583     /*
584      * libvhost-user signals the call fd in VHOST_USER_SET_VRING_CALL, make
585      * sure to wait for the isr here so we don't race and confuse it later on.
586      */
587     qvirtio_wait_queue_isr(qts, dev, vq, QVIRTIO_BLK_TIMEOUT_US);
588 
589     /* Write request */
590     req.type = VIRTIO_BLK_T_OUT;
591     req.ioprio = 1;
592     req.sector = 0;
593     req.data = g_malloc0(512);
594     strcpy(req.data, "TEST");
595 
596     req_addr = virtio_blk_request(t_alloc, dev, &req, 512);
597 
598     g_free(req.data);
599 
600     free_head = qvirtqueue_add(qts, vq, req_addr, 16, false, true);
601     qvirtqueue_add(qts, vq, req_addr + 16, 512, false, true);
602     qvirtqueue_add(qts, vq, req_addr + 528, 1, true, false);
603     qvirtqueue_kick(qts, dev, vq, free_head);
604 
605     qvirtio_wait_used_elem(qts, dev, vq, free_head, NULL,
606                            QVIRTIO_BLK_TIMEOUT_US);
607 
608     /* Write request */
609     req.type = VIRTIO_BLK_T_OUT;
610     req.ioprio = 1;
611     req.sector = 1;
612     req.data = g_malloc0(512);
613     strcpy(req.data, "TEST");
614 
615     req_addr = virtio_blk_request(t_alloc, dev, &req, 512);
616 
617     g_free(req.data);
618 
619     /* Notify after processing the third request */
620     qvirtqueue_set_used_event(qts, vq, 2);
621     free_head = qvirtqueue_add(qts, vq, req_addr, 16, false, true);
622     qvirtqueue_add(qts, vq, req_addr + 16, 512, false, true);
623     qvirtqueue_add(qts, vq, req_addr + 528, 1, true, false);
624     qvirtqueue_kick(qts, dev, vq, free_head);
625     write_head = free_head;
626 
627     /* No notification expected */
628     status = qvirtio_wait_status_byte_no_isr(qts, dev,
629                                              vq, req_addr + 528,
630                                              QVIRTIO_BLK_TIMEOUT_US);
631     g_assert_cmpint(status, ==, 0);
632 
633     guest_free(t_alloc, req_addr);
634 
635     /* Read request */
636     req.type = VIRTIO_BLK_T_IN;
637     req.ioprio = 1;
638     req.sector = 1;
639     req.data = g_malloc0(512);
640 
641     req_addr = virtio_blk_request(t_alloc, dev, &req, 512);
642 
643     g_free(req.data);
644 
645     free_head = qvirtqueue_add(qts, vq, req_addr, 16, false, true);
646     qvirtqueue_add(qts, vq, req_addr + 16, 512, true, true);
647     qvirtqueue_add(qts, vq, req_addr + 528, 1, true, false);
648 
649     qvirtqueue_kick(qts, dev, vq, free_head);
650 
651     /* We get just one notification for both requests */
652     qvirtio_wait_used_elem(qts, dev, vq, write_head, NULL,
653                            QVIRTIO_BLK_TIMEOUT_US);
654     g_assert(qvirtqueue_get_buf(qts, vq, &desc_idx, NULL));
655     g_assert_cmpint(desc_idx, ==, free_head);
656 
657     status = readb(req_addr + 528);
658     g_assert_cmpint(status, ==, 0);
659 
660     data = g_malloc0(512);
661     qtest_memread(qts, req_addr + 16, data, 512);
662     g_assert_cmpstr(data, ==, "TEST");
663     g_free(data);
664 
665     guest_free(t_alloc, req_addr);
666 
667     /* End test */
668     qpci_msix_disable(pdev->pdev);
669 
670     qvirtqueue_cleanup(dev->bus, vq, t_alloc);
671 }
672 
673 static void pci_hotplug(void *obj, void *data, QGuestAllocator *t_alloc)
674 {
675     QVirtioPCIDevice *dev1 = obj;
676     QVirtioPCIDevice *dev;
677     QTestState *qts = dev1->pdev->bus->qts;
678 
679     /* plug secondary disk */
680     qtest_qmp_device_add(qts, "vhost-user-blk-pci", "drv1",
681                          "{'addr': %s, 'chardev': 'char2'}",
682                          stringify(PCI_SLOT_HP) ".0");
683 
684     dev = virtio_pci_new(dev1->pdev->bus,
685                          &(QPCIAddress) { .devfn = QPCI_DEVFN(PCI_SLOT_HP, 0)
686                                         });
687     g_assert_nonnull(dev);
688     g_assert_cmpint(dev->vdev.device_type, ==, VIRTIO_ID_BLOCK);
689     qvirtio_pci_device_disable(dev);
690     qos_object_destroy((QOSGraphObject *)dev);
691 
692     /* unplug secondary disk */
693     qpci_unplug_acpi_device_test(qts, "drv1", PCI_SLOT_HP);
694 }
695 
696 static void multiqueue(void *obj, void *data, QGuestAllocator *t_alloc)
697 {
698     QVirtioPCIDevice *pdev1 = obj;
699     QVirtioDevice *dev1 = &pdev1->vdev;
700     QVirtioPCIDevice *pdev8;
701     QVirtioDevice *dev8;
702     QTestState *qts = pdev1->pdev->bus->qts;
703     uint64_t features;
704     uint16_t num_queues;
705 
706     /*
707      * The primary device has 1 queue and VIRTIO_BLK_F_MQ is not enabled. The
708      * VIRTIO specification allows VIRTIO_BLK_F_MQ to be enabled when there is
709      * only 1 virtqueue, but --device vhost-user-blk-pci doesn't do this (which
710      * is also spec-compliant).
711      */
712     features = qvirtio_get_features(dev1);
713     g_assert_cmpint(features & (1u << VIRTIO_BLK_F_MQ), ==, 0);
714     features = features & ~(QVIRTIO_F_BAD_FEATURE |
715                             (1u << VIRTIO_RING_F_INDIRECT_DESC) |
716                             (1u << VIRTIO_F_NOTIFY_ON_EMPTY) |
717                             (1u << VIRTIO_BLK_F_SCSI));
718     qvirtio_set_features(dev1, features);
719 
720     /* Hotplug a secondary device with 8 queues */
721     qtest_qmp_device_add(qts, "vhost-user-blk-pci", "drv1",
722                          "{'addr': %s, 'chardev': 'char2', 'num-queues': 8}",
723                          stringify(PCI_SLOT_HP) ".0");
724 
725     pdev8 = virtio_pci_new(pdev1->pdev->bus,
726                            &(QPCIAddress) {
727                                .devfn = QPCI_DEVFN(PCI_SLOT_HP, 0)
728                            });
729     g_assert_nonnull(pdev8);
730     g_assert_cmpint(pdev8->vdev.device_type, ==, VIRTIO_ID_BLOCK);
731 
732     qos_object_start_hw(&pdev8->obj);
733 
734     dev8 = &pdev8->vdev;
735     features = qvirtio_get_features(dev8);
736     g_assert_cmpint(features & (1u << VIRTIO_BLK_F_MQ),
737                     ==,
738                     (1u << VIRTIO_BLK_F_MQ));
739     features = features & ~(QVIRTIO_F_BAD_FEATURE |
740                             (1u << VIRTIO_RING_F_INDIRECT_DESC) |
741                             (1u << VIRTIO_F_NOTIFY_ON_EMPTY) |
742                             (1u << VIRTIO_BLK_F_SCSI) |
743                             (1u << VIRTIO_BLK_F_MQ));
744     qvirtio_set_features(dev8, features);
745 
746     num_queues = qvirtio_config_readw(dev8,
747             offsetof(struct virtio_blk_config, num_queues));
748     g_assert_cmpint(num_queues, ==, 8);
749 
750     qvirtio_pci_device_disable(pdev8);
751     qos_object_destroy(&pdev8->obj);
752 
753     /* unplug secondary disk */
754     qpci_unplug_acpi_device_test(qts, "drv1", PCI_SLOT_HP);
755 }
756 
757 /*
758  * Check that setting the vring addr on a non-existent virtqueue does
759  * not crash.
760  */
761 static void test_nonexistent_virtqueue(void *obj, void *data,
762                                        QGuestAllocator *t_alloc)
763 {
764     QVhostUserBlkPCI *blk = obj;
765     QVirtioPCIDevice *pdev = &blk->pci_vdev;
766     QPCIBar bar0;
767     QPCIDevice *dev;
768 
769     dev = qpci_device_find(pdev->pdev->bus, QPCI_DEVFN(4, 0));
770     g_assert(dev != NULL);
771     qpci_device_enable(dev);
772 
773     bar0 = qpci_iomap(dev, 0, NULL);
774 
775     qpci_io_writeb(dev, bar0, VIRTIO_PCI_QUEUE_SEL, 2);
776     qpci_io_writel(dev, bar0, VIRTIO_PCI_QUEUE_PFN, 1);
777 
778     g_free(dev);
779 }
780 
781 static const char *qtest_qemu_storage_daemon_binary(void)
782 {
783     const char *qemu_storage_daemon_bin;
784 
785     qemu_storage_daemon_bin = getenv("QTEST_QEMU_STORAGE_DAEMON_BINARY");
786     if (!qemu_storage_daemon_bin) {
787         fprintf(stderr, "Environment variable "
788                         "QTEST_QEMU_STORAGE_DAEMON_BINARY required\n");
789         exit(0);
790     }
791 
792     return qemu_storage_daemon_bin;
793 }
794 
795 /* g_test_queue_destroy() cleanup function for files */
796 static void destroy_file(void *path)
797 {
798     unlink(path);
799     g_free(path);
800     qos_invalidate_command_line();
801 }
802 
803 static char *drive_create(void)
804 {
805     int fd, ret;
806     /** vhost-user-blk won't recognize drive located in /tmp */
807     char *t_path = g_strdup("qtest.XXXXXX");
808 
809     /** Create a temporary raw image */
810     fd = mkstemp(t_path);
811     g_assert_cmpint(fd, >=, 0);
812     ret = ftruncate(fd, TEST_IMAGE_SIZE);
813     g_assert_cmpint(ret, ==, 0);
814     close(fd);
815 
816     g_test_queue_destroy(destroy_file, t_path);
817     return t_path;
818 }
819 
820 static char *create_listen_socket(int *fd)
821 {
822     int tmp_fd;
823     char *path;
824 
825     /* No race because our pid makes the path unique */
826     path = g_strdup_printf("/tmp/qtest-%d-sock.XXXXXX", getpid());
827     tmp_fd = mkstemp(path);
828     g_assert_cmpint(tmp_fd, >=, 0);
829     close(tmp_fd);
830     unlink(path);
831 
832     *fd = qtest_socket_server(path);
833     g_test_queue_destroy(destroy_file, path);
834     return path;
835 }
836 
837 /*
838  * g_test_queue_destroy() and qtest_add_abrt_handler() cleanup function for
839  * qemu-storage-daemon.
840  */
841 static void quit_storage_daemon(void *data)
842 {
843     QemuStorageDaemonState *qsd = data;
844     int wstatus;
845     pid_t pid;
846 
847     /*
848      * If we were invoked as a g_test_queue_destroy() cleanup function we need
849      * to remove the abrt handler to avoid being called again if the code below
850      * aborts. Also, we must not leave the abrt handler installed after
851      * cleanup.
852      */
853     qtest_remove_abrt_handler(data);
854 
855     /* Before quitting storage-daemon, quit qemu to avoid dubious messages */
856     qtest_kill_qemu(global_qtest);
857 
858     kill(qsd->pid, SIGTERM);
859     pid = waitpid(qsd->pid, &wstatus, 0);
860     g_assert_cmpint(pid, ==, qsd->pid);
861     if (!WIFEXITED(wstatus)) {
862         fprintf(stderr, "%s: expected qemu-storage-daemon to exit\n",
863                 __func__);
864         abort();
865     }
866     if (WEXITSTATUS(wstatus) != 0) {
867         fprintf(stderr, "%s: expected qemu-storage-daemon to exit "
868                 "successfully, got %d\n",
869                 __func__, WEXITSTATUS(wstatus));
870         abort();
871     }
872 
873     g_free(data);
874 }
875 
876 static void start_vhost_user_blk(GString *cmd_line, int vus_instances,
877                                  int num_queues)
878 {
879     const char *vhost_user_blk_bin = qtest_qemu_storage_daemon_binary();
880     int i;
881     gchar *img_path;
882     GString *storage_daemon_command = g_string_new(NULL);
883     QemuStorageDaemonState *qsd;
884 
885     g_string_append_printf(storage_daemon_command,
886                            "exec %s ",
887                            vhost_user_blk_bin);
888 
889     g_string_append_printf(cmd_line,
890             " -object memory-backend-memfd,id=mem,size=256M,share=on "
891             " -M memory-backend=mem -m 256M ");
892 
893     for (i = 0; i < vus_instances; i++) {
894         int fd;
895         char *sock_path = create_listen_socket(&fd);
896 
897         /* create image file */
898         img_path = drive_create();
899         g_string_append_printf(storage_daemon_command,
900             "--blockdev driver=file,node-name=disk%d,filename=%s "
901             "--export type=vhost-user-blk,id=disk%d,addr.type=unix,addr.path=%s,"
902             "node-name=disk%i,writable=on,num-queues=%d ",
903             i, img_path, i, sock_path, i, num_queues);
904 
905         g_string_append_printf(cmd_line, "-chardev socket,id=char%d,path=%s ",
906                                i + 1, sock_path);
907     }
908 
909     g_test_message("starting vhost-user backend: %s",
910                    storage_daemon_command->str);
911     pid_t pid = fork();
912     if (pid == 0) {
913         /*
914          * Close standard file descriptors so tap-driver.pl pipe detects when
915          * our parent terminates.
916          */
917         close(0);
918         close(1);
919         open("/dev/null", O_RDONLY);
920         open("/dev/null", O_WRONLY);
921 
922         execlp("/bin/sh", "sh", "-c", storage_daemon_command->str, NULL);
923         exit(1);
924     }
925     g_string_free(storage_daemon_command, true);
926 
927     qsd = g_new(QemuStorageDaemonState, 1);
928     qsd->pid = pid;
929 
930     /* Make sure qemu-storage-daemon is stopped */
931     qtest_add_abrt_handler(quit_storage_daemon, qsd);
932     g_test_queue_destroy(quit_storage_daemon, qsd);
933 }
934 
935 static void *vhost_user_blk_test_setup(GString *cmd_line, void *arg)
936 {
937     start_vhost_user_blk(cmd_line, 1, 1);
938     return arg;
939 }
940 
941 /*
942  * Setup for hotplug.
943  *
944  * Since vhost-user server only serves one vhost-user client one time,
945  * another exprot
946  *
947  */
948 static void *vhost_user_blk_hotplug_test_setup(GString *cmd_line, void *arg)
949 {
950     /* "-chardev socket,id=char2" is used for pci_hotplug*/
951     start_vhost_user_blk(cmd_line, 2, 1);
952     return arg;
953 }
954 
955 static void *vhost_user_blk_multiqueue_test_setup(GString *cmd_line, void *arg)
956 {
957     start_vhost_user_blk(cmd_line, 2, 8);
958     return arg;
959 }
960 
961 static void register_vhost_user_blk_test(void)
962 {
963     QOSGraphTestOptions opts = {
964         .before = vhost_user_blk_test_setup,
965     };
966 
967     /*
968      * tests for vhost-user-blk and vhost-user-blk-pci
969      * The tests are borrowed from tests/virtio-blk-test.c. But some tests
970      * regarding block_resize don't work for vhost-user-blk.
971      * vhost-user-blk device doesn't have -drive, so tests containing
972      * block_resize are also abandoned,
973      *  - config
974      *  - resize
975      */
976     qos_add_test("basic", "vhost-user-blk", basic, &opts);
977     qos_add_test("indirect", "vhost-user-blk", indirect, &opts);
978     qos_add_test("idx", "vhost-user-blk-pci", idx, &opts);
979     qos_add_test("nxvirtq", "vhost-user-blk-pci",
980                  test_nonexistent_virtqueue, &opts);
981 
982     opts.before = vhost_user_blk_hotplug_test_setup;
983     qos_add_test("hotplug", "vhost-user-blk-pci", pci_hotplug, &opts);
984 
985     opts.before = vhost_user_blk_multiqueue_test_setup;
986     qos_add_test("multiqueue", "vhost-user-blk-pci", multiqueue, &opts);
987 }
988 
989 libqos_init(register_vhost_user_blk_test);
990