xref: /openbmc/qemu/hw/9pfs/9p.h (revision b6235a759a4552d21c5b68d16c894aa5b96d4b96)
1  #ifndef QEMU_9P_H
2  #define QEMU_9P_H
3  
4  #include <dirent.h>
5  #include <utime.h>
6  #include <sys/resource.h>
7  #include "fsdev/file-op-9p.h"
8  #include "fsdev/9p-iov-marshal.h"
9  #include "qemu/thread.h"
10  #include "qemu/coroutine.h"
11  #include "qemu/qht.h"
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  
98  typedef enum P9ProtoVersion {
99      V9FS_PROTO_2000U = 0x01,
100      V9FS_PROTO_2000L = 0x02,
101  } P9ProtoVersion;
102  
103  /*
104   * 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  
114  #define P9_NOTAG    UINT16_MAX
115  #define P9_NOFID    UINT32_MAX
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;
132  typedef struct V9fsState V9fsState;
133  typedef struct V9fsTransport V9fsTransport;
134  
135  typedef struct {
136      uint32_t size_le;
137      uint8_t id;
138      uint16_t tag_le;
139  } QEMU_PACKED P9MsgHeader;
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);
145  
146  struct V9fsPDU {
147      uint32_t size;
148      uint16_t tag;
149      uint8_t id;
150      uint8_t cancelled;
151      CoQueue complete;
152      V9fsState *s;
153      QLIST_ENTRY(V9fsPDU) next;
154      uint32_t idx;
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  
183  /* 9p2000.L xattr flags (matches Linux values) */
184  #define P9_XATTR_CREATE 1
185  #define P9_XATTR_REPLACE 2
186  
187  typedef struct V9fsXattr
188  {
189      uint64_t copied_len;
190      uint64_t len;
191      void *value;
192      V9fsString name;
193      int flags;
194      bool xattrwalk_fid;
195  } V9fsXattr;
196  
197  typedef struct V9fsDir {
198      DIR *stream;
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;
204  } V9fsDir;
205  
206  static inline void coroutine_fn v9fs_readdir_lock(V9fsDir *dir)
207  {
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      }
213  }
214  
215  static inline void coroutine_fn v9fs_readdir_unlock(V9fsDir *dir)
216  {
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      }
222  }
223  
224  static inline void v9fs_readdir_init(P9ProtoVersion proto_version, V9fsDir *dir)
225  {
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      }
232  }
233  
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  
256  /*
257   * Filled by fs driver on open and other
258   * calls.
259   */
260  union V9fsFidOpenState {
261      int fd;
262      V9fsDir dir;
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  
272  struct V9fsFidState {
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;
282      bool clunked;
283      QSIMPLEQ_ENTRY(V9fsFidState) next;
284      QSLIST_ENTRY(V9fsFidState) reclaim_next;
285  };
286  
287  typedef enum AffixType_t {
288      AffixType_Prefix,
289      AffixType_Suffix, /* A.k.a. postfix. */
290  } AffixType_t;
291  
292  /*
293   * 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 ``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;
323  
324  /* QID path prefix entry, see stat_to_qid */
325  typedef struct {
326      dev_t dev;
327      uint16_t ino_prefix;
328      uint32_t qp_affix_index;
329      VariLenAffix qp_affix;
330  } QppEntry;
331  
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  
339  struct V9fsState {
340      QLIST_HEAD(, V9fsPDU) free_list;
341      QLIST_HEAD(, V9fsPDU) active_list;
342      GHashTable *fids;
343      FileOperations *ops;
344      FsContext ctx;
345      char *tag;
346      P9ProtoVersion proto_version;
347      int32_t msize;
348      V9fsPDU pdus[MAX_REQ];
349      const V9fsTransport *transport;
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;
358      struct stat root_st;
359      dev_t dev_id;
360      struct qht qpd_table;
361      struct qht qpp_table;
362      struct qht qpf_table;
363      uint64_t qp_ndevices; /* Amount of entries in qpd_table. */
364      uint16_t qp_affix_next;
365      uint64_t qp_fullpath_next;
366  };
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 coroutine_fn
428  v9fs_path_write_lock(V9fsState *s)
429  {
430      if (s->ctx.export_flags & V9FS_PATHNAME_FSCONTEXT) {
431          qemu_co_rwlock_wrlock(&s->rename_lock);
432      }
433  }
434  
435  static inline void coroutine_fn
436  v9fs_path_read_lock(V9fsState *s)
437  {
438      if (s->ctx.export_flags & V9FS_PATHNAME_FSCONTEXT) {
439          qemu_co_rwlock_rdlock(&s->rename_lock);
440      }
441  }
442  
443  static inline void coroutine_fn
444  v9fs_path_unlock(V9fsState *s)
445  {
446      if (s->ctx.export_flags & V9FS_PATHNAME_FSCONTEXT) {
447          qemu_co_rwlock_unlock(&s->rename_lock);
448      }
449  }
450  
451  static inline uint8_t v9fs_request_cancelled(V9fsPDU *pdu)
452  {
453      return pdu->cancelled;
454  }
455  
456  void coroutine_fn v9fs_reclaim_fd(V9fsPDU *pdu);
457  void v9fs_path_init(V9fsPath *path);
458  void v9fs_path_free(V9fsPath *path);
459  void v9fs_path_sprintf(V9fsPath *path, const char *fmt, ...);
460  void v9fs_path_copy(V9fsPath *dst, const V9fsPath *src);
461  size_t v9fs_readdir_response_size(V9fsString *name);
462  int v9fs_name_to_path(V9fsState *s, V9fsPath *dirpath,
463                        const char *name, V9fsPath *path);
464  int v9fs_device_realize_common(V9fsState *s, const V9fsTransport *t,
465                                 Error **errp);
466  void v9fs_device_unrealize_common(V9fsState *s);
467  
468  V9fsPDU *pdu_alloc(V9fsState *s);
469  void pdu_free(V9fsPDU *pdu);
470  void pdu_submit(V9fsPDU *pdu, P9MsgHeader *hdr);
471  void v9fs_reset(V9fsState *s);
472  
473  struct V9fsTransport {
474      ssize_t     (*pdu_vmarshal)(V9fsPDU *pdu, size_t offset, const char *fmt,
475                                  va_list ap);
476      ssize_t     (*pdu_vunmarshal)(V9fsPDU *pdu, size_t offset, const char *fmt,
477                                    va_list ap);
478      void        (*init_in_iov_from_pdu)(V9fsPDU *pdu, struct iovec **piov,
479                                          unsigned int *pniov, size_t size);
480      void        (*init_out_iov_from_pdu)(V9fsPDU *pdu, struct iovec **piov,
481                                           unsigned int *pniov, size_t size);
482      void        (*push_and_notify)(V9fsPDU *pdu);
483  };
484  
485  #endif
486