]>
Commit | Line | Data |
---|---|---|
2a6a4076 MA |
1 | #ifndef QEMU_9P_H |
2 | #define QEMU_9P_H | |
ebe74f8b | 3 | |
ebe74f8b | 4 | #include <dirent.h> |
ebe74f8b WL |
5 | #include <utime.h> |
6 | #include <sys/resource.h> | |
ebe74f8b WL |
7 | #include "fsdev/file-op-9p.h" |
8 | #include "fsdev/9p-iov-marshal.h" | |
9 | #include "qemu/thread.h" | |
10 | #include "qemu/coroutine.h" | |
1a6ed33c | 11 | #include "qemu/qht.h" |
ebe74f8b WL |
12 | |
13 | enum { | |
14 | P9_TLERROR = 6, | |
15 | P9_RLERROR, | |
16 | P9_TSTATFS = 8, | |
17 | P9_RSTATFS, | |
18 | P9_TLOPEN = 12, | |
19 | P9_RLOPEN, | |
20 | P9_TLCREATE = 14, | |
21 | P9_RLCREATE, | |
22 | P9_TSYMLINK = 16, | |
23 | P9_RSYMLINK, | |
24 | P9_TMKNOD = 18, | |
25 | P9_RMKNOD, | |
26 | P9_TRENAME = 20, | |
27 | P9_RRENAME, | |
28 | P9_TREADLINK = 22, | |
29 | P9_RREADLINK, | |
30 | P9_TGETATTR = 24, | |
31 | P9_RGETATTR, | |
32 | P9_TSETATTR = 26, | |
33 | P9_RSETATTR, | |
34 | P9_TXATTRWALK = 30, | |
35 | P9_RXATTRWALK, | |
36 | P9_TXATTRCREATE = 32, | |
37 | P9_RXATTRCREATE, | |
38 | P9_TREADDIR = 40, | |
39 | P9_RREADDIR, | |
40 | P9_TFSYNC = 50, | |
41 | P9_RFSYNC, | |
42 | P9_TLOCK = 52, | |
43 | P9_RLOCK, | |
44 | P9_TGETLOCK = 54, | |
45 | P9_RGETLOCK, | |
46 | P9_TLINK = 70, | |
47 | P9_RLINK, | |
48 | P9_TMKDIR = 72, | |
49 | P9_RMKDIR, | |
50 | P9_TRENAMEAT = 74, | |
51 | P9_RRENAMEAT, | |
52 | P9_TUNLINKAT = 76, | |
53 | P9_RUNLINKAT, | |
54 | P9_TVERSION = 100, | |
55 | P9_RVERSION, | |
56 | P9_TAUTH = 102, | |
57 | P9_RAUTH, | |
58 | P9_TATTACH = 104, | |
59 | P9_RATTACH, | |
60 | P9_TERROR = 106, | |
61 | P9_RERROR, | |
62 | P9_TFLUSH = 108, | |
63 | P9_RFLUSH, | |
64 | P9_TWALK = 110, | |
65 | P9_RWALK, | |
66 | P9_TOPEN = 112, | |
67 | P9_ROPEN, | |
68 | P9_TCREATE = 114, | |
69 | P9_RCREATE, | |
70 | P9_TREAD = 116, | |
71 | P9_RREAD, | |
72 | P9_TWRITE = 118, | |
73 | P9_RWRITE, | |
74 | P9_TCLUNK = 120, | |
75 | P9_RCLUNK, | |
76 | P9_TREMOVE = 122, | |
77 | P9_RREMOVE, | |
78 | P9_TSTAT = 124, | |
79 | P9_RSTAT, | |
80 | P9_TWSTAT = 126, | |
81 | P9_RWSTAT, | |
82 | }; | |
83 | ||
84 | ||
85 | /* qid.types */ | |
86 | enum { | |
87 | P9_QTDIR = 0x80, | |
88 | P9_QTAPPEND = 0x40, | |
89 | P9_QTEXCL = 0x20, | |
90 | P9_QTMOUNT = 0x10, | |
91 | P9_QTAUTH = 0x08, | |
92 | P9_QTTMP = 0x04, | |
93 | P9_QTSYMLINK = 0x02, | |
94 | P9_QTLINK = 0x01, | |
95 | P9_QTFILE = 0x00, | |
96 | }; | |
97 | ||
8e71b96c | 98 | typedef enum P9ProtoVersion { |
ebe74f8b WL |
99 | V9FS_PROTO_2000U = 0x01, |
100 | V9FS_PROTO_2000L = 0x02, | |
8e71b96c | 101 | } P9ProtoVersion; |
ebe74f8b | 102 | |
e16453a3 CS |
103 | /** |
104 | * @brief Minimum message size supported by this 9pfs server. | |
105 | * | |
106 | * A client establishes a session by sending a Tversion request along with a | |
107 | * 'msize' parameter which suggests the server a maximum message size ever to be | |
108 | * used for communication (for both requests and replies) between client and | |
109 | * server during that session. If client suggests a 'msize' smaller than this | |
110 | * value then session is denied by server with an error response. | |
111 | */ | |
112 | #define P9_MIN_MSIZE 4096 | |
113 | ||
baecbde6 GK |
114 | #define P9_NOTAG UINT16_MAX |
115 | #define P9_NOFID UINT32_MAX | |
ebe74f8b WL |
116 | #define P9_MAXWELEM 16 |
117 | ||
118 | #define FID_REFERENCED 0x1 | |
119 | #define FID_NON_RECLAIMABLE 0x2 | |
120 | static inline char *rpath(FsContext *ctx, const char *path) | |
121 | { | |
122 | return g_strdup_printf("%s/%s", ctx->fs_root, path); | |
123 | } | |
124 | ||
125 | /* | |
126 | * ample room for Twrite/Rread header | |
127 | * size[4] Tread/Twrite tag[2] fid[4] offset[8] count[4] | |
128 | */ | |
129 | #define P9_IOHDRSZ 24 | |
130 | ||
131 | typedef struct V9fsPDU V9fsPDU; | |
21cf9edf | 132 | typedef struct V9fsState V9fsState; |
8e71b96c | 133 | typedef struct V9fsTransport V9fsTransport; |
ebe74f8b | 134 | |
c9fb47e7 SS |
135 | typedef struct { |
136 | uint32_t size_le; | |
137 | uint8_t id; | |
138 | uint16_t tag_le; | |
139 | } QEMU_PACKED P9MsgHeader; | |
a4d99854 GK |
140 | /* According to the specification, 9p messages start with a 7-byte header. |
141 | * Since most of the code uses this header size in literal form, we must be | |
142 | * sure this is indeed the case. | |
143 | */ | |
144 | QEMU_BUILD_BUG_ON(sizeof(P9MsgHeader) != 7); | |
c9fb47e7 | 145 | |
487729e9 | 146 | struct V9fsPDU { |
ebe74f8b WL |
147 | uint32_t size; |
148 | uint16_t tag; | |
149 | uint8_t id; | |
150 | uint8_t cancelled; | |
151 | CoQueue complete; | |
21cf9edf | 152 | V9fsState *s; |
ebe74f8b | 153 | QLIST_ENTRY(V9fsPDU) next; |
00588a0a | 154 | uint32_t idx; |
ebe74f8b WL |
155 | }; |
156 | ||
157 | ||
158 | /* FIXME | |
159 | * 1) change user needs to set groups and stuff | |
160 | */ | |
161 | ||
162 | #define MAX_REQ 128 | |
163 | #define MAX_TAG_LEN 32 | |
164 | ||
165 | #define BUG_ON(cond) assert(!(cond)) | |
166 | ||
167 | typedef struct V9fsFidState V9fsFidState; | |
168 | ||
169 | enum { | |
170 | P9_FID_NONE = 0, | |
171 | P9_FID_FILE, | |
172 | P9_FID_DIR, | |
173 | P9_FID_XATTR, | |
174 | }; | |
175 | ||
176 | typedef struct V9fsConf | |
177 | { | |
178 | /* tag name for the device */ | |
179 | char *tag; | |
180 | char *fsdev_id; | |
181 | } V9fsConf; | |
182 | ||
aca6897f KF |
183 | /* 9p2000.L xattr flags (matches Linux values) */ |
184 | #define P9_XATTR_CREATE 1 | |
185 | #define P9_XATTR_REPLACE 2 | |
186 | ||
ebe74f8b WL |
187 | typedef struct V9fsXattr |
188 | { | |
8495f9ad LQ |
189 | uint64_t copied_len; |
190 | uint64_t len; | |
ebe74f8b WL |
191 | void *value; |
192 | V9fsString name; | |
193 | int flags; | |
dd28fbbc | 194 | bool xattrwalk_fid; |
ebe74f8b WL |
195 | } V9fsXattr; |
196 | ||
f314ea4e GK |
197 | typedef struct V9fsDir { |
198 | DIR *stream; | |
d2c5cf7c CS |
199 | P9ProtoVersion proto_version; |
200 | /* readdir mutex type used for 9P2000.u protocol variant */ | |
201 | CoMutex readdir_mutex_u; | |
202 | /* readdir mutex type used for 9P2000.L protocol variant */ | |
203 | QemuMutex readdir_mutex_L; | |
f314ea4e GK |
204 | } V9fsDir; |
205 | ||
7cde47d4 GK |
206 | static inline void v9fs_readdir_lock(V9fsDir *dir) |
207 | { | |
d2c5cf7c CS |
208 | if (dir->proto_version == V9FS_PROTO_2000U) { |
209 | qemu_co_mutex_lock(&dir->readdir_mutex_u); | |
210 | } else { | |
211 | qemu_mutex_lock(&dir->readdir_mutex_L); | |
212 | } | |
7cde47d4 GK |
213 | } |
214 | ||
215 | static inline void v9fs_readdir_unlock(V9fsDir *dir) | |
216 | { | |
d2c5cf7c CS |
217 | if (dir->proto_version == V9FS_PROTO_2000U) { |
218 | qemu_co_mutex_unlock(&dir->readdir_mutex_u); | |
219 | } else { | |
220 | qemu_mutex_unlock(&dir->readdir_mutex_L); | |
221 | } | |
7cde47d4 GK |
222 | } |
223 | ||
d2c5cf7c | 224 | static inline void v9fs_readdir_init(P9ProtoVersion proto_version, V9fsDir *dir) |
7cde47d4 | 225 | { |
d2c5cf7c CS |
226 | dir->proto_version = proto_version; |
227 | if (proto_version == V9FS_PROTO_2000U) { | |
228 | qemu_co_mutex_init(&dir->readdir_mutex_u); | |
229 | } else { | |
230 | qemu_mutex_init(&dir->readdir_mutex_L); | |
231 | } | |
7cde47d4 GK |
232 | } |
233 | ||
2149675b CS |
234 | /** |
235 | * Type for 9p fs drivers' (a.k.a. 9p backends) result of readdir requests, | |
236 | * which is a chained list of directory entries. | |
237 | */ | |
238 | typedef struct V9fsDirEnt { | |
239 | /* mandatory (must not be NULL) information for all readdir requests */ | |
240 | struct dirent *dent; | |
241 | /* | |
242 | * optional (may be NULL): A full stat of each directory entry is just | |
243 | * done if explicitly told to fs driver. | |
244 | */ | |
245 | struct stat *st; | |
246 | /* | |
247 | * instead of an array, directory entries are always returned as | |
248 | * chained list, that's because the amount of entries retrieved by fs | |
249 | * drivers is dependent on the individual entries' name (since response | |
250 | * messages are size limited), so the final amount cannot be estimated | |
251 | * before hand | |
252 | */ | |
253 | struct V9fsDirEnt *next; | |
254 | } V9fsDirEnt; | |
255 | ||
ebe74f8b WL |
256 | /* |
257 | * Filled by fs driver on open and other | |
258 | * calls. | |
259 | */ | |
260 | union V9fsFidOpenState { | |
261 | int fd; | |
f314ea4e | 262 | V9fsDir dir; |
ebe74f8b WL |
263 | V9fsXattr xattr; |
264 | /* | |
265 | * private pointer for fs drivers, that | |
266 | * have its own internal representation of | |
267 | * open files. | |
268 | */ | |
269 | void *private; | |
270 | }; | |
271 | ||
487729e9 | 272 | struct V9fsFidState { |
ebe74f8b WL |
273 | int fid_type; |
274 | int32_t fid; | |
275 | V9fsPath path; | |
276 | V9fsFidOpenState fs; | |
277 | V9fsFidOpenState fs_reclaim; | |
278 | int flags; | |
279 | int open_flags; | |
280 | uid_t uid; | |
281 | int ref; | |
2e53160f | 282 | bool clunked; |
feabd6cf | 283 | QSIMPLEQ_ENTRY(V9fsFidState) next; |
81f9766b | 284 | QSLIST_ENTRY(V9fsFidState) reclaim_next; |
ebe74f8b WL |
285 | }; |
286 | ||
6b6aa828 CS |
287 | typedef enum AffixType_t { |
288 | AffixType_Prefix, | |
289 | AffixType_Suffix, /* A.k.a. postfix. */ | |
290 | } AffixType_t; | |
291 | ||
292 | /** | |
293 | * @brief Unique affix of variable length. | |
294 | * | |
295 | * An affix is (currently) either a suffix or a prefix, which is either | |
296 | * going to be prepended (prefix) or appended (suffix) with some other | |
297 | * number for the goal to generate unique numbers. Accordingly the | |
298 | * suffixes (or prefixes) we generate @b must all have the mathematical | |
299 | * property of being suffix-free (or prefix-free in case of prefixes) | |
300 | * so that no matter what number we concatenate the affix with, that we | |
301 | * always reliably get unique numbers as result after concatenation. | |
302 | */ | |
303 | typedef struct VariLenAffix { | |
304 | AffixType_t type; /* Whether this affix is a suffix or a prefix. */ | |
305 | uint64_t value; /* Actual numerical value of this affix. */ | |
306 | /* | |
307 | * Lenght of the affix, that is how many (of the lowest) bits of @c value | |
308 | * must be used for appending/prepending this affix to its final resulting, | |
309 | * unique number. | |
310 | */ | |
311 | int bits; | |
312 | } VariLenAffix; | |
313 | ||
314 | /* See qid_inode_prefix_hash_bits(). */ | |
315 | typedef struct { | |
316 | dev_t dev; /* FS device on host. */ | |
317 | /* | |
318 | * How many (high) bits of the original inode number shall be used for | |
319 | * hashing. | |
320 | */ | |
321 | int prefix_bits; | |
322 | } QpdEntry; | |
1a6ed33c AM |
323 | |
324 | /* QID path prefix entry, see stat_to_qid */ | |
325 | typedef struct { | |
326 | dev_t dev; | |
327 | uint16_t ino_prefix; | |
6b6aa828 CS |
328 | uint32_t qp_affix_index; |
329 | VariLenAffix qp_affix; | |
1a6ed33c AM |
330 | } QppEntry; |
331 | ||
f3fe4a2d AM |
332 | /* QID path full entry, as above */ |
333 | typedef struct { | |
334 | dev_t dev; | |
335 | ino_t ino; | |
336 | uint64_t path; | |
337 | } QpfEntry; | |
338 | ||
487729e9 | 339 | struct V9fsState { |
ebe74f8b WL |
340 | QLIST_HEAD(, V9fsPDU) free_list; |
341 | QLIST_HEAD(, V9fsPDU) active_list; | |
feabd6cf | 342 | QSIMPLEQ_HEAD(, V9fsFidState) fid_list; |
ebe74f8b WL |
343 | FileOperations *ops; |
344 | FsContext ctx; | |
345 | char *tag; | |
8e71b96c | 346 | P9ProtoVersion proto_version; |
ebe74f8b | 347 | int32_t msize; |
583f21f8 | 348 | V9fsPDU pdus[MAX_REQ]; |
8e71b96c | 349 | const V9fsTransport *transport; |
ebe74f8b WL |
350 | /* |
351 | * lock ensuring atomic path update | |
352 | * on rename. | |
353 | */ | |
354 | CoRwlock rename_lock; | |
355 | int32_t root_fid; | |
356 | Error *migration_blocker; | |
357 | V9fsConf fsconf; | |
56f101ec | 358 | V9fsQID root_qid; |
3b5ee9e8 | 359 | dev_t dev_id; |
6b6aa828 | 360 | struct qht qpd_table; |
1a6ed33c | 361 | struct qht qpp_table; |
f3fe4a2d | 362 | struct qht qpf_table; |
6b6aa828 CS |
363 | uint64_t qp_ndevices; /* Amount of entries in qpd_table. */ |
364 | uint16_t qp_affix_next; | |
f3fe4a2d | 365 | uint64_t qp_fullpath_next; |
21cf9edf | 366 | }; |
ebe74f8b WL |
367 | |
368 | /* 9p2000.L open flags */ | |
369 | #define P9_DOTL_RDONLY 00000000 | |
370 | #define P9_DOTL_WRONLY 00000001 | |
371 | #define P9_DOTL_RDWR 00000002 | |
372 | #define P9_DOTL_NOACCESS 00000003 | |
373 | #define P9_DOTL_CREATE 00000100 | |
374 | #define P9_DOTL_EXCL 00000200 | |
375 | #define P9_DOTL_NOCTTY 00000400 | |
376 | #define P9_DOTL_TRUNC 00001000 | |
377 | #define P9_DOTL_APPEND 00002000 | |
378 | #define P9_DOTL_NONBLOCK 00004000 | |
379 | #define P9_DOTL_DSYNC 00010000 | |
380 | #define P9_DOTL_FASYNC 00020000 | |
381 | #define P9_DOTL_DIRECT 00040000 | |
382 | #define P9_DOTL_LARGEFILE 00100000 | |
383 | #define P9_DOTL_DIRECTORY 00200000 | |
384 | #define P9_DOTL_NOFOLLOW 00400000 | |
385 | #define P9_DOTL_NOATIME 01000000 | |
386 | #define P9_DOTL_CLOEXEC 02000000 | |
387 | #define P9_DOTL_SYNC 04000000 | |
388 | ||
389 | /* 9p2000.L at flags */ | |
390 | #define P9_DOTL_AT_REMOVEDIR 0x200 | |
391 | ||
392 | /* 9P2000.L lock type */ | |
393 | #define P9_LOCK_TYPE_RDLCK 0 | |
394 | #define P9_LOCK_TYPE_WRLCK 1 | |
395 | #define P9_LOCK_TYPE_UNLCK 2 | |
396 | ||
397 | #define P9_LOCK_SUCCESS 0 | |
398 | #define P9_LOCK_BLOCKED 1 | |
399 | #define P9_LOCK_ERROR 2 | |
400 | #define P9_LOCK_GRACE 3 | |
401 | ||
402 | #define P9_LOCK_FLAGS_BLOCK 1 | |
403 | #define P9_LOCK_FLAGS_RECLAIM 2 | |
404 | ||
405 | typedef struct V9fsFlock | |
406 | { | |
407 | uint8_t type; | |
408 | uint32_t flags; | |
409 | uint64_t start; /* absolute offset */ | |
410 | uint64_t length; | |
411 | uint32_t proc_id; | |
412 | V9fsString client_id; | |
413 | } V9fsFlock; | |
414 | ||
415 | typedef struct V9fsGetlock | |
416 | { | |
417 | uint8_t type; | |
418 | uint64_t start; /* absolute offset */ | |
419 | uint64_t length; | |
420 | uint32_t proc_id; | |
421 | V9fsString client_id; | |
422 | } V9fsGetlock; | |
423 | ||
424 | extern int open_fd_hw; | |
425 | extern int total_open_fd; | |
426 | ||
427 | static inline void v9fs_path_write_lock(V9fsState *s) | |
428 | { | |
429 | if (s->ctx.export_flags & V9FS_PATHNAME_FSCONTEXT) { | |
430 | qemu_co_rwlock_wrlock(&s->rename_lock); | |
431 | } | |
432 | } | |
433 | ||
434 | static inline void v9fs_path_read_lock(V9fsState *s) | |
435 | { | |
436 | if (s->ctx.export_flags & V9FS_PATHNAME_FSCONTEXT) { | |
437 | qemu_co_rwlock_rdlock(&s->rename_lock); | |
438 | } | |
439 | } | |
440 | ||
441 | static inline void v9fs_path_unlock(V9fsState *s) | |
442 | { | |
443 | if (s->ctx.export_flags & V9FS_PATHNAME_FSCONTEXT) { | |
444 | qemu_co_rwlock_unlock(&s->rename_lock); | |
445 | } | |
446 | } | |
447 | ||
448 | static inline uint8_t v9fs_request_cancelled(V9fsPDU *pdu) | |
449 | { | |
450 | return pdu->cancelled; | |
451 | } | |
452 | ||
8440e22e | 453 | void coroutine_fn v9fs_reclaim_fd(V9fsPDU *pdu); |
bc70a592 GK |
454 | void v9fs_path_init(V9fsPath *path); |
455 | void v9fs_path_free(V9fsPath *path); | |
456 | void v9fs_path_sprintf(V9fsPath *path, const char *fmt, ...); | |
e446a1eb | 457 | void v9fs_path_copy(V9fsPath *dst, const V9fsPath *src); |
29c9d2ca | 458 | size_t v9fs_readdir_response_size(V9fsString *name); |
bc70a592 GK |
459 | int v9fs_name_to_path(V9fsState *s, V9fsPath *dirpath, |
460 | const char *name, V9fsPath *path); | |
066eb006 GK |
461 | int v9fs_device_realize_common(V9fsState *s, const V9fsTransport *t, |
462 | Error **errp); | |
b69c3c21 | 463 | void v9fs_device_unrealize_common(V9fsState *s); |
ebe74f8b | 464 | |
4b311c5f WL |
465 | V9fsPDU *pdu_alloc(V9fsState *s); |
466 | void pdu_free(V9fsPDU *pdu); | |
506f3275 | 467 | void pdu_submit(V9fsPDU *pdu, P9MsgHeader *hdr); |
0e44a0fd | 468 | void v9fs_reset(V9fsState *s); |
ebe74f8b | 469 | |
ea83441c SS |
470 | struct V9fsTransport { |
471 | ssize_t (*pdu_vmarshal)(V9fsPDU *pdu, size_t offset, const char *fmt, | |
472 | va_list ap); | |
473 | ssize_t (*pdu_vunmarshal)(V9fsPDU *pdu, size_t offset, const char *fmt, | |
474 | va_list ap); | |
88da0b03 | 475 | void (*init_in_iov_from_pdu)(V9fsPDU *pdu, struct iovec **piov, |
cf45183b | 476 | unsigned int *pniov, size_t size); |
88da0b03 | 477 | void (*init_out_iov_from_pdu)(V9fsPDU *pdu, struct iovec **piov, |
8d37de41 | 478 | unsigned int *pniov, size_t size); |
ea83441c SS |
479 | void (*push_and_notify)(V9fsPDU *pdu); |
480 | }; | |
481 | ||
ebe74f8b | 482 | #endif |