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 void v9fs_set_allocator(QGuestAllocator *t_alloc); 186 void v9fs_memwrite(P9Req *req, const void *addr, size_t len); 187 void v9fs_memskip(P9Req *req, size_t len); 188 void v9fs_memread(P9Req *req, void *addr, size_t len); 189 void v9fs_uint8_read(P9Req *req, uint8_t *val); 190 void v9fs_uint16_write(P9Req *req, uint16_t val); 191 void v9fs_uint16_read(P9Req *req, uint16_t *val); 192 void v9fs_uint32_write(P9Req *req, uint32_t val); 193 void v9fs_uint64_write(P9Req *req, uint64_t val); 194 void v9fs_uint32_read(P9Req *req, uint32_t *val); 195 void v9fs_uint64_read(P9Req *req, uint64_t *val); 196 uint16_t v9fs_string_size(const char *string); 197 void v9fs_string_write(P9Req *req, const char *string); 198 void v9fs_string_read(P9Req *req, uint16_t *len, char **string); 199 P9Req *v9fs_req_init(QVirtio9P *v9p, uint32_t size, uint8_t id, 200 uint16_t tag); 201 void v9fs_req_send(P9Req *req); 202 void v9fs_req_wait_for_reply(P9Req *req, uint32_t *len); 203 void v9fs_req_recv(P9Req *req, uint8_t id); 204 void v9fs_req_free(P9Req *req); 205 void v9fs_rlerror(P9Req *req, uint32_t *err); 206 TVersionRes v9fs_tversion(TVersionOpt); 207 void v9fs_rversion(P9Req *req, uint16_t *len, char **version); 208 TAttachRes v9fs_tattach(TAttachOpt); 209 void v9fs_rattach(P9Req *req, v9fs_qid *qid); 210 TWalkRes v9fs_twalk(TWalkOpt opt); 211 void v9fs_rwalk(P9Req *req, uint16_t *nwqid, v9fs_qid **wqid); 212 TGetAttrRes v9fs_tgetattr(TGetAttrOpt); 213 void v9fs_rgetattr(P9Req *req, v9fs_attr *attr); 214 P9Req *v9fs_treaddir(QVirtio9P *v9p, uint32_t fid, uint64_t offset, 215 uint32_t count, uint16_t tag); 216 void v9fs_rreaddir(P9Req *req, uint32_t *count, uint32_t *nentries, 217 struct V9fsDirent **entries); 218 void v9fs_free_dirents(struct V9fsDirent *e); 219 P9Req *v9fs_tlopen(QVirtio9P *v9p, uint32_t fid, uint32_t flags, 220 uint16_t tag); 221 void v9fs_rlopen(P9Req *req, v9fs_qid *qid, uint32_t *iounit); 222 P9Req *v9fs_twrite(QVirtio9P *v9p, uint32_t fid, uint64_t offset, 223 uint32_t count, const void *data, uint16_t tag); 224 void v9fs_rwrite(P9Req *req, uint32_t *count); 225 P9Req *v9fs_tflush(QVirtio9P *v9p, uint16_t oldtag, uint16_t tag); 226 void v9fs_rflush(P9Req *req); 227 P9Req *v9fs_tmkdir(QVirtio9P *v9p, uint32_t dfid, const char *name, 228 uint32_t mode, uint32_t gid, uint16_t tag); 229 void v9fs_rmkdir(P9Req *req, v9fs_qid *qid); 230 P9Req *v9fs_tlcreate(QVirtio9P *v9p, uint32_t fid, const char *name, 231 uint32_t flags, uint32_t mode, uint32_t gid, 232 uint16_t tag); 233 void v9fs_rlcreate(P9Req *req, v9fs_qid *qid, uint32_t *iounit); 234 P9Req *v9fs_tsymlink(QVirtio9P *v9p, uint32_t fid, const char *name, 235 const char *symtgt, uint32_t gid, uint16_t tag); 236 void v9fs_rsymlink(P9Req *req, v9fs_qid *qid); 237 P9Req *v9fs_tlink(QVirtio9P *v9p, uint32_t dfid, uint32_t fid, 238 const char *name, uint16_t tag); 239 void v9fs_rlink(P9Req *req); 240 P9Req *v9fs_tunlinkat(QVirtio9P *v9p, uint32_t dirfd, const char *name, 241 uint32_t flags, uint16_t tag); 242 void v9fs_runlinkat(P9Req *req); 243 244 #endif 245