cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

cofile.c (7259B)


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