Statistics
| Branch: | Revision:

root / hw / 9pfs / cofs.c @ a8aec295

History | View | Annotate | Download (8 kB)

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 "block/coroutine.h"
18
#include "virtio-9p-coth.h"
19

    
20
int v9fs_co_readlink(V9fsPDU *pdu, V9fsPath *path, V9fsString *buf)
21
{
22
    int err;
23
    ssize_t len;
24
    V9fsState *s = pdu->s;
25

    
26
    if (v9fs_request_cancelled(pdu)) {
27
        return -EINTR;
28
    }
29
    buf->data = g_malloc(PATH_MAX);
30
    v9fs_path_read_lock(s);
31
    v9fs_co_run_in_worker(
32
        {
33
            len = s->ops->readlink(&s->ctx, path,
34
                                   buf->data, PATH_MAX - 1);
35
            if (len > -1) {
36
                buf->size = len;
37
                buf->data[len] = 0;
38
                err = 0;
39
            } else {
40
                err = -errno;
41
            }
42
        });
43
    v9fs_path_unlock(s);
44
    if (err) {
45
        g_free(buf->data);
46
        buf->data = NULL;
47
        buf->size = 0;
48
    }
49
    return err;
50
}
51

    
52
int v9fs_co_statfs(V9fsPDU *pdu, V9fsPath *path, struct statfs *stbuf)
53
{
54
    int err;
55
    V9fsState *s = pdu->s;
56

    
57
    if (v9fs_request_cancelled(pdu)) {
58
        return -EINTR;
59
    }
60
    v9fs_path_read_lock(s);
61
    v9fs_co_run_in_worker(
62
        {
63
            err = s->ops->statfs(&s->ctx, path, stbuf);
64
            if (err < 0) {
65
                err = -errno;
66
            }
67
        });
68
    v9fs_path_unlock(s);
69
    return err;
70
}
71

    
72
int v9fs_co_chmod(V9fsPDU *pdu, V9fsPath *path, mode_t mode)
73
{
74
    int err;
75
    FsCred cred;
76
    V9fsState *s = pdu->s;
77

    
78
    if (v9fs_request_cancelled(pdu)) {
79
        return -EINTR;
80
    }
81
    cred_init(&cred);
82
    cred.fc_mode = mode;
83
    v9fs_path_read_lock(s);
84
    v9fs_co_run_in_worker(
85
        {
86
            err = s->ops->chmod(&s->ctx, path, &cred);
87
            if (err < 0) {
88
                err = -errno;
89
            }
90
        });
91
    v9fs_path_unlock(s);
92
    return err;
93
}
94

    
95
int v9fs_co_utimensat(V9fsPDU *pdu, V9fsPath *path,
96
                      struct timespec times[2])
97
{
98
    int err;
99
    V9fsState *s = pdu->s;
100

    
101
    if (v9fs_request_cancelled(pdu)) {
102
        return -EINTR;
103
    }
104
    v9fs_path_read_lock(s);
105
    v9fs_co_run_in_worker(
106
        {
107
            err = s->ops->utimensat(&s->ctx, path, times);
108
            if (err < 0) {
109
                err = -errno;
110
            }
111
        });
112
    v9fs_path_unlock(s);
113
    return err;
114
}
115

    
116
int v9fs_co_chown(V9fsPDU *pdu, V9fsPath *path, uid_t uid, gid_t gid)
117
{
118
    int err;
119
    FsCred cred;
120
    V9fsState *s = pdu->s;
121

    
122
    if (v9fs_request_cancelled(pdu)) {
123
        return -EINTR;
124
    }
125
    cred_init(&cred);
126
    cred.fc_uid = uid;
127
    cred.fc_gid = gid;
128
    v9fs_path_read_lock(s);
129
    v9fs_co_run_in_worker(
130
        {
131
            err = s->ops->chown(&s->ctx, path, &cred);
132
            if (err < 0) {
133
                err = -errno;
134
            }
135
        });
136
    v9fs_path_unlock(s);
137
    return err;
138
}
139

    
140
int v9fs_co_truncate(V9fsPDU *pdu, V9fsPath *path, off_t size)
141
{
142
    int err;
143
    V9fsState *s = pdu->s;
144

    
145
    if (v9fs_request_cancelled(pdu)) {
146
        return -EINTR;
147
    }
148
    v9fs_path_read_lock(s);
149
    v9fs_co_run_in_worker(
150
        {
151
            err = s->ops->truncate(&s->ctx, path, size);
152
            if (err < 0) {
153
                err = -errno;
154
            }
155
        });
156
    v9fs_path_unlock(s);
157
    return err;
158
}
159

    
160
int v9fs_co_mknod(V9fsPDU *pdu, V9fsFidState *fidp, V9fsString *name, uid_t uid,
161
                  gid_t gid, dev_t dev, mode_t mode, struct stat *stbuf)
162
{
163
    int err;
164
    V9fsPath path;
165
    FsCred cred;
166
    V9fsState *s = pdu->s;
167

    
168
    if (v9fs_request_cancelled(pdu)) {
169
        return -EINTR;
170
    }
171
    cred_init(&cred);
172
    cred.fc_uid  = uid;
173
    cred.fc_gid  = gid;
174
    cred.fc_mode = mode;
175
    cred.fc_rdev = dev;
176
    v9fs_path_read_lock(s);
177
    v9fs_co_run_in_worker(
178
        {
179
            err = s->ops->mknod(&s->ctx, &fidp->path, name->data, &cred);
180
            if (err < 0) {
181
                err = -errno;
182
            } else {
183
                v9fs_path_init(&path);
184
                err = v9fs_name_to_path(s, &fidp->path, name->data, &path);
185
                if (!err) {
186
                    err = s->ops->lstat(&s->ctx, &path, stbuf);
187
                    if (err < 0) {
188
                        err = -errno;
189
                    }
190
                }
191
                v9fs_path_free(&path);
192
            }
193
        });
194
    v9fs_path_unlock(s);
195
    return err;
196
}
197

    
198
/* Only works with path name based fid */
199
int v9fs_co_remove(V9fsPDU *pdu, V9fsPath *path)
200
{
201
    int err;
202
    V9fsState *s = pdu->s;
203

    
204
    if (v9fs_request_cancelled(pdu)) {
205
        return -EINTR;
206
    }
207
    v9fs_path_read_lock(s);
208
    v9fs_co_run_in_worker(
209
        {
210
            err = s->ops->remove(&s->ctx, path->data);
211
            if (err < 0) {
212
                err = -errno;
213
            }
214
        });
215
    v9fs_path_unlock(s);
216
    return err;
217
}
218

    
219
int v9fs_co_unlinkat(V9fsPDU *pdu, V9fsPath *path, V9fsString *name, int flags)
220
{
221
    int err;
222
    V9fsState *s = pdu->s;
223

    
224
    if (v9fs_request_cancelled(pdu)) {
225
        return -EINTR;
226
    }
227
    v9fs_path_read_lock(s);
228
    v9fs_co_run_in_worker(
229
        {
230
            err = s->ops->unlinkat(&s->ctx, path, name->data, flags);
231
            if (err < 0) {
232
                err = -errno;
233
            }
234
        });
235
    v9fs_path_unlock(s);
236
    return err;
237
}
238

    
239
/* Only work with path name based fid */
240
int v9fs_co_rename(V9fsPDU *pdu, V9fsPath *oldpath, V9fsPath *newpath)
241
{
242
    int err;
243
    V9fsState *s = pdu->s;
244

    
245
    if (v9fs_request_cancelled(pdu)) {
246
        return -EINTR;
247
    }
248
    v9fs_co_run_in_worker(
249
        {
250
            err = s->ops->rename(&s->ctx, oldpath->data, newpath->data);
251
            if (err < 0) {
252
                err = -errno;
253
            }
254
        });
255
    return err;
256
}
257

    
258
int v9fs_co_renameat(V9fsPDU *pdu, V9fsPath *olddirpath, V9fsString *oldname,
259
                     V9fsPath *newdirpath, V9fsString *newname)
260
{
261
    int err;
262
    V9fsState *s = pdu->s;
263

    
264
    if (v9fs_request_cancelled(pdu)) {
265
        return -EINTR;
266
    }
267
    v9fs_co_run_in_worker(
268
        {
269
            err = s->ops->renameat(&s->ctx, olddirpath, oldname->data,
270
                                   newdirpath, newname->data);
271
            if (err < 0) {
272
                err = -errno;
273
            }
274
        });
275
    return err;
276
}
277

    
278
int v9fs_co_symlink(V9fsPDU *pdu, V9fsFidState *dfidp, V9fsString *name,
279
                    const char *oldpath, gid_t gid, struct stat *stbuf)
280
{
281
    int err;
282
    FsCred cred;
283
    V9fsPath path;
284
    V9fsState *s = pdu->s;
285

    
286
    if (v9fs_request_cancelled(pdu)) {
287
        return -EINTR;
288
    }
289
    cred_init(&cred);
290
    cred.fc_uid = dfidp->uid;
291
    cred.fc_gid = gid;
292
    cred.fc_mode = 0777;
293
    v9fs_path_read_lock(s);
294
    v9fs_co_run_in_worker(
295
        {
296
            err = s->ops->symlink(&s->ctx, oldpath, &dfidp->path,
297
                                  name->data, &cred);
298
            if (err < 0) {
299
                err = -errno;
300
            } else {
301
                v9fs_path_init(&path);
302
                err = v9fs_name_to_path(s, &dfidp->path, name->data, &path);
303
                if (!err) {
304
                    err = s->ops->lstat(&s->ctx, &path, stbuf);
305
                    if (err < 0) {
306
                        err = -errno;
307
                    }
308
                }
309
                v9fs_path_free(&path);
310
            }
311
        });
312
    v9fs_path_unlock(s);
313
    return err;
314
}
315

    
316
/*
317
 * For path name based fid we don't block. So we can
318
 * directly call the fs driver ops.
319
 */
320
int v9fs_co_name_to_path(V9fsPDU *pdu, V9fsPath *dirpath,
321
                         const char *name, V9fsPath *path)
322
{
323
    int err;
324
    V9fsState *s = pdu->s;
325

    
326
    if (s->ctx.export_flags & V9FS_PATHNAME_FSCONTEXT) {
327
        err = s->ops->name_to_path(&s->ctx, dirpath, name, path);
328
        if (err < 0) {
329
            err = -errno;
330
        }
331
    } else {
332
        if (v9fs_request_cancelled(pdu)) {
333
            return -EINTR;
334
        }
335
        v9fs_co_run_in_worker(
336
            {
337
                err = s->ops->name_to_path(&s->ctx, dirpath, name, path);
338
                if (err < 0) {
339
                    err = -errno;
340
                }
341
            });
342
    }
343
    return err;
344
}