qemu/hw/9pfs/cofile.c
<<
>>
Prefs
   1/*
   2 * 9p backend
   3 *
   4 * Copyright IBM, Corp. 2011
   5 *
   6 * Authors:
   7 *  Aneesh Kumar K.V <aneesh.kumar@linux.vnet.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 "fsdev/qemu-fsdev.h"
  16#include "qemu/thread.h"
  17#include "qemu/coroutine.h"
  18#include "qemu/main-loop.h"
  19#include "coth.h"
  20
  21int coroutine_fn 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 coroutine_fn 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 coroutine_fn v9fs_co_fstat(V9fsPDU *pdu, V9fsFidState *fidp,
  66                               struct stat *stbuf)
  67{
  68    int err;
  69    V9fsState *s = pdu->s;
  70
  71    if (v9fs_request_cancelled(pdu)) {
  72        return -EINTR;
  73    }
  74    v9fs_co_run_in_worker(
  75        {
  76            err = s->ops->fstat(&s->ctx, fidp->fid_type, &fidp->fs, stbuf);
  77            if (err < 0) {
  78                err = -errno;
  79            }
  80        });
  81    /*
  82     * Some FS driver (local:mapped-file) can't support fetching attributes
  83     * using file descriptor. Use Path name in that case.
  84     */
  85    if (err == -EOPNOTSUPP) {
  86        err = v9fs_co_lstat(pdu, &fidp->path, stbuf);
  87        if (err == -ENOENT) {
  88            /*
  89             * fstat on an unlinked file. Work with partial results
  90             * returned from s->ops->fstat
  91             */
  92            err = 0;
  93        }
  94    }
  95    return err;
  96}
  97
  98int coroutine_fn v9fs_co_open(V9fsPDU *pdu, V9fsFidState *fidp, int flags)
  99{
 100    int err;
 101    V9fsState *s = pdu->s;
 102
 103    if (v9fs_request_cancelled(pdu)) {
 104        return -EINTR;
 105    }
 106    v9fs_path_read_lock(s);
 107    v9fs_co_run_in_worker(
 108        {
 109            err = s->ops->open(&s->ctx, &fidp->path, flags, &fidp->fs);
 110            if (err == -1) {
 111                err = -errno;
 112            } else {
 113                err = 0;
 114            }
 115        });
 116    v9fs_path_unlock(s);
 117    if (!err) {
 118        total_open_fd++;
 119        if (total_open_fd > open_fd_hw) {
 120            v9fs_reclaim_fd(pdu);
 121        }
 122    }
 123    return err;
 124}
 125
 126int coroutine_fn v9fs_co_open2(V9fsPDU *pdu, V9fsFidState *fidp,
 127                               V9fsString *name, gid_t gid, int flags, int mode,
 128                               struct stat *stbuf)
 129{
 130    int err;
 131    FsCred cred;
 132    V9fsPath path;
 133    V9fsState *s = pdu->s;
 134
 135    if (v9fs_request_cancelled(pdu)) {
 136        return -EINTR;
 137    }
 138    cred_init(&cred);
 139    cred.fc_mode = mode & 07777;
 140    cred.fc_uid = fidp->uid;
 141    cred.fc_gid = gid;
 142    /*
 143     * Hold the directory fid lock so that directory path name
 144     * don't change. Take the write lock to be sure this fid
 145     * cannot be used by another operation.
 146     */
 147    v9fs_path_write_lock(s);
 148    v9fs_co_run_in_worker(
 149        {
 150            err = s->ops->open2(&s->ctx, &fidp->path,
 151                                name->data, flags, &cred, &fidp->fs);
 152            if (err < 0) {
 153                err = -errno;
 154            } else {
 155                v9fs_path_init(&path);
 156                err = v9fs_name_to_path(s, &fidp->path, name->data, &path);
 157                if (!err) {
 158                    err = s->ops->lstat(&s->ctx, &path, stbuf);
 159                    if (err < 0) {
 160                        err = -errno;
 161                        s->ops->close(&s->ctx, &fidp->fs);
 162                    } else {
 163                        v9fs_path_copy(&fidp->path, &path);
 164                    }
 165                } else {
 166                    s->ops->close(&s->ctx, &fidp->fs);
 167                }
 168                v9fs_path_free(&path);
 169            }
 170        });
 171    v9fs_path_unlock(s);
 172    if (!err) {
 173        total_open_fd++;
 174        if (total_open_fd > open_fd_hw) {
 175            v9fs_reclaim_fd(pdu);
 176        }
 177    }
 178    return err;
 179}
 180
 181int coroutine_fn v9fs_co_close(V9fsPDU *pdu, V9fsFidOpenState *fs)
 182{
 183    int err;
 184    V9fsState *s = pdu->s;
 185
 186    if (v9fs_request_cancelled(pdu)) {
 187        return -EINTR;
 188    }
 189    v9fs_co_run_in_worker(
 190        {
 191            err = s->ops->close(&s->ctx, fs);
 192            if (err < 0) {
 193                err = -errno;
 194            }
 195        });
 196    if (!err) {
 197        total_open_fd--;
 198    }
 199    return err;
 200}
 201
 202int coroutine_fn v9fs_co_fsync(V9fsPDU *pdu, V9fsFidState *fidp, int datasync)
 203{
 204    int err;
 205    V9fsState *s = pdu->s;
 206
 207    if (v9fs_request_cancelled(pdu)) {
 208        return -EINTR;
 209    }
 210    v9fs_co_run_in_worker(
 211        {
 212            err = s->ops->fsync(&s->ctx, fidp->fid_type, &fidp->fs, datasync);
 213            if (err < 0) {
 214                err = -errno;
 215            }
 216        });
 217    return err;
 218}
 219
 220int coroutine_fn v9fs_co_link(V9fsPDU *pdu, V9fsFidState *oldfid,
 221                              V9fsFidState *newdirfid, V9fsString *name)
 222{
 223    int err;
 224    V9fsState *s = pdu->s;
 225
 226    if (v9fs_request_cancelled(pdu)) {
 227        return -EINTR;
 228    }
 229    v9fs_path_read_lock(s);
 230    v9fs_co_run_in_worker(
 231        {
 232            err = s->ops->link(&s->ctx, &oldfid->path,
 233                               &newdirfid->path, name->data);
 234            if (err < 0) {
 235                err = -errno;
 236            }
 237        });
 238    v9fs_path_unlock(s);
 239    return err;
 240}
 241
 242int coroutine_fn v9fs_co_pwritev(V9fsPDU *pdu, V9fsFidState *fidp,
 243                                 struct iovec *iov, int iovcnt, int64_t offset)
 244{
 245    int err;
 246    V9fsState *s = pdu->s;
 247
 248    if (v9fs_request_cancelled(pdu)) {
 249        return -EINTR;
 250    }
 251    fsdev_co_throttle_request(s->ctx.fst, true, iov, iovcnt);
 252    v9fs_co_run_in_worker(
 253        {
 254            err = s->ops->pwritev(&s->ctx, &fidp->fs, iov, iovcnt, offset);
 255            if (err < 0) {
 256                err = -errno;
 257            }
 258        });
 259    return err;
 260}
 261
 262int coroutine_fn v9fs_co_preadv(V9fsPDU *pdu, V9fsFidState *fidp,
 263                                struct iovec *iov, int iovcnt, int64_t offset)
 264{
 265    int err;
 266    V9fsState *s = pdu->s;
 267
 268    if (v9fs_request_cancelled(pdu)) {
 269        return -EINTR;
 270    }
 271    fsdev_co_throttle_request(s->ctx.fst, false, iov, iovcnt);
 272    v9fs_co_run_in_worker(
 273        {
 274            err = s->ops->preadv(&s->ctx, &fidp->fs, iov, iovcnt, offset);
 275            if (err < 0) {
 276                err = -errno;
 277            }
 278        });
 279    return err;
 280}
 281