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