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