qemu/hw/9pfs/9p.h
<<
>>
Prefs
   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
  13enum {
  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 */
  86enum {
  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
  98typedef enum P9ProtoVersion {
  99    V9FS_PROTO_2000U = 0x01,
 100    V9FS_PROTO_2000L = 0x02,
 101} P9ProtoVersion;
 102
 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
 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
 120static 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
 131typedef struct V9fsPDU V9fsPDU;
 132typedef struct V9fsState V9fsState;
 133typedef struct V9fsTransport V9fsTransport;
 134
 135typedef 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 */
 144QEMU_BUILD_BUG_ON(sizeof(P9MsgHeader) != 7);
 145
 146struct 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
 167typedef struct V9fsFidState V9fsFidState;
 168
 169enum {
 170    P9_FID_NONE = 0,
 171    P9_FID_FILE,
 172    P9_FID_DIR,
 173    P9_FID_XATTR,
 174};
 175
 176typedef 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
 187typedef 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
 197typedef 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
 206static inline void 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
 215static inline void 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
 224static 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 */
 238typedef 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 */
 260union 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
 272struct 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
 287typedef 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 */
 303typedef 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(). */
 315typedef 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 */
 325typedef 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 */
 333typedef struct {
 334    dev_t dev;
 335    ino_t ino;
 336    uint64_t path;
 337} QpfEntry;
 338
 339struct V9fsState {
 340    QLIST_HEAD(, V9fsPDU) free_list;
 341    QLIST_HEAD(, V9fsPDU) active_list;
 342    QSIMPLEQ_HEAD(, V9fsFidState) fid_list;
 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
 405typedef 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
 415typedef 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
 424extern int open_fd_hw;
 425extern int total_open_fd;
 426
 427static 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
 434static 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
 441static 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
 448static inline uint8_t v9fs_request_cancelled(V9fsPDU *pdu)
 449{
 450    return pdu->cancelled;
 451}
 452
 453void coroutine_fn v9fs_reclaim_fd(V9fsPDU *pdu);
 454void v9fs_path_init(V9fsPath *path);
 455void v9fs_path_free(V9fsPath *path);
 456void v9fs_path_sprintf(V9fsPath *path, const char *fmt, ...);
 457void v9fs_path_copy(V9fsPath *dst, const V9fsPath *src);
 458size_t v9fs_readdir_response_size(V9fsString *name);
 459int v9fs_name_to_path(V9fsState *s, V9fsPath *dirpath,
 460                      const char *name, V9fsPath *path);
 461int v9fs_device_realize_common(V9fsState *s, const V9fsTransport *t,
 462                               Error **errp);
 463void v9fs_device_unrealize_common(V9fsState *s);
 464
 465V9fsPDU *pdu_alloc(V9fsState *s);
 466void pdu_free(V9fsPDU *pdu);
 467void pdu_submit(V9fsPDU *pdu, P9MsgHeader *hdr);
 468void v9fs_reset(V9fsState *s);
 469
 470struct 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);
 475    void        (*init_in_iov_from_pdu)(V9fsPDU *pdu, struct iovec **piov,
 476                                        unsigned int *pniov, size_t size);
 477    void        (*init_out_iov_from_pdu)(V9fsPDU *pdu, struct iovec **piov,
 478                                         unsigned int *pniov, size_t size);
 479    void        (*push_and_notify)(V9fsPDU *pdu);
 480};
 481
 482#endif
 483