]> git.proxmox.com Git - mirror_qemu.git/blame - hw/9pfs/virtio-9p-proxy.c
hw/9pfs: File system helper process for qemu 9p proxy FS
[mirror_qemu.git] / hw / 9pfs / virtio-9p-proxy.c
CommitLineData
4c793dda
MK
1/*
2 * Virtio 9p Proxy callback
3 *
4 * Copyright IBM, Corp. 2011
5 *
6 * Authors:
7 * M. Mohan Kumar <mohan@in.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#include <sys/socket.h>
13#include <sys/un.h>
14#include "hw/virtio.h"
15#include "virtio-9p.h"
16#include "fsdev/qemu-fsdev.h"
17#include "virtio-9p-proxy.h"
18
19typedef struct V9fsProxy {
20 int sockfd;
21 QemuMutex mutex;
22 struct iovec iovec;
23} V9fsProxy;
24
25static int proxy_lstat(FsContext *fs_ctx, V9fsPath *fs_path, struct stat *stbuf)
26{
27 errno = EOPNOTSUPP;
28 return -1;
29}
30
31static ssize_t proxy_readlink(FsContext *fs_ctx, V9fsPath *fs_path,
32 char *buf, size_t bufsz)
33{
34 errno = EOPNOTSUPP;
35 return -1;
36}
37
38static int proxy_close(FsContext *ctx, V9fsFidOpenState *fs)
39{
40 return close(fs->fd);
41}
42
43static int proxy_closedir(FsContext *ctx, V9fsFidOpenState *fs)
44{
45 return closedir(fs->dir);
46}
47
48static int proxy_open(FsContext *ctx, V9fsPath *fs_path,
49 int flags, V9fsFidOpenState *fs)
50{
51 fs->fd = -1;
52 return fs->fd;
53}
54
55static int proxy_opendir(FsContext *ctx,
56 V9fsPath *fs_path, V9fsFidOpenState *fs)
57{
58 fs->dir = NULL;
59 errno = EOPNOTSUPP;
60 return -1;
61}
62
63static void proxy_rewinddir(FsContext *ctx, V9fsFidOpenState *fs)
64{
65 return rewinddir(fs->dir);
66}
67
68static off_t proxy_telldir(FsContext *ctx, V9fsFidOpenState *fs)
69{
70 return telldir(fs->dir);
71}
72
73static int proxy_readdir_r(FsContext *ctx, V9fsFidOpenState *fs,
74 struct dirent *entry,
75 struct dirent **result)
76{
77 return readdir_r(fs->dir, entry, result);
78}
79
80static void proxy_seekdir(FsContext *ctx, V9fsFidOpenState *fs, off_t off)
81{
82 return seekdir(fs->dir, off);
83}
84
85static ssize_t proxy_preadv(FsContext *ctx, V9fsFidOpenState *fs,
86 const struct iovec *iov,
87 int iovcnt, off_t offset)
88{
89#ifdef CONFIG_PREADV
90 return preadv(fs->fd, iov, iovcnt, offset);
91#else
92 int err = lseek(fs->fd, offset, SEEK_SET);
93 if (err == -1) {
94 return err;
95 } else {
96 return readv(fs->fd, iov, iovcnt);
97 }
98#endif
99}
100
101static ssize_t proxy_pwritev(FsContext *ctx, V9fsFidOpenState *fs,
102 const struct iovec *iov,
103 int iovcnt, off_t offset)
104{
105 ssize_t ret;
106
107#ifdef CONFIG_PREADV
108 ret = pwritev(fs->fd, iov, iovcnt, offset);
109#else
110 int err = lseek(fs->fd, offset, SEEK_SET);
111 if (err == -1) {
112 return err;
113 } else {
114 ret = writev(fs->fd, iov, iovcnt);
115 }
116#endif
117#ifdef CONFIG_SYNC_FILE_RANGE
118 if (ret > 0 && ctx->export_flags & V9FS_IMMEDIATE_WRITEOUT) {
119 /*
120 * Initiate a writeback. This is not a data integrity sync.
121 * We want to ensure that we don't leave dirty pages in the cache
122 * after write when writeout=immediate is sepcified.
123 */
124 sync_file_range(fs->fd, offset, ret,
125 SYNC_FILE_RANGE_WAIT_BEFORE | SYNC_FILE_RANGE_WRITE);
126 }
127#endif
128 return ret;
129}
130
131static int proxy_chmod(FsContext *fs_ctx, V9fsPath *fs_path, FsCred *credp)
132{
133 errno = EOPNOTSUPP;
134 return -1;
135}
136
137static int proxy_mknod(FsContext *fs_ctx, V9fsPath *dir_path,
138 const char *name, FsCred *credp)
139{
140 errno = EOPNOTSUPP;
141 return -1;
142}
143
144static int proxy_mkdir(FsContext *fs_ctx, V9fsPath *dir_path,
145 const char *name, FsCred *credp)
146{
147 errno = EOPNOTSUPP;
148 return -1;
149}
150
151static int proxy_fstat(FsContext *fs_ctx, int fid_type,
152 V9fsFidOpenState *fs, struct stat *stbuf)
153{
154 int fd;
155
156 if (fid_type == P9_FID_DIR) {
157 fd = dirfd(fs->dir);
158 } else {
159 fd = fs->fd;
160 }
161 return fstat(fd, stbuf);
162}
163
164static int proxy_open2(FsContext *fs_ctx, V9fsPath *dir_path, const char *name,
165 int flags, FsCred *credp, V9fsFidOpenState *fs)
166{
167 fs->fd = -1;
168 errno = EOPNOTSUPP;
169 return -1;
170}
171
172
173static int proxy_symlink(FsContext *fs_ctx, const char *oldpath,
174 V9fsPath *dir_path, const char *name, FsCred *credp)
175{
176 errno = EOPNOTSUPP;
177 return -1;
178}
179
180static int proxy_link(FsContext *ctx, V9fsPath *oldpath,
181 V9fsPath *dirpath, const char *name)
182{
183 errno = EOPNOTSUPP;
184 return -1;
185}
186
187static int proxy_truncate(FsContext *ctx, V9fsPath *fs_path, off_t size)
188{
189 errno = EOPNOTSUPP;
190 return -1;
191}
192
193static int proxy_rename(FsContext *ctx, const char *oldpath,
194 const char *newpath)
195{
196 errno = EOPNOTSUPP;
197 return -1;
198}
199
200static int proxy_chown(FsContext *fs_ctx, V9fsPath *fs_path, FsCred *credp)
201{
202 errno = EOPNOTSUPP;
203 return -1;
204}
205
206static int proxy_utimensat(FsContext *s, V9fsPath *fs_path,
207 const struct timespec *buf)
208{
209 errno = EOPNOTSUPP;
210 return -1;
211}
212
213static int proxy_remove(FsContext *ctx, const char *path)
214{
215 errno = EOPNOTSUPP;
216 return -1;
217}
218
219static int proxy_fsync(FsContext *ctx, int fid_type,
220 V9fsFidOpenState *fs, int datasync)
221{
222 int fd;
223
224 if (fid_type == P9_FID_DIR) {
225 fd = dirfd(fs->dir);
226 } else {
227 fd = fs->fd;
228 }
229
230 if (datasync) {
231 return qemu_fdatasync(fd);
232 } else {
233 return fsync(fd);
234 }
235}
236
237static int proxy_statfs(FsContext *s, V9fsPath *fs_path, struct statfs *stbuf)
238{
239 errno = EOPNOTSUPP;
240 return -1;
241}
242
243static ssize_t proxy_lgetxattr(FsContext *ctx, V9fsPath *fs_path,
244 const char *name, void *value, size_t size)
245{
246 errno = EOPNOTSUPP;
247 return -1;
248}
249
250static ssize_t proxy_llistxattr(FsContext *ctx, V9fsPath *fs_path,
251 void *value, size_t size)
252{
253 errno = EOPNOTSUPP;
254 return -1;
255}
256
257static int proxy_lsetxattr(FsContext *ctx, V9fsPath *fs_path, const char *name,
258 void *value, size_t size, int flags)
259{
260 errno = EOPNOTSUPP;
261 return -1;
262}
263
264static int proxy_lremovexattr(FsContext *ctx, V9fsPath *fs_path,
265 const char *name)
266{
267 errno = EOPNOTSUPP;
268 return -1;
269}
270
271static int proxy_name_to_path(FsContext *ctx, V9fsPath *dir_path,
272 const char *name, V9fsPath *target)
273{
274 if (dir_path) {
275 v9fs_string_sprintf((V9fsString *)target, "%s/%s",
276 dir_path->data, name);
277 } else {
278 v9fs_string_sprintf((V9fsString *)target, "%s", name);
279 }
280 /* Bump the size for including terminating NULL */
281 target->size++;
282 return 0;
283}
284
285static int proxy_renameat(FsContext *ctx, V9fsPath *olddir,
286 const char *old_name, V9fsPath *newdir,
287 const char *new_name)
288{
289 int ret;
290 V9fsString old_full_name, new_full_name;
291
292 v9fs_string_init(&old_full_name);
293 v9fs_string_init(&new_full_name);
294
295 v9fs_string_sprintf(&old_full_name, "%s/%s", olddir->data, old_name);
296 v9fs_string_sprintf(&new_full_name, "%s/%s", newdir->data, new_name);
297
298 ret = proxy_rename(ctx, old_full_name.data, new_full_name.data);
299 v9fs_string_free(&old_full_name);
300 v9fs_string_free(&new_full_name);
301 return ret;
302}
303
304static int proxy_unlinkat(FsContext *ctx, V9fsPath *dir,
305 const char *name, int flags)
306{
307 int ret;
308 V9fsString fullname;
309 v9fs_string_init(&fullname);
310
311 v9fs_string_sprintf(&fullname, "%s/%s", dir->data, name);
312 ret = proxy_remove(ctx, fullname.data);
313 v9fs_string_free(&fullname);
314
315 return ret;
316}
317
318static int proxy_parse_opts(QemuOpts *opts, struct FsDriverEntry *fs)
319{
320 const char *sock_fd = qemu_opt_get(opts, "sock_fd");
321
322 if (sock_fd) {
323 fprintf(stderr, "sock_fd option not specified\n");
324 return -1;
325 }
326 fs->path = g_strdup(sock_fd);
327 return 0;
328}
329
330static int proxy_init(FsContext *ctx)
331{
332 V9fsProxy *proxy = g_malloc(sizeof(V9fsProxy));
333 int sock_id;
334
335 sock_id = atoi(ctx->fs_root);
336 if (sock_id < 0) {
337 fprintf(stderr, "socket descriptor not initialized\n");
338 return -1;
339 }
340 g_free(ctx->fs_root);
341
342 proxy->iovec.iov_base = g_malloc(PROXY_MAX_IO_SZ + PROXY_HDR_SZ);
343 proxy->iovec.iov_len = PROXY_MAX_IO_SZ + PROXY_HDR_SZ;
344 ctx->private = proxy;
345 proxy->sockfd = sock_id;
346 qemu_mutex_init(&proxy->mutex);
347
348 ctx->export_flags |= V9FS_PATHNAME_FSCONTEXT;
349 return 0;
350}
351
352FileOperations proxy_ops = {
353 .parse_opts = proxy_parse_opts,
354 .init = proxy_init,
355 .lstat = proxy_lstat,
356 .readlink = proxy_readlink,
357 .close = proxy_close,
358 .closedir = proxy_closedir,
359 .open = proxy_open,
360 .opendir = proxy_opendir,
361 .rewinddir = proxy_rewinddir,
362 .telldir = proxy_telldir,
363 .readdir_r = proxy_readdir_r,
364 .seekdir = proxy_seekdir,
365 .preadv = proxy_preadv,
366 .pwritev = proxy_pwritev,
367 .chmod = proxy_chmod,
368 .mknod = proxy_mknod,
369 .mkdir = proxy_mkdir,
370 .fstat = proxy_fstat,
371 .open2 = proxy_open2,
372 .symlink = proxy_symlink,
373 .link = proxy_link,
374 .truncate = proxy_truncate,
375 .rename = proxy_rename,
376 .chown = proxy_chown,
377 .utimensat = proxy_utimensat,
378 .remove = proxy_remove,
379 .fsync = proxy_fsync,
380 .statfs = proxy_statfs,
381 .lgetxattr = proxy_lgetxattr,
382 .llistxattr = proxy_llistxattr,
383 .lsetxattr = proxy_lsetxattr,
384 .lremovexattr = proxy_lremovexattr,
385 .name_to_path = proxy_name_to_path,
386 .renameat = proxy_renameat,
387 .unlinkat = proxy_unlinkat,
388};