qemu/hw/9pfs/cofile.c
<<
>>
Prefs
   1
   2/*
   3 * Virtio 9p backend
   4 *
   5 * Copyright IBM, Corp. 2011
   6 *
   7 * Authors:
   8 *  Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
   9 *
  10 * This work is licensed under the terms of the GNU GPL, version 2.  See
  11 * the COPYING file in the top-level directory.
  12 *
  13 */
  14
  15#include "fsdev/qemu-fsdev.h"
  16#include "qemu/thread.h"
  17#include "block/coroutine.h"
  18#include "virtio-9p-coth.h"
  19
  20int v9fs_co_st_gen(V9fsPDU *pdu, V9fsPath *path, mode_t st_mode,
  21                   V9fsStatDotl *v9stat)
  22{
  23    int err = 0;
  24    V9fsState *s = pdu->s;
  25
  26    if (v9fs_request_cancelled(pdu)) {
  27        return -EINTR;
  28    }
  29    if (s->ctx.exops.get_st_gen) {
  30        v9fs_path_read_lock(s);
  31        v9fs_co_run_in_worker(
  32            {
  33                err = s->ctx.exops.get_st_gen(&s->ctx, path, st_mode,
  34                                              &v9stat->st_gen);
  35                if (err < 0) {
  36                    err = -errno;
  37                }
  38            });
  39        v9fs_path_unlock(s);
  40    }
  41    return err;
  42}
  43
  44int v9fs_co_lstat(V9fsPDU *pdu, V9fsPath *path, struct stat *stbuf)
  45{
  46    int err;
  47    V9fsState *s = pdu->s;
  48
  49    if (v9fs_request_cancelled(pdu)) {
  50        return -EINTR;
  51    }
  52    v9fs_path_read_lock(s);
  53    v9fs_co_run_in_worker(
  54        {
  55            err = s->ops->lstat(&s->ctx, path, stbuf);
  56            if (err < 0) {
  57                err = -errno;
  58            }
  59        });
  60    v9fs_path_unlock(s);
  61    return err;
  62}
  63
  64int v9fs_co_fstat(V9fsPDU *pdu, V9fsFidState *fidp, struct stat *stbuf)
  65{
  66    int err;
  67    V9fsState *s = pdu->s;
  68
  69    if (v9fs_request_cancelled(pdu)) {
  70        return -EINTR;
  71    }
  72    v9fs_co_run_in_worker(
  73        {
  74            err = s->ops->fstat(&s->ctx, fidp->fid_type, &fidp->fs, stbuf);
  75            if (err < 0) {
  76                err = -errno;
  77            }
  78        });
  79    /*
  80     * Some FS driver (local:mapped-file) can't support fetching attributes
  81     * using file descriptor. Use Path name in that case.
  82     */
  83    if (err == -EOPNOTSUPP) {
  84        err = v9fs_co_lstat(pdu, &fidp->path, stbuf);
  85        if (err == -ENOENT) {
  86            /*
  87             * fstat on an unlinked file. Work with partial results
  88             * returned from s->ops->fstat
  89             */
  90            err = 0;
  91        }
  92    }
  93    return err;
  94}
  95
  96int v9fs_co_open(V9fsPDU *pdu, V9fsFidState *fidp, int flags)
  97{
  98    int err;
  99    V9fsState *s = pdu->s;
 100
 101    if (v9fs_request_cancelled(pdu)) {
 102        return -EINTR;
 103    }
 104    v9fs_path_read_lock(s);
 105    v9fs_co_run_in_worker(
 106        {
 107            err = s->ops->open(&s->ctx, &fidp->path, flags, &fidp->fs);
 108            if (err == -1) {
 109                err = -errno;
 110            } else {
 111                err = 0;
 112            }
 113        });
 114    v9fs_path_unlock(s);
 115    if (!err) {
 116        total_open_fd++;
 117        if (total_open_fd > open_fd_hw) {
 118            v9fs_reclaim_fd(pdu);
 119        }
 120    }
 121    return err;
 122}
 123
 124int v9fs_co_open2(V9fsPDU *pdu, V9fsFidState *fidp, V9fsString *name, gid_t gid,
 125                  int flags, int mode, struct stat *stbuf)
 126{
 127    int err;
 128    FsCred cred;
 129    V9fsPath path;
 130    V9fsState *s = pdu->s;
 131
 132    if (v9fs_request_cancelled(pdu)) {
 133        return -EINTR;
 134    }
 135    cred_init(&cred);
 136    cred.fc_mode = mode & 07777;
 137    cred.fc_uid = fidp->uid;
 138    cred.fc_gid = gid;
 139    /*
 140     * Hold the directory fid lock so that directory path name
 141     * don't change. Read lock is fine because this fid cannot
 142     * be used by any other operation.
 143     */
 144    v9fs_path_read_lock(s);
 145    v9fs_co_run_in_worker(
 146        {
 147            err = s->ops->open2(&s->ctx, &fidp->path,
 148                                name->data, flags, &cred, &fidp->fs);
 149            if (err < 0) {
 150                err = -errno;
 151            } else {
 152                v9fs_path_init(&path);
 153                err = v9fs_name_to_path(s, &fidp->path, name->data, &path);
 154                if (!err) {
 155                    err = s->ops->lstat(&s->ctx, &path, stbuf);
 156                    if (err < 0) {
 157                        err = -errno;
 158                        s->ops->close(&s->ctx, &fidp->fs);
 159                    } else {
 160                        v9fs_path_copy(&fidp->path, &path);
 161                    }
 162                } else {
 163                    s->ops->close(&s->ctx, &fidp->fs);
 164                }
 165                v9fs_path_free(&path);
 166            }
 167        });
 168    v9fs_path_unlock(s);
 169    if (!err) {
 170        total_open_fd++;
 171        if (total_open_fd > open_fd_hw) {
 172            v9fs_reclaim_fd(pdu);
 173        }
 174    }
 175    return err;
 176}
 177
 178int v9fs_co_close(V9fsPDU *pdu, V9fsFidOpenState *fs)
 179{
 180    int err;
 181    V9fsState *s = pdu->s;
 182
 183    if (v9fs_request_cancelled(pdu)) {
 184        return -EINTR;
 185    }
 186    v9fs_co_run_in_worker(
 187        {
 188            err = s->ops->close(&s->ctx, fs);
 189            if (err < 0) {
 190                err = -errno;
 191            }
 192        });
 193    if (!err) {
 194        total_open_fd--;
 195    }
 196    return err;
 197}
 198
 199int v9fs_co_fsync(V9fsPDU *pdu, V9fsFidState *fidp, int datasync)
 200{
 201    int err;
 202    V9fsState *s = pdu->s;
 203
 204    if (v9fs_request_cancelled(pdu)) {
 205        return -EINTR;
 206    }
 207    v9fs_co_run_in_worker(
 208        {
 209            err = s->ops->fsync(&s->ctx, fidp->fid_type, &fidp->fs, datasync);
 210            if (err < 0) {
 211                err = -errno;
 212            }
 213        });
 214    return err;
 215}
 216
 217int v9fs_co_link(V9fsPDU *pdu, V9fsFidState *oldfid,
 218                 V9fsFidState *newdirfid, V9fsString *name)
 219{
 220    int err;
 221    V9fsState *s = pdu->s;
 222
 223    if (v9fs_request_cancelled(pdu)) {
 224        return -EINTR;
 225    }
 226    v9fs_path_read_lock(s);
 227    v9fs_co_run_in_worker(
 228        {
 229            err = s->ops->link(&s->ctx, &oldfid->path,
 230                               &newdirfid->path, name->data);
 231            if (err < 0) {
 232                err = -errno;
 233            }
 234        });
 235    v9fs_path_unlock(s);
 236    return err;
 237}
 238
 239int v9fs_co_pwritev(V9fsPDU *pdu, V9fsFidState *fidp,
 240                    struct iovec *iov, int iovcnt, int64_t offset)
 241{
 242    int err;
 243    V9fsState *s = pdu->s;
 244
 245    if (v9fs_request_cancelled(pdu)) {
 246        return -EINTR;
 247    }
 248    v9fs_co_run_in_worker(
 249        {
 250            err = s->ops->pwritev(&s->ctx, &fidp->fs, iov, iovcnt, offset);
 251            if (err < 0) {
 252                err = -errno;
 253            }
 254        });
 255    return err;
 256}
 257
 258int v9fs_co_preadv(V9fsPDU *pdu, V9fsFidState *fidp,
 259                   struct iovec *iov, int iovcnt, int64_t offset)
 260{
 261    int err;
 262    V9fsState *s = pdu->s;
 263
 264    if (v9fs_request_cancelled(pdu)) {
 265        return -EINTR;
 266    }
 267    v9fs_co_run_in_worker(
 268        {
 269            err = s->ops->preadv(&s->ctx, &fidp->fs, iov, iovcnt, offset);
 270            if (err < 0) {
 271                err = -errno;
 272            }
 273        });
 274    return err;
 275}
 276