master
h 614 lines 20.6 KB
Raw
1 /*
2 * 9P network client for VirtIO 9P test cases (based on QTest)
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 /*
11 * Not so fast! You might want to read the 9p developer docs first:
12 * https://wiki.qemu.org/Documentation/9p
13 */
14
15 #ifndef TESTS_LIBQOS_VIRTIO_9P_CLIENT_H
16 #define TESTS_LIBQOS_VIRTIO_9P_CLIENT_H
17
18 #include "hw/9pfs/9p.h"
19 #include "hw/9pfs/9p-synth.h"
20 #include "virtio-9p.h"
21 #include "qgraph.h"
22 #include "tests/qtest/libqtest-single.h"
23
24 /* Max size of a T-message or R-message */
25 #define P9_MAX_SIZE (32 * 1024)
26
27 typedef struct {
28 QTestState *qts;
29 QVirtio9P *v9p;
30 uint16_t tag;
31 uint64_t t_msg;
32 uint32_t t_size;
33 uint64_t r_msg;
34 /* No r_size, it is hardcoded to P9_MAX_SIZE */
35 size_t t_off;
36 size_t r_off;
37 uint32_t free_head;
38 } P9Req;
39
40 /* type[1] version[4] path[8] */
41 typedef char v9fs_qid[13];
42
43 typedef struct v9fs_attr {
44 uint64_t valid;
45 v9fs_qid qid;
46 uint32_t mode;
47 uint32_t uid;
48 uint32_t gid;
49 uint64_t nlink;
50 uint64_t rdev;
51 uint64_t size;
52 uint64_t blksize;
53 uint64_t blocks;
54 uint64_t atime_sec;
55 uint64_t atime_nsec;
56 uint64_t mtime_sec;
57 uint64_t mtime_nsec;
58 uint64_t ctime_sec;
59 uint64_t ctime_nsec;
60 uint64_t btime_sec;
61 uint64_t btime_nsec;
62 uint64_t gen;
63 uint64_t data_version;
64 } v9fs_attr;
65
66 #define P9_GETATTR_BASIC 0x000007ffULL /* Mask for fields up to BLOCKS */
67 #define P9_GETATTR_ALL 0x00003fffULL /* Mask for ALL fields */
68
69 #define P9_SETATTR_MODE 0x00000001UL
70 #define P9_SETATTR_UID 0x00000002UL
71 #define P9_SETATTR_GID 0x00000004UL
72 #define P9_SETATTR_SIZE 0x00000008UL
73 #define P9_SETATTR_ATIME 0x00000010UL
74 #define P9_SETATTR_MTIME 0x00000020UL
75 #define P9_SETATTR_CTIME 0x00000040UL
76 #define P9_SETATTR_ATIME_SET 0x00000080UL
77 #define P9_SETATTR_MTIME_SET 0x00000100UL
78
79 struct V9fsDirent {
80 v9fs_qid qid;
81 uint64_t offset;
82 uint8_t type;
83 char *name;
84 struct V9fsDirent *next;
85 };
86
87 /* options for 'Twalk' 9p request */
88 typedef struct TWalkOpt {
89 /* 9P client being used (mandatory) */
90 QVirtio9P *client;
91 /* user supplied tag number being returned with response (optional) */
92 uint16_t tag;
93 /* file ID of directory from where walk should start (optional) */
94 uint32_t fid;
95 /* file ID for target directory being walked to (optional) */
96 uint32_t newfid;
97 /* low level variant of path to walk to (optional) */
98 uint16_t nwname;
99 char **wnames;
100 /* high level variant of path to walk to (optional) */
101 const char *path;
102 /* data being received from 9p server as 'Rwalk' response (optional) */
103 struct {
104 uint16_t *nwqid;
105 v9fs_qid **wqid;
106 } rwalk;
107 /* only send Twalk request but not wait for a reply? (optional) */
108 bool requestOnly;
109 /* do we expect an Rlerror response, if yes which error code? (optional) */
110 uint32_t expectErr;
111 } TWalkOpt;
112
113 /* result of 'Twalk' 9p request */
114 typedef struct TWalkRes {
115 /* file ID of target directory been walked to */
116 uint32_t newfid;
117 /* if requestOnly was set: request object for further processing */
118 P9Req *req;
119 } TWalkRes;
120
121 /* options for 'Tversion' 9p request */
122 typedef struct TVersionOpt {
123 /* 9P client being used (mandatory) */
124 QVirtio9P *client;
125 /* user supplied tag number being returned with response (optional) */
126 uint16_t tag;
127 /* maximum message size that can be handled by client (optional) */
128 uint32_t msize;
129 /* protocol version (optional) */
130 const char *version;
131 /* only send Tversion request but not wait for a reply? (optional) */
132 bool requestOnly;
133 /* do we expect an Rlerror response, if yes which error code? (optional) */
134 uint32_t expectErr;
135 } TVersionOpt;
136
137 /* result of 'Tversion' 9p request */
138 typedef struct TVersionRes {
139 /* if requestOnly was set: request object for further processing */
140 P9Req *req;
141 } TVersionRes;
142
143 /* options for 'Tattach' 9p request */
144 typedef struct TAttachOpt {
145 /* 9P client being used (mandatory) */
146 QVirtio9P *client;
147 /* user supplied tag number being returned with response (optional) */
148 uint16_t tag;
149 /* file ID to be associated with root of file tree (optional) */
150 uint32_t fid;
151 /* numerical uid of user being introduced to server (optional) */
152 uint32_t n_uname;
153 /* data being received from 9p server as 'Rattach' response (optional) */
154 struct {
155 /* server's idea of the root of the file tree */
156 v9fs_qid *qid;
157 } rattach;
158 /* only send Tattach request but not wait for a reply? (optional) */
159 bool requestOnly;
160 /* do we expect an Rlerror response, if yes which error code? (optional) */
161 uint32_t expectErr;
162 } TAttachOpt;
163
164 /* result of 'Tattach' 9p request */
165 typedef struct TAttachRes {
166 /* if requestOnly was set: request object for further processing */
167 P9Req *req;
168 } TAttachRes;
169
170 /* options for 'Tgetattr' 9p request */
171 typedef struct TGetAttrOpt {
172 /* 9P client being used (mandatory) */
173 QVirtio9P *client;
174 /* user supplied tag number being returned with response (optional) */
175 uint16_t tag;
176 /* file ID of file/dir whose attributes shall be retrieved (required) */
177 uint32_t fid;
178 /* bitmask indicating attribute fields to be retrieved (optional) */
179 uint64_t request_mask;
180 /* data being received from 9p server as 'Rgetattr' response (optional) */
181 struct {
182 v9fs_attr *attr;
183 } rgetattr;
184 /* only send Tgetattr request but not wait for a reply? (optional) */
185 bool requestOnly;
186 /* do we expect an Rlerror response, if yes which error code? (optional) */
187 uint32_t expectErr;
188 } TGetAttrOpt;
189
190 /* result of 'Tgetattr' 9p request */
191 typedef struct TGetAttrRes {
192 /* if requestOnly was set: request object for further processing */
193 P9Req *req;
194 } TGetAttrRes;
195
196 /* options for 'Tsetattr' 9p request */
197 typedef struct TSetAttrOpt {
198 /* 9P client being used (mandatory) */
199 QVirtio9P *client;
200 /* user supplied tag number being returned with response (optional) */
201 uint16_t tag;
202 /* file ID of file/dir whose attributes shall be modified (required) */
203 uint32_t fid;
204 /* new attribute values to be set by 9p server */
205 v9fs_attr attr;
206 /* only send Tsetattr request but not wait for a reply? (optional) */
207 bool requestOnly;
208 /* do we expect an Rlerror response, if yes which error code? (optional) */
209 uint32_t expectErr;
210 } TSetAttrOpt;
211
212 /* result of 'Tsetattr' 9p request */
213 typedef struct TSetAttrRes {
214 /* if requestOnly was set: request object for further processing */
215 P9Req *req;
216 } TSetAttrRes;
217
218 /* options for 'Treaddir' 9p request */
219 typedef struct TReadDirOpt {
220 /* 9P client being used (mandatory) */
221 QVirtio9P *client;
222 /* user supplied tag number being returned with response (optional) */
223 uint16_t tag;
224 /* file ID of directory whose entries shall be retrieved (required) */
225 uint32_t fid;
226 /* offset in entries stream, i.e. for multiple requests (optional) */
227 uint64_t offset;
228 /* maximum bytes to be returned by server (required) */
229 uint32_t count;
230 /* data being received from 9p server as 'Rreaddir' response (optional) */
231 struct {
232 uint32_t *count;
233 uint32_t *nentries;
234 struct V9fsDirent **entries;
235 } rreaddir;
236 /* only send Treaddir request but not wait for a reply? (optional) */
237 bool requestOnly;
238 /* do we expect an Rlerror response, if yes which error code? (optional) */
239 uint32_t expectErr;
240 } TReadDirOpt;
241
242 /* result of 'Treaddir' 9p request */
243 typedef struct TReadDirRes {
244 /* if requestOnly was set: request object for further processing */
245 P9Req *req;
246 } TReadDirRes;
247
248 /* options for 'Tlopen' 9p request */
249 typedef struct TLOpenOpt {
250 /* 9P client being used (mandatory) */
251 QVirtio9P *client;
252 /* user supplied tag number being returned with response (optional) */
253 uint16_t tag;
254 /* file ID of file / directory to be opened (required) */
255 uint32_t fid;
256 /* Linux open(2) flags such as O_RDONLY, O_RDWR, O_WRONLY (optional) */
257 uint32_t flags;
258 /* data being received from 9p server as 'Rlopen' response (optional) */
259 struct {
260 v9fs_qid *qid;
261 uint32_t *iounit;
262 } rlopen;
263 /* only send Tlopen request but not wait for a reply? (optional) */
264 bool requestOnly;
265 /* do we expect an Rlerror response, if yes which error code? (optional) */
266 uint32_t expectErr;
267 } TLOpenOpt;
268
269 /* result of 'Tlopen' 9p request */
270 typedef struct TLOpenRes {
271 /* if requestOnly was set: request object for further processing */
272 P9Req *req;
273 } TLOpenRes;
274
275 /* options for 'Twrite' 9p request */
276 typedef struct TWriteOpt {
277 /* 9P client being used (mandatory) */
278 QVirtio9P *client;
279 /* user supplied tag number being returned with response (optional) */
280 uint16_t tag;
281 /* file ID of file to write to (required) */
282 uint32_t fid;
283 /* start position of write from beginning of file (optional) */
284 uint64_t offset;
285 /* how many bytes to write */
286 uint32_t count;
287 /* data to be written */
288 const void *data;
289 /* only send Twrite request but not wait for a reply? (optional) */
290 bool requestOnly;
291 /* do we expect an Rlerror response, if yes which error code? (optional) */
292 uint32_t expectErr;
293 } TWriteOpt;
294
295 /* result of 'Twrite' 9p request */
296 typedef struct TWriteRes {
297 /* if requestOnly was set: request object for further processing */
298 P9Req *req;
299 /* amount of bytes written */
300 uint32_t count;
301 } TWriteRes;
302
303 /* options for 'Tflush' 9p request */
304 typedef struct TFlushOpt {
305 /* 9P client being used (mandatory) */
306 QVirtio9P *client;
307 /* user supplied tag number being returned with response (optional) */
308 uint16_t tag;
309 /* message to flush (required) */
310 uint16_t oldtag;
311 /* only send Tflush request but not wait for a reply? (optional) */
312 bool requestOnly;
313 /* do we expect an Rlerror response, if yes which error code? (optional) */
314 uint32_t expectErr;
315 } TFlushOpt;
316
317 /* result of 'Tflush' 9p request */
318 typedef struct TFlushRes {
319 /* if requestOnly was set: request object for further processing */
320 P9Req *req;
321 } TFlushRes;
322
323 /* options for 'Tmkdir' 9p request */
324 typedef struct TMkdirOpt {
325 /* 9P client being used (mandatory) */
326 QVirtio9P *client;
327 /* user supplied tag number being returned with response (optional) */
328 uint16_t tag;
329 /* low level variant of directory where new one shall be created */
330 uint32_t dfid;
331 /* high-level variant of directory where new one shall be created */
332 const char *atPath;
333 /* New directory's name (required) */
334 const char *name;
335 /* Linux mkdir(2) mode bits (optional) */
336 uint32_t mode;
337 /* effective group ID of caller */
338 uint32_t gid;
339 /* data being received from 9p server as 'Rmkdir' response (optional) */
340 struct {
341 /* QID of newly created directory */
342 v9fs_qid *qid;
343 } rmkdir;
344 /* only send Tmkdir request but not wait for a reply? (optional) */
345 bool requestOnly;
346 /* do we expect an Rlerror response, if yes which error code? (optional) */
347 uint32_t expectErr;
348 } TMkdirOpt;
349
350 /* result of 'TMkdir' 9p request */
351 typedef struct TMkdirRes {
352 /* if requestOnly was set: request object for further processing */
353 P9Req *req;
354 } TMkdirRes;
355
356 /* options for 'Tlcreate' 9p request */
357 typedef struct TlcreateOpt {
358 /* 9P client being used (mandatory) */
359 QVirtio9P *client;
360 /* user supplied tag number being returned with response (optional) */
361 uint16_t tag;
362 /* low-level variant of directory where new file shall be created */
363 uint32_t fid;
364 /* high-level variant of directory where new file shall be created */
365 const char *atPath;
366 /* name of new file (required) */
367 const char *name;
368 /* Linux kernel intent bits */
369 uint32_t flags;
370 /* Linux create(2) mode bits */
371 uint32_t mode;
372 /* effective group ID of caller */
373 uint32_t gid;
374 /* data being received from 9p server as 'Rlcreate' response (optional) */
375 struct {
376 v9fs_qid *qid;
377 uint32_t *iounit;
378 } rlcreate;
379 /* only send Tlcreate request but not wait for a reply? (optional) */
380 bool requestOnly;
381 /* do we expect an Rlerror response, if yes which error code? (optional) */
382 uint32_t expectErr;
383 } TlcreateOpt;
384
385 /* result of 'Tlcreate' 9p request */
386 typedef struct TlcreateRes {
387 /* if requestOnly was set: request object for further processing */
388 P9Req *req;
389 } TlcreateRes;
390
391 /* options for 'Tsymlink' 9p request */
392 typedef struct TsymlinkOpt {
393 /* 9P client being used (mandatory) */
394 QVirtio9P *client;
395 /* user supplied tag number being returned with response (optional) */
396 uint16_t tag;
397 /* low-level variant of directory where symlink shall be created */
398 uint32_t fid;
399 /* high-level variant of directory where symlink shall be created */
400 const char *atPath;
401 /* name of symlink (required) */
402 const char *name;
403 /* where symlink will point to (required) */
404 const char *symtgt;
405 /* effective group ID of caller */
406 uint32_t gid;
407 /* data being received from 9p server as 'Rsymlink' response (optional) */
408 struct {
409 v9fs_qid *qid;
410 } rsymlink;
411 /* only send Tsymlink request but not wait for a reply? (optional) */
412 bool requestOnly;
413 /* do we expect an Rlerror response, if yes which error code? (optional) */
414 uint32_t expectErr;
415 } TsymlinkOpt;
416
417 /* result of 'Tsymlink' 9p request */
418 typedef struct TsymlinkRes {
419 /* if requestOnly was set: request object for further processing */
420 P9Req *req;
421 } TsymlinkRes;
422
423 /* options for 'Tlink' 9p request */
424 typedef struct TlinkOpt {
425 /* 9P client being used (mandatory) */
426 QVirtio9P *client;
427 /* user supplied tag number being returned with response (optional) */
428 uint16_t tag;
429 /* low-level variant of directory where hard link shall be created */
430 uint32_t dfid;
431 /* high-level variant of directory where hard link shall be created */
432 const char *atPath;
433 /* low-level variant of target referenced by new hard link */
434 uint32_t fid;
435 /* high-level variant of target referenced by new hard link */
436 const char *toPath;
437 /* name of hard link (required) */
438 const char *name;
439 /* only send Tlink request but not wait for a reply? (optional) */
440 bool requestOnly;
441 /* do we expect an Rlerror response, if yes which error code? (optional) */
442 uint32_t expectErr;
443 } TlinkOpt;
444
445 /* result of 'Tlink' 9p request */
446 typedef struct TlinkRes {
447 /* if requestOnly was set: request object for further processing */
448 P9Req *req;
449 } TlinkRes;
450
451 /* options for 'Tunlinkat' 9p request */
452 typedef struct TunlinkatOpt {
453 /* 9P client being used (mandatory) */
454 QVirtio9P *client;
455 /* user supplied tag number being returned with response (optional) */
456 uint16_t tag;
457 /* low-level variant of directory where name shall be unlinked */
458 uint32_t dirfd;
459 /* high-level variant of directory where name shall be unlinked */
460 const char *atPath;
461 /* name of directory entry to be unlinked (required) */
462 const char *name;
463 /* Linux unlinkat(2) flags */
464 uint32_t flags;
465 /* only send Tunlinkat request but not wait for a reply? (optional) */
466 bool requestOnly;
467 /* do we expect an Rlerror response, if yes which error code? (optional) */
468 uint32_t expectErr;
469 } TunlinkatOpt;
470
471 /* result of 'Tunlinkat' 9p request */
472 typedef struct TunlinkatRes {
473 /* if requestOnly was set: request object for further processing */
474 P9Req *req;
475 } TunlinkatRes;
476
477 /* options for 'Tread' 9p request */
478 typedef struct TReadOpt {
479 /* 9P client being used (mandatory) */
480 QVirtio9P *client;
481 /* user supplied tag number being returned with response (optional) */
482 uint16_t tag;
483 /* file ID of file to read from (required) */
484 uint32_t fid;
485 /* start position of read from beginning of file (optional) */
486 uint64_t offset;
487 /* how many bytes to read (required) */
488 uint32_t count;
489 /* data being received from 9p server as 'Rread' response (optional) */
490 struct {
491 uint32_t *count;
492 void *data;
493 } rread;
494 /* only send Tread request but not wait for a reply? (optional) */
495 bool requestOnly;
496 /* do we expect an Rlerror response, if yes which error code? (optional) */
497 uint32_t expectErr;
498 } TReadOpt;
499
500 /* result of 'Tread' 9p request */
501 typedef struct TReadRes {
502 /* if requestOnly was set: request object for further processing */
503 P9Req *req;
504 /* amount of bytes read */
505 uint32_t count;
506 } TReadRes;
507
508 /* options for 'Tclunk' 9p request */
509 typedef struct TClunkOpt {
510 /* 9P client being used (mandatory) */
511 QVirtio9P *client;
512 /* user supplied tag number being returned with response (optional) */
513 uint16_t tag;
514 /* file ID to clunk (required) */
515 uint32_t fid;
516 /* only send Tclunk request but not wait for a reply? (optional) */
517 bool requestOnly;
518 /* do we expect an Rlerror response, if yes which error code? (optional) */
519 uint32_t expectErr;
520 } TClunkOpt;
521
522 /* result of 'Tclunk' 9p request */
523 typedef struct TClunkRes {
524 /* if requestOnly was set: request object for further processing */
525 P9Req *req;
526 } TClunkRes;
527
528 /* options for 'Txattrcreate' 9p request */
529 typedef struct TXattrCreateOpt {
530 /* 9P client being used (mandatory) */
531 QVirtio9P *client;
532 /* user supplied tag number being returned with response (optional) */
533 uint16_t tag;
534 /* file ID to convert to xattr fid (required) */
535 uint32_t fid;
536 /* name of the xattr (required) */
537 const char *name;
538 /* size of the xattr value (required) */
539 uint64_t size;
540 /* flags: P9_XATTR_CREATE or P9_XATTR_REPLACE (optional) */
541 uint32_t flags;
542 /* only send Txattrcreate request but not wait for a reply? (optional) */
543 bool requestOnly;
544 /* do we expect an Rlerror response, if yes which error code? (optional) */
545 uint32_t expectErr;
546 } TXattrCreateOpt;
547
548 /* result of 'Txattrcreate' 9p request */
549 typedef struct TXattrCreateRes {
550 /* if requestOnly was set: request object for further processing */
551 P9Req *req;
552 /* error code if Rlerror received */
553 uint32_t err;
554 } TXattrCreateRes;
555
556 void v9fs_set_allocator(QGuestAllocator *t_alloc);
557 void v9fs_memwrite(P9Req *req, const void *addr, size_t len);
558 void v9fs_memskip(P9Req *req, size_t len);
559 void v9fs_memread(P9Req *req, void *addr, size_t len);
560 void v9fs_uint8_read(P9Req *req, uint8_t *val);
561 void v9fs_uint16_write(P9Req *req, uint16_t val);
562 void v9fs_uint16_read(P9Req *req, uint16_t *val);
563 void v9fs_uint32_write(P9Req *req, uint32_t val);
564 void v9fs_uint64_write(P9Req *req, uint64_t val);
565 void v9fs_uint32_read(P9Req *req, uint32_t *val);
566 void v9fs_uint64_read(P9Req *req, uint64_t *val);
567 uint16_t v9fs_string_size(const char *string);
568 void v9fs_string_write(P9Req *req, const char *string);
569 void v9fs_string_read(P9Req *req, uint16_t *len, char **string);
570 P9Req *v9fs_req_init(QVirtio9P *v9p, uint32_t size, uint8_t id,
571 uint16_t tag);
572 void v9fs_req_send(P9Req *req);
573 void v9fs_req_wait_for_reply(P9Req *req, uint32_t *len);
574 void v9fs_req_recv(P9Req *req, uint8_t id);
575 void v9fs_req_free(P9Req *req);
576 void v9fs_rlerror(P9Req *req, uint32_t *err);
577 TVersionRes v9fs_tversion(TVersionOpt);
578 void v9fs_rversion(P9Req *req, uint16_t *len, char **version);
579 TAttachRes v9fs_tattach(TAttachOpt);
580 void v9fs_rattach(P9Req *req, v9fs_qid *qid);
581 TWalkRes v9fs_twalk(TWalkOpt opt);
582 void v9fs_rwalk(P9Req *req, uint16_t *nwqid, v9fs_qid **wqid);
583 TGetAttrRes v9fs_tgetattr(TGetAttrOpt);
584 void v9fs_rgetattr(P9Req *req, v9fs_attr *attr);
585 TSetAttrRes v9fs_tsetattr(TSetAttrOpt opt);
586 void v9fs_rsetattr(P9Req *req);
587 TReadDirRes v9fs_treaddir(TReadDirOpt);
588 void v9fs_rreaddir(P9Req *req, uint32_t *count, uint32_t *nentries,
589 struct V9fsDirent **entries);
590 void v9fs_free_dirents(struct V9fsDirent *e);
591 TLOpenRes v9fs_tlopen(TLOpenOpt);
592 void v9fs_rlopen(P9Req *req, v9fs_qid *qid, uint32_t *iounit);
593 TWriteRes v9fs_twrite(TWriteOpt);
594 void v9fs_rwrite(P9Req *req, uint32_t *count);
595 TFlushRes v9fs_tflush(TFlushOpt);
596 void v9fs_rflush(P9Req *req);
597 TMkdirRes v9fs_tmkdir(TMkdirOpt);
598 void v9fs_rmkdir(P9Req *req, v9fs_qid *qid);
599 TlcreateRes v9fs_tlcreate(TlcreateOpt);
600 void v9fs_rlcreate(P9Req *req, v9fs_qid *qid, uint32_t *iounit);
601 TsymlinkRes v9fs_tsymlink(TsymlinkOpt);
602 void v9fs_rsymlink(P9Req *req, v9fs_qid *qid);
603 TlinkRes v9fs_tlink(TlinkOpt);
604 void v9fs_rlink(P9Req *req);
605 TunlinkatRes v9fs_tunlinkat(TunlinkatOpt);
606 void v9fs_runlinkat(P9Req *req);
607 TReadRes v9fs_tread(TReadOpt opt);
608 void v9fs_rread(P9Req *req, uint32_t *count, void *data);
609 TClunkRes v9fs_tclunk(TClunkOpt opt);
610 void v9fs_rclunk(P9Req *req);
611 TXattrCreateRes v9fs_txattrcreate(TXattrCreateOpt opt);
612 void v9fs_rxattrcreate(P9Req *req);
613
614 #endif