codir.c 3.7 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19

/*
 * Virtio 9p backend
 *
 * Copyright IBM, Corp. 2011
 *
 * Authors:
 *  Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
 *
 * This work is licensed under the terms of the GNU GPL, version 2.  See
 * the COPYING file in the top-level directory.
 *
 */

#include "fsdev/qemu-fsdev.h"
#include "qemu-thread.h"
#include "qemu-coroutine.h"
#include "virtio-9p-coth.h"

20
int 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 27 28
    if (v9fs_request_cancelled(pdu)) {
        return -EINTR;
    }
29 30 31
    v9fs_co_run_in_worker(
        {
            errno = 0;
32
            err = s->ops->readdir_r(&s->ctx, &fidp->fs, dent, result);
33
            if (!*result && errno) {
34 35 36 37 38 39 40 41
                err = -errno;
            } else {
                err = 0;
            }
        });
    return err;
}

42
off_t v9fs_co_telldir(V9fsPDU *pdu, V9fsFidState *fidp)
43 44
{
    off_t err;
45
    V9fsState *s = pdu->s;
46

47 48 49
    if (v9fs_request_cancelled(pdu)) {
        return -EINTR;
    }
50 51
    v9fs_co_run_in_worker(
        {
52
            err = s->ops->telldir(&s->ctx, &fidp->fs);
53 54 55 56 57 58 59
            if (err < 0) {
                err = -errno;
            }
        });
    return err;
}

60
void v9fs_co_seekdir(V9fsPDU *pdu, V9fsFidState *fidp, off_t offset)
61
{
62 63 64 65
    V9fsState *s = pdu->s;
    if (v9fs_request_cancelled(pdu)) {
        return;
    }
66 67
    v9fs_co_run_in_worker(
        {
68
            s->ops->seekdir(&s->ctx, &fidp->fs, offset);
69 70 71
        });
}

72
void v9fs_co_rewinddir(V9fsPDU *pdu, V9fsFidState *fidp)
73
{
74 75 76 77
    V9fsState *s = pdu->s;
    if (v9fs_request_cancelled(pdu)) {
        return;
    }
78 79
    v9fs_co_run_in_worker(
        {
80
            s->ops->rewinddir(&s->ctx, &fidp->fs);
81 82
        });
}
83

84
int v9fs_co_mkdir(V9fsPDU *pdu, V9fsFidState *fidp, V9fsString *name,
85
                  mode_t mode, uid_t uid, gid_t gid, struct stat *stbuf)
86 87 88
{
    int err;
    FsCred cred;
89
    V9fsPath path;
90
    V9fsState *s = pdu->s;
91

92
    if (v9fs_request_cancelled(pdu)) {
93
        return -EINTR;
94
    }
95 96 97 98
    cred_init(&cred);
    cred.fc_mode = mode;
    cred.fc_uid = uid;
    cred.fc_gid = gid;
99
    v9fs_path_read_lock(s);
100 101
    v9fs_co_run_in_worker(
        {
102
            err = s->ops->mkdir(&s->ctx, &fidp->path, name->data,  &cred);
103 104
            if (err < 0) {
                err = -errno;
105
            } else {
106 107 108 109 110 111 112
                v9fs_path_init(&path);
                err = v9fs_name_to_path(s, &fidp->path, name->data, &path);
                if (!err) {
                    err = s->ops->lstat(&s->ctx, &path, stbuf);
                    if (err < 0) {
                        err = -errno;
                    }
113
                }
114
                v9fs_path_free(&path);
115 116
            }
        });
117
    v9fs_path_unlock(s);
118 119
    return err;
}
120

121
int 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 131
    v9fs_co_run_in_worker(
        {
132 133
            err = s->ops->opendir(&s->ctx, &fidp->path, &fidp->fs);
            if (err < 0) {
134 135 136 137 138
                err = -errno;
            } else {
                err = 0;
            }
        });
139
    v9fs_path_unlock(s);
140 141 142
    if (!err) {
        total_open_fd++;
        if (total_open_fd > open_fd_hw) {
143
            v9fs_reclaim_fd(pdu);
144 145
        }
    }
146 147
    return err;
}
148

149
int 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 158
    v9fs_co_run_in_worker(
        {
159
            err = s->ops->closedir(&s->ctx, fs);
160 161 162 163
            if (err < 0) {
                err = -errno;
            }
        });
164 165 166
    if (!err) {
        total_open_fd--;
    }
167 168
    return err;
}