]> Git Repo - qemu.git/blob - tests/virtio-9p-test.c
crypto: refactor XTS cipher mode test suite
[qemu.git] / tests / virtio-9p-test.c
1 /*
2  * QTest testcase for VirtIO 9P
3  *
4  * Copyright (c) 2014 SUSE LINUX Products GmbH
5  *
6  * This work is licensed under the terms of the GNU GPL, version 2 or later.
7  * See the COPYING file in the top-level directory.
8  */
9
10 #include "qemu/osdep.h"
11 #include "libqtest.h"
12 #include "qemu-common.h"
13 #include "libqos/libqos-pc.h"
14 #include "libqos/libqos-spapr.h"
15 #include "libqos/virtio.h"
16 #include "libqos/virtio-pci.h"
17 #include "standard-headers/linux/virtio_ids.h"
18 #include "standard-headers/linux/virtio_pci.h"
19 #include "hw/9pfs/9p.h"
20 #include "hw/9pfs/9p-synth.h"
21
22 #define QVIRTIO_9P_TIMEOUT_US (10 * 1000 * 1000)
23
24 static const char mount_tag[] = "qtest";
25
26 typedef struct {
27     QVirtioDevice *dev;
28     QOSState *qs;
29     QVirtQueue *vq;
30 } QVirtIO9P;
31
32 static QVirtIO9P *qvirtio_9p_start(const char *driver)
33 {
34     const char *arch = qtest_get_arch();
35     const char *cmd = "-fsdev synth,id=fsdev0 "
36                       "-device %s,fsdev=fsdev0,mount_tag=%s";
37     QVirtIO9P *v9p = g_new0(QVirtIO9P, 1);
38
39     if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) {
40         v9p->qs = qtest_pc_boot(cmd, driver, mount_tag);
41     } else if (strcmp(arch, "ppc64") == 0) {
42         v9p->qs = qtest_spapr_boot(cmd, driver, mount_tag);
43     } else {
44         g_printerr("virtio-9p tests are only available on x86 or ppc64\n");
45         exit(EXIT_FAILURE);
46     }
47     global_qtest = v9p->qs->qts;
48
49     return v9p;
50 }
51
52 static void qvirtio_9p_stop(QVirtIO9P *v9p)
53 {
54     qtest_shutdown(v9p->qs);
55     g_free(v9p);
56 }
57
58 static QVirtIO9P *qvirtio_9p_pci_start(void)
59 {
60     QVirtIO9P *v9p = qvirtio_9p_start("virtio-9p-pci");
61     QVirtioPCIDevice *dev = qvirtio_pci_device_find(v9p->qs->pcibus,
62                                                     VIRTIO_ID_9P);
63     g_assert_nonnull(dev);
64     g_assert_cmphex(dev->vdev.device_type, ==, VIRTIO_ID_9P);
65     v9p->dev = (QVirtioDevice *) dev;
66
67     qvirtio_pci_device_enable(dev);
68     qvirtio_reset(v9p->dev);
69     qvirtio_set_acknowledge(v9p->dev);
70     qvirtio_set_driver(v9p->dev);
71
72     v9p->vq = qvirtqueue_setup(v9p->dev, v9p->qs->alloc, 0);
73
74     qvirtio_set_driver_ok(v9p->dev);
75
76     return v9p;
77 }
78
79 static void qvirtio_9p_pci_stop(QVirtIO9P *v9p)
80 {
81     qvirtqueue_cleanup(v9p->dev->bus, v9p->vq, v9p->qs->alloc);
82     qvirtio_pci_device_disable(container_of(v9p->dev, QVirtioPCIDevice, vdev));
83     qvirtio_pci_device_free((QVirtioPCIDevice *)v9p->dev);
84     qvirtio_9p_stop(v9p);
85 }
86
87 static void pci_config(QVirtIO9P *v9p)
88 {
89     size_t tag_len = qvirtio_config_readw(v9p->dev, 0);
90     char *tag;
91     int i;
92
93     g_assert_cmpint(tag_len, ==, strlen(mount_tag));
94
95     tag = g_malloc(tag_len);
96     for (i = 0; i < tag_len; i++) {
97         tag[i] = qvirtio_config_readb(v9p->dev, i + 2);
98     }
99     g_assert_cmpmem(tag, tag_len, mount_tag, tag_len);
100     g_free(tag);
101 }
102
103 #define P9_MAX_SIZE 4096 /* Max size of a T-message or R-message */
104
105 typedef struct {
106     QVirtIO9P *v9p;
107     uint16_t tag;
108     uint64_t t_msg;
109     uint32_t t_size;
110     uint64_t r_msg;
111     /* No r_size, it is hardcoded to P9_MAX_SIZE */
112     size_t t_off;
113     size_t r_off;
114     uint32_t free_head;
115 } P9Req;
116
117 static void v9fs_memwrite(P9Req *req, const void *addr, size_t len)
118 {
119     memwrite(req->t_msg + req->t_off, addr, len);
120     req->t_off += len;
121 }
122
123 static void v9fs_memskip(P9Req *req, size_t len)
124 {
125     req->r_off += len;
126 }
127
128 static void v9fs_memread(P9Req *req, void *addr, size_t len)
129 {
130     memread(req->r_msg + req->r_off, addr, len);
131     req->r_off += len;
132 }
133
134 static void v9fs_uint16_write(P9Req *req, uint16_t val)
135 {
136     uint16_t le_val = cpu_to_le16(val);
137
138     v9fs_memwrite(req, &le_val, 2);
139 }
140
141 static void v9fs_uint16_read(P9Req *req, uint16_t *val)
142 {
143     v9fs_memread(req, val, 2);
144     le16_to_cpus(val);
145 }
146
147 static void v9fs_uint32_write(P9Req *req, uint32_t val)
148 {
149     uint32_t le_val = cpu_to_le32(val);
150
151     v9fs_memwrite(req, &le_val, 4);
152 }
153
154 static void v9fs_uint64_write(P9Req *req, uint64_t val)
155 {
156     uint64_t le_val = cpu_to_le64(val);
157
158     v9fs_memwrite(req, &le_val, 8);
159 }
160
161 static void v9fs_uint32_read(P9Req *req, uint32_t *val)
162 {
163     v9fs_memread(req, val, 4);
164     le32_to_cpus(val);
165 }
166
167 /* len[2] string[len] */
168 static uint16_t v9fs_string_size(const char *string)
169 {
170     size_t len = strlen(string);
171
172     g_assert_cmpint(len, <=, UINT16_MAX - 2);
173
174     return 2 + len;
175 }
176
177 static void v9fs_string_write(P9Req *req, const char *string)
178 {
179     int len = strlen(string);
180
181     g_assert_cmpint(len, <=, UINT16_MAX);
182
183     v9fs_uint16_write(req, (uint16_t) len);
184     v9fs_memwrite(req, string, len);
185 }
186
187 static void v9fs_string_read(P9Req *req, uint16_t *len, char **string)
188 {
189     uint16_t local_len;
190
191     v9fs_uint16_read(req, &local_len);
192     if (len) {
193         *len = local_len;
194     }
195     if (string) {
196         *string = g_malloc(local_len);
197         v9fs_memread(req, *string, local_len);
198     } else {
199         v9fs_memskip(req, local_len);
200     }
201 }
202
203  typedef struct {
204     uint32_t size;
205     uint8_t id;
206     uint16_t tag;
207 } QEMU_PACKED P9Hdr;
208
209 static P9Req *v9fs_req_init(QVirtIO9P *v9p, uint32_t size, uint8_t id,
210                             uint16_t tag)
211 {
212     P9Req *req = g_new0(P9Req, 1);
213     uint32_t total_size = 7; /* 9P header has well-known size of 7 bytes */
214     P9Hdr hdr = {
215         .id = id,
216         .tag = cpu_to_le16(tag)
217     };
218
219     g_assert_cmpint(total_size, <=, UINT32_MAX - size);
220     total_size += size;
221     hdr.size = cpu_to_le32(total_size);
222
223     g_assert_cmpint(total_size, <=, P9_MAX_SIZE);
224
225     req->v9p = v9p;
226     req->t_size = total_size;
227     req->t_msg = guest_alloc(v9p->qs->alloc, req->t_size);
228     v9fs_memwrite(req, &hdr, 7);
229     req->tag = tag;
230     return req;
231 }
232
233 static void v9fs_req_send(P9Req *req)
234 {
235     QVirtIO9P *v9p = req->v9p;
236
237     req->r_msg = guest_alloc(v9p->qs->alloc, P9_MAX_SIZE);
238     req->free_head = qvirtqueue_add(v9p->vq, req->t_msg, req->t_size, false,
239                                     true);
240     qvirtqueue_add(v9p->vq, req->r_msg, P9_MAX_SIZE, true, false);
241     qvirtqueue_kick(v9p->dev, v9p->vq, req->free_head);
242     req->t_off = 0;
243 }
244
245 static const char *rmessage_name(uint8_t id)
246 {
247     return
248         id == P9_RLERROR ? "RLERROR" :
249         id == P9_RVERSION ? "RVERSION" :
250         id == P9_RATTACH ? "RATTACH" :
251         id == P9_RWALK ? "RWALK" :
252         id == P9_RLOPEN ? "RLOPEN" :
253         id == P9_RWRITE ? "RWRITE" :
254         id == P9_RFLUSH ? "RFLUSH" :
255         "<unknown>";
256 }
257
258 static void v9fs_req_wait_for_reply(P9Req *req, uint32_t *len)
259 {
260     QVirtIO9P *v9p = req->v9p;
261
262     qvirtio_wait_used_elem(v9p->dev, v9p->vq, req->free_head, len,
263                            QVIRTIO_9P_TIMEOUT_US);
264 }
265
266 static void v9fs_req_recv(P9Req *req, uint8_t id)
267 {
268     P9Hdr hdr;
269
270     v9fs_memread(req, &hdr, 7);
271     hdr.size = ldl_le_p(&hdr.size);
272     hdr.tag = lduw_le_p(&hdr.tag);
273
274     g_assert_cmpint(hdr.size, >=, 7);
275     g_assert_cmpint(hdr.size, <=, P9_MAX_SIZE);
276     g_assert_cmpint(hdr.tag, ==, req->tag);
277
278     if (hdr.id != id) {
279         g_printerr("Received response %d (%s) instead of %d (%s)\n",
280                    hdr.id, rmessage_name(hdr.id), id, rmessage_name(id));
281
282         if (hdr.id == P9_RLERROR) {
283             uint32_t err;
284             v9fs_uint32_read(req, &err);
285             g_printerr("Rlerror has errno %d (%s)\n", err, strerror(err));
286         }
287     }
288     g_assert_cmpint(hdr.id, ==, id);
289 }
290
291 static void v9fs_req_free(P9Req *req)
292 {
293     QVirtIO9P *v9p = req->v9p;
294
295     guest_free(v9p->qs->alloc, req->t_msg);
296     guest_free(v9p->qs->alloc, req->r_msg);
297     g_free(req);
298 }
299
300 /* size[4] Rlerror tag[2] ecode[4] */
301 static void v9fs_rlerror(P9Req *req, uint32_t *err)
302 {
303     v9fs_req_recv(req, P9_RLERROR);
304     v9fs_uint32_read(req, err);
305     v9fs_req_free(req);
306 }
307
308 /* size[4] Tversion tag[2] msize[4] version[s] */
309 static P9Req *v9fs_tversion(QVirtIO9P *v9p, uint32_t msize, const char *version,
310                             uint16_t tag)
311 {
312     P9Req *req;
313     uint32_t body_size = 4;
314     uint16_t string_size = v9fs_string_size(version);
315
316     g_assert_cmpint(body_size, <=, UINT32_MAX - string_size);
317     body_size += string_size;
318     req = v9fs_req_init(v9p, body_size, P9_TVERSION, tag);
319
320     v9fs_uint32_write(req, msize);
321     v9fs_string_write(req, version);
322     v9fs_req_send(req);
323     return req;
324 }
325
326 /* size[4] Rversion tag[2] msize[4] version[s] */
327 static void v9fs_rversion(P9Req *req, uint16_t *len, char **version)
328 {
329     uint32_t msize;
330
331     v9fs_req_recv(req, P9_RVERSION);
332     v9fs_uint32_read(req, &msize);
333
334     g_assert_cmpint(msize, ==, P9_MAX_SIZE);
335
336     if (len || version) {
337         v9fs_string_read(req, len, version);
338     }
339
340     v9fs_req_free(req);
341 }
342
343 /* size[4] Tattach tag[2] fid[4] afid[4] uname[s] aname[s] n_uname[4] */
344 static P9Req *v9fs_tattach(QVirtIO9P *v9p, uint32_t fid, uint32_t n_uname,
345                            uint16_t tag)
346 {
347     const char *uname = ""; /* ignored by QEMU */
348     const char *aname = ""; /* ignored by QEMU */
349     P9Req *req = v9fs_req_init(v9p, 4 + 4 + 2 + 2 + 4, P9_TATTACH, tag);
350
351     v9fs_uint32_write(req, fid);
352     v9fs_uint32_write(req, P9_NOFID);
353     v9fs_string_write(req, uname);
354     v9fs_string_write(req, aname);
355     v9fs_uint32_write(req, n_uname);
356     v9fs_req_send(req);
357     return req;
358 }
359
360 typedef char v9fs_qid[13];
361
362 /* size[4] Rattach tag[2] qid[13] */
363 static void v9fs_rattach(P9Req *req, v9fs_qid *qid)
364 {
365     v9fs_req_recv(req, P9_RATTACH);
366     if (qid) {
367         v9fs_memread(req, qid, 13);
368     }
369     v9fs_req_free(req);
370 }
371
372 /* size[4] Twalk tag[2] fid[4] newfid[4] nwname[2] nwname*(wname[s]) */
373 static P9Req *v9fs_twalk(QVirtIO9P *v9p, uint32_t fid, uint32_t newfid,
374                          uint16_t nwname, char *const wnames[], uint16_t tag)
375 {
376     P9Req *req;
377     int i;
378     uint32_t body_size = 4 + 4 + 2;
379
380     for (i = 0; i < nwname; i++) {
381         uint16_t wname_size = v9fs_string_size(wnames[i]);
382
383         g_assert_cmpint(body_size, <=, UINT32_MAX - wname_size);
384         body_size += wname_size;
385     }
386     req = v9fs_req_init(v9p,  body_size, P9_TWALK, tag);
387     v9fs_uint32_write(req, fid);
388     v9fs_uint32_write(req, newfid);
389     v9fs_uint16_write(req, nwname);
390     for (i = 0; i < nwname; i++) {
391         v9fs_string_write(req, wnames[i]);
392     }
393     v9fs_req_send(req);
394     return req;
395 }
396
397 /* size[4] Rwalk tag[2] nwqid[2] nwqid*(wqid[13]) */
398 static void v9fs_rwalk(P9Req *req, uint16_t *nwqid, v9fs_qid **wqid)
399 {
400     uint16_t local_nwqid;
401
402     v9fs_req_recv(req, P9_RWALK);
403     v9fs_uint16_read(req, &local_nwqid);
404     if (nwqid) {
405         *nwqid = local_nwqid;
406     }
407     if (wqid) {
408         *wqid = g_malloc(local_nwqid * 13);
409         v9fs_memread(req, *wqid, local_nwqid * 13);
410     }
411     v9fs_req_free(req);
412 }
413
414 /* size[4] Tlopen tag[2] fid[4] flags[4] */
415 static P9Req *v9fs_tlopen(QVirtIO9P *v9p, uint32_t fid, uint32_t flags,
416                           uint16_t tag)
417 {
418     P9Req *req;
419
420     req = v9fs_req_init(v9p,  4 + 4, P9_TLOPEN, tag);
421     v9fs_uint32_write(req, fid);
422     v9fs_uint32_write(req, flags);
423     v9fs_req_send(req);
424     return req;
425 }
426
427 /* size[4] Rlopen tag[2] qid[13] iounit[4] */
428 static void v9fs_rlopen(P9Req *req, v9fs_qid *qid, uint32_t *iounit)
429 {
430     v9fs_req_recv(req, P9_RLOPEN);
431     if (qid) {
432         v9fs_memread(req, qid, 13);
433     } else {
434         v9fs_memskip(req, 13);
435     }
436     if (iounit) {
437         v9fs_uint32_read(req, iounit);
438     }
439     v9fs_req_free(req);
440 }
441
442 /* size[4] Twrite tag[2] fid[4] offset[8] count[4] data[count] */
443 static P9Req *v9fs_twrite(QVirtIO9P *v9p, uint32_t fid, uint64_t offset,
444                           uint32_t count, const void *data, uint16_t tag)
445 {
446     P9Req *req;
447     uint32_t body_size = 4 + 8 + 4;
448
449     g_assert_cmpint(body_size, <=, UINT32_MAX - count);
450     body_size += count;
451     req = v9fs_req_init(v9p,  body_size, P9_TWRITE, tag);
452     v9fs_uint32_write(req, fid);
453     v9fs_uint64_write(req, offset);
454     v9fs_uint32_write(req, count);
455     v9fs_memwrite(req, data, count);
456     v9fs_req_send(req);
457     return req;
458 }
459
460 /* size[4] Rwrite tag[2] count[4] */
461 static void v9fs_rwrite(P9Req *req, uint32_t *count)
462 {
463     v9fs_req_recv(req, P9_RWRITE);
464     if (count) {
465         v9fs_uint32_read(req, count);
466     }
467     v9fs_req_free(req);
468 }
469
470 /* size[4] Tflush tag[2] oldtag[2] */
471 static P9Req *v9fs_tflush(QVirtIO9P *v9p, uint16_t oldtag, uint16_t tag)
472 {
473     P9Req *req;
474
475     req = v9fs_req_init(v9p,  2, P9_TFLUSH, tag);
476     v9fs_uint32_write(req, oldtag);
477     v9fs_req_send(req);
478     return req;
479 }
480
481 /* size[4] Rflush tag[2] */
482 static void v9fs_rflush(P9Req *req)
483 {
484     v9fs_req_recv(req, P9_RFLUSH);
485     v9fs_req_free(req);
486 }
487
488 static void fs_version(QVirtIO9P *v9p)
489 {
490     const char *version = "9P2000.L";
491     uint16_t server_len;
492     char *server_version;
493     P9Req *req;
494
495     req = v9fs_tversion(v9p, P9_MAX_SIZE, version, P9_NOTAG);
496     v9fs_req_wait_for_reply(req, NULL);
497     v9fs_rversion(req, &server_len, &server_version);
498
499     g_assert_cmpmem(server_version, server_len, version, strlen(version));
500
501     g_free(server_version);
502 }
503
504 static void fs_attach(QVirtIO9P *v9p)
505 {
506     P9Req *req;
507
508     fs_version(v9p);
509     req = v9fs_tattach(v9p, 0, getuid(), 0);
510     v9fs_req_wait_for_reply(req, NULL);
511     v9fs_rattach(req, NULL);
512 }
513
514 static void fs_walk(QVirtIO9P *v9p)
515 {
516     char *wnames[P9_MAXWELEM];
517     uint16_t nwqid;
518     v9fs_qid *wqid;
519     int i;
520     P9Req *req;
521
522     for (i = 0; i < P9_MAXWELEM; i++) {
523         wnames[i] = g_strdup_printf(QTEST_V9FS_SYNTH_WALK_FILE, i);
524     }
525
526     fs_attach(v9p);
527     req = v9fs_twalk(v9p, 0, 1, P9_MAXWELEM, wnames, 0);
528     v9fs_req_wait_for_reply(req, NULL);
529     v9fs_rwalk(req, &nwqid, &wqid);
530
531     g_assert_cmpint(nwqid, ==, P9_MAXWELEM);
532
533     for (i = 0; i < P9_MAXWELEM; i++) {
534         g_free(wnames[i]);
535     }
536
537     g_free(wqid);
538 }
539
540 static void fs_walk_no_slash(QVirtIO9P *v9p)
541 {
542     char *const wnames[] = { g_strdup(" /") };
543     P9Req *req;
544     uint32_t err;
545
546     fs_attach(v9p);
547     req = v9fs_twalk(v9p, 0, 1, 1, wnames, 0);
548     v9fs_req_wait_for_reply(req, NULL);
549     v9fs_rlerror(req, &err);
550
551     g_assert_cmpint(err, ==, ENOENT);
552
553     g_free(wnames[0]);
554 }
555
556 static void fs_walk_dotdot(QVirtIO9P *v9p)
557 {
558     char *const wnames[] = { g_strdup("..") };
559     v9fs_qid root_qid, *wqid;
560     P9Req *req;
561
562     fs_version(v9p);
563     req = v9fs_tattach(v9p, 0, getuid(), 0);
564     v9fs_req_wait_for_reply(req, NULL);
565     v9fs_rattach(req, &root_qid);
566
567     req = v9fs_twalk(v9p, 0, 1, 1, wnames, 0);
568     v9fs_req_wait_for_reply(req, NULL);
569     v9fs_rwalk(req, NULL, &wqid); /* We now we'll get one qid */
570
571     g_assert_cmpmem(&root_qid, 13, wqid[0], 13);
572
573     g_free(wqid);
574     g_free(wnames[0]);
575 }
576
577 static void fs_lopen(QVirtIO9P *v9p)
578 {
579     char *const wnames[] = { g_strdup(QTEST_V9FS_SYNTH_LOPEN_FILE) };
580     P9Req *req;
581
582     fs_attach(v9p);
583     req = v9fs_twalk(v9p, 0, 1, 1, wnames, 0);
584     v9fs_req_wait_for_reply(req, NULL);
585     v9fs_rwalk(req, NULL, NULL);
586
587     req = v9fs_tlopen(v9p, 1, O_WRONLY, 0);
588     v9fs_req_wait_for_reply(req, NULL);
589     v9fs_rlopen(req, NULL, NULL);
590
591     g_free(wnames[0]);
592 }
593
594 static void fs_write(QVirtIO9P *v9p)
595 {
596     static const uint32_t write_count = P9_MAX_SIZE / 2;
597     char *const wnames[] = { g_strdup(QTEST_V9FS_SYNTH_WRITE_FILE) };
598     char *buf = g_malloc0(write_count);
599     uint32_t count;
600     P9Req *req;
601
602     fs_attach(v9p);
603     req = v9fs_twalk(v9p, 0, 1, 1, wnames, 0);
604     v9fs_req_wait_for_reply(req, NULL);
605     v9fs_rwalk(req, NULL, NULL);
606
607     req = v9fs_tlopen(v9p, 1, O_WRONLY, 0);
608     v9fs_req_wait_for_reply(req, NULL);
609     v9fs_rlopen(req, NULL, NULL);
610
611     req = v9fs_twrite(v9p, 1, 0, write_count, buf, 0);
612     v9fs_req_wait_for_reply(req, NULL);
613     v9fs_rwrite(req, &count);
614     g_assert_cmpint(count, ==, write_count);
615
616     g_free(buf);
617     g_free(wnames[0]);
618 }
619
620 static void fs_flush_success(QVirtIO9P *v9p)
621 {
622     char *const wnames[] = { g_strdup(QTEST_V9FS_SYNTH_FLUSH_FILE) };
623     P9Req *req, *flush_req;
624     uint32_t reply_len;
625     uint8_t should_block;
626
627     fs_attach(v9p);
628     req = v9fs_twalk(v9p, 0, 1, 1, wnames, 0);
629     v9fs_req_wait_for_reply(req, NULL);
630     v9fs_rwalk(req, NULL, NULL);
631
632     req = v9fs_tlopen(v9p, 1, O_WRONLY, 0);
633     v9fs_req_wait_for_reply(req, NULL);
634     v9fs_rlopen(req, NULL, NULL);
635
636     /* This will cause the 9p server to try to write data to the backend,
637      * until the write request gets cancelled.
638      */
639     should_block = 1;
640     req = v9fs_twrite(v9p, 1, 0, sizeof(should_block), &should_block, 0);
641
642     flush_req = v9fs_tflush(v9p, req->tag, 1);
643
644     /* The write request is supposed to be flushed: the server should just
645      * mark the write request as used and reply to the flush request.
646      */
647     v9fs_req_wait_for_reply(req, &reply_len);
648     g_assert_cmpint(reply_len, ==, 0);
649     v9fs_req_free(req);
650     v9fs_rflush(flush_req);
651
652     g_free(wnames[0]);
653 }
654
655 static void fs_flush_ignored(QVirtIO9P *v9p)
656 {
657     char *const wnames[] = { g_strdup(QTEST_V9FS_SYNTH_FLUSH_FILE) };
658     P9Req *req, *flush_req;
659     uint32_t count;
660     uint8_t should_block;
661
662     fs_attach(v9p);
663     req = v9fs_twalk(v9p, 0, 1, 1, wnames, 0);
664     v9fs_req_wait_for_reply(req, NULL);
665     v9fs_rwalk(req, NULL, NULL);
666
667     req = v9fs_tlopen(v9p, 1, O_WRONLY, 0);
668     v9fs_req_wait_for_reply(req, NULL);
669     v9fs_rlopen(req, NULL, NULL);
670
671     /* This will cause the write request to complete right away, before it
672      * could be actually cancelled.
673      */
674     should_block = 0;
675     req = v9fs_twrite(v9p, 1, 0, sizeof(should_block), &should_block, 0);
676
677     flush_req = v9fs_tflush(v9p, req->tag, 1);
678
679     /* The write request is supposed to complete. The server should
680      * reply to the write request and the flush request.
681      */
682     v9fs_req_wait_for_reply(req, NULL);
683     v9fs_rwrite(req, &count);
684     g_assert_cmpint(count, ==, sizeof(should_block));
685     v9fs_rflush(flush_req);
686
687     g_free(wnames[0]);
688 }
689
690 typedef void (*v9fs_test_fn)(QVirtIO9P *v9p);
691
692 static void v9fs_run_pci_test(gconstpointer data)
693 {
694     v9fs_test_fn fn = data;
695     QVirtIO9P *v9p = qvirtio_9p_pci_start();
696
697     if (fn) {
698         fn(v9p);
699     }
700     qvirtio_9p_pci_stop(v9p);
701 }
702
703 static void v9fs_qtest_pci_add(const char *path, v9fs_test_fn fn)
704 {
705     qtest_add_data_func(path, fn, v9fs_run_pci_test);
706 }
707
708 int main(int argc, char **argv)
709 {
710     g_test_init(&argc, &argv, NULL);
711     v9fs_qtest_pci_add("/virtio/9p/pci/nop", NULL);
712     v9fs_qtest_pci_add("/virtio/9p/pci/config", pci_config);
713     v9fs_qtest_pci_add("/virtio/9p/pci/fs/version/basic", fs_version);
714     v9fs_qtest_pci_add("/virtio/9p/pci/fs/attach/basic", fs_attach);
715     v9fs_qtest_pci_add("/virtio/9p/pci/fs/walk/basic", fs_walk);
716     v9fs_qtest_pci_add("/virtio/9p/pci/fs/walk/no_slash", fs_walk_no_slash);
717     v9fs_qtest_pci_add("/virtio/9p/pci/fs/walk/dotdot_from_root",
718                        fs_walk_dotdot);
719     v9fs_qtest_pci_add("/virtio/9p/pci/fs/lopen/basic", fs_lopen);
720     v9fs_qtest_pci_add("/virtio/9p/pci/fs/write/basic", fs_write);
721     v9fs_qtest_pci_add("/virtio/9p/pci/fs/flush/success", fs_flush_success);
722     v9fs_qtest_pci_add("/virtio/9p/pci/fs/flush/ignored", fs_flush_ignored);
723
724     return g_test_run();
725 }
This page took 0.065318 seconds and 4 git commands to generate.