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 <glib.h> 10 #include "standard-headers/linux/virtio_9p.h" 11 #include "hw/virtio/virtio.h" 12 #include "hw/virtio/virtio-9p.h" 13 #include "fsdev/file-op-9p.h" 14 #include "fsdev/virtio-9p-marshal.h" 15 #include "qemu/thread.h" 16 #include "block/coroutine.h" 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 char *rpath(FsContext *ctx, const char *path) 115 { 116 return g_strdup_printf("%s/%s", ctx->fs_root, path); 117 } 118 119 /* 120 * ample room for Twrite/Rread header 121 * size[4] Tread/Twrite tag[2] fid[4] offset[8] count[4] 122 */ 123 #define P9_IOHDRSZ 24 124 125 typedef struct V9fsPDU V9fsPDU; 126 struct V9fsState; 127 128 struct V9fsPDU 129 { 130 uint32_t size; 131 uint16_t tag; 132 uint8_t id; 133 uint8_t cancelled; 134 CoQueue complete; 135 VirtQueueElement elem; 136 struct V9fsState *s; 137 QLIST_ENTRY(V9fsPDU) next; 138 }; 139 140 141 /* FIXME 142 * 1) change user needs to set groups and stuff 143 */ 144 145 #define MAX_REQ 128 146 #define MAX_TAG_LEN 32 147 148 #define BUG_ON(cond) assert(!(cond)) 149 150 typedef struct V9fsFidState V9fsFidState; 151 152 enum { 153 P9_FID_NONE = 0, 154 P9_FID_FILE, 155 P9_FID_DIR, 156 P9_FID_XATTR, 157 }; 158 159 typedef struct V9fsXattr 160 { 161 int64_t copied_len; 162 int64_t len; 163 void *value; 164 V9fsString name; 165 int flags; 166 } V9fsXattr; 167 168 /* 169 * Filled by fs driver on open and other 170 * calls. 171 */ 172 union V9fsFidOpenState { 173 int fd; 174 DIR *dir; 175 V9fsXattr xattr; 176 /* 177 * private pointer for fs drivers, that 178 * have its own internal representation of 179 * open files. 180 */ 181 void *private; 182 }; 183 184 struct V9fsFidState 185 { 186 int fid_type; 187 int32_t fid; 188 V9fsPath path; 189 V9fsFidOpenState fs; 190 V9fsFidOpenState fs_reclaim; 191 int flags; 192 int open_flags; 193 uid_t uid; 194 int ref; 195 int clunked; 196 V9fsFidState *next; 197 V9fsFidState *rclm_lst; 198 }; 199 200 typedef struct V9fsState 201 { 202 VirtIODevice parent_obj; 203 VirtQueue *vq; 204 V9fsPDU pdus[MAX_REQ]; 205 QLIST_HEAD(, V9fsPDU) free_list; 206 QLIST_HEAD(, V9fsPDU) active_list; 207 V9fsFidState *fid_list; 208 FileOperations *ops; 209 FsContext ctx; 210 char *tag; 211 size_t config_size; 212 enum p9_proto_version proto_version; 213 int32_t msize; 214 /* 215 * lock ensuring atomic path update 216 * on rename. 217 */ 218 CoRwlock rename_lock; 219 int32_t root_fid; 220 Error *migration_blocker; 221 V9fsConf fsconf; 222 } V9fsState; 223 224 typedef struct V9fsStatState { 225 V9fsPDU *pdu; 226 size_t offset; 227 V9fsStat v9stat; 228 V9fsFidState *fidp; 229 struct stat stbuf; 230 } V9fsStatState; 231 232 typedef struct V9fsOpenState { 233 V9fsPDU *pdu; 234 size_t offset; 235 int32_t mode; 236 V9fsFidState *fidp; 237 V9fsQID qid; 238 struct stat stbuf; 239 int iounit; 240 } V9fsOpenState; 241 242 typedef struct V9fsReadState { 243 V9fsPDU *pdu; 244 size_t offset; 245 int32_t count; 246 int32_t total; 247 int64_t off; 248 V9fsFidState *fidp; 249 struct iovec iov[128]; /* FIXME: bad, bad, bad */ 250 struct iovec *sg; 251 off_t dir_pos; 252 struct dirent *dent; 253 struct stat stbuf; 254 V9fsString name; 255 V9fsStat v9stat; 256 int32_t len; 257 int32_t cnt; 258 int32_t max_count; 259 } V9fsReadState; 260 261 typedef struct V9fsWriteState { 262 V9fsPDU *pdu; 263 size_t offset; 264 int32_t len; 265 int32_t count; 266 int32_t total; 267 int64_t off; 268 V9fsFidState *fidp; 269 struct iovec iov[128]; /* FIXME: bad, bad, bad */ 270 struct iovec *sg; 271 int cnt; 272 } V9fsWriteState; 273 274 typedef struct V9fsMkState { 275 V9fsPDU *pdu; 276 size_t offset; 277 V9fsQID qid; 278 struct stat stbuf; 279 V9fsString name; 280 V9fsString fullname; 281 } V9fsMkState; 282 283 /* 9p2000.L open flags */ 284 #define P9_DOTL_RDONLY 00000000 285 #define P9_DOTL_WRONLY 00000001 286 #define P9_DOTL_RDWR 00000002 287 #define P9_DOTL_NOACCESS 00000003 288 #define P9_DOTL_CREATE 00000100 289 #define P9_DOTL_EXCL 00000200 290 #define P9_DOTL_NOCTTY 00000400 291 #define P9_DOTL_TRUNC 00001000 292 #define P9_DOTL_APPEND 00002000 293 #define P9_DOTL_NONBLOCK 00004000 294 #define P9_DOTL_DSYNC 00010000 295 #define P9_DOTL_FASYNC 00020000 296 #define P9_DOTL_DIRECT 00040000 297 #define P9_DOTL_LARGEFILE 00100000 298 #define P9_DOTL_DIRECTORY 00200000 299 #define P9_DOTL_NOFOLLOW 00400000 300 #define P9_DOTL_NOATIME 01000000 301 #define P9_DOTL_CLOEXEC 02000000 302 #define P9_DOTL_SYNC 04000000 303 304 /* 9p2000.L at flags */ 305 #define P9_DOTL_AT_REMOVEDIR 0x200 306 307 /* 9P2000.L lock type */ 308 #define P9_LOCK_TYPE_RDLCK 0 309 #define P9_LOCK_TYPE_WRLCK 1 310 #define P9_LOCK_TYPE_UNLCK 2 311 312 #define P9_LOCK_SUCCESS 0 313 #define P9_LOCK_BLOCKED 1 314 #define P9_LOCK_ERROR 2 315 #define P9_LOCK_GRACE 3 316 317 #define P9_LOCK_FLAGS_BLOCK 1 318 #define P9_LOCK_FLAGS_RECLAIM 2 319 320 typedef struct V9fsFlock 321 { 322 uint8_t type; 323 uint32_t flags; 324 uint64_t start; /* absolute offset */ 325 uint64_t length; 326 uint32_t proc_id; 327 V9fsString client_id; 328 } V9fsFlock; 329 330 typedef struct V9fsGetlock 331 { 332 uint8_t type; 333 uint64_t start; /* absolute offset */ 334 uint64_t length; 335 uint32_t proc_id; 336 V9fsString client_id; 337 } V9fsGetlock; 338 339 extern int open_fd_hw; 340 extern int total_open_fd; 341 342 size_t pdu_packunpack(void *addr, struct iovec *sg, int sg_count, 343 size_t offset, size_t size, int pack); 344 345 static inline size_t do_pdu_unpack(void *dst, struct iovec *sg, int sg_count, 346 size_t offset, size_t size) 347 { 348 return pdu_packunpack(dst, sg, sg_count, offset, size, 0); 349 } 350 351 static inline void v9fs_path_write_lock(V9fsState *s) 352 { 353 if (s->ctx.export_flags & V9FS_PATHNAME_FSCONTEXT) { 354 qemu_co_rwlock_wrlock(&s->rename_lock); 355 } 356 } 357 358 static inline void v9fs_path_read_lock(V9fsState *s) 359 { 360 if (s->ctx.export_flags & V9FS_PATHNAME_FSCONTEXT) { 361 qemu_co_rwlock_rdlock(&s->rename_lock); 362 } 363 } 364 365 static inline void v9fs_path_unlock(V9fsState *s) 366 { 367 if (s->ctx.export_flags & V9FS_PATHNAME_FSCONTEXT) { 368 qemu_co_rwlock_unlock(&s->rename_lock); 369 } 370 } 371 372 static inline uint8_t v9fs_request_cancelled(V9fsPDU *pdu) 373 { 374 return pdu->cancelled; 375 } 376 377 extern void handle_9p_output(VirtIODevice *vdev, VirtQueue *vq); 378 extern void v9fs_reclaim_fd(V9fsPDU *pdu); 379 extern void v9fs_path_init(V9fsPath *path); 380 extern void v9fs_path_free(V9fsPath *path); 381 extern void v9fs_path_copy(V9fsPath *lhs, V9fsPath *rhs); 382 extern int v9fs_name_to_path(V9fsState *s, V9fsPath *dirpath, 383 const char *name, V9fsPath *path); 384 385 #define pdu_marshal(pdu, offset, fmt, args...) \ 386 v9fs_marshal(pdu->elem.in_sg, pdu->elem.in_num, offset, 1, fmt, ##args) 387 #define pdu_unmarshal(pdu, offset, fmt, args...) \ 388 v9fs_unmarshal(pdu->elem.out_sg, pdu->elem.out_num, offset, 1, fmt, ##args) 389 390 #define TYPE_VIRTIO_9P "virtio-9p-device" 391 #define VIRTIO_9P(obj) \ 392 OBJECT_CHECK(V9fsState, (obj), TYPE_VIRTIO_9P) 393 394 #endif 395