qemu/tests/qtest/libqos/virtio-9p-client.h
<<
>>
Prefs
   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
  26typedef 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] */
  40typedef char v9fs_qid[13];
  41
  42typedef 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
  68struct 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 */
  77typedef 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 */
 103typedef 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 */
 111typedef 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 */
 127typedef struct TVersionRes {
 128    /* if requestOnly was set: request object for further processing */
 129    P9Req *req;
 130} TVersionRes;
 131
 132/* options for 'Tattach' 9p request */
 133typedef 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 */
 154typedef struct TAttachRes {
 155    /* if requestOnly was set: request object for further processing */
 156    P9Req *req;
 157} TAttachRes;
 158
 159/* options for 'Tgetattr' 9p request */
 160typedef 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 */
 180typedef struct TGetAttrRes {
 181    /* if requestOnly was set: request object for further processing */
 182    P9Req *req;
 183} TGetAttrRes;
 184
 185/* options for 'Treaddir' 9p request */
 186typedef 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 */
 210typedef struct TReadDirRes {
 211    /* if requestOnly was set: request object for further processing */
 212    P9Req *req;
 213} TReadDirRes;
 214
 215/* options for 'Tlopen' 9p request */
 216typedef 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 */
 237typedef struct TLOpenRes {
 238    /* if requestOnly was set: request object for further processing */
 239    P9Req *req;
 240} TLOpenRes;
 241
 242/* options for 'Twrite' 9p request */
 243typedef 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 */
 263typedef 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 */
 271typedef 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 */
 285typedef struct TFlushRes {
 286    /* if requestOnly was set: request object for further processing */
 287    P9Req *req;
 288} TFlushRes;
 289
 290/* options for 'Tmkdir' 9p request */
 291typedef 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 */
 318typedef struct TMkdirRes {
 319    /* if requestOnly was set: request object for further processing */
 320    P9Req *req;
 321} TMkdirRes;
 322
 323/* options for 'Tlcreate' 9p request */
 324typedef 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 */
 353typedef struct TlcreateRes {
 354    /* if requestOnly was set: request object for further processing */
 355    P9Req *req;
 356} TlcreateRes;
 357
 358/* options for 'Tsymlink' 9p request */
 359typedef 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 */
 385typedef struct TsymlinkRes {
 386    /* if requestOnly was set: request object for further processing */
 387    P9Req *req;
 388} TsymlinkRes;
 389
 390/* options for 'Tlink' 9p request */
 391typedef 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 */
 413typedef struct TlinkRes {
 414    /* if requestOnly was set: request object for further processing */
 415    P9Req *req;
 416} TlinkRes;
 417
 418/* options for 'Tunlinkat' 9p request */
 419typedef 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 */
 439typedef struct TunlinkatRes {
 440    /* if requestOnly was set: request object for further processing */
 441    P9Req *req;
 442} TunlinkatRes;
 443
 444void v9fs_set_allocator(QGuestAllocator *t_alloc);
 445void v9fs_memwrite(P9Req *req, const void *addr, size_t len);
 446void v9fs_memskip(P9Req *req, size_t len);
 447void v9fs_memread(P9Req *req, void *addr, size_t len);
 448void v9fs_uint8_read(P9Req *req, uint8_t *val);
 449void v9fs_uint16_write(P9Req *req, uint16_t val);
 450void v9fs_uint16_read(P9Req *req, uint16_t *val);
 451void v9fs_uint32_write(P9Req *req, uint32_t val);
 452void v9fs_uint64_write(P9Req *req, uint64_t val);
 453void v9fs_uint32_read(P9Req *req, uint32_t *val);
 454void v9fs_uint64_read(P9Req *req, uint64_t *val);
 455uint16_t v9fs_string_size(const char *string);
 456void v9fs_string_write(P9Req *req, const char *string);
 457void v9fs_string_read(P9Req *req, uint16_t *len, char **string);
 458P9Req *v9fs_req_init(QVirtio9P *v9p, uint32_t size, uint8_t id,
 459                     uint16_t tag);
 460void v9fs_req_send(P9Req *req);
 461void v9fs_req_wait_for_reply(P9Req *req, uint32_t *len);
 462void v9fs_req_recv(P9Req *req, uint8_t id);
 463void v9fs_req_free(P9Req *req);
 464void v9fs_rlerror(P9Req *req, uint32_t *err);
 465TVersionRes v9fs_tversion(TVersionOpt);
 466void v9fs_rversion(P9Req *req, uint16_t *len, char **version);
 467TAttachRes v9fs_tattach(TAttachOpt);
 468void v9fs_rattach(P9Req *req, v9fs_qid *qid);
 469TWalkRes v9fs_twalk(TWalkOpt opt);
 470void v9fs_rwalk(P9Req *req, uint16_t *nwqid, v9fs_qid **wqid);
 471TGetAttrRes v9fs_tgetattr(TGetAttrOpt);
 472void v9fs_rgetattr(P9Req *req, v9fs_attr *attr);
 473TReadDirRes v9fs_treaddir(TReadDirOpt);
 474void v9fs_rreaddir(P9Req *req, uint32_t *count, uint32_t *nentries,
 475                   struct V9fsDirent **entries);
 476void v9fs_free_dirents(struct V9fsDirent *e);
 477TLOpenRes v9fs_tlopen(TLOpenOpt);
 478void v9fs_rlopen(P9Req *req, v9fs_qid *qid, uint32_t *iounit);
 479TWriteRes v9fs_twrite(TWriteOpt);
 480void v9fs_rwrite(P9Req *req, uint32_t *count);
 481TFlushRes v9fs_tflush(TFlushOpt);
 482void v9fs_rflush(P9Req *req);
 483TMkdirRes v9fs_tmkdir(TMkdirOpt);
 484void v9fs_rmkdir(P9Req *req, v9fs_qid *qid);
 485TlcreateRes v9fs_tlcreate(TlcreateOpt);
 486void v9fs_rlcreate(P9Req *req, v9fs_qid *qid, uint32_t *iounit);
 487TsymlinkRes v9fs_tsymlink(TsymlinkOpt);
 488void v9fs_rsymlink(P9Req *req, v9fs_qid *qid);
 489TlinkRes v9fs_tlink(TlinkOpt);
 490void v9fs_rlink(P9Req *req);
 491TunlinkatRes v9fs_tunlinkat(TunlinkatOpt);
 492void v9fs_runlinkat(P9Req *req);
 493
 494#endif
 495