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