qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

virtio-9p-client.h (16869B)


      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 #define P9_MAX_SIZE 4096 /* Max size of a T-message or R-message */
     25 
     26 typedef struct {
     27     QTestState *qts;
     28     QVirtio9P *v9p;
     29     uint16_t tag;
     30     uint64_t t_msg;
     31     uint32_t t_size;
     32     uint64_t r_msg;
     33     /* No r_size, it is hardcoded to P9_MAX_SIZE */
     34     size_t t_off;
     35     size_t r_off;
     36     uint32_t free_head;
     37 } P9Req;
     38 
     39 /* type[1] version[4] path[8] */
     40 typedef char v9fs_qid[13];
     41 
     42 typedef struct v9fs_attr {
     43     uint64_t valid;
     44     v9fs_qid qid;
     45     uint32_t mode;
     46     uint32_t uid;
     47     uint32_t gid;
     48     uint64_t nlink;
     49     uint64_t rdev;
     50     uint64_t size;
     51     uint64_t blksize;
     52     uint64_t blocks;
     53     uint64_t atime_sec;
     54     uint64_t atime_nsec;
     55     uint64_t mtime_sec;
     56     uint64_t mtime_nsec;
     57     uint64_t ctime_sec;
     58     uint64_t ctime_nsec;
     59     uint64_t btime_sec;
     60     uint64_t btime_nsec;
     61     uint64_t gen;
     62     uint64_t data_version;
     63 } v9fs_attr;
     64 
     65 #define P9_GETATTR_BASIC    0x000007ffULL /* Mask for fields up to BLOCKS */
     66 #define P9_GETATTR_ALL      0x00003fffULL /* Mask for ALL fields */
     67 
     68 struct V9fsDirent {
     69     v9fs_qid qid;
     70     uint64_t offset;
     71     uint8_t type;
     72     char *name;
     73     struct V9fsDirent *next;
     74 };
     75 
     76 /* options for 'Twalk' 9p request */
     77 typedef struct TWalkOpt {
     78     /* 9P client being used (mandatory) */
     79     QVirtio9P *client;
     80     /* user supplied tag number being returned with response (optional) */
     81     uint16_t tag;
     82     /* file ID of directory from where walk should start (optional) */
     83     uint32_t fid;
     84     /* file ID for target directory being walked to (optional) */
     85     uint32_t newfid;
     86     /* low level variant of path to walk to (optional) */
     87     uint16_t nwname;
     88     char **wnames;
     89     /* high level variant of path to walk to (optional) */
     90     const char *path;
     91     /* data being received from 9p server as 'Rwalk' response (optional) */
     92     struct {
     93         uint16_t *nwqid;
     94         v9fs_qid **wqid;
     95     } rwalk;
     96     /* only send Twalk request but not wait for a reply? (optional) */
     97     bool requestOnly;
     98     /* do we expect an Rlerror response, if yes which error code? (optional) */
     99     uint32_t expectErr;
    100 } TWalkOpt;
    101 
    102 /* result of 'Twalk' 9p request */
    103 typedef struct TWalkRes {
    104     /* file ID of target directory been walked to */
    105     uint32_t newfid;
    106     /* if requestOnly was set: request object for further processing */
    107     P9Req *req;
    108 } TWalkRes;
    109 
    110 /* options for 'Tversion' 9p request */
    111 typedef struct TVersionOpt {
    112     /* 9P client being used (mandatory) */
    113     QVirtio9P *client;
    114     /* user supplied tag number being returned with response (optional) */
    115     uint16_t tag;
    116     /* maximum message size that can be handled by client (optional) */
    117     uint32_t msize;
    118     /* protocol version (optional) */
    119     const char *version;
    120     /* only send Tversion request but not wait for a reply? (optional) */
    121     bool requestOnly;
    122     /* do we expect an Rlerror response, if yes which error code? (optional) */
    123     uint32_t expectErr;
    124 } TVersionOpt;
    125 
    126 /* result of 'Tversion' 9p request */
    127 typedef struct TVersionRes {
    128     /* if requestOnly was set: request object for further processing */
    129     P9Req *req;
    130 } TVersionRes;
    131 
    132 /* options for 'Tattach' 9p request */
    133 typedef struct TAttachOpt {
    134     /* 9P client being used (mandatory) */
    135     QVirtio9P *client;
    136     /* user supplied tag number being returned with response (optional) */
    137     uint16_t tag;
    138     /* file ID to be associated with root of file tree (optional) */
    139     uint32_t fid;
    140     /* numerical uid of user being introduced to server (optional) */
    141     uint32_t n_uname;
    142     /* data being received from 9p server as 'Rattach' response (optional) */
    143     struct {
    144         /* server's idea of the root of the file tree */
    145         v9fs_qid *qid;
    146     } rattach;
    147     /* only send Tattach request but not wait for a reply? (optional) */
    148     bool requestOnly;
    149     /* do we expect an Rlerror response, if yes which error code? (optional) */
    150     uint32_t expectErr;
    151 } TAttachOpt;
    152 
    153 /* result of 'Tattach' 9p request */
    154 typedef struct TAttachRes {
    155     /* if requestOnly was set: request object for further processing */
    156     P9Req *req;
    157 } TAttachRes;
    158 
    159 /* options for 'Tgetattr' 9p request */
    160 typedef struct TGetAttrOpt {
    161     /* 9P client being used (mandatory) */
    162     QVirtio9P *client;
    163     /* user supplied tag number being returned with response (optional) */
    164     uint16_t tag;
    165     /* file ID of file/dir whose attributes shall be retrieved (required) */
    166     uint32_t fid;
    167     /* bitmask indicating attribute fields to be retrieved (optional) */
    168     uint64_t request_mask;
    169     /* data being received from 9p server as 'Rgetattr' response (optional) */
    170     struct {
    171         v9fs_attr *attr;
    172     } rgetattr;
    173     /* only send Tgetattr request but not wait for a reply? (optional) */
    174     bool requestOnly;
    175     /* do we expect an Rlerror response, if yes which error code? (optional) */
    176     uint32_t expectErr;
    177 } TGetAttrOpt;
    178 
    179 /* result of 'Tgetattr' 9p request */
    180 typedef struct TGetAttrRes {
    181     /* if requestOnly was set: request object for further processing */
    182     P9Req *req;
    183 } TGetAttrRes;
    184 
    185 /* options for 'Treaddir' 9p request */
    186 typedef struct TReadDirOpt {
    187     /* 9P client being used (mandatory) */
    188     QVirtio9P *client;
    189     /* user supplied tag number being returned with response (optional) */
    190     uint16_t tag;
    191     /* file ID of directory whose entries shall be retrieved (required) */
    192     uint32_t fid;
    193     /* offset in entries stream, i.e. for multiple requests (optional) */
    194     uint64_t offset;
    195     /* maximum bytes to be returned by server (required) */
    196     uint32_t count;
    197     /* data being received from 9p server as 'Rreaddir' response (optional) */
    198     struct {
    199         uint32_t *count;
    200         uint32_t *nentries;
    201         struct V9fsDirent **entries;
    202     } rreaddir;
    203     /* only send Treaddir request but not wait for a reply? (optional) */
    204     bool requestOnly;
    205     /* do we expect an Rlerror response, if yes which error code? (optional) */
    206     uint32_t expectErr;
    207 } TReadDirOpt;
    208 
    209 /* result of 'Treaddir' 9p request */
    210 typedef struct TReadDirRes {
    211     /* if requestOnly was set: request object for further processing */
    212     P9Req *req;
    213 } TReadDirRes;
    214 
    215 /* options for 'Tlopen' 9p request */
    216 typedef struct TLOpenOpt {
    217     /* 9P client being used (mandatory) */
    218     QVirtio9P *client;
    219     /* user supplied tag number being returned with response (optional) */
    220     uint16_t tag;
    221     /* file ID of file / directory to be opened (required) */
    222     uint32_t fid;
    223     /* Linux open(2) flags such as O_RDONLY, O_RDWR, O_WRONLY (optional) */
    224     uint32_t flags;
    225     /* data being received from 9p server as 'Rlopen' response (optional) */
    226     struct {
    227         v9fs_qid *qid;
    228         uint32_t *iounit;
    229     } rlopen;
    230     /* only send Tlopen request but not wait for a reply? (optional) */
    231     bool requestOnly;
    232     /* do we expect an Rlerror response, if yes which error code? (optional) */
    233     uint32_t expectErr;
    234 } TLOpenOpt;
    235 
    236 /* result of 'Tlopen' 9p request */
    237 typedef struct TLOpenRes {
    238     /* if requestOnly was set: request object for further processing */
    239     P9Req *req;
    240 } TLOpenRes;
    241 
    242 /* options for 'Twrite' 9p request */
    243 typedef struct TWriteOpt {
    244     /* 9P client being used (mandatory) */
    245     QVirtio9P *client;
    246     /* user supplied tag number being returned with response (optional) */
    247     uint16_t tag;
    248     /* file ID of file to write to (required) */
    249     uint32_t fid;
    250     /* start position of write from beginning of file (optional) */
    251     uint64_t offset;
    252     /* how many bytes to write */
    253     uint32_t count;
    254     /* data to be written */
    255     const void *data;
    256     /* only send Twrite request but not wait for a reply? (optional) */
    257     bool requestOnly;
    258     /* do we expect an Rlerror response, if yes which error code? (optional) */
    259     uint32_t expectErr;
    260 } TWriteOpt;
    261 
    262 /* result of 'Twrite' 9p request */
    263 typedef struct TWriteRes {
    264     /* if requestOnly was set: request object for further processing */
    265     P9Req *req;
    266     /* amount of bytes written */
    267     uint32_t count;
    268 } TWriteRes;
    269 
    270 /* options for 'Tflush' 9p request */
    271 typedef struct TFlushOpt {
    272     /* 9P client being used (mandatory) */
    273     QVirtio9P *client;
    274     /* user supplied tag number being returned with response (optional) */
    275     uint16_t tag;
    276     /* message to flush (required) */
    277     uint16_t oldtag;
    278     /* only send Tflush request but not wait for a reply? (optional) */
    279     bool requestOnly;
    280     /* do we expect an Rlerror response, if yes which error code? (optional) */
    281     uint32_t expectErr;
    282 } TFlushOpt;
    283 
    284 /* result of 'Tflush' 9p request */
    285 typedef struct TFlushRes {
    286     /* if requestOnly was set: request object for further processing */
    287     P9Req *req;
    288 } TFlushRes;
    289 
    290 /* options for 'Tmkdir' 9p request */
    291 typedef struct TMkdirOpt {
    292     /* 9P client being used (mandatory) */
    293     QVirtio9P *client;
    294     /* user supplied tag number being returned with response (optional) */
    295     uint16_t tag;
    296     /* low level variant of directory where new one shall be created */
    297     uint32_t dfid;
    298     /* high-level variant of directory where new one shall be created */
    299     const char *atPath;
    300     /* New directory's name (required) */
    301     const char *name;
    302     /* Linux mkdir(2) mode bits (optional) */
    303     uint32_t mode;
    304     /* effective group ID of caller */
    305     uint32_t gid;
    306     /* data being received from 9p server as 'Rmkdir' response (optional) */
    307     struct {
    308         /* QID of newly created directory */
    309         v9fs_qid *qid;
    310     } rmkdir;
    311     /* only send Tmkdir 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 } TMkdirOpt;
    316 
    317 /* result of 'TMkdir' 9p request */
    318 typedef struct TMkdirRes {
    319     /* if requestOnly was set: request object for further processing */
    320     P9Req *req;
    321 } TMkdirRes;
    322 
    323 /* options for 'Tlcreate' 9p request */
    324 typedef struct TlcreateOpt {
    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 file shall be created */
    330     uint32_t fid;
    331     /* high-level variant of directory where new file shall be created */
    332     const char *atPath;
    333     /* name of new file (required) */
    334     const char *name;
    335     /* Linux kernel intent bits */
    336     uint32_t flags;
    337     /* Linux create(2) mode bits */
    338     uint32_t mode;
    339     /* effective group ID of caller */
    340     uint32_t gid;
    341     /* data being received from 9p server as 'Rlcreate' response (optional) */
    342     struct {
    343         v9fs_qid *qid;
    344         uint32_t *iounit;
    345     } rlcreate;
    346     /* only send Tlcreate request but not wait for a reply? (optional) */
    347     bool requestOnly;
    348     /* do we expect an Rlerror response, if yes which error code? (optional) */
    349     uint32_t expectErr;
    350 } TlcreateOpt;
    351 
    352 /* result of 'Tlcreate' 9p request */
    353 typedef struct TlcreateRes {
    354     /* if requestOnly was set: request object for further processing */
    355     P9Req *req;
    356 } TlcreateRes;
    357 
    358 /* options for 'Tsymlink' 9p request */
    359 typedef struct TsymlinkOpt {
    360     /* 9P client being used (mandatory) */
    361     QVirtio9P *client;
    362     /* user supplied tag number being returned with response (optional) */
    363     uint16_t tag;
    364     /* low-level variant of directory where symlink shall be created */
    365     uint32_t fid;
    366     /* high-level variant of directory where symlink shall be created */
    367     const char *atPath;
    368     /* name of symlink (required) */
    369     const char *name;
    370     /* where symlink will point to (required) */
    371     const char *symtgt;
    372     /* effective group ID of caller */
    373     uint32_t gid;
    374     /* data being received from 9p server as 'Rsymlink' response (optional) */
    375     struct {
    376         v9fs_qid *qid;
    377     } rsymlink;
    378     /* only send Tsymlink request but not wait for a reply? (optional) */
    379     bool requestOnly;
    380     /* do we expect an Rlerror response, if yes which error code? (optional) */
    381     uint32_t expectErr;
    382 } TsymlinkOpt;
    383 
    384 /* result of 'Tsymlink' 9p request */
    385 typedef struct TsymlinkRes {
    386     /* if requestOnly was set: request object for further processing */
    387     P9Req *req;
    388 } TsymlinkRes;
    389 
    390 /* options for 'Tlink' 9p request */
    391 typedef struct TlinkOpt {
    392     /* 9P client being used (mandatory) */
    393     QVirtio9P *client;
    394     /* user supplied tag number being returned with response (optional) */
    395     uint16_t tag;
    396     /* low-level variant of directory where hard link shall be created */
    397     uint32_t dfid;
    398     /* high-level variant of directory where hard link shall be created */
    399     const char *atPath;
    400     /* low-level variant of target referenced by new hard link */
    401     uint32_t fid;
    402     /* high-level variant of target referenced by new hard link */
    403     const char *toPath;
    404     /* name of hard link (required) */
    405     const char *name;
    406     /* only send Tlink request but not wait for a reply? (optional) */
    407     bool requestOnly;
    408     /* do we expect an Rlerror response, if yes which error code? (optional) */
    409     uint32_t expectErr;
    410 } TlinkOpt;
    411 
    412 /* result of 'Tlink' 9p request */
    413 typedef struct TlinkRes {
    414     /* if requestOnly was set: request object for further processing */
    415     P9Req *req;
    416 } TlinkRes;
    417 
    418 /* options for 'Tunlinkat' 9p request */
    419 typedef struct TunlinkatOpt {
    420     /* 9P client being used (mandatory) */
    421     QVirtio9P *client;
    422     /* user supplied tag number being returned with response (optional) */
    423     uint16_t tag;
    424     /* low-level variant of directory where name shall be unlinked */
    425     uint32_t dirfd;
    426     /* high-level variant of directory where name shall be unlinked */
    427     const char *atPath;
    428     /* name of directory entry to be unlinked (required) */
    429     const char *name;
    430     /* Linux unlinkat(2) flags */
    431     uint32_t flags;
    432     /* only send Tunlinkat request but not wait for a reply? (optional) */
    433     bool requestOnly;
    434     /* do we expect an Rlerror response, if yes which error code? (optional) */
    435     uint32_t expectErr;
    436 } TunlinkatOpt;
    437 
    438 /* result of 'Tunlinkat' 9p request */
    439 typedef struct TunlinkatRes {
    440     /* if requestOnly was set: request object for further processing */
    441     P9Req *req;
    442 } TunlinkatRes;
    443 
    444 void v9fs_set_allocator(QGuestAllocator *t_alloc);
    445 void v9fs_memwrite(P9Req *req, const void *addr, size_t len);
    446 void v9fs_memskip(P9Req *req, size_t len);
    447 void v9fs_memread(P9Req *req, void *addr, size_t len);
    448 void v9fs_uint8_read(P9Req *req, uint8_t *val);
    449 void v9fs_uint16_write(P9Req *req, uint16_t val);
    450 void v9fs_uint16_read(P9Req *req, uint16_t *val);
    451 void v9fs_uint32_write(P9Req *req, uint32_t val);
    452 void v9fs_uint64_write(P9Req *req, uint64_t val);
    453 void v9fs_uint32_read(P9Req *req, uint32_t *val);
    454 void v9fs_uint64_read(P9Req *req, uint64_t *val);
    455 uint16_t v9fs_string_size(const char *string);
    456 void v9fs_string_write(P9Req *req, const char *string);
    457 void v9fs_string_read(P9Req *req, uint16_t *len, char **string);
    458 P9Req *v9fs_req_init(QVirtio9P *v9p, uint32_t size, uint8_t id,
    459                      uint16_t tag);
    460 void v9fs_req_send(P9Req *req);
    461 void v9fs_req_wait_for_reply(P9Req *req, uint32_t *len);
    462 void v9fs_req_recv(P9Req *req, uint8_t id);
    463 void v9fs_req_free(P9Req *req);
    464 void v9fs_rlerror(P9Req *req, uint32_t *err);
    465 TVersionRes v9fs_tversion(TVersionOpt);
    466 void v9fs_rversion(P9Req *req, uint16_t *len, char **version);
    467 TAttachRes v9fs_tattach(TAttachOpt);
    468 void v9fs_rattach(P9Req *req, v9fs_qid *qid);
    469 TWalkRes v9fs_twalk(TWalkOpt opt);
    470 void v9fs_rwalk(P9Req *req, uint16_t *nwqid, v9fs_qid **wqid);
    471 TGetAttrRes v9fs_tgetattr(TGetAttrOpt);
    472 void v9fs_rgetattr(P9Req *req, v9fs_attr *attr);
    473 TReadDirRes v9fs_treaddir(TReadDirOpt);
    474 void v9fs_rreaddir(P9Req *req, uint32_t *count, uint32_t *nentries,
    475                    struct V9fsDirent **entries);
    476 void v9fs_free_dirents(struct V9fsDirent *e);
    477 TLOpenRes v9fs_tlopen(TLOpenOpt);
    478 void v9fs_rlopen(P9Req *req, v9fs_qid *qid, uint32_t *iounit);
    479 TWriteRes v9fs_twrite(TWriteOpt);
    480 void v9fs_rwrite(P9Req *req, uint32_t *count);
    481 TFlushRes v9fs_tflush(TFlushOpt);
    482 void v9fs_rflush(P9Req *req);
    483 TMkdirRes v9fs_tmkdir(TMkdirOpt);
    484 void v9fs_rmkdir(P9Req *req, v9fs_qid *qid);
    485 TlcreateRes v9fs_tlcreate(TlcreateOpt);
    486 void v9fs_rlcreate(P9Req *req, v9fs_qid *qid, uint32_t *iounit);
    487 TsymlinkRes v9fs_tsymlink(TsymlinkOpt);
    488 void v9fs_rsymlink(P9Req *req, v9fs_qid *qid);
    489 TlinkRes v9fs_tlink(TlinkOpt);
    490 void v9fs_rlink(P9Req *req);
    491 TunlinkatRes v9fs_tunlinkat(TunlinkatOpt);
    492 void v9fs_runlinkat(P9Req *req);
    493 
    494 #endif