qemu/hw/9pfs/codir.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_readdir_r(V9fsPDU *pdu, V9fsFidState *fidp, struct dirent *dent,
  22                      struct dirent **result)
  23{
  24    int err;
  25    V9fsState *s = pdu->s;
  26
  27    if (v9fs_request_cancelled(pdu)) {
  28        return -EINTR;
  29    }
  30    v9fs_co_run_in_worker(
  31        {
  32            errno = 0;
  33            err = s->ops->readdir_r(&s->ctx, &fidp->fs, dent, result);
  34            if (!*result && errno) {
  35                err = -errno;
  36            } else {
  37                err = 0;
  38            }
  39        });
  40    return err;
  41}
  42
  43off_t v9fs_co_telldir(V9fsPDU *pdu, V9fsFidState *fidp)
  44{
  45    off_t err;
  46    V9fsState *s = pdu->s;
  47
  48    if (v9fs_request_cancelled(pdu)) {
  49        return -EINTR;
  50    }
  51    v9fs_co_run_in_worker(
  52        {
  53            err = s->ops->telldir(&s->ctx, &fidp->fs);
  54            if (err < 0) {
  55                err = -errno;
  56            }
  57        });
  58    return err;
  59}
  60
  61void v9fs_co_seekdir(V9fsPDU *pdu, V9fsFidState *fidp, off_t offset)
  62{
  63    V9fsState *s = pdu->s;
  64    if (v9fs_request_cancelled(pdu)) {
  65        return;
  66    }
  67    v9fs_co_run_in_worker(
  68        {
  69            s->ops->seekdir(&s->ctx, &fidp->fs, offset);
  70        });
  71}
  72
  73void v9fs_co_rewinddir(V9fsPDU *pdu, V9fsFidState *fidp)
  74{
  75    V9fsState *s = pdu->s;
  76    if (v9fs_request_cancelled(pdu)) {
  77        return;
  78    }
  79    v9fs_co_run_in_worker(
  80        {
  81            s->ops->rewinddir(&s->ctx, &fidp->fs);
  82        });
  83}
  84
  85int v9fs_co_mkdir(V9fsPDU *pdu, V9fsFidState *fidp, V9fsString *name,
  86                  mode_t mode, uid_t uid, gid_t gid, struct stat *stbuf)
  87{
  88    int err;
  89    FsCred cred;
  90    V9fsPath path;
  91    V9fsState *s = pdu->s;
  92
  93    if (v9fs_request_cancelled(pdu)) {
  94        return -EINTR;
  95    }
  96    cred_init(&cred);
  97    cred.fc_mode = mode;
  98    cred.fc_uid = uid;
  99    cred.fc_gid = gid;
 100    v9fs_path_read_lock(s);
 101    v9fs_co_run_in_worker(
 102        {
 103            err = s->ops->mkdir(&s->ctx, &fidp->path, name->data,  &cred);
 104            if (err < 0) {
 105                err = -errno;
 106            } else {
 107                v9fs_path_init(&path);
 108                err = v9fs_name_to_path(s, &fidp->path, name->data, &path);
 109                if (!err) {
 110                    err = s->ops->lstat(&s->ctx, &path, stbuf);
 111                    if (err < 0) {
 112                        err = -errno;
 113                    }
 114                }
 115                v9fs_path_free(&path);
 116            }
 117        });
 118    v9fs_path_unlock(s);
 119    return err;
 120}
 121
 122int v9fs_co_opendir(V9fsPDU *pdu, V9fsFidState *fidp)
 123{
 124    int err;
 125    V9fsState *s = pdu->s;
 126
 127    if (v9fs_request_cancelled(pdu)) {
 128        return -EINTR;
 129    }
 130    v9fs_path_read_lock(s);
 131    v9fs_co_run_in_worker(
 132        {
 133            err = s->ops->opendir(&s->ctx, &fidp->path, &fidp->fs);
 134            if (err < 0) {
 135                err = -errno;
 136            } else {
 137                err = 0;
 138            }
 139        });
 140    v9fs_path_unlock(s);
 141    if (!err) {
 142        total_open_fd++;
 143        if (total_open_fd > open_fd_hw) {
 144            v9fs_reclaim_fd(pdu);
 145        }
 146    }
 147    return err;
 148}
 149
 150int v9fs_co_closedir(V9fsPDU *pdu, V9fsFidOpenState *fs)
 151{
 152    int err;
 153    V9fsState *s = pdu->s;
 154
 155    if (v9fs_request_cancelled(pdu)) {
 156        return -EINTR;
 157    }
 158    v9fs_co_run_in_worker(
 159        {
 160            err = s->ops->closedir(&s->ctx, fs);
 161            if (err < 0) {
 162                err = -errno;
 163            }
 164        });
 165    if (!err) {
 166        total_open_fd--;
 167    }
 168    return err;
 169}
 170