qemu/hw/9pfs/9p.c
<<
>>
Prefs
   1/*
   2 * Virtio 9p backend
   3 *
   4 * Copyright IBM, Corp. 2010
   5 *
   6 * Authors:
   7 *  Anthony Liguori   <aliguori@us.ibm.com>
   8 *
   9 * This work is licensed under the terms of the GNU GPL, version 2.  See
  10 * the COPYING file in the top-level directory.
  11 *
  12 */
  13
  14#include "qemu/osdep.h"
  15#include <glib/gprintf.h>
  16#include "hw/virtio/virtio.h"
  17#include "qapi/error.h"
  18#include "qemu/error-report.h"
  19#include "qemu/iov.h"
  20#include "qemu/sockets.h"
  21#include "virtio-9p.h"
  22#include "fsdev/qemu-fsdev.h"
  23#include "9p-xattr.h"
  24#include "coth.h"
  25#include "trace.h"
  26#include "migration/migration.h"
  27
  28int open_fd_hw;
  29int total_open_fd;
  30static int open_fd_rc;
  31
  32enum {
  33    Oread   = 0x00,
  34    Owrite  = 0x01,
  35    Ordwr   = 0x02,
  36    Oexec   = 0x03,
  37    Oexcl   = 0x04,
  38    Otrunc  = 0x10,
  39    Orexec  = 0x20,
  40    Orclose = 0x40,
  41    Oappend = 0x80,
  42};
  43
  44ssize_t pdu_marshal(V9fsPDU *pdu, size_t offset, const char *fmt, ...)
  45{
  46    ssize_t ret;
  47    va_list ap;
  48
  49    va_start(ap, fmt);
  50    ret = virtio_pdu_vmarshal(pdu, offset, fmt, ap);
  51    va_end(ap);
  52
  53    return ret;
  54}
  55
  56ssize_t pdu_unmarshal(V9fsPDU *pdu, size_t offset, const char *fmt, ...)
  57{
  58    ssize_t ret;
  59    va_list ap;
  60
  61    va_start(ap, fmt);
  62    ret = virtio_pdu_vunmarshal(pdu, offset, fmt, ap);
  63    va_end(ap);
  64
  65    return ret;
  66}
  67
  68static void pdu_push_and_notify(V9fsPDU *pdu)
  69{
  70    virtio_9p_push_and_notify(pdu);
  71}
  72
  73static int omode_to_uflags(int8_t mode)
  74{
  75    int ret = 0;
  76
  77    switch (mode & 3) {
  78    case Oread:
  79        ret = O_RDONLY;
  80        break;
  81    case Ordwr:
  82        ret = O_RDWR;
  83        break;
  84    case Owrite:
  85        ret = O_WRONLY;
  86        break;
  87    case Oexec:
  88        ret = O_RDONLY;
  89        break;
  90    }
  91
  92    if (mode & Otrunc) {
  93        ret |= O_TRUNC;
  94    }
  95
  96    if (mode & Oappend) {
  97        ret |= O_APPEND;
  98    }
  99
 100    if (mode & Oexcl) {
 101        ret |= O_EXCL;
 102    }
 103
 104    return ret;
 105}
 106
 107struct dotl_openflag_map {
 108    int dotl_flag;
 109    int open_flag;
 110};
 111
 112static int dotl_to_open_flags(int flags)
 113{
 114    int i;
 115    /*
 116     * We have same bits for P9_DOTL_READONLY, P9_DOTL_WRONLY
 117     * and P9_DOTL_NOACCESS
 118     */
 119    int oflags = flags & O_ACCMODE;
 120
 121    struct dotl_openflag_map dotl_oflag_map[] = {
 122        { P9_DOTL_CREATE, O_CREAT },
 123        { P9_DOTL_EXCL, O_EXCL },
 124        { P9_DOTL_NOCTTY , O_NOCTTY },
 125        { P9_DOTL_TRUNC, O_TRUNC },
 126        { P9_DOTL_APPEND, O_APPEND },
 127        { P9_DOTL_NONBLOCK, O_NONBLOCK } ,
 128        { P9_DOTL_DSYNC, O_DSYNC },
 129        { P9_DOTL_FASYNC, FASYNC },
 130        { P9_DOTL_DIRECT, O_DIRECT },
 131        { P9_DOTL_LARGEFILE, O_LARGEFILE },
 132        { P9_DOTL_DIRECTORY, O_DIRECTORY },
 133        { P9_DOTL_NOFOLLOW, O_NOFOLLOW },
 134        { P9_DOTL_NOATIME, O_NOATIME },
 135        { P9_DOTL_SYNC, O_SYNC },
 136    };
 137
 138    for (i = 0; i < ARRAY_SIZE(dotl_oflag_map); i++) {
 139        if (flags & dotl_oflag_map[i].dotl_flag) {
 140            oflags |= dotl_oflag_map[i].open_flag;
 141        }
 142    }
 143
 144    return oflags;
 145}
 146
 147void cred_init(FsCred *credp)
 148{
 149    credp->fc_uid = -1;
 150    credp->fc_gid = -1;
 151    credp->fc_mode = -1;
 152    credp->fc_rdev = -1;
 153}
 154
 155static int get_dotl_openflags(V9fsState *s, int oflags)
 156{
 157    int flags;
 158    /*
 159     * Filter the client open flags
 160     */
 161    flags = dotl_to_open_flags(oflags);
 162    flags &= ~(O_NOCTTY | O_ASYNC | O_CREAT);
 163    /*
 164     * Ignore direct disk access hint until the server supports it.
 165     */
 166    flags &= ~O_DIRECT;
 167    return flags;
 168}
 169
 170void v9fs_path_init(V9fsPath *path)
 171{
 172    path->data = NULL;
 173    path->size = 0;
 174}
 175
 176void v9fs_path_free(V9fsPath *path)
 177{
 178    g_free(path->data);
 179    path->data = NULL;
 180    path->size = 0;
 181}
 182
 183
 184void GCC_FMT_ATTR(2, 3)
 185v9fs_path_sprintf(V9fsPath *path, const char *fmt, ...)
 186{
 187    va_list ap;
 188
 189    v9fs_path_free(path);
 190
 191    va_start(ap, fmt);
 192    /* Bump the size for including terminating NULL */
 193    path->size = g_vasprintf(&path->data, fmt, ap) + 1;
 194    va_end(ap);
 195}
 196
 197void v9fs_path_copy(V9fsPath *lhs, V9fsPath *rhs)
 198{
 199    v9fs_path_free(lhs);
 200    lhs->data = g_malloc(rhs->size);
 201    memcpy(lhs->data, rhs->data, rhs->size);
 202    lhs->size = rhs->size;
 203}
 204
 205int v9fs_name_to_path(V9fsState *s, V9fsPath *dirpath,
 206                      const char *name, V9fsPath *path)
 207{
 208    int err;
 209    err = s->ops->name_to_path(&s->ctx, dirpath, name, path);
 210    if (err < 0) {
 211        err = -errno;
 212    }
 213    return err;
 214}
 215
 216/*
 217 * Return TRUE if s1 is an ancestor of s2.
 218 *
 219 * E.g. "a/b" is an ancestor of "a/b/c" but not of "a/bc/d".
 220 * As a special case, We treat s1 as ancestor of s2 if they are same!
 221 */
 222static int v9fs_path_is_ancestor(V9fsPath *s1, V9fsPath *s2)
 223{
 224    if (!strncmp(s1->data, s2->data, s1->size - 1)) {
 225        if (s2->data[s1->size - 1] == '\0' || s2->data[s1->size - 1] == '/') {
 226            return 1;
 227        }
 228    }
 229    return 0;
 230}
 231
 232static size_t v9fs_string_size(V9fsString *str)
 233{
 234    return str->size;
 235}
 236
 237/*
 238 * returns 0 if fid got re-opened, 1 if not, < 0 on error */
 239static int coroutine_fn v9fs_reopen_fid(V9fsPDU *pdu, V9fsFidState *f)
 240{
 241    int err = 1;
 242    if (f->fid_type == P9_FID_FILE) {
 243        if (f->fs.fd == -1) {
 244            do {
 245                err = v9fs_co_open(pdu, f, f->open_flags);
 246            } while (err == -EINTR && !pdu->cancelled);
 247        }
 248    } else if (f->fid_type == P9_FID_DIR) {
 249        if (f->fs.dir.stream == NULL) {
 250            do {
 251                err = v9fs_co_opendir(pdu, f);
 252            } while (err == -EINTR && !pdu->cancelled);
 253        }
 254    }
 255    return err;
 256}
 257
 258static V9fsFidState *coroutine_fn get_fid(V9fsPDU *pdu, int32_t fid)
 259{
 260    int err;
 261    V9fsFidState *f;
 262    V9fsState *s = pdu->s;
 263
 264    for (f = s->fid_list; f; f = f->next) {
 265        BUG_ON(f->clunked);
 266        if (f->fid == fid) {
 267            /*
 268             * Update the fid ref upfront so that
 269             * we don't get reclaimed when we yield
 270             * in open later.
 271             */
 272            f->ref++;
 273            /*
 274             * check whether we need to reopen the
 275             * file. We might have closed the fd
 276             * while trying to free up some file
 277             * descriptors.
 278             */
 279            err = v9fs_reopen_fid(pdu, f);
 280            if (err < 0) {
 281                f->ref--;
 282                return NULL;
 283            }
 284            /*
 285             * Mark the fid as referenced so that the LRU
 286             * reclaim won't close the file descriptor
 287             */
 288            f->flags |= FID_REFERENCED;
 289            return f;
 290        }
 291    }
 292    return NULL;
 293}
 294
 295static V9fsFidState *alloc_fid(V9fsState *s, int32_t fid)
 296{
 297    V9fsFidState *f;
 298
 299    for (f = s->fid_list; f; f = f->next) {
 300        /* If fid is already there return NULL */
 301        BUG_ON(f->clunked);
 302        if (f->fid == fid) {
 303            return NULL;
 304        }
 305    }
 306    f = g_malloc0(sizeof(V9fsFidState));
 307    f->fid = fid;
 308    f->fid_type = P9_FID_NONE;
 309    f->ref = 1;
 310    /*
 311     * Mark the fid as referenced so that the LRU
 312     * reclaim won't close the file descriptor
 313     */
 314    f->flags |= FID_REFERENCED;
 315    f->next = s->fid_list;
 316    s->fid_list = f;
 317
 318    v9fs_readdir_init(&f->fs.dir);
 319    v9fs_readdir_init(&f->fs_reclaim.dir);
 320
 321    return f;
 322}
 323
 324static int coroutine_fn v9fs_xattr_fid_clunk(V9fsPDU *pdu, V9fsFidState *fidp)
 325{
 326    int retval = 0;
 327
 328    if (fidp->fs.xattr.xattrwalk_fid) {
 329        /* getxattr/listxattr fid */
 330        goto free_value;
 331    }
 332    /*
 333     * if this is fid for setxattr. clunk should
 334     * result in setxattr localcall
 335     */
 336    if (fidp->fs.xattr.len != fidp->fs.xattr.copied_len) {
 337        /* clunk after partial write */
 338        retval = -EINVAL;
 339        goto free_out;
 340    }
 341    if (fidp->fs.xattr.len) {
 342        retval = v9fs_co_lsetxattr(pdu, &fidp->path, &fidp->fs.xattr.name,
 343                                   fidp->fs.xattr.value,
 344                                   fidp->fs.xattr.len,
 345                                   fidp->fs.xattr.flags);
 346    } else {
 347        retval = v9fs_co_lremovexattr(pdu, &fidp->path, &fidp->fs.xattr.name);
 348    }
 349free_out:
 350    v9fs_string_free(&fidp->fs.xattr.name);
 351free_value:
 352    g_free(fidp->fs.xattr.value);
 353    return retval;
 354}
 355
 356static int coroutine_fn free_fid(V9fsPDU *pdu, V9fsFidState *fidp)
 357{
 358    int retval = 0;
 359
 360    if (fidp->fid_type == P9_FID_FILE) {
 361        /* If we reclaimed the fd no need to close */
 362        if (fidp->fs.fd != -1) {
 363            retval = v9fs_co_close(pdu, &fidp->fs);
 364        }
 365    } else if (fidp->fid_type == P9_FID_DIR) {
 366        if (fidp->fs.dir.stream != NULL) {
 367            retval = v9fs_co_closedir(pdu, &fidp->fs);
 368        }
 369    } else if (fidp->fid_type == P9_FID_XATTR) {
 370        retval = v9fs_xattr_fid_clunk(pdu, fidp);
 371    }
 372    v9fs_path_free(&fidp->path);
 373    g_free(fidp);
 374    return retval;
 375}
 376
 377static int coroutine_fn put_fid(V9fsPDU *pdu, V9fsFidState *fidp)
 378{
 379    BUG_ON(!fidp->ref);
 380    fidp->ref--;
 381    /*
 382     * Don't free the fid if it is in reclaim list
 383     */
 384    if (!fidp->ref && fidp->clunked) {
 385        if (fidp->fid == pdu->s->root_fid) {
 386            /*
 387             * if the clunked fid is root fid then we
 388             * have unmounted the fs on the client side.
 389             * delete the migration blocker. Ideally, this
 390             * should be hooked to transport close notification
 391             */
 392            if (pdu->s->migration_blocker) {
 393                migrate_del_blocker(pdu->s->migration_blocker);
 394                error_free(pdu->s->migration_blocker);
 395                pdu->s->migration_blocker = NULL;
 396            }
 397        }
 398        return free_fid(pdu, fidp);
 399    }
 400    return 0;
 401}
 402
 403static V9fsFidState *clunk_fid(V9fsState *s, int32_t fid)
 404{
 405    V9fsFidState **fidpp, *fidp;
 406
 407    for (fidpp = &s->fid_list; *fidpp; fidpp = &(*fidpp)->next) {
 408        if ((*fidpp)->fid == fid) {
 409            break;
 410        }
 411    }
 412    if (*fidpp == NULL) {
 413        return NULL;
 414    }
 415    fidp = *fidpp;
 416    *fidpp = fidp->next;
 417    fidp->clunked = 1;
 418    return fidp;
 419}
 420
 421void coroutine_fn v9fs_reclaim_fd(V9fsPDU *pdu)
 422{
 423    int reclaim_count = 0;
 424    V9fsState *s = pdu->s;
 425    V9fsFidState *f, *reclaim_list = NULL;
 426
 427    for (f = s->fid_list; f; f = f->next) {
 428        /*
 429         * Unlink fids cannot be reclaimed. Check
 430         * for them and skip them. Also skip fids
 431         * currently being operated on.
 432         */
 433        if (f->ref || f->flags & FID_NON_RECLAIMABLE) {
 434            continue;
 435        }
 436        /*
 437         * if it is a recently referenced fid
 438         * we leave the fid untouched and clear the
 439         * reference bit. We come back to it later
 440         * in the next iteration. (a simple LRU without
 441         * moving list elements around)
 442         */
 443        if (f->flags & FID_REFERENCED) {
 444            f->flags &= ~FID_REFERENCED;
 445            continue;
 446        }
 447        /*
 448         * Add fids to reclaim list.
 449         */
 450        if (f->fid_type == P9_FID_FILE) {
 451            if (f->fs.fd != -1) {
 452                /*
 453                 * Up the reference count so that
 454                 * a clunk request won't free this fid
 455                 */
 456                f->ref++;
 457                f->rclm_lst = reclaim_list;
 458                reclaim_list = f;
 459                f->fs_reclaim.fd = f->fs.fd;
 460                f->fs.fd = -1;
 461                reclaim_count++;
 462            }
 463        } else if (f->fid_type == P9_FID_DIR) {
 464            if (f->fs.dir.stream != NULL) {
 465                /*
 466                 * Up the reference count so that
 467                 * a clunk request won't free this fid
 468                 */
 469                f->ref++;
 470                f->rclm_lst = reclaim_list;
 471                reclaim_list = f;
 472                f->fs_reclaim.dir.stream = f->fs.dir.stream;
 473                f->fs.dir.stream = NULL;
 474                reclaim_count++;
 475            }
 476        }
 477        if (reclaim_count >= open_fd_rc) {
 478            break;
 479        }
 480    }
 481    /*
 482     * Now close the fid in reclaim list. Free them if they
 483     * are already clunked.
 484     */
 485    while (reclaim_list) {
 486        f = reclaim_list;
 487        reclaim_list = f->rclm_lst;
 488        if (f->fid_type == P9_FID_FILE) {
 489            v9fs_co_close(pdu, &f->fs_reclaim);
 490        } else if (f->fid_type == P9_FID_DIR) {
 491            v9fs_co_closedir(pdu, &f->fs_reclaim);
 492        }
 493        f->rclm_lst = NULL;
 494        /*
 495         * Now drop the fid reference, free it
 496         * if clunked.
 497         */
 498        put_fid(pdu, f);
 499    }
 500}
 501
 502static int coroutine_fn v9fs_mark_fids_unreclaim(V9fsPDU *pdu, V9fsPath *path)
 503{
 504    int err;
 505    V9fsState *s = pdu->s;
 506    V9fsFidState *fidp, head_fid;
 507
 508    head_fid.next = s->fid_list;
 509    for (fidp = s->fid_list; fidp; fidp = fidp->next) {
 510        if (fidp->path.size != path->size) {
 511            continue;
 512        }
 513        if (!memcmp(fidp->path.data, path->data, path->size)) {
 514            /* Mark the fid non reclaimable. */
 515            fidp->flags |= FID_NON_RECLAIMABLE;
 516
 517            /* reopen the file/dir if already closed */
 518            err = v9fs_reopen_fid(pdu, fidp);
 519            if (err < 0) {
 520                return -1;
 521            }
 522            /*
 523             * Go back to head of fid list because
 524             * the list could have got updated when
 525             * switched to the worker thread
 526             */
 527            if (err == 0) {
 528                fidp = &head_fid;
 529            }
 530        }
 531    }
 532    return 0;
 533}
 534
 535static void coroutine_fn virtfs_reset(V9fsPDU *pdu)
 536{
 537    V9fsState *s = pdu->s;
 538    V9fsFidState *fidp;
 539
 540    /* Free all fids */
 541    while (s->fid_list) {
 542        fidp = s->fid_list;
 543        s->fid_list = fidp->next;
 544
 545        if (fidp->ref) {
 546            fidp->clunked = 1;
 547        } else {
 548            free_fid(pdu, fidp);
 549        }
 550    }
 551}
 552
 553#define P9_QID_TYPE_DIR         0x80
 554#define P9_QID_TYPE_SYMLINK     0x02
 555
 556#define P9_STAT_MODE_DIR        0x80000000
 557#define P9_STAT_MODE_APPEND     0x40000000
 558#define P9_STAT_MODE_EXCL       0x20000000
 559#define P9_STAT_MODE_MOUNT      0x10000000
 560#define P9_STAT_MODE_AUTH       0x08000000
 561#define P9_STAT_MODE_TMP        0x04000000
 562#define P9_STAT_MODE_SYMLINK    0x02000000
 563#define P9_STAT_MODE_LINK       0x01000000
 564#define P9_STAT_MODE_DEVICE     0x00800000
 565#define P9_STAT_MODE_NAMED_PIPE 0x00200000
 566#define P9_STAT_MODE_SOCKET     0x00100000
 567#define P9_STAT_MODE_SETUID     0x00080000
 568#define P9_STAT_MODE_SETGID     0x00040000
 569#define P9_STAT_MODE_SETVTX     0x00010000
 570
 571#define P9_STAT_MODE_TYPE_BITS (P9_STAT_MODE_DIR |          \
 572                                P9_STAT_MODE_SYMLINK |      \
 573                                P9_STAT_MODE_LINK |         \
 574                                P9_STAT_MODE_DEVICE |       \
 575                                P9_STAT_MODE_NAMED_PIPE |   \
 576                                P9_STAT_MODE_SOCKET)
 577
 578/* This is the algorithm from ufs in spfs */
 579static void stat_to_qid(const struct stat *stbuf, V9fsQID *qidp)
 580{
 581    size_t size;
 582
 583    memset(&qidp->path, 0, sizeof(qidp->path));
 584    size = MIN(sizeof(stbuf->st_ino), sizeof(qidp->path));
 585    memcpy(&qidp->path, &stbuf->st_ino, size);
 586    qidp->version = stbuf->st_mtime ^ (stbuf->st_size << 8);
 587    qidp->type = 0;
 588    if (S_ISDIR(stbuf->st_mode)) {
 589        qidp->type |= P9_QID_TYPE_DIR;
 590    }
 591    if (S_ISLNK(stbuf->st_mode)) {
 592        qidp->type |= P9_QID_TYPE_SYMLINK;
 593    }
 594}
 595
 596static int coroutine_fn fid_to_qid(V9fsPDU *pdu, V9fsFidState *fidp,
 597                                   V9fsQID *qidp)
 598{
 599    struct stat stbuf;
 600    int err;
 601
 602    err = v9fs_co_lstat(pdu, &fidp->path, &stbuf);
 603    if (err < 0) {
 604        return err;
 605    }
 606    stat_to_qid(&stbuf, qidp);
 607    return 0;
 608}
 609
 610V9fsPDU *pdu_alloc(V9fsState *s)
 611{
 612    V9fsPDU *pdu = NULL;
 613
 614    if (!QLIST_EMPTY(&s->free_list)) {
 615        pdu = QLIST_FIRST(&s->free_list);
 616        QLIST_REMOVE(pdu, next);
 617        QLIST_INSERT_HEAD(&s->active_list, pdu, next);
 618    }
 619    return pdu;
 620}
 621
 622void pdu_free(V9fsPDU *pdu)
 623{
 624    V9fsState *s = pdu->s;
 625
 626    g_assert(!pdu->cancelled);
 627    QLIST_REMOVE(pdu, next);
 628    QLIST_INSERT_HEAD(&s->free_list, pdu, next);
 629}
 630
 631/*
 632 * We don't do error checking for pdu_marshal/unmarshal here
 633 * because we always expect to have enough space to encode
 634 * error details
 635 */
 636static void coroutine_fn pdu_complete(V9fsPDU *pdu, ssize_t len)
 637{
 638    int8_t id = pdu->id + 1; /* Response */
 639    V9fsState *s = pdu->s;
 640
 641    if (len < 0) {
 642        int err = -len;
 643        len = 7;
 644
 645        if (s->proto_version != V9FS_PROTO_2000L) {
 646            V9fsString str;
 647
 648            str.data = strerror(err);
 649            str.size = strlen(str.data);
 650
 651            len += pdu_marshal(pdu, len, "s", &str);
 652            id = P9_RERROR;
 653        }
 654
 655        len += pdu_marshal(pdu, len, "d", err);
 656
 657        if (s->proto_version == V9FS_PROTO_2000L) {
 658            id = P9_RLERROR;
 659        }
 660        trace_v9fs_rerror(pdu->tag, pdu->id, err); /* Trace ERROR */
 661    }
 662
 663    /* fill out the header */
 664    pdu_marshal(pdu, 0, "dbw", (int32_t)len, id, pdu->tag);
 665
 666    /* keep these in sync */
 667    pdu->size = len;
 668    pdu->id = id;
 669
 670    pdu_push_and_notify(pdu);
 671
 672    /* Now wakeup anybody waiting in flush for this request */
 673    if (!qemu_co_queue_next(&pdu->complete)) {
 674        pdu_free(pdu);
 675    }
 676}
 677
 678static mode_t v9mode_to_mode(uint32_t mode, V9fsString *extension)
 679{
 680    mode_t ret;
 681
 682    ret = mode & 0777;
 683    if (mode & P9_STAT_MODE_DIR) {
 684        ret |= S_IFDIR;
 685    }
 686
 687    if (mode & P9_STAT_MODE_SYMLINK) {
 688        ret |= S_IFLNK;
 689    }
 690    if (mode & P9_STAT_MODE_SOCKET) {
 691        ret |= S_IFSOCK;
 692    }
 693    if (mode & P9_STAT_MODE_NAMED_PIPE) {
 694        ret |= S_IFIFO;
 695    }
 696    if (mode & P9_STAT_MODE_DEVICE) {
 697        if (extension->size && extension->data[0] == 'c') {
 698            ret |= S_IFCHR;
 699        } else {
 700            ret |= S_IFBLK;
 701        }
 702    }
 703
 704    if (!(ret&~0777)) {
 705        ret |= S_IFREG;
 706    }
 707
 708    if (mode & P9_STAT_MODE_SETUID) {
 709        ret |= S_ISUID;
 710    }
 711    if (mode & P9_STAT_MODE_SETGID) {
 712        ret |= S_ISGID;
 713    }
 714    if (mode & P9_STAT_MODE_SETVTX) {
 715        ret |= S_ISVTX;
 716    }
 717
 718    return ret;
 719}
 720
 721static int donttouch_stat(V9fsStat *stat)
 722{
 723    if (stat->type == -1 &&
 724        stat->dev == -1 &&
 725        stat->qid.type == -1 &&
 726        stat->qid.version == -1 &&
 727        stat->qid.path == -1 &&
 728        stat->mode == -1 &&
 729        stat->atime == -1 &&
 730        stat->mtime == -1 &&
 731        stat->length == -1 &&
 732        !stat->name.size &&
 733        !stat->uid.size &&
 734        !stat->gid.size &&
 735        !stat->muid.size &&
 736        stat->n_uid == -1 &&
 737        stat->n_gid == -1 &&
 738        stat->n_muid == -1) {
 739        return 1;
 740    }
 741
 742    return 0;
 743}
 744
 745static void v9fs_stat_init(V9fsStat *stat)
 746{
 747    v9fs_string_init(&stat->name);
 748    v9fs_string_init(&stat->uid);
 749    v9fs_string_init(&stat->gid);
 750    v9fs_string_init(&stat->muid);
 751    v9fs_string_init(&stat->extension);
 752}
 753
 754static void v9fs_stat_free(V9fsStat *stat)
 755{
 756    v9fs_string_free(&stat->name);
 757    v9fs_string_free(&stat->uid);
 758    v9fs_string_free(&stat->gid);
 759    v9fs_string_free(&stat->muid);
 760    v9fs_string_free(&stat->extension);
 761}
 762
 763static uint32_t stat_to_v9mode(const struct stat *stbuf)
 764{
 765    uint32_t mode;
 766
 767    mode = stbuf->st_mode & 0777;
 768    if (S_ISDIR(stbuf->st_mode)) {
 769        mode |= P9_STAT_MODE_DIR;
 770    }
 771
 772    if (S_ISLNK(stbuf->st_mode)) {
 773        mode |= P9_STAT_MODE_SYMLINK;
 774    }
 775
 776    if (S_ISSOCK(stbuf->st_mode)) {
 777        mode |= P9_STAT_MODE_SOCKET;
 778    }
 779
 780    if (S_ISFIFO(stbuf->st_mode)) {
 781        mode |= P9_STAT_MODE_NAMED_PIPE;
 782    }
 783
 784    if (S_ISBLK(stbuf->st_mode) || S_ISCHR(stbuf->st_mode)) {
 785        mode |= P9_STAT_MODE_DEVICE;
 786    }
 787
 788    if (stbuf->st_mode & S_ISUID) {
 789        mode |= P9_STAT_MODE_SETUID;
 790    }
 791
 792    if (stbuf->st_mode & S_ISGID) {
 793        mode |= P9_STAT_MODE_SETGID;
 794    }
 795
 796    if (stbuf->st_mode & S_ISVTX) {
 797        mode |= P9_STAT_MODE_SETVTX;
 798    }
 799
 800    return mode;
 801}
 802
 803static int coroutine_fn stat_to_v9stat(V9fsPDU *pdu, V9fsPath *name,
 804                                       const struct stat *stbuf,
 805                                       V9fsStat *v9stat)
 806{
 807    int err;
 808    const char *str;
 809
 810    memset(v9stat, 0, sizeof(*v9stat));
 811
 812    stat_to_qid(stbuf, &v9stat->qid);
 813    v9stat->mode = stat_to_v9mode(stbuf);
 814    v9stat->atime = stbuf->st_atime;
 815    v9stat->mtime = stbuf->st_mtime;
 816    v9stat->length = stbuf->st_size;
 817
 818    v9fs_string_free(&v9stat->uid);
 819    v9fs_string_free(&v9stat->gid);
 820    v9fs_string_free(&v9stat->muid);
 821
 822    v9stat->n_uid = stbuf->st_uid;
 823    v9stat->n_gid = stbuf->st_gid;
 824    v9stat->n_muid = 0;
 825
 826    v9fs_string_free(&v9stat->extension);
 827
 828    if (v9stat->mode & P9_STAT_MODE_SYMLINK) {
 829        err = v9fs_co_readlink(pdu, name, &v9stat->extension);
 830        if (err < 0) {
 831            return err;
 832        }
 833    } else if (v9stat->mode & P9_STAT_MODE_DEVICE) {
 834        v9fs_string_sprintf(&v9stat->extension, "%c %u %u",
 835                S_ISCHR(stbuf->st_mode) ? 'c' : 'b',
 836                major(stbuf->st_rdev), minor(stbuf->st_rdev));
 837    } else if (S_ISDIR(stbuf->st_mode) || S_ISREG(stbuf->st_mode)) {
 838        v9fs_string_sprintf(&v9stat->extension, "%s %lu",
 839                "HARDLINKCOUNT", (unsigned long)stbuf->st_nlink);
 840    }
 841
 842    str = strrchr(name->data, '/');
 843    if (str) {
 844        str += 1;
 845    } else {
 846        str = name->data;
 847    }
 848
 849    v9fs_string_sprintf(&v9stat->name, "%s", str);
 850
 851    v9stat->size = 61 +
 852        v9fs_string_size(&v9stat->name) +
 853        v9fs_string_size(&v9stat->uid) +
 854        v9fs_string_size(&v9stat->gid) +
 855        v9fs_string_size(&v9stat->muid) +
 856        v9fs_string_size(&v9stat->extension);
 857    return 0;
 858}
 859
 860#define P9_STATS_MODE          0x00000001ULL
 861#define P9_STATS_NLINK         0x00000002ULL
 862#define P9_STATS_UID           0x00000004ULL
 863#define P9_STATS_GID           0x00000008ULL
 864#define P9_STATS_RDEV          0x00000010ULL
 865#define P9_STATS_ATIME         0x00000020ULL
 866#define P9_STATS_MTIME         0x00000040ULL
 867#define P9_STATS_CTIME         0x00000080ULL
 868#define P9_STATS_INO           0x00000100ULL
 869#define P9_STATS_SIZE          0x00000200ULL
 870#define P9_STATS_BLOCKS        0x00000400ULL
 871
 872#define P9_STATS_BTIME         0x00000800ULL
 873#define P9_STATS_GEN           0x00001000ULL
 874#define P9_STATS_DATA_VERSION  0x00002000ULL
 875
 876#define P9_STATS_BASIC         0x000007ffULL /* Mask for fields up to BLOCKS */
 877#define P9_STATS_ALL           0x00003fffULL /* Mask for All fields above */
 878
 879
 880static void stat_to_v9stat_dotl(V9fsState *s, const struct stat *stbuf,
 881                                V9fsStatDotl *v9lstat)
 882{
 883    memset(v9lstat, 0, sizeof(*v9lstat));
 884
 885    v9lstat->st_mode = stbuf->st_mode;
 886    v9lstat->st_nlink = stbuf->st_nlink;
 887    v9lstat->st_uid = stbuf->st_uid;
 888    v9lstat->st_gid = stbuf->st_gid;
 889    v9lstat->st_rdev = stbuf->st_rdev;
 890    v9lstat->st_size = stbuf->st_size;
 891    v9lstat->st_blksize = stbuf->st_blksize;
 892    v9lstat->st_blocks = stbuf->st_blocks;
 893    v9lstat->st_atime_sec = stbuf->st_atime;
 894    v9lstat->st_atime_nsec = stbuf->st_atim.tv_nsec;
 895    v9lstat->st_mtime_sec = stbuf->st_mtime;
 896    v9lstat->st_mtime_nsec = stbuf->st_mtim.tv_nsec;
 897    v9lstat->st_ctime_sec = stbuf->st_ctime;
 898    v9lstat->st_ctime_nsec = stbuf->st_ctim.tv_nsec;
 899    /* Currently we only support BASIC fields in stat */
 900    v9lstat->st_result_mask = P9_STATS_BASIC;
 901
 902    stat_to_qid(stbuf, &v9lstat->qid);
 903}
 904
 905static void print_sg(struct iovec *sg, int cnt)
 906{
 907    int i;
 908
 909    printf("sg[%d]: {", cnt);
 910    for (i = 0; i < cnt; i++) {
 911        if (i) {
 912            printf(", ");
 913        }
 914        printf("(%p, %zd)", sg[i].iov_base, sg[i].iov_len);
 915    }
 916    printf("}\n");
 917}
 918
 919/* Will call this only for path name based fid */
 920static void v9fs_fix_path(V9fsPath *dst, V9fsPath *src, int len)
 921{
 922    V9fsPath str;
 923    v9fs_path_init(&str);
 924    v9fs_path_copy(&str, dst);
 925    v9fs_path_sprintf(dst, "%s%s", src->data, str.data + len);
 926    v9fs_path_free(&str);
 927}
 928
 929static inline bool is_ro_export(FsContext *ctx)
 930{
 931    return ctx->export_flags & V9FS_RDONLY;
 932}
 933
 934static void coroutine_fn v9fs_version(void *opaque)
 935{
 936    ssize_t err;
 937    V9fsPDU *pdu = opaque;
 938    V9fsState *s = pdu->s;
 939    V9fsString version;
 940    size_t offset = 7;
 941
 942    v9fs_string_init(&version);
 943    err = pdu_unmarshal(pdu, offset, "ds", &s->msize, &version);
 944    if (err < 0) {
 945        offset = err;
 946        goto out;
 947    }
 948    trace_v9fs_version(pdu->tag, pdu->id, s->msize, version.data);
 949
 950    virtfs_reset(pdu);
 951
 952    if (!strcmp(version.data, "9P2000.u")) {
 953        s->proto_version = V9FS_PROTO_2000U;
 954    } else if (!strcmp(version.data, "9P2000.L")) {
 955        s->proto_version = V9FS_PROTO_2000L;
 956    } else {
 957        v9fs_string_sprintf(&version, "unknown");
 958    }
 959
 960    err = pdu_marshal(pdu, offset, "ds", s->msize, &version);
 961    if (err < 0) {
 962        offset = err;
 963        goto out;
 964    }
 965    offset += err;
 966    trace_v9fs_version_return(pdu->tag, pdu->id, s->msize, version.data);
 967out:
 968    pdu_complete(pdu, offset);
 969    v9fs_string_free(&version);
 970}
 971
 972static void coroutine_fn v9fs_attach(void *opaque)
 973{
 974    V9fsPDU *pdu = opaque;
 975    V9fsState *s = pdu->s;
 976    int32_t fid, afid, n_uname;
 977    V9fsString uname, aname;
 978    V9fsFidState *fidp;
 979    size_t offset = 7;
 980    V9fsQID qid;
 981    ssize_t err;
 982
 983    v9fs_string_init(&uname);
 984    v9fs_string_init(&aname);
 985    err = pdu_unmarshal(pdu, offset, "ddssd", &fid,
 986                        &afid, &uname, &aname, &n_uname);
 987    if (err < 0) {
 988        goto out_nofid;
 989    }
 990    trace_v9fs_attach(pdu->tag, pdu->id, fid, afid, uname.data, aname.data);
 991
 992    fidp = alloc_fid(s, fid);
 993    if (fidp == NULL) {
 994        err = -EINVAL;
 995        goto out_nofid;
 996    }
 997    fidp->uid = n_uname;
 998    err = v9fs_co_name_to_path(pdu, NULL, "/", &fidp->path);
 999    if (err < 0) {
1000        err = -EINVAL;
1001        clunk_fid(s, fid);
1002        goto out;
1003    }
1004    err = fid_to_qid(pdu, fidp, &qid);
1005    if (err < 0) {
1006        err = -EINVAL;
1007        clunk_fid(s, fid);
1008        goto out;
1009    }
1010    err = pdu_marshal(pdu, offset, "Q", &qid);
1011    if (err < 0) {
1012        clunk_fid(s, fid);
1013        goto out;
1014    }
1015    err += offset;
1016    memcpy(&s->root_qid, &qid, sizeof(qid));
1017    trace_v9fs_attach_return(pdu->tag, pdu->id,
1018                             qid.type, qid.version, qid.path);
1019    /*
1020     * disable migration if we haven't done already.
1021     * attach could get called multiple times for the same export.
1022     */
1023    if (!s->migration_blocker) {
1024        s->root_fid = fid;
1025        error_setg(&s->migration_blocker,
1026                   "Migration is disabled when VirtFS export path '%s' is mounted in the guest using mount_tag '%s'",
1027                   s->ctx.fs_root ? s->ctx.fs_root : "NULL", s->tag);
1028        migrate_add_blocker(s->migration_blocker);
1029    }
1030out:
1031    put_fid(pdu, fidp);
1032out_nofid:
1033    pdu_complete(pdu, err);
1034    v9fs_string_free(&uname);
1035    v9fs_string_free(&aname);
1036}
1037
1038static void coroutine_fn v9fs_stat(void *opaque)
1039{
1040    int32_t fid;
1041    V9fsStat v9stat;
1042    ssize_t err = 0;
1043    size_t offset = 7;
1044    struct stat stbuf;
1045    V9fsFidState *fidp;
1046    V9fsPDU *pdu = opaque;
1047
1048    err = pdu_unmarshal(pdu, offset, "d", &fid);
1049    if (err < 0) {
1050        goto out_nofid;
1051    }
1052    trace_v9fs_stat(pdu->tag, pdu->id, fid);
1053
1054    fidp = get_fid(pdu, fid);
1055    if (fidp == NULL) {
1056        err = -ENOENT;
1057        goto out_nofid;
1058    }
1059    err = v9fs_co_lstat(pdu, &fidp->path, &stbuf);
1060    if (err < 0) {
1061        goto out;
1062    }
1063    err = stat_to_v9stat(pdu, &fidp->path, &stbuf, &v9stat);
1064    if (err < 0) {
1065        goto out;
1066    }
1067    err = pdu_marshal(pdu, offset, "wS", 0, &v9stat);
1068    if (err < 0) {
1069        v9fs_stat_free(&v9stat);
1070        goto out;
1071    }
1072    trace_v9fs_stat_return(pdu->tag, pdu->id, v9stat.mode,
1073                           v9stat.atime, v9stat.mtime, v9stat.length);
1074    err += offset;
1075    v9fs_stat_free(&v9stat);
1076out:
1077    put_fid(pdu, fidp);
1078out_nofid:
1079    pdu_complete(pdu, err);
1080}
1081
1082static void coroutine_fn v9fs_getattr(void *opaque)
1083{
1084    int32_t fid;
1085    size_t offset = 7;
1086    ssize_t retval = 0;
1087    struct stat stbuf;
1088    V9fsFidState *fidp;
1089    uint64_t request_mask;
1090    V9fsStatDotl v9stat_dotl;
1091    V9fsPDU *pdu = opaque;
1092    V9fsState *s = pdu->s;
1093
1094    retval = pdu_unmarshal(pdu, offset, "dq", &fid, &request_mask);
1095    if (retval < 0) {
1096        goto out_nofid;
1097    }
1098    trace_v9fs_getattr(pdu->tag, pdu->id, fid, request_mask);
1099
1100    fidp = get_fid(pdu, fid);
1101    if (fidp == NULL) {
1102        retval = -ENOENT;
1103        goto out_nofid;
1104    }
1105    /*
1106     * Currently we only support BASIC fields in stat, so there is no
1107     * need to look at request_mask.
1108     */
1109    retval = v9fs_co_lstat(pdu, &fidp->path, &stbuf);
1110    if (retval < 0) {
1111        goto out;
1112    }
1113    stat_to_v9stat_dotl(s, &stbuf, &v9stat_dotl);
1114
1115    /*  fill st_gen if requested and supported by underlying fs */
1116    if (request_mask & P9_STATS_GEN) {
1117        retval = v9fs_co_st_gen(pdu, &fidp->path, stbuf.st_mode, &v9stat_dotl);
1118        switch (retval) {
1119        case 0:
1120            /* we have valid st_gen: update result mask */
1121            v9stat_dotl.st_result_mask |= P9_STATS_GEN;
1122            break;
1123        case -EINTR:
1124            /* request cancelled, e.g. by Tflush */
1125            goto out;
1126        default:
1127            /* failed to get st_gen: not fatal, ignore */
1128            break;
1129        }
1130    }
1131    retval = pdu_marshal(pdu, offset, "A", &v9stat_dotl);
1132    if (retval < 0) {
1133        goto out;
1134    }
1135    retval += offset;
1136    trace_v9fs_getattr_return(pdu->tag, pdu->id, v9stat_dotl.st_result_mask,
1137                              v9stat_dotl.st_mode, v9stat_dotl.st_uid,
1138                              v9stat_dotl.st_gid);
1139out:
1140    put_fid(pdu, fidp);
1141out_nofid:
1142    pdu_complete(pdu, retval);
1143}
1144
1145/* Attribute flags */
1146#define P9_ATTR_MODE       (1 << 0)
1147#define P9_ATTR_UID        (1 << 1)
1148#define P9_ATTR_GID        (1 << 2)
1149#define P9_ATTR_SIZE       (1 << 3)
1150#define P9_ATTR_ATIME      (1 << 4)
1151#define P9_ATTR_MTIME      (1 << 5)
1152#define P9_ATTR_CTIME      (1 << 6)
1153#define P9_ATTR_ATIME_SET  (1 << 7)
1154#define P9_ATTR_MTIME_SET  (1 << 8)
1155
1156#define P9_ATTR_MASK    127
1157
1158static void coroutine_fn v9fs_setattr(void *opaque)
1159{
1160    int err = 0;
1161    int32_t fid;
1162    V9fsFidState *fidp;
1163    size_t offset = 7;
1164    V9fsIattr v9iattr;
1165    V9fsPDU *pdu = opaque;
1166
1167    err = pdu_unmarshal(pdu, offset, "dI", &fid, &v9iattr);
1168    if (err < 0) {
1169        goto out_nofid;
1170    }
1171
1172    fidp = get_fid(pdu, fid);
1173    if (fidp == NULL) {
1174        err = -EINVAL;
1175        goto out_nofid;
1176    }
1177    if (v9iattr.valid & P9_ATTR_MODE) {
1178        err = v9fs_co_chmod(pdu, &fidp->path, v9iattr.mode);
1179        if (err < 0) {
1180            goto out;
1181        }
1182    }
1183    if (v9iattr.valid & (P9_ATTR_ATIME | P9_ATTR_MTIME)) {
1184        struct timespec times[2];
1185        if (v9iattr.valid & P9_ATTR_ATIME) {
1186            if (v9iattr.valid & P9_ATTR_ATIME_SET) {
1187                times[0].tv_sec = v9iattr.atime_sec;
1188                times[0].tv_nsec = v9iattr.atime_nsec;
1189            } else {
1190                times[0].tv_nsec = UTIME_NOW;
1191            }
1192        } else {
1193            times[0].tv_nsec = UTIME_OMIT;
1194        }
1195        if (v9iattr.valid & P9_ATTR_MTIME) {
1196            if (v9iattr.valid & P9_ATTR_MTIME_SET) {
1197                times[1].tv_sec = v9iattr.mtime_sec;
1198                times[1].tv_nsec = v9iattr.mtime_nsec;
1199            } else {
1200                times[1].tv_nsec = UTIME_NOW;
1201            }
1202        } else {
1203            times[1].tv_nsec = UTIME_OMIT;
1204        }
1205        err = v9fs_co_utimensat(pdu, &fidp->path, times);
1206        if (err < 0) {
1207            goto out;
1208        }
1209    }
1210    /*
1211     * If the only valid entry in iattr is ctime we can call
1212     * chown(-1,-1) to update the ctime of the file
1213     */
1214    if ((v9iattr.valid & (P9_ATTR_UID | P9_ATTR_GID)) ||
1215        ((v9iattr.valid & P9_ATTR_CTIME)
1216         && !((v9iattr.valid & P9_ATTR_MASK) & ~P9_ATTR_CTIME))) {
1217        if (!(v9iattr.valid & P9_ATTR_UID)) {
1218            v9iattr.uid = -1;
1219        }
1220        if (!(v9iattr.valid & P9_ATTR_GID)) {
1221            v9iattr.gid = -1;
1222        }
1223        err = v9fs_co_chown(pdu, &fidp->path, v9iattr.uid,
1224                            v9iattr.gid);
1225        if (err < 0) {
1226            goto out;
1227        }
1228    }
1229    if (v9iattr.valid & (P9_ATTR_SIZE)) {
1230        err = v9fs_co_truncate(pdu, &fidp->path, v9iattr.size);
1231        if (err < 0) {
1232            goto out;
1233        }
1234    }
1235    err = offset;
1236out:
1237    put_fid(pdu, fidp);
1238out_nofid:
1239    pdu_complete(pdu, err);
1240}
1241
1242static int v9fs_walk_marshal(V9fsPDU *pdu, uint16_t nwnames, V9fsQID *qids)
1243{
1244    int i;
1245    ssize_t err;
1246    size_t offset = 7;
1247
1248    err = pdu_marshal(pdu, offset, "w", nwnames);
1249    if (err < 0) {
1250        return err;
1251    }
1252    offset += err;
1253    for (i = 0; i < nwnames; i++) {
1254        err = pdu_marshal(pdu, offset, "Q", &qids[i]);
1255        if (err < 0) {
1256            return err;
1257        }
1258        offset += err;
1259    }
1260    return offset;
1261}
1262
1263static bool name_is_illegal(const char *name)
1264{
1265    return !*name || strchr(name, '/') != NULL;
1266}
1267
1268static bool not_same_qid(const V9fsQID *qid1, const V9fsQID *qid2)
1269{
1270    return
1271        qid1->type != qid2->type ||
1272        qid1->version != qid2->version ||
1273        qid1->path != qid2->path;
1274}
1275
1276static void coroutine_fn v9fs_walk(void *opaque)
1277{
1278    int name_idx;
1279    V9fsQID *qids = NULL;
1280    int i, err = 0;
1281    V9fsPath dpath, path;
1282    uint16_t nwnames;
1283    struct stat stbuf;
1284    size_t offset = 7;
1285    int32_t fid, newfid;
1286    V9fsString *wnames = NULL;
1287    V9fsFidState *fidp;
1288    V9fsFidState *newfidp = NULL;
1289    V9fsPDU *pdu = opaque;
1290    V9fsState *s = pdu->s;
1291    V9fsQID qid;
1292
1293    err = pdu_unmarshal(pdu, offset, "ddw", &fid, &newfid, &nwnames);
1294    if (err < 0) {
1295        pdu_complete(pdu, err);
1296        return ;
1297    }
1298    offset += err;
1299
1300    trace_v9fs_walk(pdu->tag, pdu->id, fid, newfid, nwnames);
1301
1302    if (nwnames && nwnames <= P9_MAXWELEM) {
1303        wnames = g_malloc0(sizeof(wnames[0]) * nwnames);
1304        qids   = g_malloc0(sizeof(qids[0]) * nwnames);
1305        for (i = 0; i < nwnames; i++) {
1306            err = pdu_unmarshal(pdu, offset, "s", &wnames[i]);
1307            if (err < 0) {
1308                goto out_nofid;
1309            }
1310            if (name_is_illegal(wnames[i].data)) {
1311                err = -ENOENT;
1312                goto out_nofid;
1313            }
1314            offset += err;
1315        }
1316    } else if (nwnames > P9_MAXWELEM) {
1317        err = -EINVAL;
1318        goto out_nofid;
1319    }
1320    fidp = get_fid(pdu, fid);
1321    if (fidp == NULL) {
1322        err = -ENOENT;
1323        goto out_nofid;
1324    }
1325
1326    v9fs_path_init(&dpath);
1327    v9fs_path_init(&path);
1328
1329    err = fid_to_qid(pdu, fidp, &qid);
1330    if (err < 0) {
1331        goto out;
1332    }
1333
1334    /*
1335     * Both dpath and path initially poin to fidp.
1336     * Needed to handle request with nwnames == 0
1337     */
1338    v9fs_path_copy(&dpath, &fidp->path);
1339    v9fs_path_copy(&path, &fidp->path);
1340    for (name_idx = 0; name_idx < nwnames; name_idx++) {
1341        if (not_same_qid(&pdu->s->root_qid, &qid) ||
1342            strcmp("..", wnames[name_idx].data)) {
1343            err = v9fs_co_name_to_path(pdu, &dpath, wnames[name_idx].data,
1344                                       &path);
1345            if (err < 0) {
1346                goto out;
1347            }
1348
1349            err = v9fs_co_lstat(pdu, &path, &stbuf);
1350            if (err < 0) {
1351                goto out;
1352            }
1353            stat_to_qid(&stbuf, &qid);
1354            v9fs_path_copy(&dpath, &path);
1355        }
1356        memcpy(&qids[name_idx], &qid, sizeof(qid));
1357    }
1358    if (fid == newfid) {
1359        if (fidp->fid_type != P9_FID_NONE) {
1360            err = -EINVAL;
1361            goto out;
1362        }
1363        v9fs_path_copy(&fidp->path, &path);
1364    } else {
1365        newfidp = alloc_fid(s, newfid);
1366        if (newfidp == NULL) {
1367            err = -EINVAL;
1368            goto out;
1369        }
1370        newfidp->uid = fidp->uid;
1371        v9fs_path_copy(&newfidp->path, &path);
1372    }
1373    err = v9fs_walk_marshal(pdu, nwnames, qids);
1374    trace_v9fs_walk_return(pdu->tag, pdu->id, nwnames, qids);
1375out:
1376    put_fid(pdu, fidp);
1377    if (newfidp) {
1378        put_fid(pdu, newfidp);
1379    }
1380    v9fs_path_free(&dpath);
1381    v9fs_path_free(&path);
1382out_nofid:
1383    pdu_complete(pdu, err);
1384    if (nwnames && nwnames <= P9_MAXWELEM) {
1385        for (name_idx = 0; name_idx < nwnames; name_idx++) {
1386            v9fs_string_free(&wnames[name_idx]);
1387        }
1388        g_free(wnames);
1389        g_free(qids);
1390    }
1391}
1392
1393static int32_t coroutine_fn get_iounit(V9fsPDU *pdu, V9fsPath *path)
1394{
1395    struct statfs stbuf;
1396    int32_t iounit = 0;
1397    V9fsState *s = pdu->s;
1398
1399    /*
1400     * iounit should be multiples of f_bsize (host filesystem block size
1401     * and as well as less than (client msize - P9_IOHDRSZ))
1402     */
1403    if (!v9fs_co_statfs(pdu, path, &stbuf)) {
1404        iounit = stbuf.f_bsize;
1405        iounit *= (s->msize - P9_IOHDRSZ)/stbuf.f_bsize;
1406    }
1407    if (!iounit) {
1408        iounit = s->msize - P9_IOHDRSZ;
1409    }
1410    return iounit;
1411}
1412
1413static void coroutine_fn v9fs_open(void *opaque)
1414{
1415    int flags;
1416    int32_t fid;
1417    int32_t mode;
1418    V9fsQID qid;
1419    int iounit = 0;
1420    ssize_t err = 0;
1421    size_t offset = 7;
1422    struct stat stbuf;
1423    V9fsFidState *fidp;
1424    V9fsPDU *pdu = opaque;
1425    V9fsState *s = pdu->s;
1426
1427    if (s->proto_version == V9FS_PROTO_2000L) {
1428        err = pdu_unmarshal(pdu, offset, "dd", &fid, &mode);
1429    } else {
1430        uint8_t modebyte;
1431        err = pdu_unmarshal(pdu, offset, "db", &fid, &modebyte);
1432        mode = modebyte;
1433    }
1434    if (err < 0) {
1435        goto out_nofid;
1436    }
1437    trace_v9fs_open(pdu->tag, pdu->id, fid, mode);
1438
1439    fidp = get_fid(pdu, fid);
1440    if (fidp == NULL) {
1441        err = -ENOENT;
1442        goto out_nofid;
1443    }
1444    if (fidp->fid_type != P9_FID_NONE) {
1445        err = -EINVAL;
1446        goto out;
1447    }
1448
1449    err = v9fs_co_lstat(pdu, &fidp->path, &stbuf);
1450    if (err < 0) {
1451        goto out;
1452    }
1453    stat_to_qid(&stbuf, &qid);
1454    if (S_ISDIR(stbuf.st_mode)) {
1455        err = v9fs_co_opendir(pdu, fidp);
1456        if (err < 0) {
1457            goto out;
1458        }
1459        fidp->fid_type = P9_FID_DIR;
1460        err = pdu_marshal(pdu, offset, "Qd", &qid, 0);
1461        if (err < 0) {
1462            goto out;
1463        }
1464        err += offset;
1465    } else {
1466        if (s->proto_version == V9FS_PROTO_2000L) {
1467            flags = get_dotl_openflags(s, mode);
1468        } else {
1469            flags = omode_to_uflags(mode);
1470        }
1471        if (is_ro_export(&s->ctx)) {
1472            if (mode & O_WRONLY || mode & O_RDWR ||
1473                mode & O_APPEND || mode & O_TRUNC) {
1474                err = -EROFS;
1475                goto out;
1476            }
1477        }
1478        err = v9fs_co_open(pdu, fidp, flags);
1479        if (err < 0) {
1480            goto out;
1481        }
1482        fidp->fid_type = P9_FID_FILE;
1483        fidp->open_flags = flags;
1484        if (flags & O_EXCL) {
1485            /*
1486             * We let the host file system do O_EXCL check
1487             * We should not reclaim such fd
1488             */
1489            fidp->flags |= FID_NON_RECLAIMABLE;
1490        }
1491        iounit = get_iounit(pdu, &fidp->path);
1492        err = pdu_marshal(pdu, offset, "Qd", &qid, iounit);
1493        if (err < 0) {
1494            goto out;
1495        }
1496        err += offset;
1497    }
1498    trace_v9fs_open_return(pdu->tag, pdu->id,
1499                           qid.type, qid.version, qid.path, iounit);
1500out:
1501    put_fid(pdu, fidp);
1502out_nofid:
1503    pdu_complete(pdu, err);
1504}
1505
1506static void coroutine_fn v9fs_lcreate(void *opaque)
1507{
1508    int32_t dfid, flags, mode;
1509    gid_t gid;
1510    ssize_t err = 0;
1511    ssize_t offset = 7;
1512    V9fsString name;
1513    V9fsFidState *fidp;
1514    struct stat stbuf;
1515    V9fsQID qid;
1516    int32_t iounit;
1517    V9fsPDU *pdu = opaque;
1518
1519    v9fs_string_init(&name);
1520    err = pdu_unmarshal(pdu, offset, "dsddd", &dfid,
1521                        &name, &flags, &mode, &gid);
1522    if (err < 0) {
1523        goto out_nofid;
1524    }
1525    trace_v9fs_lcreate(pdu->tag, pdu->id, dfid, flags, mode, gid);
1526
1527    if (name_is_illegal(name.data)) {
1528        err = -ENOENT;
1529        goto out_nofid;
1530    }
1531
1532    if (!strcmp(".", name.data) || !strcmp("..", name.data)) {
1533        err = -EEXIST;
1534        goto out_nofid;
1535    }
1536
1537    fidp = get_fid(pdu, dfid);
1538    if (fidp == NULL) {
1539        err = -ENOENT;
1540        goto out_nofid;
1541    }
1542
1543    flags = get_dotl_openflags(pdu->s, flags);
1544    err = v9fs_co_open2(pdu, fidp, &name, gid,
1545                        flags | O_CREAT, mode, &stbuf);
1546    if (err < 0) {
1547        goto out;
1548    }
1549    fidp->fid_type = P9_FID_FILE;
1550    fidp->open_flags = flags;
1551    if (flags & O_EXCL) {
1552        /*
1553         * We let the host file system do O_EXCL check
1554         * We should not reclaim such fd
1555         */
1556        fidp->flags |= FID_NON_RECLAIMABLE;
1557    }
1558    iounit =  get_iounit(pdu, &fidp->path);
1559    stat_to_qid(&stbuf, &qid);
1560    err = pdu_marshal(pdu, offset, "Qd", &qid, iounit);
1561    if (err < 0) {
1562        goto out;
1563    }
1564    err += offset;
1565    trace_v9fs_lcreate_return(pdu->tag, pdu->id,
1566                              qid.type, qid.version, qid.path, iounit);
1567out:
1568    put_fid(pdu, fidp);
1569out_nofid:
1570    pdu_complete(pdu, err);
1571    v9fs_string_free(&name);
1572}
1573
1574static void v9fs_fsync(void *opaque)
1575{
1576    int err;
1577    int32_t fid;
1578    int datasync;
1579    size_t offset = 7;
1580    V9fsFidState *fidp;
1581    V9fsPDU *pdu = opaque;
1582
1583    err = pdu_unmarshal(pdu, offset, "dd", &fid, &datasync);
1584    if (err < 0) {
1585        goto out_nofid;
1586    }
1587    trace_v9fs_fsync(pdu->tag, pdu->id, fid, datasync);
1588
1589    fidp = get_fid(pdu, fid);
1590    if (fidp == NULL) {
1591        err = -ENOENT;
1592        goto out_nofid;
1593    }
1594    err = v9fs_co_fsync(pdu, fidp, datasync);
1595    if (!err) {
1596        err = offset;
1597    }
1598    put_fid(pdu, fidp);
1599out_nofid:
1600    pdu_complete(pdu, err);
1601}
1602
1603static void coroutine_fn v9fs_clunk(void *opaque)
1604{
1605    int err;
1606    int32_t fid;
1607    size_t offset = 7;
1608    V9fsFidState *fidp;
1609    V9fsPDU *pdu = opaque;
1610    V9fsState *s = pdu->s;
1611
1612    err = pdu_unmarshal(pdu, offset, "d", &fid);
1613    if (err < 0) {
1614        goto out_nofid;
1615    }
1616    trace_v9fs_clunk(pdu->tag, pdu->id, fid);
1617
1618    fidp = clunk_fid(s, fid);
1619    if (fidp == NULL) {
1620        err = -ENOENT;
1621        goto out_nofid;
1622    }
1623    /*
1624     * Bump the ref so that put_fid will
1625     * free the fid.
1626     */
1627    fidp->ref++;
1628    err = put_fid(pdu, fidp);
1629    if (!err) {
1630        err = offset;
1631    }
1632out_nofid:
1633    pdu_complete(pdu, err);
1634}
1635
1636static int v9fs_xattr_read(V9fsState *s, V9fsPDU *pdu, V9fsFidState *fidp,
1637                           uint64_t off, uint32_t max_count)
1638{
1639    ssize_t err;
1640    size_t offset = 7;
1641    uint64_t read_count;
1642    V9fsVirtioState *v = container_of(s, V9fsVirtioState, state);
1643    VirtQueueElement *elem = v->elems[pdu->idx];
1644
1645    if (fidp->fs.xattr.len < off) {
1646        read_count = 0;
1647    } else {
1648        read_count = fidp->fs.xattr.len - off;
1649    }
1650    if (read_count > max_count) {
1651        read_count = max_count;
1652    }
1653    err = pdu_marshal(pdu, offset, "d", read_count);
1654    if (err < 0) {
1655        return err;
1656    }
1657    offset += err;
1658
1659    err = v9fs_pack(elem->in_sg, elem->in_num, offset,
1660                    ((char *)fidp->fs.xattr.value) + off,
1661                    read_count);
1662    if (err < 0) {
1663        return err;
1664    }
1665    offset += err;
1666    return offset;
1667}
1668
1669static int coroutine_fn v9fs_do_readdir_with_stat(V9fsPDU *pdu,
1670                                                  V9fsFidState *fidp,
1671                                                  uint32_t max_count)
1672{
1673    V9fsPath path;
1674    V9fsStat v9stat;
1675    int len, err = 0;
1676    int32_t count = 0;
1677    struct stat stbuf;
1678    off_t saved_dir_pos;
1679    struct dirent *dent;
1680
1681    /* save the directory position */
1682    saved_dir_pos = v9fs_co_telldir(pdu, fidp);
1683    if (saved_dir_pos < 0) {
1684        return saved_dir_pos;
1685    }
1686
1687    while (1) {
1688        v9fs_path_init(&path);
1689
1690        v9fs_readdir_lock(&fidp->fs.dir);
1691
1692        err = v9fs_co_readdir(pdu, fidp, &dent);
1693        if (err || !dent) {
1694            break;
1695        }
1696        err = v9fs_co_name_to_path(pdu, &fidp->path, dent->d_name, &path);
1697        if (err < 0) {
1698            break;
1699        }
1700        err = v9fs_co_lstat(pdu, &path, &stbuf);
1701        if (err < 0) {
1702            break;
1703        }
1704        err = stat_to_v9stat(pdu, &path, &stbuf, &v9stat);
1705        if (err < 0) {
1706            break;
1707        }
1708        /* 11 = 7 + 4 (7 = start offset, 4 = space for storing count) */
1709        len = pdu_marshal(pdu, 11 + count, "S", &v9stat);
1710
1711        v9fs_readdir_unlock(&fidp->fs.dir);
1712
1713        if ((len != (v9stat.size + 2)) || ((count + len) > max_count)) {
1714            /* Ran out of buffer. Set dir back to old position and return */
1715            v9fs_co_seekdir(pdu, fidp, saved_dir_pos);
1716            v9fs_stat_free(&v9stat);
1717            v9fs_path_free(&path);
1718            return count;
1719        }
1720        count += len;
1721        v9fs_stat_free(&v9stat);
1722        v9fs_path_free(&path);
1723        saved_dir_pos = dent->d_off;
1724    }
1725
1726    v9fs_readdir_unlock(&fidp->fs.dir);
1727
1728    v9fs_path_free(&path);
1729    if (err < 0) {
1730        return err;
1731    }
1732    return count;
1733}
1734
1735/*
1736 * Create a QEMUIOVector for a sub-region of PDU iovecs
1737 *
1738 * @qiov:       uninitialized QEMUIOVector
1739 * @skip:       number of bytes to skip from beginning of PDU
1740 * @size:       number of bytes to include
1741 * @is_write:   true - write, false - read
1742 *
1743 * The resulting QEMUIOVector has heap-allocated iovecs and must be cleaned up
1744 * with qemu_iovec_destroy().
1745 */
1746static void v9fs_init_qiov_from_pdu(QEMUIOVector *qiov, V9fsPDU *pdu,
1747                                    size_t skip, size_t size,
1748                                    bool is_write)
1749{
1750    QEMUIOVector elem;
1751    struct iovec *iov;
1752    unsigned int niov;
1753
1754    virtio_init_iov_from_pdu(pdu, &iov, &niov, is_write);
1755
1756    qemu_iovec_init_external(&elem, iov, niov);
1757    qemu_iovec_init(qiov, niov);
1758    qemu_iovec_concat(qiov, &elem, skip, size);
1759}
1760
1761static void coroutine_fn v9fs_read(void *opaque)
1762{
1763    int32_t fid;
1764    uint64_t off;
1765    ssize_t err = 0;
1766    int32_t count = 0;
1767    size_t offset = 7;
1768    uint32_t max_count;
1769    V9fsFidState *fidp;
1770    V9fsPDU *pdu = opaque;
1771    V9fsState *s = pdu->s;
1772
1773    err = pdu_unmarshal(pdu, offset, "dqd", &fid, &off, &max_count);
1774    if (err < 0) {
1775        goto out_nofid;
1776    }
1777    trace_v9fs_read(pdu->tag, pdu->id, fid, off, max_count);
1778
1779    fidp = get_fid(pdu, fid);
1780    if (fidp == NULL) {
1781        err = -EINVAL;
1782        goto out_nofid;
1783    }
1784    if (fidp->fid_type == P9_FID_DIR) {
1785
1786        if (off == 0) {
1787            v9fs_co_rewinddir(pdu, fidp);
1788        }
1789        count = v9fs_do_readdir_with_stat(pdu, fidp, max_count);
1790        if (count < 0) {
1791            err = count;
1792            goto out;
1793        }
1794        err = pdu_marshal(pdu, offset, "d", count);
1795        if (err < 0) {
1796            goto out;
1797        }
1798        err += offset + count;
1799    } else if (fidp->fid_type == P9_FID_FILE) {
1800        QEMUIOVector qiov_full;
1801        QEMUIOVector qiov;
1802        int32_t len;
1803
1804        v9fs_init_qiov_from_pdu(&qiov_full, pdu, offset + 4, max_count, false);
1805        qemu_iovec_init(&qiov, qiov_full.niov);
1806        do {
1807            qemu_iovec_reset(&qiov);
1808            qemu_iovec_concat(&qiov, &qiov_full, count, qiov_full.size - count);
1809            if (0) {
1810                print_sg(qiov.iov, qiov.niov);
1811            }
1812            /* Loop in case of EINTR */
1813            do {
1814                len = v9fs_co_preadv(pdu, fidp, qiov.iov, qiov.niov, off);
1815                if (len >= 0) {
1816                    off   += len;
1817                    count += len;
1818                }
1819            } while (len == -EINTR && !pdu->cancelled);
1820            if (len < 0) {
1821                /* IO error return the error */
1822                err = len;
1823                goto out_free_iovec;
1824            }
1825        } while (count < max_count && len > 0);
1826        err = pdu_marshal(pdu, offset, "d", count);
1827        if (err < 0) {
1828            goto out_free_iovec;
1829        }
1830        err += offset + count;
1831out_free_iovec:
1832        qemu_iovec_destroy(&qiov);
1833        qemu_iovec_destroy(&qiov_full);
1834    } else if (fidp->fid_type == P9_FID_XATTR) {
1835        err = v9fs_xattr_read(s, pdu, fidp, off, max_count);
1836    } else {
1837        err = -EINVAL;
1838    }
1839    trace_v9fs_read_return(pdu->tag, pdu->id, count, err);
1840out:
1841    put_fid(pdu, fidp);
1842out_nofid:
1843    pdu_complete(pdu, err);
1844}
1845
1846static size_t v9fs_readdir_data_size(V9fsString *name)
1847{
1848    /*
1849     * Size of each dirent on the wire: size of qid (13) + size of offset (8)
1850     * size of type (1) + size of name.size (2) + strlen(name.data)
1851     */
1852    return 24 + v9fs_string_size(name);
1853}
1854
1855static int coroutine_fn v9fs_do_readdir(V9fsPDU *pdu, V9fsFidState *fidp,
1856                                        int32_t max_count)
1857{
1858    size_t size;
1859    V9fsQID qid;
1860    V9fsString name;
1861    int len, err = 0;
1862    int32_t count = 0;
1863    off_t saved_dir_pos;
1864    struct dirent *dent;
1865
1866    /* save the directory position */
1867    saved_dir_pos = v9fs_co_telldir(pdu, fidp);
1868    if (saved_dir_pos < 0) {
1869        return saved_dir_pos;
1870    }
1871
1872    while (1) {
1873        v9fs_readdir_lock(&fidp->fs.dir);
1874
1875        err = v9fs_co_readdir(pdu, fidp, &dent);
1876        if (err || !dent) {
1877            break;
1878        }
1879        v9fs_string_init(&name);
1880        v9fs_string_sprintf(&name, "%s", dent->d_name);
1881        if ((count + v9fs_readdir_data_size(&name)) > max_count) {
1882            v9fs_readdir_unlock(&fidp->fs.dir);
1883
1884            /* Ran out of buffer. Set dir back to old position and return */
1885            v9fs_co_seekdir(pdu, fidp, saved_dir_pos);
1886            v9fs_string_free(&name);
1887            return count;
1888        }
1889        /*
1890         * Fill up just the path field of qid because the client uses
1891         * only that. To fill the entire qid structure we will have
1892         * to stat each dirent found, which is expensive
1893         */
1894        size = MIN(sizeof(dent->d_ino), sizeof(qid.path));
1895        memcpy(&qid.path, &dent->d_ino, size);
1896        /* Fill the other fields with dummy values */
1897        qid.type = 0;
1898        qid.version = 0;
1899
1900        /* 11 = 7 + 4 (7 = start offset, 4 = space for storing count) */
1901        len = pdu_marshal(pdu, 11 + count, "Qqbs",
1902                          &qid, dent->d_off,
1903                          dent->d_type, &name);
1904
1905        v9fs_readdir_unlock(&fidp->fs.dir);
1906
1907        if (len < 0) {
1908            v9fs_co_seekdir(pdu, fidp, saved_dir_pos);
1909            v9fs_string_free(&name);
1910            return len;
1911        }
1912        count += len;
1913        v9fs_string_free(&name);
1914        saved_dir_pos = dent->d_off;
1915    }
1916
1917    v9fs_readdir_unlock(&fidp->fs.dir);
1918
1919    if (err < 0) {
1920        return err;
1921    }
1922    return count;
1923}
1924
1925static void coroutine_fn v9fs_readdir(void *opaque)
1926{
1927    int32_t fid;
1928    V9fsFidState *fidp;
1929    ssize_t retval = 0;
1930    size_t offset = 7;
1931    uint64_t initial_offset;
1932    int32_t count;
1933    uint32_t max_count;
1934    V9fsPDU *pdu = opaque;
1935
1936    retval = pdu_unmarshal(pdu, offset, "dqd", &fid,
1937                           &initial_offset, &max_count);
1938    if (retval < 0) {
1939        goto out_nofid;
1940    }
1941    trace_v9fs_readdir(pdu->tag, pdu->id, fid, initial_offset, max_count);
1942
1943    fidp = get_fid(pdu, fid);
1944    if (fidp == NULL) {
1945        retval = -EINVAL;
1946        goto out_nofid;
1947    }
1948    if (!fidp->fs.dir.stream) {
1949        retval = -EINVAL;
1950        goto out;
1951    }
1952    if (initial_offset == 0) {
1953        v9fs_co_rewinddir(pdu, fidp);
1954    } else {
1955        v9fs_co_seekdir(pdu, fidp, initial_offset);
1956    }
1957    count = v9fs_do_readdir(pdu, fidp, max_count);
1958    if (count < 0) {
1959        retval = count;
1960        goto out;
1961    }
1962    retval = pdu_marshal(pdu, offset, "d", count);
1963    if (retval < 0) {
1964        goto out;
1965    }
1966    retval += count + offset;
1967    trace_v9fs_readdir_return(pdu->tag, pdu->id, count, retval);
1968out:
1969    put_fid(pdu, fidp);
1970out_nofid:
1971    pdu_complete(pdu, retval);
1972}
1973
1974static int v9fs_xattr_write(V9fsState *s, V9fsPDU *pdu, V9fsFidState *fidp,
1975                            uint64_t off, uint32_t count,
1976                            struct iovec *sg, int cnt)
1977{
1978    int i, to_copy;
1979    ssize_t err = 0;
1980    uint64_t write_count;
1981    size_t offset = 7;
1982
1983
1984    if (fidp->fs.xattr.len < off) {
1985        err = -ENOSPC;
1986        goto out;
1987    }
1988    write_count = fidp->fs.xattr.len - off;
1989    if (write_count > count) {
1990        write_count = count;
1991    }
1992    err = pdu_marshal(pdu, offset, "d", write_count);
1993    if (err < 0) {
1994        return err;
1995    }
1996    err += offset;
1997    fidp->fs.xattr.copied_len += write_count;
1998    /*
1999     * Now copy the content from sg list
2000     */
2001    for (i = 0; i < cnt; i++) {
2002        if (write_count > sg[i].iov_len) {
2003            to_copy = sg[i].iov_len;
2004        } else {
2005            to_copy = write_count;
2006        }
2007        memcpy((char *)fidp->fs.xattr.value + off, sg[i].iov_base, to_copy);
2008        /* updating vs->off since we are not using below */
2009        off += to_copy;
2010        write_count -= to_copy;
2011    }
2012out:
2013    return err;
2014}
2015
2016static void coroutine_fn v9fs_write(void *opaque)
2017{
2018    ssize_t err;
2019    int32_t fid;
2020    uint64_t off;
2021    uint32_t count;
2022    int32_t len = 0;
2023    int32_t total = 0;
2024    size_t offset = 7;
2025    V9fsFidState *fidp;
2026    V9fsPDU *pdu = opaque;
2027    V9fsState *s = pdu->s;
2028    QEMUIOVector qiov_full;
2029    QEMUIOVector qiov;
2030
2031    err = pdu_unmarshal(pdu, offset, "dqd", &fid, &off, &count);
2032    if (err < 0) {
2033        pdu_complete(pdu, err);
2034        return;
2035    }
2036    offset += err;
2037    v9fs_init_qiov_from_pdu(&qiov_full, pdu, offset, count, true);
2038    trace_v9fs_write(pdu->tag, pdu->id, fid, off, count, qiov_full.niov);
2039
2040    fidp = get_fid(pdu, fid);
2041    if (fidp == NULL) {
2042        err = -EINVAL;
2043        goto out_nofid;
2044    }
2045    if (fidp->fid_type == P9_FID_FILE) {
2046        if (fidp->fs.fd == -1) {
2047            err = -EINVAL;
2048            goto out;
2049        }
2050    } else if (fidp->fid_type == P9_FID_XATTR) {
2051        /*
2052         * setxattr operation
2053         */
2054        err = v9fs_xattr_write(s, pdu, fidp, off, count,
2055                               qiov_full.iov, qiov_full.niov);
2056        goto out;
2057    } else {
2058        err = -EINVAL;
2059        goto out;
2060    }
2061    qemu_iovec_init(&qiov, qiov_full.niov);
2062    do {
2063        qemu_iovec_reset(&qiov);
2064        qemu_iovec_concat(&qiov, &qiov_full, total, qiov_full.size - total);
2065        if (0) {
2066            print_sg(qiov.iov, qiov.niov);
2067        }
2068        /* Loop in case of EINTR */
2069        do {
2070            len = v9fs_co_pwritev(pdu, fidp, qiov.iov, qiov.niov, off);
2071            if (len >= 0) {
2072                off   += len;
2073                total += len;
2074            }
2075        } while (len == -EINTR && !pdu->cancelled);
2076        if (len < 0) {
2077            /* IO error return the error */
2078            err = len;
2079            goto out_qiov;
2080        }
2081    } while (total < count && len > 0);
2082
2083    offset = 7;
2084    err = pdu_marshal(pdu, offset, "d", total);
2085    if (err < 0) {
2086        goto out_qiov;
2087    }
2088    err += offset;
2089    trace_v9fs_write_return(pdu->tag, pdu->id, total, err);
2090out_qiov:
2091    qemu_iovec_destroy(&qiov);
2092out:
2093    put_fid(pdu, fidp);
2094out_nofid:
2095    qemu_iovec_destroy(&qiov_full);
2096    pdu_complete(pdu, err);
2097}
2098
2099static void coroutine_fn v9fs_create(void *opaque)
2100{
2101    int32_t fid;
2102    int err = 0;
2103    size_t offset = 7;
2104    V9fsFidState *fidp;
2105    V9fsQID qid;
2106    int32_t perm;
2107    int8_t mode;
2108    V9fsPath path;
2109    struct stat stbuf;
2110    V9fsString name;
2111    V9fsString extension;
2112    int iounit;
2113    V9fsPDU *pdu = opaque;
2114
2115    v9fs_path_init(&path);
2116    v9fs_string_init(&name);
2117    v9fs_string_init(&extension);
2118    err = pdu_unmarshal(pdu, offset, "dsdbs", &fid, &name,
2119                        &perm, &mode, &extension);
2120    if (err < 0) {
2121        goto out_nofid;
2122    }
2123    trace_v9fs_create(pdu->tag, pdu->id, fid, name.data, perm, mode);
2124
2125    if (name_is_illegal(name.data)) {
2126        err = -ENOENT;
2127        goto out_nofid;
2128    }
2129
2130    if (!strcmp(".", name.data) || !strcmp("..", name.data)) {
2131        err = -EEXIST;
2132        goto out_nofid;
2133    }
2134
2135    fidp = get_fid(pdu, fid);
2136    if (fidp == NULL) {
2137        err = -EINVAL;
2138        goto out_nofid;
2139    }
2140    if (perm & P9_STAT_MODE_DIR) {
2141        err = v9fs_co_mkdir(pdu, fidp, &name, perm & 0777,
2142                            fidp->uid, -1, &stbuf);
2143        if (err < 0) {
2144            goto out;
2145        }
2146        err = v9fs_co_name_to_path(pdu, &fidp->path, name.data, &path);
2147        if (err < 0) {
2148            goto out;
2149        }
2150        v9fs_path_copy(&fidp->path, &path);
2151        err = v9fs_co_opendir(pdu, fidp);
2152        if (err < 0) {
2153            goto out;
2154        }
2155        fidp->fid_type = P9_FID_DIR;
2156    } else if (perm & P9_STAT_MODE_SYMLINK) {
2157        err = v9fs_co_symlink(pdu, fidp, &name,
2158                              extension.data, -1 , &stbuf);
2159        if (err < 0) {
2160            goto out;
2161        }
2162        err = v9fs_co_name_to_path(pdu, &fidp->path, name.data, &path);
2163        if (err < 0) {
2164            goto out;
2165        }
2166        v9fs_path_copy(&fidp->path, &path);
2167    } else if (perm & P9_STAT_MODE_LINK) {
2168        int32_t ofid = atoi(extension.data);
2169        V9fsFidState *ofidp = get_fid(pdu, ofid);
2170        if (ofidp == NULL) {
2171            err = -EINVAL;
2172            goto out;
2173        }
2174        err = v9fs_co_link(pdu, ofidp, fidp, &name);
2175        put_fid(pdu, ofidp);
2176        if (err < 0) {
2177            goto out;
2178        }
2179        err = v9fs_co_name_to_path(pdu, &fidp->path, name.data, &path);
2180        if (err < 0) {
2181            fidp->fid_type = P9_FID_NONE;
2182            goto out;
2183        }
2184        v9fs_path_copy(&fidp->path, &path);
2185        err = v9fs_co_lstat(pdu, &fidp->path, &stbuf);
2186        if (err < 0) {
2187            fidp->fid_type = P9_FID_NONE;
2188            goto out;
2189        }
2190    } else if (perm & P9_STAT_MODE_DEVICE) {
2191        char ctype;
2192        uint32_t major, minor;
2193        mode_t nmode = 0;
2194
2195        if (sscanf(extension.data, "%c %u %u", &ctype, &major, &minor) != 3) {
2196            err = -errno;
2197            goto out;
2198        }
2199
2200        switch (ctype) {
2201        case 'c':
2202            nmode = S_IFCHR;
2203            break;
2204        case 'b':
2205            nmode = S_IFBLK;
2206            break;
2207        default:
2208            err = -EIO;
2209            goto out;
2210        }
2211
2212        nmode |= perm & 0777;
2213        err = v9fs_co_mknod(pdu, fidp, &name, fidp->uid, -1,
2214                            makedev(major, minor), nmode, &stbuf);
2215        if (err < 0) {
2216            goto out;
2217        }
2218        err = v9fs_co_name_to_path(pdu, &fidp->path, name.data, &path);
2219        if (err < 0) {
2220            goto out;
2221        }
2222        v9fs_path_copy(&fidp->path, &path);
2223    } else if (perm & P9_STAT_MODE_NAMED_PIPE) {
2224        err = v9fs_co_mknod(pdu, fidp, &name, fidp->uid, -1,
2225                            0, S_IFIFO | (perm & 0777), &stbuf);
2226        if (err < 0) {
2227            goto out;
2228        }
2229        err = v9fs_co_name_to_path(pdu, &fidp->path, name.data, &path);
2230        if (err < 0) {
2231            goto out;
2232        }
2233        v9fs_path_copy(&fidp->path, &path);
2234    } else if (perm & P9_STAT_MODE_SOCKET) {
2235        err = v9fs_co_mknod(pdu, fidp, &name, fidp->uid, -1,
2236                            0, S_IFSOCK | (perm & 0777), &stbuf);
2237        if (err < 0) {
2238            goto out;
2239        }
2240        err = v9fs_co_name_to_path(pdu, &fidp->path, name.data, &path);
2241        if (err < 0) {
2242            goto out;
2243        }
2244        v9fs_path_copy(&fidp->path, &path);
2245    } else {
2246        err = v9fs_co_open2(pdu, fidp, &name, -1,
2247                            omode_to_uflags(mode)|O_CREAT, perm, &stbuf);
2248        if (err < 0) {
2249            goto out;
2250        }
2251        fidp->fid_type = P9_FID_FILE;
2252        fidp->open_flags = omode_to_uflags(mode);
2253        if (fidp->open_flags & O_EXCL) {
2254            /*
2255             * We let the host file system do O_EXCL check
2256             * We should not reclaim such fd
2257             */
2258            fidp->flags |= FID_NON_RECLAIMABLE;
2259        }
2260    }
2261    iounit = get_iounit(pdu, &fidp->path);
2262    stat_to_qid(&stbuf, &qid);
2263    err = pdu_marshal(pdu, offset, "Qd", &qid, iounit);
2264    if (err < 0) {
2265        goto out;
2266    }
2267    err += offset;
2268    trace_v9fs_create_return(pdu->tag, pdu->id,
2269                             qid.type, qid.version, qid.path, iounit);
2270out:
2271    put_fid(pdu, fidp);
2272out_nofid:
2273   pdu_complete(pdu, err);
2274   v9fs_string_free(&name);
2275   v9fs_string_free(&extension);
2276   v9fs_path_free(&path);
2277}
2278
2279static void coroutine_fn v9fs_symlink(void *opaque)
2280{
2281    V9fsPDU *pdu = opaque;
2282    V9fsString name;
2283    V9fsString symname;
2284    V9fsFidState *dfidp;
2285    V9fsQID qid;
2286    struct stat stbuf;
2287    int32_t dfid;
2288    int err = 0;
2289    gid_t gid;
2290    size_t offset = 7;
2291
2292    v9fs_string_init(&name);
2293    v9fs_string_init(&symname);
2294    err = pdu_unmarshal(pdu, offset, "dssd", &dfid, &name, &symname, &gid);
2295    if (err < 0) {
2296        goto out_nofid;
2297    }
2298    trace_v9fs_symlink(pdu->tag, pdu->id, dfid, name.data, symname.data, gid);
2299
2300    if (name_is_illegal(name.data)) {
2301        err = -ENOENT;
2302        goto out_nofid;
2303    }
2304
2305    if (!strcmp(".", name.data) || !strcmp("..", name.data)) {
2306        err = -EEXIST;
2307        goto out_nofid;
2308    }
2309
2310    dfidp = get_fid(pdu, dfid);
2311    if (dfidp == NULL) {
2312        err = -EINVAL;
2313        goto out_nofid;
2314    }
2315    err = v9fs_co_symlink(pdu, dfidp, &name, symname.data, gid, &stbuf);
2316    if (err < 0) {
2317        goto out;
2318    }
2319    stat_to_qid(&stbuf, &qid);
2320    err =  pdu_marshal(pdu, offset, "Q", &qid);
2321    if (err < 0) {
2322        goto out;
2323    }
2324    err += offset;
2325    trace_v9fs_symlink_return(pdu->tag, pdu->id,
2326                              qid.type, qid.version, qid.path);
2327out:
2328    put_fid(pdu, dfidp);
2329out_nofid:
2330    pdu_complete(pdu, err);
2331    v9fs_string_free(&name);
2332    v9fs_string_free(&symname);
2333}
2334
2335static void v9fs_flush(void *opaque)
2336{
2337    ssize_t err;
2338    int16_t tag;
2339    size_t offset = 7;
2340    V9fsPDU *cancel_pdu = NULL;
2341    V9fsPDU *pdu = opaque;
2342    V9fsState *s = pdu->s;
2343
2344    err = pdu_unmarshal(pdu, offset, "w", &tag);
2345    if (err < 0) {
2346        pdu_complete(pdu, err);
2347        return;
2348    }
2349    trace_v9fs_flush(pdu->tag, pdu->id, tag);
2350
2351    if (pdu->tag == tag) {
2352        error_report("Warning: the guest sent a self-referencing 9P flush request");
2353    } else {
2354        QLIST_FOREACH(cancel_pdu, &s->active_list, next) {
2355            if (cancel_pdu->tag == tag) {
2356                break;
2357            }
2358        }
2359    }
2360    if (cancel_pdu) {
2361        cancel_pdu->cancelled = 1;
2362        /*
2363         * Wait for pdu to complete.
2364         */
2365        qemu_co_queue_wait(&cancel_pdu->complete);
2366        cancel_pdu->cancelled = 0;
2367        pdu_free(cancel_pdu);
2368    }
2369    pdu_complete(pdu, 7);
2370}
2371
2372static void coroutine_fn v9fs_link(void *opaque)
2373{
2374    V9fsPDU *pdu = opaque;
2375    int32_t dfid, oldfid;
2376    V9fsFidState *dfidp, *oldfidp;
2377    V9fsString name;
2378    size_t offset = 7;
2379    int err = 0;
2380
2381    v9fs_string_init(&name);
2382    err = pdu_unmarshal(pdu, offset, "dds", &dfid, &oldfid, &name);
2383    if (err < 0) {
2384        goto out_nofid;
2385    }
2386    trace_v9fs_link(pdu->tag, pdu->id, dfid, oldfid, name.data);
2387
2388    if (name_is_illegal(name.data)) {
2389        err = -ENOENT;
2390        goto out_nofid;
2391    }
2392
2393    if (!strcmp(".", name.data) || !strcmp("..", name.data)) {
2394        err = -EEXIST;
2395        goto out_nofid;
2396    }
2397
2398    dfidp = get_fid(pdu, dfid);
2399    if (dfidp == NULL) {
2400        err = -ENOENT;
2401        goto out_nofid;
2402    }
2403
2404    oldfidp = get_fid(pdu, oldfid);
2405    if (oldfidp == NULL) {
2406        err = -ENOENT;
2407        goto out;
2408    }
2409    err = v9fs_co_link(pdu, oldfidp, dfidp, &name);
2410    if (!err) {
2411        err = offset;
2412    }
2413    put_fid(pdu, oldfidp);
2414out:
2415    put_fid(pdu, dfidp);
2416out_nofid:
2417    v9fs_string_free(&name);
2418    pdu_complete(pdu, err);
2419}
2420
2421/* Only works with path name based fid */
2422static void coroutine_fn v9fs_remove(void *opaque)
2423{
2424    int32_t fid;
2425    int err = 0;
2426    size_t offset = 7;
2427    V9fsFidState *fidp;
2428    V9fsPDU *pdu = opaque;
2429
2430    err = pdu_unmarshal(pdu, offset, "d", &fid);
2431    if (err < 0) {
2432        goto out_nofid;
2433    }
2434    trace_v9fs_remove(pdu->tag, pdu->id, fid);
2435
2436    fidp = get_fid(pdu, fid);
2437    if (fidp == NULL) {
2438        err = -EINVAL;
2439        goto out_nofid;
2440    }
2441    /* if fs driver is not path based, return EOPNOTSUPP */
2442    if (!(pdu->s->ctx.export_flags & V9FS_PATHNAME_FSCONTEXT)) {
2443        err = -EOPNOTSUPP;
2444        goto out_err;
2445    }
2446    /*
2447     * IF the file is unlinked, we cannot reopen
2448     * the file later. So don't reclaim fd
2449     */
2450    err = v9fs_mark_fids_unreclaim(pdu, &fidp->path);
2451    if (err < 0) {
2452        goto out_err;
2453    }
2454    err = v9fs_co_remove(pdu, &fidp->path);
2455    if (!err) {
2456        err = offset;
2457    }
2458out_err:
2459    /* For TREMOVE we need to clunk the fid even on failed remove */
2460    clunk_fid(pdu->s, fidp->fid);
2461    put_fid(pdu, fidp);
2462out_nofid:
2463    pdu_complete(pdu, err);
2464}
2465
2466static void coroutine_fn v9fs_unlinkat(void *opaque)
2467{
2468    int err = 0;
2469    V9fsString name;
2470    int32_t dfid, flags;
2471    size_t offset = 7;
2472    V9fsPath path;
2473    V9fsFidState *dfidp;
2474    V9fsPDU *pdu = opaque;
2475
2476    v9fs_string_init(&name);
2477    err = pdu_unmarshal(pdu, offset, "dsd", &dfid, &name, &flags);
2478    if (err < 0) {
2479        goto out_nofid;
2480    }
2481
2482    if (name_is_illegal(name.data)) {
2483        err = -ENOENT;
2484        goto out_nofid;
2485    }
2486
2487    if (!strcmp(".", name.data)) {
2488        err = -EINVAL;
2489        goto out_nofid;
2490    }
2491
2492    if (!strcmp("..", name.data)) {
2493        err = -ENOTEMPTY;
2494        goto out_nofid;
2495    }
2496
2497    dfidp = get_fid(pdu, dfid);
2498    if (dfidp == NULL) {
2499        err = -EINVAL;
2500        goto out_nofid;
2501    }
2502    /*
2503     * IF the file is unlinked, we cannot reopen
2504     * the file later. So don't reclaim fd
2505     */
2506    v9fs_path_init(&path);
2507    err = v9fs_co_name_to_path(pdu, &dfidp->path, name.data, &path);
2508    if (err < 0) {
2509        goto out_err;
2510    }
2511    err = v9fs_mark_fids_unreclaim(pdu, &path);
2512    if (err < 0) {
2513        goto out_err;
2514    }
2515    err = v9fs_co_unlinkat(pdu, &dfidp->path, &name, flags);
2516    if (!err) {
2517        err = offset;
2518    }
2519out_err:
2520    put_fid(pdu, dfidp);
2521    v9fs_path_free(&path);
2522out_nofid:
2523    pdu_complete(pdu, err);
2524    v9fs_string_free(&name);
2525}
2526
2527
2528/* Only works with path name based fid */
2529static int coroutine_fn v9fs_complete_rename(V9fsPDU *pdu, V9fsFidState *fidp,
2530                                             int32_t newdirfid,
2531                                             V9fsString *name)
2532{
2533    char *end;
2534    int err = 0;
2535    V9fsPath new_path;
2536    V9fsFidState *tfidp;
2537    V9fsState *s = pdu->s;
2538    V9fsFidState *dirfidp = NULL;
2539    char *old_name, *new_name;
2540
2541    v9fs_path_init(&new_path);
2542    if (newdirfid != -1) {
2543        dirfidp = get_fid(pdu, newdirfid);
2544        if (dirfidp == NULL) {
2545            err = -ENOENT;
2546            goto out_nofid;
2547        }
2548        if (fidp->fid_type != P9_FID_NONE) {
2549            err = -EINVAL;
2550            goto out;
2551        }
2552        v9fs_co_name_to_path(pdu, &dirfidp->path, name->data, &new_path);
2553    } else {
2554        old_name = fidp->path.data;
2555        end = strrchr(old_name, '/');
2556        if (end) {
2557            end++;
2558        } else {
2559            end = old_name;
2560        }
2561        new_name = g_malloc0(end - old_name + name->size + 1);
2562        strncat(new_name, old_name, end - old_name);
2563        strncat(new_name + (end - old_name), name->data, name->size);
2564        v9fs_co_name_to_path(pdu, NULL, new_name, &new_path);
2565        g_free(new_name);
2566    }
2567    err = v9fs_co_rename(pdu, &fidp->path, &new_path);
2568    if (err < 0) {
2569        goto out;
2570    }
2571    /*
2572     * Fixup fid's pointing to the old name to
2573     * start pointing to the new name
2574     */
2575    for (tfidp = s->fid_list; tfidp; tfidp = tfidp->next) {
2576        if (v9fs_path_is_ancestor(&fidp->path, &tfidp->path)) {
2577            /* replace the name */
2578            v9fs_fix_path(&tfidp->path, &new_path, strlen(fidp->path.data));
2579        }
2580    }
2581out:
2582    if (dirfidp) {
2583        put_fid(pdu, dirfidp);
2584    }
2585    v9fs_path_free(&new_path);
2586out_nofid:
2587    return err;
2588}
2589
2590/* Only works with path name based fid */
2591static void coroutine_fn v9fs_rename(void *opaque)
2592{
2593    int32_t fid;
2594    ssize_t err = 0;
2595    size_t offset = 7;
2596    V9fsString name;
2597    int32_t newdirfid;
2598    V9fsFidState *fidp;
2599    V9fsPDU *pdu = opaque;
2600    V9fsState *s = pdu->s;
2601
2602    v9fs_string_init(&name);
2603    err = pdu_unmarshal(pdu, offset, "dds", &fid, &newdirfid, &name);
2604    if (err < 0) {
2605        goto out_nofid;
2606    }
2607
2608    if (name_is_illegal(name.data)) {
2609        err = -ENOENT;
2610        goto out_nofid;
2611    }
2612
2613    if (!strcmp(".", name.data) || !strcmp("..", name.data)) {
2614        err = -EISDIR;
2615        goto out_nofid;
2616    }
2617
2618    fidp = get_fid(pdu, fid);
2619    if (fidp == NULL) {
2620        err = -ENOENT;
2621        goto out_nofid;
2622    }
2623    if (fidp->fid_type != P9_FID_NONE) {
2624        err = -EINVAL;
2625        goto out;
2626    }
2627    /* if fs driver is not path based, return EOPNOTSUPP */
2628    if (!(pdu->s->ctx.export_flags & V9FS_PATHNAME_FSCONTEXT)) {
2629        err = -EOPNOTSUPP;
2630        goto out;
2631    }
2632    v9fs_path_write_lock(s);
2633    err = v9fs_complete_rename(pdu, fidp, newdirfid, &name);
2634    v9fs_path_unlock(s);
2635    if (!err) {
2636        err = offset;
2637    }
2638out:
2639    put_fid(pdu, fidp);
2640out_nofid:
2641    pdu_complete(pdu, err);
2642    v9fs_string_free(&name);
2643}
2644
2645static void coroutine_fn v9fs_fix_fid_paths(V9fsPDU *pdu, V9fsPath *olddir,
2646                                            V9fsString *old_name,
2647                                            V9fsPath *newdir,
2648                                            V9fsString *new_name)
2649{
2650    V9fsFidState *tfidp;
2651    V9fsPath oldpath, newpath;
2652    V9fsState *s = pdu->s;
2653
2654
2655    v9fs_path_init(&oldpath);
2656    v9fs_path_init(&newpath);
2657    v9fs_co_name_to_path(pdu, olddir, old_name->data, &oldpath);
2658    v9fs_co_name_to_path(pdu, newdir, new_name->data, &newpath);
2659
2660    /*
2661     * Fixup fid's pointing to the old name to
2662     * start pointing to the new name
2663     */
2664    for (tfidp = s->fid_list; tfidp; tfidp = tfidp->next) {
2665        if (v9fs_path_is_ancestor(&oldpath, &tfidp->path)) {
2666            /* replace the name */
2667            v9fs_fix_path(&tfidp->path, &newpath, strlen(oldpath.data));
2668        }
2669    }
2670    v9fs_path_free(&oldpath);
2671    v9fs_path_free(&newpath);
2672}
2673
2674static int coroutine_fn v9fs_complete_renameat(V9fsPDU *pdu, int32_t olddirfid,
2675                                               V9fsString *old_name,
2676                                               int32_t newdirfid,
2677                                               V9fsString *new_name)
2678{
2679    int err = 0;
2680    V9fsState *s = pdu->s;
2681    V9fsFidState *newdirfidp = NULL, *olddirfidp = NULL;
2682
2683    olddirfidp = get_fid(pdu, olddirfid);
2684    if (olddirfidp == NULL) {
2685        err = -ENOENT;
2686        goto out;
2687    }
2688    if (newdirfid != -1) {
2689        newdirfidp = get_fid(pdu, newdirfid);
2690        if (newdirfidp == NULL) {
2691            err = -ENOENT;
2692            goto out;
2693        }
2694    } else {
2695        newdirfidp = get_fid(pdu, olddirfid);
2696    }
2697
2698    err = v9fs_co_renameat(pdu, &olddirfidp->path, old_name,
2699                           &newdirfidp->path, new_name);
2700    if (err < 0) {
2701        goto out;
2702    }
2703    if (s->ctx.export_flags & V9FS_PATHNAME_FSCONTEXT) {
2704        /* Only for path based fid  we need to do the below fixup */
2705        v9fs_fix_fid_paths(pdu, &olddirfidp->path, old_name,
2706                           &newdirfidp->path, new_name);
2707    }
2708out:
2709    if (olddirfidp) {
2710        put_fid(pdu, olddirfidp);
2711    }
2712    if (newdirfidp) {
2713        put_fid(pdu, newdirfidp);
2714    }
2715    return err;
2716}
2717
2718static void coroutine_fn v9fs_renameat(void *opaque)
2719{
2720    ssize_t err = 0;
2721    size_t offset = 7;
2722    V9fsPDU *pdu = opaque;
2723    V9fsState *s = pdu->s;
2724    int32_t olddirfid, newdirfid;
2725    V9fsString old_name, new_name;
2726
2727    v9fs_string_init(&old_name);
2728    v9fs_string_init(&new_name);
2729    err = pdu_unmarshal(pdu, offset, "dsds", &olddirfid,
2730                        &old_name, &newdirfid, &new_name);
2731    if (err < 0) {
2732        goto out_err;
2733    }
2734
2735    if (name_is_illegal(old_name.data) || name_is_illegal(new_name.data)) {
2736        err = -ENOENT;
2737        goto out_err;
2738    }
2739
2740    if (!strcmp(".", old_name.data) || !strcmp("..", old_name.data) ||
2741        !strcmp(".", new_name.data) || !strcmp("..", new_name.data)) {
2742        err = -EISDIR;
2743        goto out_err;
2744    }
2745
2746    v9fs_path_write_lock(s);
2747    err = v9fs_complete_renameat(pdu, olddirfid,
2748                                 &old_name, newdirfid, &new_name);
2749    v9fs_path_unlock(s);
2750    if (!err) {
2751        err = offset;
2752    }
2753
2754out_err:
2755    pdu_complete(pdu, err);
2756    v9fs_string_free(&old_name);
2757    v9fs_string_free(&new_name);
2758}
2759
2760static void coroutine_fn v9fs_wstat(void *opaque)
2761{
2762    int32_t fid;
2763    int err = 0;
2764    int16_t unused;
2765    V9fsStat v9stat;
2766    size_t offset = 7;
2767    struct stat stbuf;
2768    V9fsFidState *fidp;
2769    V9fsPDU *pdu = opaque;
2770
2771    v9fs_stat_init(&v9stat);
2772    err = pdu_unmarshal(pdu, offset, "dwS", &fid, &unused, &v9stat);
2773    if (err < 0) {
2774        goto out_nofid;
2775    }
2776    trace_v9fs_wstat(pdu->tag, pdu->id, fid,
2777                     v9stat.mode, v9stat.atime, v9stat.mtime);
2778
2779    fidp = get_fid(pdu, fid);
2780    if (fidp == NULL) {
2781        err = -EINVAL;
2782        goto out_nofid;
2783    }
2784    /* do we need to sync the file? */
2785    if (donttouch_stat(&v9stat)) {
2786        err = v9fs_co_fsync(pdu, fidp, 0);
2787        goto out;
2788    }
2789    if (v9stat.mode != -1) {
2790        uint32_t v9_mode;
2791        err = v9fs_co_lstat(pdu, &fidp->path, &stbuf);
2792        if (err < 0) {
2793            goto out;
2794        }
2795        v9_mode = stat_to_v9mode(&stbuf);
2796        if ((v9stat.mode & P9_STAT_MODE_TYPE_BITS) !=
2797            (v9_mode & P9_STAT_MODE_TYPE_BITS)) {
2798            /* Attempting to change the type */
2799            err = -EIO;
2800            goto out;
2801        }
2802        err = v9fs_co_chmod(pdu, &fidp->path,
2803                            v9mode_to_mode(v9stat.mode,
2804                                           &v9stat.extension));
2805        if (err < 0) {
2806            goto out;
2807        }
2808    }
2809    if (v9stat.mtime != -1 || v9stat.atime != -1) {
2810        struct timespec times[2];
2811        if (v9stat.atime != -1) {
2812            times[0].tv_sec = v9stat.atime;
2813            times[0].tv_nsec = 0;
2814        } else {
2815            times[0].tv_nsec = UTIME_OMIT;
2816        }
2817        if (v9stat.mtime != -1) {
2818            times[1].tv_sec = v9stat.mtime;
2819            times[1].tv_nsec = 0;
2820        } else {
2821            times[1].tv_nsec = UTIME_OMIT;
2822        }
2823        err = v9fs_co_utimensat(pdu, &fidp->path, times);
2824        if (err < 0) {
2825            goto out;
2826        }
2827    }
2828    if (v9stat.n_gid != -1 || v9stat.n_uid != -1) {
2829        err = v9fs_co_chown(pdu, &fidp->path, v9stat.n_uid, v9stat.n_gid);
2830        if (err < 0) {
2831            goto out;
2832        }
2833    }
2834    if (v9stat.name.size != 0) {
2835        err = v9fs_complete_rename(pdu, fidp, -1, &v9stat.name);
2836        if (err < 0) {
2837            goto out;
2838        }
2839    }
2840    if (v9stat.length != -1) {
2841        err = v9fs_co_truncate(pdu, &fidp->path, v9stat.length);
2842        if (err < 0) {
2843            goto out;
2844        }
2845    }
2846    err = offset;
2847out:
2848    put_fid(pdu, fidp);
2849out_nofid:
2850    v9fs_stat_free(&v9stat);
2851    pdu_complete(pdu, err);
2852}
2853
2854static int v9fs_fill_statfs(V9fsState *s, V9fsPDU *pdu, struct statfs *stbuf)
2855{
2856    uint32_t f_type;
2857    uint32_t f_bsize;
2858    uint64_t f_blocks;
2859    uint64_t f_bfree;
2860    uint64_t f_bavail;
2861    uint64_t f_files;
2862    uint64_t f_ffree;
2863    uint64_t fsid_val;
2864    uint32_t f_namelen;
2865    size_t offset = 7;
2866    int32_t bsize_factor;
2867
2868    /*
2869     * compute bsize factor based on host file system block size
2870     * and client msize
2871     */
2872    bsize_factor = (s->msize - P9_IOHDRSZ)/stbuf->f_bsize;
2873    if (!bsize_factor) {
2874        bsize_factor = 1;
2875    }
2876    f_type  = stbuf->f_type;
2877    f_bsize = stbuf->f_bsize;
2878    f_bsize *= bsize_factor;
2879    /*
2880     * f_bsize is adjusted(multiplied) by bsize factor, so we need to
2881     * adjust(divide) the number of blocks, free blocks and available
2882     * blocks by bsize factor
2883     */
2884    f_blocks = stbuf->f_blocks/bsize_factor;
2885    f_bfree  = stbuf->f_bfree/bsize_factor;
2886    f_bavail = stbuf->f_bavail/bsize_factor;
2887    f_files  = stbuf->f_files;
2888    f_ffree  = stbuf->f_ffree;
2889    fsid_val = (unsigned int) stbuf->f_fsid.__val[0] |
2890               (unsigned long long)stbuf->f_fsid.__val[1] << 32;
2891    f_namelen = stbuf->f_namelen;
2892
2893    return pdu_marshal(pdu, offset, "ddqqqqqqd",
2894                       f_type, f_bsize, f_blocks, f_bfree,
2895                       f_bavail, f_files, f_ffree,
2896                       fsid_val, f_namelen);
2897}
2898
2899static void coroutine_fn v9fs_statfs(void *opaque)
2900{
2901    int32_t fid;
2902    ssize_t retval = 0;
2903    size_t offset = 7;
2904    V9fsFidState *fidp;
2905    struct statfs stbuf;
2906    V9fsPDU *pdu = opaque;
2907    V9fsState *s = pdu->s;
2908
2909    retval = pdu_unmarshal(pdu, offset, "d", &fid);
2910    if (retval < 0) {
2911        goto out_nofid;
2912    }
2913    fidp = get_fid(pdu, fid);
2914    if (fidp == NULL) {
2915        retval = -ENOENT;
2916        goto out_nofid;
2917    }
2918    retval = v9fs_co_statfs(pdu, &fidp->path, &stbuf);
2919    if (retval < 0) {
2920        goto out;
2921    }
2922    retval = v9fs_fill_statfs(s, pdu, &stbuf);
2923    if (retval < 0) {
2924        goto out;
2925    }
2926    retval += offset;
2927out:
2928    put_fid(pdu, fidp);
2929out_nofid:
2930    pdu_complete(pdu, retval);
2931}
2932
2933static void coroutine_fn v9fs_mknod(void *opaque)
2934{
2935
2936    int mode;
2937    gid_t gid;
2938    int32_t fid;
2939    V9fsQID qid;
2940    int err = 0;
2941    int major, minor;
2942    size_t offset = 7;
2943    V9fsString name;
2944    struct stat stbuf;
2945    V9fsFidState *fidp;
2946    V9fsPDU *pdu = opaque;
2947
2948    v9fs_string_init(&name);
2949    err = pdu_unmarshal(pdu, offset, "dsdddd", &fid, &name, &mode,
2950                        &major, &minor, &gid);
2951    if (err < 0) {
2952        goto out_nofid;
2953    }
2954    trace_v9fs_mknod(pdu->tag, pdu->id, fid, mode, major, minor);
2955
2956    if (name_is_illegal(name.data)) {
2957        err = -ENOENT;
2958        goto out_nofid;
2959    }
2960
2961    if (!strcmp(".", name.data) || !strcmp("..", name.data)) {
2962        err = -EEXIST;
2963        goto out_nofid;
2964    }
2965
2966    fidp = get_fid(pdu, fid);
2967    if (fidp == NULL) {
2968        err = -ENOENT;
2969        goto out_nofid;
2970    }
2971    err = v9fs_co_mknod(pdu, fidp, &name, fidp->uid, gid,
2972                        makedev(major, minor), mode, &stbuf);
2973    if (err < 0) {
2974        goto out;
2975    }
2976    stat_to_qid(&stbuf, &qid);
2977    err = pdu_marshal(pdu, offset, "Q", &qid);
2978    if (err < 0) {
2979        goto out;
2980    }
2981    err += offset;
2982    trace_v9fs_mknod_return(pdu->tag, pdu->id,
2983                            qid.type, qid.version, qid.path);
2984out:
2985    put_fid(pdu, fidp);
2986out_nofid:
2987    pdu_complete(pdu, err);
2988    v9fs_string_free(&name);
2989}
2990
2991/*
2992 * Implement posix byte range locking code
2993 * Server side handling of locking code is very simple, because 9p server in
2994 * QEMU can handle only one client. And most of the lock handling
2995 * (like conflict, merging) etc is done by the VFS layer itself, so no need to
2996 * do any thing in * qemu 9p server side lock code path.
2997 * So when a TLOCK request comes, always return success
2998 */
2999static void coroutine_fn v9fs_lock(void *opaque)
3000{
3001    int8_t status;
3002    V9fsFlock flock;
3003    size_t offset = 7;
3004    struct stat stbuf;
3005    V9fsFidState *fidp;
3006    int32_t fid, err = 0;
3007    V9fsPDU *pdu = opaque;
3008
3009    status = P9_LOCK_ERROR;
3010    v9fs_string_init(&flock.client_id);
3011    err = pdu_unmarshal(pdu, offset, "dbdqqds", &fid, &flock.type,
3012                        &flock.flags, &flock.start, &flock.length,
3013                        &flock.proc_id, &flock.client_id);
3014    if (err < 0) {
3015        goto out_nofid;
3016    }
3017    trace_v9fs_lock(pdu->tag, pdu->id, fid,
3018                    flock.type, flock.start, flock.length);
3019
3020
3021    /* We support only block flag now (that too ignored currently) */
3022    if (flock.flags & ~P9_LOCK_FLAGS_BLOCK) {
3023        err = -EINVAL;
3024        goto out_nofid;
3025    }
3026    fidp = get_fid(pdu, fid);
3027    if (fidp == NULL) {
3028        err = -ENOENT;
3029        goto out_nofid;
3030    }
3031    err = v9fs_co_fstat(pdu, fidp, &stbuf);
3032    if (err < 0) {
3033        goto out;
3034    }
3035    status = P9_LOCK_SUCCESS;
3036out:
3037    put_fid(pdu, fidp);
3038out_nofid:
3039    err = pdu_marshal(pdu, offset, "b", status);
3040    if (err > 0) {
3041        err += offset;
3042    }
3043    trace_v9fs_lock_return(pdu->tag, pdu->id, status);
3044    pdu_complete(pdu, err);
3045    v9fs_string_free(&flock.client_id);
3046}
3047
3048/*
3049 * When a TGETLOCK request comes, always return success because all lock
3050 * handling is done by client's VFS layer.
3051 */
3052static void coroutine_fn v9fs_getlock(void *opaque)
3053{
3054    size_t offset = 7;
3055    struct stat stbuf;
3056    V9fsFidState *fidp;
3057    V9fsGetlock glock;
3058    int32_t fid, err = 0;
3059    V9fsPDU *pdu = opaque;
3060
3061    v9fs_string_init(&glock.client_id);
3062    err = pdu_unmarshal(pdu, offset, "dbqqds", &fid, &glock.type,
3063                        &glock.start, &glock.length, &glock.proc_id,
3064                        &glock.client_id);
3065    if (err < 0) {
3066        goto out_nofid;
3067    }
3068    trace_v9fs_getlock(pdu->tag, pdu->id, fid,
3069                       glock.type, glock.start, glock.length);
3070
3071    fidp = get_fid(pdu, fid);
3072    if (fidp == NULL) {
3073        err = -ENOENT;
3074        goto out_nofid;
3075    }
3076    err = v9fs_co_fstat(pdu, fidp, &stbuf);
3077    if (err < 0) {
3078        goto out;
3079    }
3080    glock.type = P9_LOCK_TYPE_UNLCK;
3081    err = pdu_marshal(pdu, offset, "bqqds", glock.type,
3082                          glock.start, glock.length, glock.proc_id,
3083                          &glock.client_id);
3084    if (err < 0) {
3085        goto out;
3086    }
3087    err += offset;
3088    trace_v9fs_getlock_return(pdu->tag, pdu->id, glock.type, glock.start,
3089                              glock.length, glock.proc_id);
3090out:
3091    put_fid(pdu, fidp);
3092out_nofid:
3093    pdu_complete(pdu, err);
3094    v9fs_string_free(&glock.client_id);
3095}
3096
3097static void coroutine_fn v9fs_mkdir(void *opaque)
3098{
3099    V9fsPDU *pdu = opaque;
3100    size_t offset = 7;
3101    int32_t fid;
3102    struct stat stbuf;
3103    V9fsQID qid;
3104    V9fsString name;
3105    V9fsFidState *fidp;
3106    gid_t gid;
3107    int mode;
3108    int err = 0;
3109
3110    v9fs_string_init(&name);
3111    err = pdu_unmarshal(pdu, offset, "dsdd", &fid, &name, &mode, &gid);
3112    if (err < 0) {
3113        goto out_nofid;
3114    }
3115    trace_v9fs_mkdir(pdu->tag, pdu->id, fid, name.data, mode, gid);
3116
3117    if (name_is_illegal(name.data)) {
3118        err = -ENOENT;
3119        goto out_nofid;
3120    }
3121
3122    if (!strcmp(".", name.data) || !strcmp("..", name.data)) {
3123        err = -EEXIST;
3124        goto out_nofid;
3125    }
3126
3127    fidp = get_fid(pdu, fid);
3128    if (fidp == NULL) {
3129        err = -ENOENT;
3130        goto out_nofid;
3131    }
3132    err = v9fs_co_mkdir(pdu, fidp, &name, mode, fidp->uid, gid, &stbuf);
3133    if (err < 0) {
3134        goto out;
3135    }
3136    stat_to_qid(&stbuf, &qid);
3137    err = pdu_marshal(pdu, offset, "Q", &qid);
3138    if (err < 0) {
3139        goto out;
3140    }
3141    err += offset;
3142    trace_v9fs_mkdir_return(pdu->tag, pdu->id,
3143                            qid.type, qid.version, qid.path, err);
3144out:
3145    put_fid(pdu, fidp);
3146out_nofid:
3147    pdu_complete(pdu, err);
3148    v9fs_string_free(&name);
3149}
3150
3151static void coroutine_fn v9fs_xattrwalk(void *opaque)
3152{
3153    int64_t size;
3154    V9fsString name;
3155    ssize_t err = 0;
3156    size_t offset = 7;
3157    int32_t fid, newfid;
3158    V9fsFidState *file_fidp;
3159    V9fsFidState *xattr_fidp = NULL;
3160    V9fsPDU *pdu = opaque;
3161    V9fsState *s = pdu->s;
3162
3163    v9fs_string_init(&name);
3164    err = pdu_unmarshal(pdu, offset, "dds", &fid, &newfid, &name);
3165    if (err < 0) {
3166        goto out_nofid;
3167    }
3168    trace_v9fs_xattrwalk(pdu->tag, pdu->id, fid, newfid, name.data);
3169
3170    file_fidp = get_fid(pdu, fid);
3171    if (file_fidp == NULL) {
3172        err = -ENOENT;
3173        goto out_nofid;
3174    }
3175    xattr_fidp = alloc_fid(s, newfid);
3176    if (xattr_fidp == NULL) {
3177        err = -EINVAL;
3178        goto out;
3179    }
3180    v9fs_path_copy(&xattr_fidp->path, &file_fidp->path);
3181    if (!v9fs_string_size(&name)) {
3182        /*
3183         * listxattr request. Get the size first
3184         */
3185        size = v9fs_co_llistxattr(pdu, &xattr_fidp->path, NULL, 0);
3186        if (size < 0) {
3187            err = size;
3188            clunk_fid(s, xattr_fidp->fid);
3189            goto out;
3190        }
3191        /*
3192         * Read the xattr value
3193         */
3194        xattr_fidp->fs.xattr.len = size;
3195        xattr_fidp->fid_type = P9_FID_XATTR;
3196        xattr_fidp->fs.xattr.xattrwalk_fid = true;
3197        if (size) {
3198            xattr_fidp->fs.xattr.value = g_malloc(size);
3199            err = v9fs_co_llistxattr(pdu, &xattr_fidp->path,
3200                                     xattr_fidp->fs.xattr.value,
3201                                     xattr_fidp->fs.xattr.len);
3202            if (err < 0) {
3203                clunk_fid(s, xattr_fidp->fid);
3204                goto out;
3205            }
3206        }
3207        err = pdu_marshal(pdu, offset, "q", size);
3208        if (err < 0) {
3209            goto out;
3210        }
3211        err += offset;
3212    } else {
3213        /*
3214         * specific xattr fid. We check for xattr
3215         * presence also collect the xattr size
3216         */
3217        size = v9fs_co_lgetxattr(pdu, &xattr_fidp->path,
3218                                 &name, NULL, 0);
3219        if (size < 0) {
3220            err = size;
3221            clunk_fid(s, xattr_fidp->fid);
3222            goto out;
3223        }
3224        /*
3225         * Read the xattr value
3226         */
3227        xattr_fidp->fs.xattr.len = size;
3228        xattr_fidp->fid_type = P9_FID_XATTR;
3229        xattr_fidp->fs.xattr.xattrwalk_fid = true;
3230        if (size) {
3231            xattr_fidp->fs.xattr.value = g_malloc(size);
3232            err = v9fs_co_lgetxattr(pdu, &xattr_fidp->path,
3233                                    &name, xattr_fidp->fs.xattr.value,
3234                                    xattr_fidp->fs.xattr.len);
3235            if (err < 0) {
3236                clunk_fid(s, xattr_fidp->fid);
3237                goto out;
3238            }
3239        }
3240        err = pdu_marshal(pdu, offset, "q", size);
3241        if (err < 0) {
3242            goto out;
3243        }
3244        err += offset;
3245    }
3246    trace_v9fs_xattrwalk_return(pdu->tag, pdu->id, size);
3247out:
3248    put_fid(pdu, file_fidp);
3249    if (xattr_fidp) {
3250        put_fid(pdu, xattr_fidp);
3251    }
3252out_nofid:
3253    pdu_complete(pdu, err);
3254    v9fs_string_free(&name);
3255}
3256
3257static void coroutine_fn v9fs_xattrcreate(void *opaque)
3258{
3259    int flags;
3260    int32_t fid;
3261    uint64_t size;
3262    ssize_t err = 0;
3263    V9fsString name;
3264    size_t offset = 7;
3265    V9fsFidState *file_fidp;
3266    V9fsFidState *xattr_fidp;
3267    V9fsPDU *pdu = opaque;
3268
3269    v9fs_string_init(&name);
3270    err = pdu_unmarshal(pdu, offset, "dsqd", &fid, &name, &size, &flags);
3271    if (err < 0) {
3272        goto out_nofid;
3273    }
3274    trace_v9fs_xattrcreate(pdu->tag, pdu->id, fid, name.data, size, flags);
3275
3276    if (size > XATTR_SIZE_MAX) {
3277        err = -E2BIG;
3278        goto out_nofid;
3279    }
3280
3281    file_fidp = get_fid(pdu, fid);
3282    if (file_fidp == NULL) {
3283        err = -EINVAL;
3284        goto out_nofid;
3285    }
3286    if (file_fidp->fid_type != P9_FID_NONE) {
3287        err = -EINVAL;
3288        goto out_put_fid;
3289    }
3290
3291    /* Make the file fid point to xattr */
3292    xattr_fidp = file_fidp;
3293    xattr_fidp->fid_type = P9_FID_XATTR;
3294    xattr_fidp->fs.xattr.copied_len = 0;
3295    xattr_fidp->fs.xattr.xattrwalk_fid = false;
3296    xattr_fidp->fs.xattr.len = size;
3297    xattr_fidp->fs.xattr.flags = flags;
3298    v9fs_string_init(&xattr_fidp->fs.xattr.name);
3299    v9fs_string_copy(&xattr_fidp->fs.xattr.name, &name);
3300    xattr_fidp->fs.xattr.value = g_malloc0(size);
3301    err = offset;
3302out_put_fid:
3303    put_fid(pdu, file_fidp);
3304out_nofid:
3305    pdu_complete(pdu, err);
3306    v9fs_string_free(&name);
3307}
3308
3309static void coroutine_fn v9fs_readlink(void *opaque)
3310{
3311    V9fsPDU *pdu = opaque;
3312    size_t offset = 7;
3313    V9fsString target;
3314    int32_t fid;
3315    int err = 0;
3316    V9fsFidState *fidp;
3317
3318    err = pdu_unmarshal(pdu, offset, "d", &fid);
3319    if (err < 0) {
3320        goto out_nofid;
3321    }
3322    trace_v9fs_readlink(pdu->tag, pdu->id, fid);
3323    fidp = get_fid(pdu, fid);
3324    if (fidp == NULL) {
3325        err = -ENOENT;
3326        goto out_nofid;
3327    }
3328
3329    v9fs_string_init(&target);
3330    err = v9fs_co_readlink(pdu, &fidp->path, &target);
3331    if (err < 0) {
3332        goto out;
3333    }
3334    err = pdu_marshal(pdu, offset, "s", &target);
3335    if (err < 0) {
3336        v9fs_string_free(&target);
3337        goto out;
3338    }
3339    err += offset;
3340    trace_v9fs_readlink_return(pdu->tag, pdu->id, target.data);
3341    v9fs_string_free(&target);
3342out:
3343    put_fid(pdu, fidp);
3344out_nofid:
3345    pdu_complete(pdu, err);
3346}
3347
3348static CoroutineEntry *pdu_co_handlers[] = {
3349    [P9_TREADDIR] = v9fs_readdir,
3350    [P9_TSTATFS] = v9fs_statfs,
3351    [P9_TGETATTR] = v9fs_getattr,
3352    [P9_TSETATTR] = v9fs_setattr,
3353    [P9_TXATTRWALK] = v9fs_xattrwalk,
3354    [P9_TXATTRCREATE] = v9fs_xattrcreate,
3355    [P9_TMKNOD] = v9fs_mknod,
3356    [P9_TRENAME] = v9fs_rename,
3357    [P9_TLOCK] = v9fs_lock,
3358    [P9_TGETLOCK] = v9fs_getlock,
3359    [P9_TRENAMEAT] = v9fs_renameat,
3360    [P9_TREADLINK] = v9fs_readlink,
3361    [P9_TUNLINKAT] = v9fs_unlinkat,
3362    [P9_TMKDIR] = v9fs_mkdir,
3363    [P9_TVERSION] = v9fs_version,
3364    [P9_TLOPEN] = v9fs_open,
3365    [P9_TATTACH] = v9fs_attach,
3366    [P9_TSTAT] = v9fs_stat,
3367    [P9_TWALK] = v9fs_walk,
3368    [P9_TCLUNK] = v9fs_clunk,
3369    [P9_TFSYNC] = v9fs_fsync,
3370    [P9_TOPEN] = v9fs_open,
3371    [P9_TREAD] = v9fs_read,
3372#if 0
3373    [P9_TAUTH] = v9fs_auth,
3374#endif
3375    [P9_TFLUSH] = v9fs_flush,
3376    [P9_TLINK] = v9fs_link,
3377    [P9_TSYMLINK] = v9fs_symlink,
3378    [P9_TCREATE] = v9fs_create,
3379    [P9_TLCREATE] = v9fs_lcreate,
3380    [P9_TWRITE] = v9fs_write,
3381    [P9_TWSTAT] = v9fs_wstat,
3382    [P9_TREMOVE] = v9fs_remove,
3383};
3384
3385static void coroutine_fn v9fs_op_not_supp(void *opaque)
3386{
3387    V9fsPDU *pdu = opaque;
3388    pdu_complete(pdu, -EOPNOTSUPP);
3389}
3390
3391static void coroutine_fn v9fs_fs_ro(void *opaque)
3392{
3393    V9fsPDU *pdu = opaque;
3394    pdu_complete(pdu, -EROFS);
3395}
3396
3397static inline bool is_read_only_op(V9fsPDU *pdu)
3398{
3399    switch (pdu->id) {
3400    case P9_TREADDIR:
3401    case P9_TSTATFS:
3402    case P9_TGETATTR:
3403    case P9_TXATTRWALK:
3404    case P9_TLOCK:
3405    case P9_TGETLOCK:
3406    case P9_TREADLINK:
3407    case P9_TVERSION:
3408    case P9_TLOPEN:
3409    case P9_TATTACH:
3410    case P9_TSTAT:
3411    case P9_TWALK:
3412    case P9_TCLUNK:
3413    case P9_TFSYNC:
3414    case P9_TOPEN:
3415    case P9_TREAD:
3416    case P9_TAUTH:
3417    case P9_TFLUSH:
3418        return 1;
3419    default:
3420        return 0;
3421    }
3422}
3423
3424void pdu_submit(V9fsPDU *pdu)
3425{
3426    Coroutine *co;
3427    CoroutineEntry *handler;
3428    V9fsState *s = pdu->s;
3429
3430    if (pdu->id >= ARRAY_SIZE(pdu_co_handlers) ||
3431        (pdu_co_handlers[pdu->id] == NULL)) {
3432        handler = v9fs_op_not_supp;
3433    } else {
3434        handler = pdu_co_handlers[pdu->id];
3435    }
3436
3437    if (is_ro_export(&s->ctx) && !is_read_only_op(pdu)) {
3438        handler = v9fs_fs_ro;
3439    }
3440    co = qemu_coroutine_create(handler, pdu);
3441    qemu_coroutine_enter(co);
3442}
3443
3444/* Returns 0 on success, 1 on failure. */
3445int v9fs_device_realize_common(V9fsState *s, Error **errp)
3446{
3447    V9fsVirtioState *v = container_of(s, V9fsVirtioState, state);
3448    int i, len;
3449    struct stat stat;
3450    FsDriverEntry *fse;
3451    V9fsPath path;
3452    int rc = 1;
3453
3454    /* initialize pdu allocator */
3455    QLIST_INIT(&s->free_list);
3456    QLIST_INIT(&s->active_list);
3457    for (i = 0; i < MAX_REQ; i++) {
3458        QLIST_INSERT_HEAD(&s->free_list, &v->pdus[i], next);
3459        v->pdus[i].s = s;
3460        v->pdus[i].idx = i;
3461    }
3462
3463    v9fs_path_init(&path);
3464
3465    fse = get_fsdev_fsentry(s->fsconf.fsdev_id);
3466
3467    if (!fse) {
3468        /* We don't have a fsdev identified by fsdev_id */
3469        error_setg(errp, "9pfs device couldn't find fsdev with the "
3470                   "id = %s",
3471                   s->fsconf.fsdev_id ? s->fsconf.fsdev_id : "NULL");
3472        goto out;
3473    }
3474
3475    if (!s->fsconf.tag) {
3476        /* we haven't specified a mount_tag */
3477        error_setg(errp, "fsdev with id %s needs mount_tag arguments",
3478                   s->fsconf.fsdev_id);
3479        goto out;
3480    }
3481
3482    s->ctx.export_flags = fse->export_flags;
3483    s->ctx.fs_root = g_strdup(fse->path);
3484    s->ctx.exops.get_st_gen = NULL;
3485    len = strlen(s->fsconf.tag);
3486    if (len > MAX_TAG_LEN - 1) {
3487        error_setg(errp, "mount tag '%s' (%d bytes) is longer than "
3488                   "maximum (%d bytes)", s->fsconf.tag, len, MAX_TAG_LEN - 1);
3489        goto out;
3490    }
3491
3492    s->tag = g_strdup(s->fsconf.tag);
3493    s->ctx.uid = -1;
3494
3495    s->ops = fse->ops;
3496
3497    s->fid_list = NULL;
3498    qemu_co_rwlock_init(&s->rename_lock);
3499
3500    if (s->ops->init(&s->ctx) < 0) {
3501        error_setg(errp, "9pfs Failed to initialize fs-driver with id:%s"
3502                   " and export path:%s", s->fsconf.fsdev_id, s->ctx.fs_root);
3503        goto out;
3504    }
3505
3506    /*
3507     * Check details of export path, We need to use fs driver
3508     * call back to do that. Since we are in the init path, we don't
3509     * use co-routines here.
3510     */
3511    if (s->ops->name_to_path(&s->ctx, NULL, "/", &path) < 0) {
3512        error_setg(errp,
3513                   "error in converting name to path %s", strerror(errno));
3514        goto out;
3515    }
3516    if (s->ops->lstat(&s->ctx, &path, &stat)) {
3517        error_setg(errp, "share path %s does not exist", fse->path);
3518        goto out;
3519    } else if (!S_ISDIR(stat.st_mode)) {
3520        error_setg(errp, "share path %s is not a directory", fse->path);
3521        goto out;
3522    }
3523    v9fs_path_free(&path);
3524
3525    rc = 0;
3526out:
3527    if (rc) {
3528        if (s->ops && s->ops->cleanup && s->ctx.private) {
3529            s->ops->cleanup(&s->ctx);
3530        }
3531        g_free(s->tag);
3532        g_free(s->ctx.fs_root);
3533        v9fs_path_free(&path);
3534    }
3535    return rc;
3536}
3537
3538void v9fs_device_unrealize_common(V9fsState *s, Error **errp)
3539{
3540    if (s->ops->cleanup) {
3541        s->ops->cleanup(&s->ctx);
3542    }
3543    g_free(s->tag);
3544    g_free(s->ctx.fs_root);
3545}
3546
3547typedef struct VirtfsCoResetData {
3548    V9fsPDU pdu;
3549    bool done;
3550} VirtfsCoResetData;
3551
3552static void coroutine_fn virtfs_co_reset(void *opaque)
3553{
3554    VirtfsCoResetData *data = opaque;
3555
3556    virtfs_reset(&data->pdu);
3557    data->done = true;
3558}
3559
3560void v9fs_reset(V9fsState *s)
3561{
3562    VirtfsCoResetData data = { .pdu = { .s = s }, .done = false };
3563    Coroutine *co;
3564
3565    while (!QLIST_EMPTY(&s->active_list)) {
3566        aio_poll(qemu_get_aio_context(), true);
3567    }
3568
3569    co = qemu_coroutine_create(virtfs_co_reset, &data);
3570    qemu_coroutine_enter(co);
3571
3572    while (!data.done) {
3573        aio_poll(qemu_get_aio_context(), true);
3574    }
3575}
3576
3577static void __attribute__((__constructor__)) v9fs_set_fd_limit(void)
3578{
3579    struct rlimit rlim;
3580    if (getrlimit(RLIMIT_NOFILE, &rlim) < 0) {
3581        error_report("Failed to get the resource limit");
3582        exit(1);
3583    }
3584    open_fd_hw = rlim.rlim_cur - MIN(400, rlim.rlim_cur/3);
3585    open_fd_rc = rlim.rlim_cur/2;
3586}
3587