qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

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 
     26 int 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 
     50 int 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 
     70 int 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 
    103 int 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 
    131 int 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 
    186 int 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 
    207 int 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 
    225 int 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 
    247 int 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 
    267 int 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 }