1 #ifndef _QEMU_VIRTIO_9P_H 2 #define _QEMU_VIRTIO_9P_H 3 4 #include <sys/types.h> 5 #include <dirent.h> 6 #include <sys/time.h> 7 #include <utime.h> 8 #include <sys/resource.h> 9 #include "hw/virtio/virtio.h" 10 #include "fsdev/file-op-9p.h" 11 #include "fsdev/virtio-9p-marshal.h" 12 #include "qemu/thread.h" 13 #include "block/coroutine.h" 14 15 16 /* The feature bitmap for virtio 9P */ 17 /* The mount point is specified in a config variable */ 18 #define VIRTIO_9P_MOUNT_TAG 0 19 20 enum { 21 P9_TLERROR = 6, 22 P9_RLERROR, 23 P9_TSTATFS = 8, 24 P9_RSTATFS, 25 P9_TLOPEN = 12, 26 P9_RLOPEN, 27 P9_TLCREATE = 14, 28 P9_RLCREATE, 29 P9_TSYMLINK = 16, 30 P9_RSYMLINK, 31 P9_TMKNOD = 18, 32 P9_RMKNOD, 33 P9_TRENAME = 20, 34 P9_RRENAME, 35 P9_TREADLINK = 22, 36 P9_RREADLINK, 37 P9_TGETATTR = 24, 38 P9_RGETATTR, 39 P9_TSETATTR = 26, 40 P9_RSETATTR, 41 P9_TXATTRWALK = 30, 42 P9_RXATTRWALK, 43 P9_TXATTRCREATE = 32, 44 P9_RXATTRCREATE, 45 P9_TREADDIR = 40, 46 P9_RREADDIR, 47 P9_TFSYNC = 50, 48 P9_RFSYNC, 49 P9_TLOCK = 52, 50 P9_RLOCK, 51 P9_TGETLOCK = 54, 52 P9_RGETLOCK, 53 P9_TLINK = 70, 54 P9_RLINK, 55 P9_TMKDIR = 72, 56 P9_RMKDIR, 57 P9_TRENAMEAT = 74, 58 P9_RRENAMEAT, 59 P9_TUNLINKAT = 76, 60 P9_RUNLINKAT, 61 P9_TVERSION = 100, 62 P9_RVERSION, 63 P9_TAUTH = 102, 64 P9_RAUTH, 65 P9_TATTACH = 104, 66 P9_RATTACH, 67 P9_TERROR = 106, 68 P9_RERROR, 69 P9_TFLUSH = 108, 70 P9_RFLUSH, 71 P9_TWALK = 110, 72 P9_RWALK, 73 P9_TOPEN = 112, 74 P9_ROPEN, 75 P9_TCREATE = 114, 76 P9_RCREATE, 77 P9_TREAD = 116, 78 P9_RREAD, 79 P9_TWRITE = 118, 80 P9_RWRITE, 81 P9_TCLUNK = 120, 82 P9_RCLUNK, 83 P9_TREMOVE = 122, 84 P9_RREMOVE, 85 P9_TSTAT = 124, 86 P9_RSTAT, 87 P9_TWSTAT = 126, 88 P9_RWSTAT, 89 }; 90 91 92 /* qid.types */ 93 enum { 94 P9_QTDIR = 0x80, 95 P9_QTAPPEND = 0x40, 96 P9_QTEXCL = 0x20, 97 P9_QTMOUNT = 0x10, 98 P9_QTAUTH = 0x08, 99 P9_QTTMP = 0x04, 100 P9_QTSYMLINK = 0x02, 101 P9_QTLINK = 0x01, 102 P9_QTFILE = 0x00, 103 }; 104 105 enum p9_proto_version { 106 V9FS_PROTO_2000U = 0x01, 107 V9FS_PROTO_2000L = 0x02, 108 }; 109 110 #define P9_NOTAG (u16)(~0) 111 #define P9_NOFID (u32)(~0) 112 #define P9_MAXWELEM 16 113 114 #define FID_REFERENCED 0x1 115 #define FID_NON_RECLAIMABLE 0x2 116 static inline const char *rpath(FsContext *ctx, const char *path, char *buffer) 117 { 118 snprintf(buffer, PATH_MAX, "%s/%s", ctx->fs_root, path); 119 return buffer; 120 } 121 122 /* 123 * ample room for Twrite/Rread header 124 * size[4] Tread/Twrite tag[2] fid[4] offset[8] count[4] 125 */ 126 #define P9_IOHDRSZ 24 127 128 typedef struct V9fsPDU V9fsPDU; 129 struct V9fsState; 130 131 struct V9fsPDU 132 { 133 uint32_t size; 134 uint16_t tag; 135 uint8_t id; 136 uint8_t cancelled; 137 CoQueue complete; 138 VirtQueueElement elem; 139 struct V9fsState *s; 140 QLIST_ENTRY(V9fsPDU) next; 141 }; 142 143 144 /* FIXME 145 * 1) change user needs to set groups and stuff 146 */ 147 148 /* from Linux's linux/virtio_9p.h */ 149 150 /* The ID for virtio console */ 151 #define VIRTIO_ID_9P 9 152 #define MAX_REQ 128 153 #define MAX_TAG_LEN 32 154 155 #define BUG_ON(cond) assert(!(cond)) 156 157 typedef struct V9fsFidState V9fsFidState; 158 159 enum { 160 P9_FID_NONE = 0, 161 P9_FID_FILE, 162 P9_FID_DIR, 163 P9_FID_XATTR, 164 }; 165 166 typedef struct V9fsXattr 167 { 168 int64_t copied_len; 169 int64_t len; 170 void *value; 171 V9fsString name; 172 int flags; 173 } V9fsXattr; 174 175 /* 176 * Filled by fs driver on open and other 177 * calls. 178 */ 179 union V9fsFidOpenState { 180 int fd; 181 DIR *dir; 182 V9fsXattr xattr; 183 /* 184 * private pointer for fs drivers, that 185 * have its own internal representation of 186 * open files. 187 */ 188 void *private; 189 }; 190 191 struct V9fsFidState 192 { 193 int fid_type; 194 int32_t fid; 195 V9fsPath path; 196 V9fsFidOpenState fs; 197 V9fsFidOpenState fs_reclaim; 198 int flags; 199 int open_flags; 200 uid_t uid; 201 int ref; 202 int clunked; 203 V9fsFidState *next; 204 V9fsFidState *rclm_lst; 205 }; 206 207 typedef struct V9fsState 208 { 209 VirtIODevice vdev; 210 VirtQueue *vq; 211 V9fsPDU pdus[MAX_REQ]; 212 QLIST_HEAD(, V9fsPDU) free_list; 213 QLIST_HEAD(, V9fsPDU) active_list; 214 V9fsFidState *fid_list; 215 FileOperations *ops; 216 FsContext ctx; 217 char *tag; 218 size_t config_size; 219 enum p9_proto_version proto_version; 220 int32_t msize; 221 /* 222 * lock ensuring atomic path update 223 * on rename. 224 */ 225 CoRwlock rename_lock; 226 int32_t root_fid; 227 Error *migration_blocker; 228 } V9fsState; 229 230 typedef struct V9fsStatState { 231 V9fsPDU *pdu; 232 size_t offset; 233 V9fsStat v9stat; 234 V9fsFidState *fidp; 235 struct stat stbuf; 236 } V9fsStatState; 237 238 typedef struct V9fsOpenState { 239 V9fsPDU *pdu; 240 size_t offset; 241 int32_t mode; 242 V9fsFidState *fidp; 243 V9fsQID qid; 244 struct stat stbuf; 245 int iounit; 246 } V9fsOpenState; 247 248 typedef struct V9fsReadState { 249 V9fsPDU *pdu; 250 size_t offset; 251 int32_t count; 252 int32_t total; 253 int64_t off; 254 V9fsFidState *fidp; 255 struct iovec iov[128]; /* FIXME: bad, bad, bad */ 256 struct iovec *sg; 257 off_t dir_pos; 258 struct dirent *dent; 259 struct stat stbuf; 260 V9fsString name; 261 V9fsStat v9stat; 262 int32_t len; 263 int32_t cnt; 264 int32_t max_count; 265 } V9fsReadState; 266 267 typedef struct V9fsWriteState { 268 V9fsPDU *pdu; 269 size_t offset; 270 int32_t len; 271 int32_t count; 272 int32_t total; 273 int64_t off; 274 V9fsFidState *fidp; 275 struct iovec iov[128]; /* FIXME: bad, bad, bad */ 276 struct iovec *sg; 277 int cnt; 278 } V9fsWriteState; 279 280 struct virtio_9p_config 281 { 282 /* number of characters in tag */ 283 uint16_t tag_len; 284 /* Variable size tag name */ 285 uint8_t tag[0]; 286 } QEMU_PACKED; 287 288 typedef struct V9fsMkState { 289 V9fsPDU *pdu; 290 size_t offset; 291 V9fsQID qid; 292 struct stat stbuf; 293 V9fsString name; 294 V9fsString fullname; 295 } V9fsMkState; 296 297 /* 9p2000.L open flags */ 298 #define P9_DOTL_RDONLY 00000000 299 #define P9_DOTL_WRONLY 00000001 300 #define P9_DOTL_RDWR 00000002 301 #define P9_DOTL_NOACCESS 00000003 302 #define P9_DOTL_CREATE 00000100 303 #define P9_DOTL_EXCL 00000200 304 #define P9_DOTL_NOCTTY 00000400 305 #define P9_DOTL_TRUNC 00001000 306 #define P9_DOTL_APPEND 00002000 307 #define P9_DOTL_NONBLOCK 00004000 308 #define P9_DOTL_DSYNC 00010000 309 #define P9_DOTL_FASYNC 00020000 310 #define P9_DOTL_DIRECT 00040000 311 #define P9_DOTL_LARGEFILE 00100000 312 #define P9_DOTL_DIRECTORY 00200000 313 #define P9_DOTL_NOFOLLOW 00400000 314 #define P9_DOTL_NOATIME 01000000 315 #define P9_DOTL_CLOEXEC 02000000 316 #define P9_DOTL_SYNC 04000000 317 318 /* 9p2000.L at flags */ 319 #define P9_DOTL_AT_REMOVEDIR 0x200 320 321 /* 9P2000.L lock type */ 322 #define P9_LOCK_TYPE_RDLCK 0 323 #define P9_LOCK_TYPE_WRLCK 1 324 #define P9_LOCK_TYPE_UNLCK 2 325 326 #define P9_LOCK_SUCCESS 0 327 #define P9_LOCK_BLOCKED 1 328 #define P9_LOCK_ERROR 2 329 #define P9_LOCK_GRACE 3 330 331 #define P9_LOCK_FLAGS_BLOCK 1 332 #define P9_LOCK_FLAGS_RECLAIM 2 333 334 typedef struct V9fsFlock 335 { 336 uint8_t type; 337 uint32_t flags; 338 uint64_t start; /* absolute offset */ 339 uint64_t length; 340 uint32_t proc_id; 341 V9fsString client_id; 342 } V9fsFlock; 343 344 typedef struct V9fsGetlock 345 { 346 uint8_t type; 347 uint64_t start; /* absolute offset */ 348 uint64_t length; 349 uint32_t proc_id; 350 V9fsString client_id; 351 } V9fsGetlock; 352 353 extern int open_fd_hw; 354 extern int total_open_fd; 355 356 size_t pdu_packunpack(void *addr, struct iovec *sg, int sg_count, 357 size_t offset, size_t size, int pack); 358 359 static inline size_t do_pdu_unpack(void *dst, struct iovec *sg, int sg_count, 360 size_t offset, size_t size) 361 { 362 return pdu_packunpack(dst, sg, sg_count, offset, size, 0); 363 } 364 365 static inline void v9fs_path_write_lock(V9fsState *s) 366 { 367 if (s->ctx.export_flags & V9FS_PATHNAME_FSCONTEXT) { 368 qemu_co_rwlock_wrlock(&s->rename_lock); 369 } 370 } 371 372 static inline void v9fs_path_read_lock(V9fsState *s) 373 { 374 if (s->ctx.export_flags & V9FS_PATHNAME_FSCONTEXT) { 375 qemu_co_rwlock_rdlock(&s->rename_lock); 376 } 377 } 378 379 static inline void v9fs_path_unlock(V9fsState *s) 380 { 381 if (s->ctx.export_flags & V9FS_PATHNAME_FSCONTEXT) { 382 qemu_co_rwlock_unlock(&s->rename_lock); 383 } 384 } 385 386 static inline uint8_t v9fs_request_cancelled(V9fsPDU *pdu) 387 { 388 return pdu->cancelled; 389 } 390 391 extern void handle_9p_output(VirtIODevice *vdev, VirtQueue *vq); 392 extern void v9fs_reclaim_fd(V9fsPDU *pdu); 393 extern void v9fs_path_init(V9fsPath *path); 394 extern void v9fs_path_free(V9fsPath *path); 395 extern void v9fs_path_copy(V9fsPath *lhs, V9fsPath *rhs); 396 extern int v9fs_name_to_path(V9fsState *s, V9fsPath *dirpath, 397 const char *name, V9fsPath *path); 398 399 #define pdu_marshal(pdu, offset, fmt, args...) \ 400 v9fs_marshal(pdu->elem.in_sg, pdu->elem.in_num, offset, 1, fmt, ##args) 401 #define pdu_unmarshal(pdu, offset, fmt, args...) \ 402 v9fs_unmarshal(pdu->elem.out_sg, pdu->elem.out_num, offset, 1, fmt, ##args) 403 404 #endif 405