diff options
Diffstat (limited to 'qemu/hw/9pfs')
-rw-r--r-- | qemu/hw/9pfs/9p-handle.c (renamed from qemu/hw/9pfs/virtio-9p-handle.c) | 15 | ||||
-rw-r--r-- | qemu/hw/9pfs/9p-local.c (renamed from qemu/hw/9pfs/virtio-9p-local.c) | 24 | ||||
-rw-r--r-- | qemu/hw/9pfs/9p-posix-acl.c (renamed from qemu/hw/9pfs/virtio-9p-posix-acl.c) | 9 | ||||
-rw-r--r-- | qemu/hw/9pfs/9p-proxy.c (renamed from qemu/hw/9pfs/virtio-9p-proxy.c) | 21 | ||||
-rw-r--r-- | qemu/hw/9pfs/9p-proxy.h (renamed from qemu/hw/9pfs/virtio-9p-proxy.h) | 10 | ||||
-rw-r--r-- | qemu/hw/9pfs/9p-synth.c (renamed from qemu/hw/9pfs/virtio-9p-synth.c) | 9 | ||||
-rw-r--r-- | qemu/hw/9pfs/9p-synth.h (renamed from qemu/hw/9pfs/virtio-9p-synth.h) | 9 | ||||
-rw-r--r-- | qemu/hw/9pfs/9p-xattr-user.c (renamed from qemu/hw/9pfs/virtio-9p-xattr-user.c) | 9 | ||||
-rw-r--r-- | qemu/hw/9pfs/9p-xattr.c (renamed from qemu/hw/9pfs/virtio-9p-xattr.c) | 8 | ||||
-rw-r--r-- | qemu/hw/9pfs/9p-xattr.h (renamed from qemu/hw/9pfs/virtio-9p-xattr.h) | 6 | ||||
-rw-r--r-- | qemu/hw/9pfs/9p.c (renamed from qemu/hw/9pfs/virtio-9p.c) | 264 | ||||
-rw-r--r-- | qemu/hw/9pfs/9p.h | 324 | ||||
-rw-r--r-- | qemu/hw/9pfs/Makefile.objs | 14 | ||||
-rw-r--r-- | qemu/hw/9pfs/codir.c | 5 | ||||
-rw-r--r-- | qemu/hw/9pfs/cofile.c | 5 | ||||
-rw-r--r-- | qemu/hw/9pfs/cofs.c | 5 | ||||
-rw-r--r-- | qemu/hw/9pfs/coth.c | 42 | ||||
-rw-r--r-- | qemu/hw/9pfs/coth.h (renamed from qemu/hw/9pfs/virtio-9p-coth.h) | 18 | ||||
-rw-r--r-- | qemu/hw/9pfs/coxattr.c | 5 | ||||
-rw-r--r-- | qemu/hw/9pfs/virtio-9p-coth.c | 82 | ||||
-rw-r--r-- | qemu/hw/9pfs/virtio-9p-device.c | 212 | ||||
-rw-r--r-- | qemu/hw/9pfs/virtio-9p.h | 391 |
22 files changed, 761 insertions, 726 deletions
diff --git a/qemu/hw/9pfs/virtio-9p-handle.c b/qemu/hw/9pfs/9p-handle.c index 13eabb98a..894041488 100644 --- a/qemu/hw/9pfs/virtio-9p-handle.c +++ b/qemu/hw/9pfs/9p-handle.c @@ -1,5 +1,5 @@ /* - * Virtio 9p handle callback + * 9p handle callback * * Copyright IBM, Corp. 2011 * @@ -11,16 +11,17 @@ * */ -#include "hw/virtio/virtio.h" -#include "virtio-9p.h" -#include "virtio-9p-xattr.h" +#include "qemu/osdep.h" +#include "9p.h" +#include "9p-xattr.h" #include <arpa/inet.h> #include <pwd.h> #include <grp.h> #include <sys/socket.h> #include <sys/un.h> #include "qemu/xattr.h" -#include <unistd.h> +#include "qemu/cutils.h" +#include "qemu/error-report.h" #include <linux/fs.h> #ifdef CONFIG_LINUX_MAGIC_H #include <linux/magic.h> @@ -656,12 +657,12 @@ static int handle_parse_opts(QemuOpts *opts, struct FsDriverEntry *fse) const char *path = qemu_opt_get(opts, "path"); if (sec_model) { - fprintf(stderr, "Invalid argument security_model specified with handle fsdriver\n"); + error_report("Invalid argument security_model specified with handle fsdriver"); return -1; } if (!path) { - fprintf(stderr, "fsdev: No path specified.\n"); + error_report("fsdev: No path specified"); return -1; } fse->path = g_strdup(path); diff --git a/qemu/hw/9pfs/virtio-9p-local.c b/qemu/hw/9pfs/9p-local.c index f1f2e2573..16f45f485 100644 --- a/qemu/hw/9pfs/virtio-9p-local.c +++ b/qemu/hw/9pfs/9p-local.c @@ -1,5 +1,5 @@ /* - * Virtio 9p Posix callback + * 9p Posix callback * * Copyright IBM, Corp. 2010 * @@ -11,9 +11,9 @@ * */ -#include "hw/virtio/virtio.h" -#include "virtio-9p.h" -#include "virtio-9p-xattr.h" +#include "qemu/osdep.h" +#include "9p.h" +#include "9p-xattr.h" #include "fsdev/qemu-fsdev.h" /* local_ops */ #include <arpa/inet.h> #include <pwd.h> @@ -21,6 +21,8 @@ #include <sys/socket.h> #include <sys/un.h> #include "qemu/xattr.h" +#include "qemu/cutils.h" +#include "qemu/error-report.h" #include <libgen.h> #include <linux/fs.h> #ifdef CONFIG_LINUX_MAGIC_H @@ -1210,9 +1212,9 @@ static int local_parse_opts(QemuOpts *opts, struct FsDriverEntry *fse) const char *path = qemu_opt_get(opts, "path"); if (!sec_model) { - fprintf(stderr, "security model not specified, " - "local fs needs security model\nvalid options are:" - "\tsecurity_model=[passthrough|mapped|none]\n"); + error_report("Security model not specified, local fs needs security model"); + error_printf("valid options are:" + "\tsecurity_model=[passthrough|mapped-xattr|mapped-file|none]\n"); return -1; } @@ -1226,14 +1228,14 @@ static int local_parse_opts(QemuOpts *opts, struct FsDriverEntry *fse) } else if (!strcmp(sec_model, "mapped-file")) { fse->export_flags |= V9FS_SM_MAPPED_FILE; } else { - fprintf(stderr, "Invalid security model %s specified, valid options are" - "\n\t [passthrough|mapped-xattr|mapped-file|none]\n", - sec_model); + error_report("Invalid security model %s specified", sec_model); + error_printf("valid options are:" + "\t[passthrough|mapped-xattr|mapped-file|none]\n"); return -1; } if (!path) { - fprintf(stderr, "fsdev: No path specified.\n"); + error_report("fsdev: No path specified"); return -1; } fse->path = g_strdup(path); diff --git a/qemu/hw/9pfs/virtio-9p-posix-acl.c b/qemu/hw/9pfs/9p-posix-acl.c index 09dad071e..ec003181c 100644 --- a/qemu/hw/9pfs/virtio-9p-posix-acl.c +++ b/qemu/hw/9pfs/9p-posix-acl.c @@ -1,5 +1,5 @@ /* - * Virtio 9p system.posix* xattr callback + * 9p system.posix* xattr callback * * Copyright IBM, Corp. 2010 * @@ -11,12 +11,11 @@ * */ -#include <sys/types.h> +#include "qemu/osdep.h" #include "qemu/xattr.h" -#include "hw/virtio/virtio.h" -#include "virtio-9p.h" +#include "9p.h" #include "fsdev/file-op-9p.h" -#include "virtio-9p-xattr.h" +#include "9p-xattr.h" #define MAP_ACL_ACCESS "user.virtfs.system.posix_acl_access" #define MAP_ACL_DEFAULT "user.virtfs.system.posix_acl_default" diff --git a/qemu/hw/9pfs/virtio-9p-proxy.c b/qemu/hw/9pfs/9p-proxy.c index 1bc7881f0..00a4eb2a7 100644 --- a/qemu/hw/9pfs/virtio-9p-proxy.c +++ b/qemu/hw/9pfs/9p-proxy.c @@ -1,5 +1,5 @@ /* - * Virtio 9p Proxy callback + * 9p Proxy callback * * Copyright IBM, Corp. 2011 * @@ -9,13 +9,14 @@ * This work is licensed under the terms of the GNU GPL, version 2. See * the COPYING file in the top-level directory. */ +#include "qemu/osdep.h" #include <sys/socket.h> #include <sys/un.h> -#include "hw/virtio/virtio.h" -#include "virtio-9p.h" +#include "9p.h" +#include "qemu/cutils.h" #include "qemu/error-report.h" #include "fsdev/qemu-fsdev.h" -#include "virtio-9p-proxy.h" +#include "9p-proxy.h" typedef struct V9fsProxy { int sockfd; @@ -1101,19 +1102,19 @@ static int connect_namedsocket(const char *path) struct sockaddr_un helper; if (strlen(path) >= sizeof(helper.sun_path)) { - fprintf(stderr, "Socket name too large\n"); + error_report("Socket name too long"); return -1; } sockfd = socket(AF_UNIX, SOCK_STREAM, 0); if (sockfd < 0) { - fprintf(stderr, "failed to create socket: %s\n", strerror(errno)); + error_report("Failed to create socket: %s", strerror(errno)); return -1; } strcpy(helper.sun_path, path); helper.sun_family = AF_UNIX; size = strlen(helper.sun_path) + sizeof(helper.sun_family); if (connect(sockfd, (struct sockaddr *)&helper, size) < 0) { - fprintf(stderr, "failed to connect to %s: %s\n", path, strerror(errno)); + error_report("Failed to connect to %s: %s", path, strerror(errno)); close(sockfd); return -1; } @@ -1129,11 +1130,11 @@ static int proxy_parse_opts(QemuOpts *opts, struct FsDriverEntry *fs) const char *sock_fd = qemu_opt_get(opts, "sock_fd"); if (!socket && !sock_fd) { - fprintf(stderr, "socket and sock_fd none of the option specified\n"); + error_report("Must specify either socket or sock_fd"); return -1; } if (socket && sock_fd) { - fprintf(stderr, "Both socket and sock_fd options specified\n"); + error_report("Both socket and sock_fd options specified"); return -1; } if (socket) { @@ -1156,7 +1157,7 @@ static int proxy_init(FsContext *ctx) } else { sock_id = atoi(ctx->fs_root); if (sock_id < 0) { - fprintf(stderr, "socket descriptor not initialized\n"); + error_report("Socket descriptor not initialized"); } } if (sock_id < 0) { diff --git a/qemu/hw/9pfs/virtio-9p-proxy.h b/qemu/hw/9pfs/9p-proxy.h index 005c1ad75..ba9ca203d 100644 --- a/qemu/hw/9pfs/virtio-9p-proxy.h +++ b/qemu/hw/9pfs/9p-proxy.h @@ -1,5 +1,5 @@ /* - * Virtio 9p Proxy callback + * 9p Proxy callback * * Copyright IBM, Corp. 2011 * @@ -9,8 +9,8 @@ * This work is licensed under the terms of the GNU GPL, version 2. See * the COPYING file in the top-level directory. */ -#ifndef _QEMU_VIRTIO_9P_PROXY_H -#define _QEMU_VIRTIO_9P_PROXY_H +#ifndef _QEMU_9P_PROXY_H +#define _QEMU_9P_PROXY_H #define PROXY_MAX_IO_SZ (64 * 1024) #define V9FS_FD_VALID INT_MAX @@ -20,9 +20,9 @@ * marsha/unmarshal doesn't do little endian conversion. */ #define proxy_unmarshal(in_sg, offset, fmt, args...) \ - v9fs_unmarshal(in_sg, 1, offset, 0, fmt, ##args) + v9fs_iov_unmarshal(in_sg, 1, offset, 0, fmt, ##args) #define proxy_marshal(out_sg, offset, fmt, args...) \ - v9fs_marshal(out_sg, 1, offset, 0, fmt, ##args) + v9fs_iov_marshal(out_sg, 1, offset, 0, fmt, ##args) union MsgControl { struct cmsghdr cmsg; diff --git a/qemu/hw/9pfs/virtio-9p-synth.c b/qemu/hw/9pfs/9p-synth.c index a0ab9a86a..f1475dfd6 100644 --- a/qemu/hw/9pfs/virtio-9p-synth.c +++ b/qemu/hw/9pfs/9p-synth.c @@ -12,14 +12,15 @@ * */ +#include "qemu/osdep.h" #include "hw/virtio/virtio.h" -#include "virtio-9p.h" -#include "virtio-9p-xattr.h" +#include "9p.h" +#include "9p-xattr.h" #include "fsdev/qemu-fsdev.h" -#include "virtio-9p-synth.h" +#include "9p-synth.h" #include "qemu/rcu.h" #include "qemu/rcu_queue.h" -#include <sys/stat.h> +#include "qemu/cutils.h" /* Root node for synth file system */ static V9fsSynthNode v9fs_synth_root = { diff --git a/qemu/hw/9pfs/virtio-9p-synth.h b/qemu/hw/9pfs/9p-synth.h index ab05a8e78..82962512a 100644 --- a/qemu/hw/9pfs/virtio-9p-synth.h +++ b/qemu/hw/9pfs/9p-synth.h @@ -1,5 +1,5 @@ /* - * Virtio 9p + * 9p * * Copyright IBM, Corp. 2011 * @@ -10,12 +10,9 @@ * the COPYING file in the top-level directory. * */ -#ifndef HW_9PFS_VIRTIO9P_SYNTH_H -#define HW_9PFS_VIRTIO9P_SYNTH_H 1 +#ifndef HW_9PFS_SYNTH_H +#define HW_9PFS_SYNTH_H 1 -#include <unistd.h> -#include <sys/types.h> -#include <limits.h> typedef struct V9fsSynthNode V9fsSynthNode; typedef ssize_t (*v9fs_synth_read)(void *buf, int len, off_t offset, diff --git a/qemu/hw/9pfs/virtio-9p-xattr-user.c b/qemu/hw/9pfs/9p-xattr-user.c index 46133e06d..f87530c8b 100644 --- a/qemu/hw/9pfs/virtio-9p-xattr-user.c +++ b/qemu/hw/9pfs/9p-xattr-user.c @@ -1,5 +1,5 @@ /* - * Virtio 9p user. xattr callback + * 9p user. xattr callback * * Copyright IBM, Corp. 2010 * @@ -11,11 +11,10 @@ * */ -#include <sys/types.h> -#include "hw/virtio/virtio.h" -#include "virtio-9p.h" +#include "qemu/osdep.h" +#include "9p.h" #include "fsdev/file-op-9p.h" -#include "virtio-9p-xattr.h" +#include "9p-xattr.h" static ssize_t mp_user_getxattr(FsContext *ctx, const char *path, diff --git a/qemu/hw/9pfs/virtio-9p-xattr.c b/qemu/hw/9pfs/9p-xattr.c index 07183887c..5d8595ed9 100644 --- a/qemu/hw/9pfs/virtio-9p-xattr.c +++ b/qemu/hw/9pfs/9p-xattr.c @@ -1,5 +1,5 @@ /* - * Virtio 9p xattr callback + * 9p xattr callback * * Copyright IBM, Corp. 2010 * @@ -11,10 +11,10 @@ * */ -#include "hw/virtio/virtio.h" -#include "virtio-9p.h" +#include "qemu/osdep.h" +#include "9p.h" #include "fsdev/file-op-9p.h" -#include "virtio-9p-xattr.h" +#include "9p-xattr.h" static XattrOperations *get_xattr_operations(XattrOperations **h, diff --git a/qemu/hw/9pfs/virtio-9p-xattr.h b/qemu/hw/9pfs/9p-xattr.h index 327b32b5a..4d39a2026 100644 --- a/qemu/hw/9pfs/virtio-9p-xattr.h +++ b/qemu/hw/9pfs/9p-xattr.h @@ -1,5 +1,5 @@ /* - * Virtio 9p + * 9p * * Copyright IBM, Corp. 2010 * @@ -10,8 +10,8 @@ * the COPYING file in the top-level directory. * */ -#ifndef _QEMU_VIRTIO_9P_XATTR_H -#define _QEMU_VIRTIO_9P_XATTR_H +#ifndef _QEMU_9P_XATTR_H +#define _QEMU_9P_XATTR_H #include "qemu/xattr.h" diff --git a/qemu/hw/9pfs/virtio-9p.c b/qemu/hw/9pfs/9p.c index f972731f5..f5e30125f 100644 --- a/qemu/hw/9pfs/virtio-9p.c +++ b/qemu/hw/9pfs/9p.c @@ -11,15 +11,17 @@ * */ +#include "qemu/osdep.h" #include "hw/virtio/virtio.h" #include "hw/i386/pc.h" +#include "qapi/error.h" #include "qemu/error-report.h" #include "qemu/iov.h" #include "qemu/sockets.h" #include "virtio-9p.h" #include "fsdev/qemu-fsdev.h" -#include "virtio-9p-xattr.h" -#include "virtio-9p-coth.h" +#include "9p-xattr.h" +#include "coth.h" #include "trace.h" #include "migration/migration.h" @@ -39,6 +41,35 @@ enum { Oappend = 0x80, }; +ssize_t pdu_marshal(V9fsPDU *pdu, size_t offset, const char *fmt, ...) +{ + ssize_t ret; + va_list ap; + + va_start(ap, fmt); + ret = virtio_pdu_vmarshal(pdu, offset, fmt, ap); + va_end(ap); + + return ret; +} + +ssize_t pdu_unmarshal(V9fsPDU *pdu, size_t offset, const char *fmt, ...) +{ + ssize_t ret; + va_list ap; + + va_start(ap, fmt); + ret = virtio_pdu_vunmarshal(pdu, offset, fmt, ap); + va_end(ap); + + return ret; +} + +static void pdu_push_and_notify(V9fsPDU *pdu) +{ + virtio_9p_push_and_notify(pdu); +} + static int omode_to_uflags(int8_t mode) { int ret = 0; @@ -563,7 +594,7 @@ static int fid_to_qid(V9fsPDU *pdu, V9fsFidState *fidp, V9fsQID *qidp) return 0; } -static V9fsPDU *alloc_pdu(V9fsState *s) +V9fsPDU *pdu_alloc(V9fsState *s) { V9fsPDU *pdu = NULL; @@ -575,9 +606,10 @@ static V9fsPDU *alloc_pdu(V9fsState *s) return pdu; } -static void free_pdu(V9fsState *s, V9fsPDU *pdu) +void pdu_free(V9fsPDU *pdu) { if (pdu) { + V9fsState *s = pdu->s; /* * Cancelled pdu are added back to the freelist * by flush request . @@ -594,9 +626,10 @@ static void free_pdu(V9fsState *s, V9fsPDU *pdu) * because we always expect to have enough space to encode * error details */ -static void complete_pdu(V9fsState *s, V9fsPDU *pdu, ssize_t len) +static void pdu_complete(V9fsPDU *pdu, ssize_t len) { int8_t id = pdu->id + 1; /* Response */ + V9fsState *s = pdu->s; if (len < 0) { int err = -len; @@ -627,16 +660,12 @@ static void complete_pdu(V9fsState *s, V9fsPDU *pdu, ssize_t len) pdu->size = len; pdu->id = id; - /* push onto queue and notify */ - virtqueue_push(s->vq, &pdu->elem, len); - - /* FIXME: we should batch these completions */ - virtio_notify(VIRTIO_DEVICE(s), s->vq); + pdu_push_and_notify(pdu); /* Now wakeup anybody waiting in flush for this request */ qemu_co_queue_next(&pdu->complete); - free_pdu(s, pdu); + pdu_free(pdu); } static mode_t v9mode_to_mode(uint32_t mode, V9fsString *extension) @@ -931,7 +960,7 @@ static void v9fs_version(void *opaque) offset += err; trace_v9fs_version_return(pdu->tag, pdu->id, s->msize, version.data); out: - complete_pdu(s, pdu, offset); + pdu_complete(pdu, offset); v9fs_string_free(&version); } @@ -995,7 +1024,7 @@ static void v9fs_attach(void *opaque) out: put_fid(pdu, fidp); out_nofid: - complete_pdu(s, pdu, err); + pdu_complete(pdu, err); v9fs_string_free(&uname); v9fs_string_free(&aname); } @@ -1009,7 +1038,6 @@ static void v9fs_stat(void *opaque) struct stat stbuf; V9fsFidState *fidp; V9fsPDU *pdu = opaque; - V9fsState *s = pdu->s; err = pdu_unmarshal(pdu, offset, "d", &fid); if (err < 0) { @@ -1042,7 +1070,7 @@ static void v9fs_stat(void *opaque) out: put_fid(pdu, fidp); out_nofid: - complete_pdu(s, pdu, err); + pdu_complete(pdu, err); } static void v9fs_getattr(void *opaque) @@ -1105,7 +1133,7 @@ static void v9fs_getattr(void *opaque) out: put_fid(pdu, fidp); out_nofid: - complete_pdu(s, pdu, retval); + pdu_complete(pdu, retval); } /* Attribute flags */ @@ -1129,7 +1157,6 @@ static void v9fs_setattr(void *opaque) size_t offset = 7; V9fsIattr v9iattr; V9fsPDU *pdu = opaque; - V9fsState *s = pdu->s; err = pdu_unmarshal(pdu, offset, "dI", &fid, &v9iattr); if (err < 0) { @@ -1203,7 +1230,7 @@ static void v9fs_setattr(void *opaque) out: put_fid(pdu, fidp); out_nofid: - complete_pdu(s, pdu, err); + pdu_complete(pdu, err); } static int v9fs_walk_marshal(V9fsPDU *pdu, uint16_t nwnames, V9fsQID *qids) @@ -1245,7 +1272,7 @@ static void v9fs_walk(void *opaque) err = pdu_unmarshal(pdu, offset, "ddw", &fid, &newfid, &nwnames); if (err < 0) { - complete_pdu(s, pdu, err); + pdu_complete(pdu, err); return ; } offset += err; @@ -1313,7 +1340,7 @@ out: v9fs_path_free(&dpath); v9fs_path_free(&path); out_nofid: - complete_pdu(s, pdu, err); + pdu_complete(pdu, err); if (nwnames && nwnames <= P9_MAXWELEM) { for (name_idx = 0; name_idx < nwnames; name_idx++) { v9fs_string_free(&wnames[name_idx]); @@ -1430,7 +1457,7 @@ static void v9fs_open(void *opaque) out: put_fid(pdu, fidp); out_nofid: - complete_pdu(s, pdu, err); + pdu_complete(pdu, err); } static void v9fs_lcreate(void *opaque) @@ -1487,7 +1514,7 @@ static void v9fs_lcreate(void *opaque) out: put_fid(pdu, fidp); out_nofid: - complete_pdu(pdu->s, pdu, err); + pdu_complete(pdu, err); v9fs_string_free(&name); } @@ -1499,7 +1526,6 @@ static void v9fs_fsync(void *opaque) size_t offset = 7; V9fsFidState *fidp; V9fsPDU *pdu = opaque; - V9fsState *s = pdu->s; err = pdu_unmarshal(pdu, offset, "dd", &fid, &datasync); if (err < 0) { @@ -1518,7 +1544,7 @@ static void v9fs_fsync(void *opaque) } put_fid(pdu, fidp); out_nofid: - complete_pdu(s, pdu, err); + pdu_complete(pdu, err); } static void v9fs_clunk(void *opaque) @@ -1551,7 +1577,7 @@ static void v9fs_clunk(void *opaque) err = offset; } out_nofid: - complete_pdu(s, pdu, err); + pdu_complete(pdu, err); } static int v9fs_xattr_read(V9fsState *s, V9fsPDU *pdu, V9fsFidState *fidp, @@ -1561,6 +1587,8 @@ static int v9fs_xattr_read(V9fsState *s, V9fsPDU *pdu, V9fsFidState *fidp, size_t offset = 7; int read_count; int64_t xattr_len; + V9fsVirtioState *v = container_of(s, V9fsVirtioState, state); + VirtQueueElement *elem = v->elems[pdu->idx]; xattr_len = fidp->fs.xattr.len; read_count = xattr_len - off; @@ -1577,7 +1605,8 @@ static int v9fs_xattr_read(V9fsState *s, V9fsPDU *pdu, V9fsFidState *fidp, return err; } offset += err; - err = v9fs_pack(pdu->elem.in_sg, pdu->elem.in_num, offset, + + err = v9fs_pack(elem->in_sg, elem->in_num, offset, ((char *)fidp->fs.xattr.value) + off, read_count); if (err < 0) { @@ -1667,13 +1696,7 @@ static void v9fs_init_qiov_from_pdu(QEMUIOVector *qiov, V9fsPDU *pdu, struct iovec *iov; unsigned int niov; - if (is_write) { - iov = pdu->elem.out_sg; - niov = pdu->elem.out_num; - } else { - iov = pdu->elem.in_sg; - niov = pdu->elem.in_num; - } + virtio_init_iov_from_pdu(pdu, &iov, &niov, is_write); qemu_iovec_init_external(&elem, iov, niov); qemu_iovec_init(qiov, niov); @@ -1761,7 +1784,7 @@ static void v9fs_read(void *opaque) out: put_fid(pdu, fidp); out_nofid: - complete_pdu(s, pdu, err); + pdu_complete(pdu, err); } static size_t v9fs_readdir_data_size(V9fsString *name) @@ -1848,7 +1871,6 @@ static void v9fs_readdir(void *opaque) int32_t count; uint32_t max_count; V9fsPDU *pdu = opaque; - V9fsState *s = pdu->s; retval = pdu_unmarshal(pdu, offset, "dqd", &fid, &initial_offset, &max_count); @@ -1885,7 +1907,7 @@ static void v9fs_readdir(void *opaque) out: put_fid(pdu, fidp); out_nofid: - complete_pdu(s, pdu, retval); + pdu_complete(pdu, retval); } static int v9fs_xattr_write(V9fsState *s, V9fsPDU *pdu, V9fsFidState *fidp, @@ -1952,7 +1974,7 @@ static void v9fs_write(void *opaque) err = pdu_unmarshal(pdu, offset, "dqd", &fid, &off, &count); if (err < 0) { - complete_pdu(s, pdu, err); + pdu_complete(pdu, err); return; } offset += err; @@ -2015,7 +2037,7 @@ out: put_fid(pdu, fidp); out_nofid: qemu_iovec_destroy(&qiov_full); - complete_pdu(s, pdu, err); + pdu_complete(pdu, err); } static void v9fs_create(void *opaque) @@ -2182,7 +2204,7 @@ static void v9fs_create(void *opaque) out: put_fid(pdu, fidp); out_nofid: - complete_pdu(pdu->s, pdu, err); + pdu_complete(pdu, err); v9fs_string_free(&name); v9fs_string_free(&extension); v9fs_path_free(&path); @@ -2229,7 +2251,7 @@ static void v9fs_symlink(void *opaque) out: put_fid(pdu, dfidp); out_nofid: - complete_pdu(pdu->s, pdu, err); + pdu_complete(pdu, err); v9fs_string_free(&name); v9fs_string_free(&symname); } @@ -2245,7 +2267,7 @@ static void v9fs_flush(void *opaque) err = pdu_unmarshal(pdu, offset, "w", &tag); if (err < 0) { - complete_pdu(s, pdu, err); + pdu_complete(pdu, err); return; } trace_v9fs_flush(pdu->tag, pdu->id, tag); @@ -2262,15 +2284,14 @@ static void v9fs_flush(void *opaque) */ qemu_co_queue_wait(&cancel_pdu->complete); cancel_pdu->cancelled = 0; - free_pdu(pdu->s, cancel_pdu); + pdu_free(cancel_pdu); } - complete_pdu(s, pdu, 7); + pdu_complete(pdu, 7); } static void v9fs_link(void *opaque) { V9fsPDU *pdu = opaque; - V9fsState *s = pdu->s; int32_t dfid, oldfid; V9fsFidState *dfidp, *oldfidp; V9fsString name; @@ -2303,7 +2324,7 @@ out: put_fid(pdu, dfidp); out_nofid: v9fs_string_free(&name); - complete_pdu(s, pdu, err); + pdu_complete(pdu, err); } /* Only works with path name based fid */ @@ -2348,7 +2369,7 @@ out_err: clunk_fid(pdu->s, fidp->fid); put_fid(pdu, fidp); out_nofid: - complete_pdu(pdu->s, pdu, err); + pdu_complete(pdu, err); } static void v9fs_unlinkat(void *opaque) @@ -2392,7 +2413,7 @@ out_err: put_fid(pdu, dfidp); v9fs_path_free(&path); out_nofid: - complete_pdu(pdu->s, pdu, err); + pdu_complete(pdu, err); v9fs_string_free(&name); } @@ -2492,7 +2513,7 @@ static void v9fs_rename(void *opaque) out: put_fid(pdu, fidp); out_nofid: - complete_pdu(s, pdu, err); + pdu_complete(pdu, err); v9fs_string_free(&name); } @@ -2593,7 +2614,7 @@ static void v9fs_renameat(void *opaque) } out_err: - complete_pdu(s, pdu, err); + pdu_complete(pdu, err); v9fs_string_free(&old_name); v9fs_string_free(&new_name); } @@ -2608,7 +2629,6 @@ static void v9fs_wstat(void *opaque) struct stat stbuf; V9fsFidState *fidp; V9fsPDU *pdu = opaque; - V9fsState *s = pdu->s; v9fs_stat_init(&v9stat); err = pdu_unmarshal(pdu, offset, "dwS", &fid, &unused, &v9stat); @@ -2690,7 +2710,7 @@ out: put_fid(pdu, fidp); out_nofid: v9fs_stat_free(&v9stat); - complete_pdu(s, pdu, err); + pdu_complete(pdu, err); } static int v9fs_fill_statfs(V9fsState *s, V9fsPDU *pdu, struct statfs *stbuf) @@ -2769,7 +2789,7 @@ static void v9fs_statfs(void *opaque) out: put_fid(pdu, fidp); out_nofid: - complete_pdu(s, pdu, retval); + pdu_complete(pdu, retval); } static void v9fs_mknod(void *opaque) @@ -2786,7 +2806,6 @@ static void v9fs_mknod(void *opaque) struct stat stbuf; V9fsFidState *fidp; V9fsPDU *pdu = opaque; - V9fsState *s = pdu->s; v9fs_string_init(&name); err = pdu_unmarshal(pdu, offset, "dsdddd", &fid, &name, &mode, @@ -2817,7 +2836,7 @@ static void v9fs_mknod(void *opaque) out: put_fid(pdu, fidp); out_nofid: - complete_pdu(s, pdu, err); + pdu_complete(pdu, err); v9fs_string_free(&name); } @@ -2838,7 +2857,6 @@ static void v9fs_lock(void *opaque) V9fsFidState *fidp; int32_t fid, err = 0; V9fsPDU *pdu = opaque; - V9fsState *s = pdu->s; status = P9_LOCK_ERROR; v9fs_string_init(&flock.client_id); @@ -2875,7 +2893,7 @@ out_nofid: err += offset; } trace_v9fs_lock_return(pdu->tag, pdu->id, status); - complete_pdu(s, pdu, err); + pdu_complete(pdu, err); v9fs_string_free(&flock.client_id); } @@ -2891,7 +2909,6 @@ static void v9fs_getlock(void *opaque) V9fsGetlock glock; int32_t fid, err = 0; V9fsPDU *pdu = opaque; - V9fsState *s = pdu->s; v9fs_string_init(&glock.client_id); err = pdu_unmarshal(pdu, offset, "dbqqds", &fid, &glock.type, @@ -2925,7 +2942,7 @@ static void v9fs_getlock(void *opaque) out: put_fid(pdu, fidp); out_nofid: - complete_pdu(s, pdu, err); + pdu_complete(pdu, err); v9fs_string_free(&glock.client_id); } @@ -2969,7 +2986,7 @@ static void v9fs_mkdir(void *opaque) out: put_fid(pdu, fidp); out_nofid: - complete_pdu(pdu->s, pdu, err); + pdu_complete(pdu, err); v9fs_string_free(&name); } @@ -3075,7 +3092,7 @@ out: put_fid(pdu, xattr_fidp); } out_nofid: - complete_pdu(s, pdu, err); + pdu_complete(pdu, err); v9fs_string_free(&name); } @@ -3090,7 +3107,6 @@ static void v9fs_xattrcreate(void *opaque) V9fsFidState *file_fidp; V9fsFidState *xattr_fidp; V9fsPDU *pdu = opaque; - V9fsState *s = pdu->s; v9fs_string_init(&name); err = pdu_unmarshal(pdu, offset, "dsqd", &fid, &name, &size, &flags); @@ -3116,7 +3132,7 @@ static void v9fs_xattrcreate(void *opaque) err = offset; put_fid(pdu, file_fidp); out_nofid: - complete_pdu(s, pdu, err); + pdu_complete(pdu, err); v9fs_string_free(&name); } @@ -3156,7 +3172,7 @@ static void v9fs_readlink(void *opaque) out: put_fid(pdu, fidp); out_nofid: - complete_pdu(pdu->s, pdu, err); + pdu_complete(pdu, err); } static CoroutineEntry *pdu_co_handlers[] = { @@ -3199,13 +3215,13 @@ static CoroutineEntry *pdu_co_handlers[] = { static void v9fs_op_not_supp(void *opaque) { V9fsPDU *pdu = opaque; - complete_pdu(pdu->s, pdu, -EOPNOTSUPP); + pdu_complete(pdu, -EOPNOTSUPP); } static void v9fs_fs_ro(void *opaque) { V9fsPDU *pdu = opaque; - complete_pdu(pdu->s, pdu, -EROFS); + pdu_complete(pdu, -EROFS); } static inline bool is_read_only_op(V9fsPDU *pdu) @@ -3235,10 +3251,11 @@ static inline bool is_read_only_op(V9fsPDU *pdu) } } -static void submit_pdu(V9fsState *s, V9fsPDU *pdu) +void pdu_submit(V9fsPDU *pdu) { Coroutine *co; CoroutineEntry *handler; + V9fsState *s = pdu->s; if (pdu->id >= ARRAY_SIZE(pdu_co_handlers) || (pdu_co_handlers[pdu->id] == NULL)) { @@ -3254,45 +3271,108 @@ static void submit_pdu(V9fsState *s, V9fsPDU *pdu) qemu_coroutine_enter(co, pdu); } -void handle_9p_output(VirtIODevice *vdev, VirtQueue *vq) +/* Returns 0 on success, 1 on failure. */ +int v9fs_device_realize_common(V9fsState *s, Error **errp) { - V9fsState *s = (V9fsState *)vdev; - V9fsPDU *pdu; - ssize_t len; + V9fsVirtioState *v = container_of(s, V9fsVirtioState, state); + int i, len; + struct stat stat; + FsDriverEntry *fse; + V9fsPath path; + int rc = 1; + + /* initialize pdu allocator */ + QLIST_INIT(&s->free_list); + QLIST_INIT(&s->active_list); + for (i = 0; i < (MAX_REQ - 1); i++) { + QLIST_INSERT_HEAD(&s->free_list, &v->pdus[i], next); + v->pdus[i].s = s; + v->pdus[i].idx = i; + } + + v9fs_path_init(&path); + + fse = get_fsdev_fsentry(s->fsconf.fsdev_id); + + if (!fse) { + /* We don't have a fsdev identified by fsdev_id */ + error_setg(errp, "9pfs device couldn't find fsdev with the " + "id = %s", + s->fsconf.fsdev_id ? s->fsconf.fsdev_id : "NULL"); + goto out; + } + + if (!s->fsconf.tag) { + /* we haven't specified a mount_tag */ + error_setg(errp, "fsdev with id %s needs mount_tag arguments", + s->fsconf.fsdev_id); + goto out; + } + + s->ctx.export_flags = fse->export_flags; + s->ctx.fs_root = g_strdup(fse->path); + s->ctx.exops.get_st_gen = NULL; + len = strlen(s->fsconf.tag); + if (len > MAX_TAG_LEN - 1) { + error_setg(errp, "mount tag '%s' (%d bytes) is longer than " + "maximum (%d bytes)", s->fsconf.tag, len, MAX_TAG_LEN - 1); + goto out; + } - while ((pdu = alloc_pdu(s)) && - (len = virtqueue_pop(vq, &pdu->elem)) != 0) { - struct { - uint32_t size_le; - uint8_t id; - uint16_t tag_le; - } QEMU_PACKED out; - int len; + s->tag = g_strdup(s->fsconf.tag); + s->ctx.uid = -1; - pdu->s = s; - BUG_ON(pdu->elem.out_num == 0 || pdu->elem.in_num == 0); - QEMU_BUILD_BUG_ON(sizeof out != 7); + s->ops = fse->ops; - len = iov_to_buf(pdu->elem.out_sg, pdu->elem.out_num, 0, - &out, sizeof out); - BUG_ON(len != sizeof out); + s->fid_list = NULL; + qemu_co_rwlock_init(&s->rename_lock); - pdu->size = le32_to_cpu(out.size_le); + if (s->ops->init(&s->ctx) < 0) { + error_setg(errp, "9pfs Failed to initialize fs-driver with id:%s" + " and export path:%s", s->fsconf.fsdev_id, s->ctx.fs_root); + goto out; + } - pdu->id = out.id; - pdu->tag = le16_to_cpu(out.tag_le); + /* + * Check details of export path, We need to use fs driver + * call back to do that. Since we are in the init path, we don't + * use co-routines here. + */ + if (s->ops->name_to_path(&s->ctx, NULL, "/", &path) < 0) { + error_setg(errp, + "error in converting name to path %s", strerror(errno)); + goto out; + } + if (s->ops->lstat(&s->ctx, &path, &stat)) { + error_setg(errp, "share path %s does not exist", fse->path); + goto out; + } else if (!S_ISDIR(stat.st_mode)) { + error_setg(errp, "share path %s is not a directory", fse->path); + goto out; + } + v9fs_path_free(&path); - qemu_co_queue_init(&pdu->complete); - submit_pdu(s, pdu); + rc = 0; +out: + if (rc) { + g_free(s->ctx.fs_root); + g_free(s->tag); + v9fs_path_free(&path); } - free_pdu(s, pdu); + return rc; +} + +void v9fs_device_unrealize_common(V9fsState *s, Error **errp) +{ + g_free(s->ctx.fs_root); + g_free(s->tag); } -static void __attribute__((__constructor__)) virtio_9p_set_fd_limit(void) +static void __attribute__((__constructor__)) v9fs_set_fd_limit(void) { struct rlimit rlim; if (getrlimit(RLIMIT_NOFILE, &rlim) < 0) { - fprintf(stderr, "Failed to get the resource limit\n"); + error_report("Failed to get the resource limit"); exit(1); } open_fd_hw = rlim.rlim_cur - MIN(400, rlim.rlim_cur/3); diff --git a/qemu/hw/9pfs/9p.h b/qemu/hw/9pfs/9p.h new file mode 100644 index 000000000..1a19418a8 --- /dev/null +++ b/qemu/hw/9pfs/9p.h @@ -0,0 +1,324 @@ +#ifndef _QEMU_9P_H +#define _QEMU_9P_H + +#include <dirent.h> +#include <utime.h> +#include <sys/resource.h> +#include <glib.h> +#include "standard-headers/linux/virtio_9p.h" +#include "hw/virtio/virtio.h" +#include "fsdev/file-op-9p.h" +#include "fsdev/9p-iov-marshal.h" +#include "qemu/thread.h" +#include "qemu/coroutine.h" + +enum { + P9_TLERROR = 6, + P9_RLERROR, + P9_TSTATFS = 8, + P9_RSTATFS, + P9_TLOPEN = 12, + P9_RLOPEN, + P9_TLCREATE = 14, + P9_RLCREATE, + P9_TSYMLINK = 16, + P9_RSYMLINK, + P9_TMKNOD = 18, + P9_RMKNOD, + P9_TRENAME = 20, + P9_RRENAME, + P9_TREADLINK = 22, + P9_RREADLINK, + P9_TGETATTR = 24, + P9_RGETATTR, + P9_TSETATTR = 26, + P9_RSETATTR, + P9_TXATTRWALK = 30, + P9_RXATTRWALK, + P9_TXATTRCREATE = 32, + P9_RXATTRCREATE, + P9_TREADDIR = 40, + P9_RREADDIR, + P9_TFSYNC = 50, + P9_RFSYNC, + P9_TLOCK = 52, + P9_RLOCK, + P9_TGETLOCK = 54, + P9_RGETLOCK, + P9_TLINK = 70, + P9_RLINK, + P9_TMKDIR = 72, + P9_RMKDIR, + P9_TRENAMEAT = 74, + P9_RRENAMEAT, + P9_TUNLINKAT = 76, + P9_RUNLINKAT, + P9_TVERSION = 100, + P9_RVERSION, + P9_TAUTH = 102, + P9_RAUTH, + P9_TATTACH = 104, + P9_RATTACH, + P9_TERROR = 106, + P9_RERROR, + P9_TFLUSH = 108, + P9_RFLUSH, + P9_TWALK = 110, + P9_RWALK, + P9_TOPEN = 112, + P9_ROPEN, + P9_TCREATE = 114, + P9_RCREATE, + P9_TREAD = 116, + P9_RREAD, + P9_TWRITE = 118, + P9_RWRITE, + P9_TCLUNK = 120, + P9_RCLUNK, + P9_TREMOVE = 122, + P9_RREMOVE, + P9_TSTAT = 124, + P9_RSTAT, + P9_TWSTAT = 126, + P9_RWSTAT, +}; + + +/* qid.types */ +enum { + P9_QTDIR = 0x80, + P9_QTAPPEND = 0x40, + P9_QTEXCL = 0x20, + P9_QTMOUNT = 0x10, + P9_QTAUTH = 0x08, + P9_QTTMP = 0x04, + P9_QTSYMLINK = 0x02, + P9_QTLINK = 0x01, + P9_QTFILE = 0x00, +}; + +enum p9_proto_version { + V9FS_PROTO_2000U = 0x01, + V9FS_PROTO_2000L = 0x02, +}; + +#define P9_NOTAG (u16)(~0) +#define P9_NOFID (u32)(~0) +#define P9_MAXWELEM 16 + +#define FID_REFERENCED 0x1 +#define FID_NON_RECLAIMABLE 0x2 +static inline char *rpath(FsContext *ctx, const char *path) +{ + return g_strdup_printf("%s/%s", ctx->fs_root, path); +} + +/* + * ample room for Twrite/Rread header + * size[4] Tread/Twrite tag[2] fid[4] offset[8] count[4] + */ +#define P9_IOHDRSZ 24 + +typedef struct V9fsPDU V9fsPDU; +struct V9fsState; + +struct V9fsPDU +{ + uint32_t size; + uint16_t tag; + uint8_t id; + uint8_t cancelled; + CoQueue complete; + struct V9fsState *s; + QLIST_ENTRY(V9fsPDU) next; + uint32_t idx; +}; + + +/* FIXME + * 1) change user needs to set groups and stuff + */ + +#define MAX_REQ 128 +#define MAX_TAG_LEN 32 + +#define BUG_ON(cond) assert(!(cond)) + +typedef struct V9fsFidState V9fsFidState; + +enum { + P9_FID_NONE = 0, + P9_FID_FILE, + P9_FID_DIR, + P9_FID_XATTR, +}; + +typedef struct V9fsConf +{ + /* tag name for the device */ + char *tag; + char *fsdev_id; +} V9fsConf; + +typedef struct V9fsXattr +{ + int64_t copied_len; + int64_t len; + void *value; + V9fsString name; + int flags; +} V9fsXattr; + +/* + * Filled by fs driver on open and other + * calls. + */ +union V9fsFidOpenState { + int fd; + DIR *dir; + V9fsXattr xattr; + /* + * private pointer for fs drivers, that + * have its own internal representation of + * open files. + */ + void *private; +}; + +struct V9fsFidState +{ + int fid_type; + int32_t fid; + V9fsPath path; + V9fsFidOpenState fs; + V9fsFidOpenState fs_reclaim; + int flags; + int open_flags; + uid_t uid; + int ref; + int clunked; + V9fsFidState *next; + V9fsFidState *rclm_lst; +}; + +typedef struct V9fsState +{ + QLIST_HEAD(, V9fsPDU) free_list; + QLIST_HEAD(, V9fsPDU) active_list; + V9fsFidState *fid_list; + FileOperations *ops; + FsContext ctx; + char *tag; + enum p9_proto_version proto_version; + int32_t msize; + /* + * lock ensuring atomic path update + * on rename. + */ + CoRwlock rename_lock; + int32_t root_fid; + Error *migration_blocker; + V9fsConf fsconf; +} V9fsState; + +/* 9p2000.L open flags */ +#define P9_DOTL_RDONLY 00000000 +#define P9_DOTL_WRONLY 00000001 +#define P9_DOTL_RDWR 00000002 +#define P9_DOTL_NOACCESS 00000003 +#define P9_DOTL_CREATE 00000100 +#define P9_DOTL_EXCL 00000200 +#define P9_DOTL_NOCTTY 00000400 +#define P9_DOTL_TRUNC 00001000 +#define P9_DOTL_APPEND 00002000 +#define P9_DOTL_NONBLOCK 00004000 +#define P9_DOTL_DSYNC 00010000 +#define P9_DOTL_FASYNC 00020000 +#define P9_DOTL_DIRECT 00040000 +#define P9_DOTL_LARGEFILE 00100000 +#define P9_DOTL_DIRECTORY 00200000 +#define P9_DOTL_NOFOLLOW 00400000 +#define P9_DOTL_NOATIME 01000000 +#define P9_DOTL_CLOEXEC 02000000 +#define P9_DOTL_SYNC 04000000 + +/* 9p2000.L at flags */ +#define P9_DOTL_AT_REMOVEDIR 0x200 + +/* 9P2000.L lock type */ +#define P9_LOCK_TYPE_RDLCK 0 +#define P9_LOCK_TYPE_WRLCK 1 +#define P9_LOCK_TYPE_UNLCK 2 + +#define P9_LOCK_SUCCESS 0 +#define P9_LOCK_BLOCKED 1 +#define P9_LOCK_ERROR 2 +#define P9_LOCK_GRACE 3 + +#define P9_LOCK_FLAGS_BLOCK 1 +#define P9_LOCK_FLAGS_RECLAIM 2 + +typedef struct V9fsFlock +{ + uint8_t type; + uint32_t flags; + uint64_t start; /* absolute offset */ + uint64_t length; + uint32_t proc_id; + V9fsString client_id; +} V9fsFlock; + +typedef struct V9fsGetlock +{ + uint8_t type; + uint64_t start; /* absolute offset */ + uint64_t length; + uint32_t proc_id; + V9fsString client_id; +} V9fsGetlock; + +extern int open_fd_hw; +extern int total_open_fd; + +static inline void v9fs_path_write_lock(V9fsState *s) +{ + if (s->ctx.export_flags & V9FS_PATHNAME_FSCONTEXT) { + qemu_co_rwlock_wrlock(&s->rename_lock); + } +} + +static inline void v9fs_path_read_lock(V9fsState *s) +{ + if (s->ctx.export_flags & V9FS_PATHNAME_FSCONTEXT) { + qemu_co_rwlock_rdlock(&s->rename_lock); + } +} + +static inline void v9fs_path_unlock(V9fsState *s) +{ + if (s->ctx.export_flags & V9FS_PATHNAME_FSCONTEXT) { + qemu_co_rwlock_unlock(&s->rename_lock); + } +} + +static inline uint8_t v9fs_request_cancelled(V9fsPDU *pdu) +{ + return pdu->cancelled; +} + +extern void v9fs_reclaim_fd(V9fsPDU *pdu); +extern void v9fs_path_init(V9fsPath *path); +extern void v9fs_path_free(V9fsPath *path); +extern void v9fs_path_copy(V9fsPath *lhs, V9fsPath *rhs); +extern int v9fs_name_to_path(V9fsState *s, V9fsPath *dirpath, + const char *name, V9fsPath *path); +extern int v9fs_device_realize_common(V9fsState *s, Error **errp); +extern void v9fs_device_unrealize_common(V9fsState *s, Error **errp); + +ssize_t pdu_marshal(V9fsPDU *pdu, size_t offset, const char *fmt, ...); +ssize_t pdu_unmarshal(V9fsPDU *pdu, size_t offset, const char *fmt, ...); +V9fsPDU *pdu_alloc(V9fsState *s); +void pdu_free(V9fsPDU *pdu); +void pdu_submit(V9fsPDU *pdu); + +#endif diff --git a/qemu/hw/9pfs/Makefile.objs b/qemu/hw/9pfs/Makefile.objs index 1e9b595cb..da0ae0cfd 100644 --- a/qemu/hw/9pfs/Makefile.objs +++ b/qemu/hw/9pfs/Makefile.objs @@ -1,9 +1,9 @@ -common-obj-y = virtio-9p.o -common-obj-y += virtio-9p-local.o virtio-9p-xattr.o -common-obj-y += virtio-9p-xattr-user.o virtio-9p-posix-acl.o -common-obj-y += virtio-9p-coth.o cofs.o codir.o cofile.o -common-obj-y += coxattr.o virtio-9p-synth.o -common-obj-$(CONFIG_OPEN_BY_HANDLE) += virtio-9p-handle.o -common-obj-y += virtio-9p-proxy.o +common-obj-y = 9p.o +common-obj-y += 9p-local.o 9p-xattr.o +common-obj-y += 9p-xattr-user.o 9p-posix-acl.o +common-obj-y += coth.o cofs.o codir.o cofile.o +common-obj-y += coxattr.o 9p-synth.o +common-obj-$(CONFIG_OPEN_BY_HANDLE) += 9p-handle.o +common-obj-y += 9p-proxy.o obj-y += virtio-9p-device.o diff --git a/qemu/hw/9pfs/codir.c b/qemu/hw/9pfs/codir.c index 65ad3298b..91df7f7a7 100644 --- a/qemu/hw/9pfs/codir.c +++ b/qemu/hw/9pfs/codir.c @@ -12,10 +12,11 @@ * */ +#include "qemu/osdep.h" #include "fsdev/qemu-fsdev.h" #include "qemu/thread.h" -#include "block/coroutine.h" -#include "virtio-9p-coth.h" +#include "qemu/coroutine.h" +#include "coth.h" int v9fs_co_readdir_r(V9fsPDU *pdu, V9fsFidState *fidp, struct dirent *dent, struct dirent **result) diff --git a/qemu/hw/9pfs/cofile.c b/qemu/hw/9pfs/cofile.c index 2efebf357..293483e0c 100644 --- a/qemu/hw/9pfs/cofile.c +++ b/qemu/hw/9pfs/cofile.c @@ -12,10 +12,11 @@ * */ +#include "qemu/osdep.h" #include "fsdev/qemu-fsdev.h" #include "qemu/thread.h" -#include "block/coroutine.h" -#include "virtio-9p-coth.h" +#include "qemu/coroutine.h" +#include "coth.h" int v9fs_co_st_gen(V9fsPDU *pdu, V9fsPath *path, mode_t st_mode, V9fsStatDotl *v9stat) diff --git a/qemu/hw/9pfs/cofs.c b/qemu/hw/9pfs/cofs.c index 42ee614e2..18c81cb3d 100644 --- a/qemu/hw/9pfs/cofs.c +++ b/qemu/hw/9pfs/cofs.c @@ -12,10 +12,11 @@ * */ +#include "qemu/osdep.h" #include "fsdev/qemu-fsdev.h" #include "qemu/thread.h" -#include "block/coroutine.h" -#include "virtio-9p-coth.h" +#include "qemu/coroutine.h" +#include "coth.h" static ssize_t __readlink(V9fsState *s, V9fsPath *path, V9fsString *buf) { diff --git a/qemu/hw/9pfs/coth.c b/qemu/hw/9pfs/coth.c new file mode 100644 index 000000000..464293ef2 --- /dev/null +++ b/qemu/hw/9pfs/coth.c @@ -0,0 +1,42 @@ +/* + * 9p backend + * + * Copyright IBM, Corp. 2010 + * + * Authors: + * Harsh Prateek Bora <harsh@linux.vnet.ibm.com> + * Venkateswararao Jujjuri(JV) <jvrao@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 "qemu/osdep.h" +#include "qemu-common.h" +#include "block/thread-pool.h" +#include "qemu/coroutine.h" +#include "qemu/main-loop.h" +#include "coth.h" + +/* Called from QEMU I/O thread. */ +static void coroutine_enter_cb(void *opaque, int ret) +{ + Coroutine *co = opaque; + qemu_coroutine_enter(co, NULL); +} + +/* Called from worker thread. */ +static int coroutine_enter_func(void *arg) +{ + Coroutine *co = arg; + qemu_coroutine_enter(co, NULL); + return 0; +} + +void co_run_in_worker_bh(void *opaque) +{ + Coroutine *co = opaque; + thread_pool_submit_aio(aio_get_thread_pool(qemu_get_aio_context()), + coroutine_enter_func, co, coroutine_enter_cb, co); +} diff --git a/qemu/hw/9pfs/virtio-9p-coth.h b/qemu/hw/9pfs/coth.h index 4f51b250d..209fc6a9a 100644 --- a/qemu/hw/9pfs/virtio-9p-coth.h +++ b/qemu/hw/9pfs/coth.h @@ -1,5 +1,5 @@ /* - * Virtio 9p backend + * 9p backend * * Copyright IBM, Corp. 2010 * @@ -12,20 +12,12 @@ * */ -#ifndef _QEMU_VIRTIO_9P_COTH_H -#define _QEMU_VIRTIO_9P_COTH_H +#ifndef _QEMU_9P_COTH_H +#define _QEMU_9P_COTH_H #include "qemu/thread.h" -#include "block/coroutine.h" +#include "qemu/coroutine.h" #include "virtio-9p.h" -#include <glib.h> - -typedef struct V9fsThPool { - EventNotifier e; - - GThreadPool *pool; - GAsyncQueue *completed; -} V9fsThPool; /* * we want to use bottom half because we want to make sure the below @@ -45,7 +37,7 @@ typedef struct V9fsThPool { qemu_bh_schedule(co_bh); \ /* \ * yield in qemu thread and re-enter back \ - * in glib worker thread \ + * in worker thread \ */ \ qemu_coroutine_yield(); \ qemu_bh_delete(co_bh); \ diff --git a/qemu/hw/9pfs/coxattr.c b/qemu/hw/9pfs/coxattr.c index 18ee08df0..6ad96ea9f 100644 --- a/qemu/hw/9pfs/coxattr.c +++ b/qemu/hw/9pfs/coxattr.c @@ -12,10 +12,11 @@ * */ +#include "qemu/osdep.h" #include "fsdev/qemu-fsdev.h" #include "qemu/thread.h" -#include "block/coroutine.h" -#include "virtio-9p-coth.h" +#include "qemu/coroutine.h" +#include "coth.h" int v9fs_co_llistxattr(V9fsPDU *pdu, V9fsPath *path, void *value, size_t size) { diff --git a/qemu/hw/9pfs/virtio-9p-coth.c b/qemu/hw/9pfs/virtio-9p-coth.c deleted file mode 100644 index 8185c533c..000000000 --- a/qemu/hw/9pfs/virtio-9p-coth.c +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Virtio 9p backend - * - * Copyright IBM, Corp. 2010 - * - * Authors: - * Harsh Prateek Bora <harsh@linux.vnet.ibm.com> - * Venkateswararao Jujjuri(JV) <jvrao@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/event_notifier.h" -#include "block/coroutine.h" -#include "virtio-9p-coth.h" - -/* v9fs glib thread pool */ -static V9fsThPool v9fs_pool; - -void co_run_in_worker_bh(void *opaque) -{ - Coroutine *co = opaque; - g_thread_pool_push(v9fs_pool.pool, co, NULL); -} - -static void v9fs_qemu_process_req_done(EventNotifier *e) -{ - Coroutine *co; - - event_notifier_test_and_clear(e); - - while ((co = g_async_queue_try_pop(v9fs_pool.completed)) != NULL) { - qemu_coroutine_enter(co, NULL); - } -} - -static void v9fs_thread_routine(gpointer data, gpointer user_data) -{ - Coroutine *co = data; - - qemu_coroutine_enter(co, NULL); - - g_async_queue_push(v9fs_pool.completed, co); - - event_notifier_set(&v9fs_pool.e); -} - -int v9fs_init_worker_threads(void) -{ - int ret = 0; - V9fsThPool *p = &v9fs_pool; - sigset_t set, oldset; - - sigfillset(&set); - /* Leave signal handling to the iothread. */ - pthread_sigmask(SIG_SETMASK, &set, &oldset); - - p->pool = g_thread_pool_new(v9fs_thread_routine, p, -1, FALSE, NULL); - if (!p->pool) { - ret = -1; - goto err_out; - } - p->completed = g_async_queue_new(); - if (!p->completed) { - /* - * We are going to terminate. - * So don't worry about cleanup - */ - ret = -1; - goto err_out; - } - event_notifier_init(&p->e, 0); - - event_notifier_set_handler(&p->e, v9fs_qemu_process_req_done); -err_out: - pthread_sigmask(SIG_SETMASK, &oldset, NULL); - return ret; -} diff --git a/qemu/hw/9pfs/virtio-9p-device.c b/qemu/hw/9pfs/virtio-9p-device.c index 93a407c45..a38850ee8 100644 --- a/qemu/hw/9pfs/virtio-9p-device.c +++ b/qemu/hw/9pfs/virtio-9p-device.c @@ -11,15 +11,70 @@ * */ +#include "qemu/osdep.h" #include "hw/virtio/virtio.h" -#include "hw/virtio/virtio-9p.h" #include "hw/i386/pc.h" #include "qemu/sockets.h" #include "virtio-9p.h" #include "fsdev/qemu-fsdev.h" -#include "virtio-9p-xattr.h" -#include "virtio-9p-coth.h" +#include "9p-xattr.h" +#include "coth.h" #include "hw/virtio/virtio-access.h" +#include "qemu/iov.h" + +void virtio_9p_push_and_notify(V9fsPDU *pdu) +{ + V9fsState *s = pdu->s; + V9fsVirtioState *v = container_of(s, V9fsVirtioState, state); + VirtQueueElement *elem = v->elems[pdu->idx]; + + /* push onto queue and notify */ + virtqueue_push(v->vq, elem, pdu->size); + g_free(elem); + v->elems[pdu->idx] = NULL; + + /* FIXME: we should batch these completions */ + virtio_notify(VIRTIO_DEVICE(v), v->vq); +} + +static void handle_9p_output(VirtIODevice *vdev, VirtQueue *vq) +{ + V9fsVirtioState *v = (V9fsVirtioState *)vdev; + V9fsState *s = &v->state; + V9fsPDU *pdu; + ssize_t len; + + while ((pdu = pdu_alloc(s))) { + struct { + uint32_t size_le; + uint8_t id; + uint16_t tag_le; + } QEMU_PACKED out; + VirtQueueElement *elem; + + elem = virtqueue_pop(vq, sizeof(VirtQueueElement)); + if (!elem) { + pdu_free(pdu); + break; + } + + BUG_ON(elem->out_num == 0 || elem->in_num == 0); + QEMU_BUILD_BUG_ON(sizeof out != 7); + + v->elems[pdu->idx] = elem; + len = iov_to_buf(elem->out_sg, elem->out_num, 0, + &out, sizeof out); + BUG_ON(len != sizeof out); + + pdu->size = le32_to_cpu(out.size_le); + + pdu->id = out.id; + pdu->tag = le16_to_cpu(out.tag_le); + + qemu_co_queue_init(&pdu->complete); + pdu_submit(pdu); + } +} static uint64_t virtio_9p_get_features(VirtIODevice *vdev, uint64_t features, Error **errp) @@ -32,117 +87,99 @@ static void virtio_9p_get_config(VirtIODevice *vdev, uint8_t *config) { int len; struct virtio_9p_config *cfg; - V9fsState *s = VIRTIO_9P(vdev); + V9fsVirtioState *v = VIRTIO_9P(vdev); + V9fsState *s = &v->state; len = strlen(s->tag); cfg = g_malloc0(sizeof(struct virtio_9p_config) + len); virtio_stw_p(vdev, &cfg->tag_len, len); /* We don't copy the terminating null to config space */ memcpy(cfg->tag, s->tag, len); - memcpy(config, cfg, s->config_size); + memcpy(config, cfg, v->config_size); g_free(cfg); } +static void virtio_9p_save(QEMUFile *f, void *opaque) +{ + virtio_save(VIRTIO_DEVICE(opaque), f); +} + +static int virtio_9p_load(QEMUFile *f, void *opaque, int version_id) +{ + return virtio_load(VIRTIO_DEVICE(opaque), f, version_id); +} + static void virtio_9p_device_realize(DeviceState *dev, Error **errp) { VirtIODevice *vdev = VIRTIO_DEVICE(dev); - V9fsState *s = VIRTIO_9P(dev); - int i, len; - struct stat stat; - FsDriverEntry *fse; - V9fsPath path; - - virtio_init(vdev, "virtio-9p", VIRTIO_ID_9P, - sizeof(struct virtio_9p_config) + MAX_TAG_LEN); - - /* initialize pdu allocator */ - QLIST_INIT(&s->free_list); - QLIST_INIT(&s->active_list); - for (i = 0; i < (MAX_REQ - 1); i++) { - QLIST_INSERT_HEAD(&s->free_list, &s->pdus[i], next); - } + V9fsVirtioState *v = VIRTIO_9P(dev); + V9fsState *s = &v->state; - s->vq = virtio_add_queue(vdev, MAX_REQ, handle_9p_output); + if (v9fs_device_realize_common(s, errp)) { + goto out; + } - v9fs_path_init(&path); + v->config_size = sizeof(struct virtio_9p_config) + strlen(s->fsconf.tag); + virtio_init(vdev, "virtio-9p", VIRTIO_ID_9P, v->config_size); + v->vq = virtio_add_queue(vdev, MAX_REQ, handle_9p_output); + register_savevm(dev, "virtio-9p", -1, 1, virtio_9p_save, virtio_9p_load, v); - fse = get_fsdev_fsentry(s->fsconf.fsdev_id); +out: + return; +} - if (!fse) { - /* We don't have a fsdev identified by fsdev_id */ - error_setg(errp, "Virtio-9p device couldn't find fsdev with the " - "id = %s", - s->fsconf.fsdev_id ? s->fsconf.fsdev_id : "NULL"); - goto out; - } +static void virtio_9p_device_unrealize(DeviceState *dev, Error **errp) +{ + VirtIODevice *vdev = VIRTIO_DEVICE(dev); + V9fsVirtioState *v = VIRTIO_9P(dev); + V9fsState *s = &v->state; - if (!s->fsconf.tag) { - /* we haven't specified a mount_tag */ - error_setg(errp, "fsdev with id %s needs mount_tag arguments", - s->fsconf.fsdev_id); - goto out; - } + virtio_cleanup(vdev); + unregister_savevm(dev, "virtio-9p", v); + v9fs_device_unrealize_common(s, errp); +} - s->ctx.export_flags = fse->export_flags; - s->ctx.fs_root = g_strdup(fse->path); - s->ctx.exops.get_st_gen = NULL; - len = strlen(s->fsconf.tag); - if (len > MAX_TAG_LEN - 1) { - error_setg(errp, "mount tag '%s' (%d bytes) is longer than " - "maximum (%d bytes)", s->fsconf.tag, len, MAX_TAG_LEN - 1); - goto out; - } +ssize_t virtio_pdu_vmarshal(V9fsPDU *pdu, size_t offset, + const char *fmt, va_list ap) +{ + V9fsState *s = pdu->s; + V9fsVirtioState *v = container_of(s, V9fsVirtioState, state); + VirtQueueElement *elem = v->elems[pdu->idx]; - s->tag = g_strdup(s->fsconf.tag); - s->ctx.uid = -1; + return v9fs_iov_vmarshal(elem->in_sg, elem->in_num, offset, 1, fmt, ap); +} - s->ops = fse->ops; - s->config_size = sizeof(struct virtio_9p_config) + len; - s->fid_list = NULL; - qemu_co_rwlock_init(&s->rename_lock); +ssize_t virtio_pdu_vunmarshal(V9fsPDU *pdu, size_t offset, + const char *fmt, va_list ap) +{ + V9fsState *s = pdu->s; + V9fsVirtioState *v = container_of(s, V9fsVirtioState, state); + VirtQueueElement *elem = v->elems[pdu->idx]; - if (s->ops->init(&s->ctx) < 0) { - error_setg(errp, "Virtio-9p Failed to initialize fs-driver with id:%s" - " and export path:%s", s->fsconf.fsdev_id, s->ctx.fs_root); - goto out; - } - if (v9fs_init_worker_threads() < 0) { - error_setg(errp, "worker thread initialization failed"); - goto out; - } + return v9fs_iov_vunmarshal(elem->out_sg, elem->out_num, offset, 1, fmt, ap); +} - /* - * Check details of export path, We need to use fs driver - * call back to do that. Since we are in the init path, we don't - * use co-routines here. - */ - if (s->ops->name_to_path(&s->ctx, NULL, "/", &path) < 0) { - error_setg(errp, - "error in converting name to path %s", strerror(errno)); - goto out; - } - if (s->ops->lstat(&s->ctx, &path, &stat)) { - error_setg(errp, "share path %s does not exist", fse->path); - goto out; - } else if (!S_ISDIR(stat.st_mode)) { - error_setg(errp, "share path %s is not a directory", fse->path); - goto out; +void virtio_init_iov_from_pdu(V9fsPDU *pdu, struct iovec **piov, + unsigned int *pniov, bool is_write) +{ + V9fsState *s = pdu->s; + V9fsVirtioState *v = container_of(s, V9fsVirtioState, state); + VirtQueueElement *elem = v->elems[pdu->idx]; + + if (is_write) { + *piov = elem->out_sg; + *pniov = elem->out_num; + } else { + *piov = elem->in_sg; + *pniov = elem->in_num; } - v9fs_path_free(&path); - - return; -out: - g_free(s->ctx.fs_root); - g_free(s->tag); - virtio_cleanup(vdev); - v9fs_path_free(&path); } /* virtio-9p device */ static Property virtio_9p_properties[] = { - DEFINE_PROP_STRING("mount_tag", V9fsState, fsconf.tag), - DEFINE_PROP_STRING("fsdev", V9fsState, fsconf.fsdev_id), + DEFINE_PROP_STRING("mount_tag", V9fsVirtioState, state.fsconf.tag), + DEFINE_PROP_STRING("fsdev", V9fsVirtioState, state.fsconf.fsdev_id), DEFINE_PROP_END_OF_LIST(), }; @@ -154,6 +191,7 @@ static void virtio_9p_class_init(ObjectClass *klass, void *data) dc->props = virtio_9p_properties; set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); vdc->realize = virtio_9p_device_realize; + vdc->unrealize = virtio_9p_device_unrealize; vdc->get_features = virtio_9p_get_features; vdc->get_config = virtio_9p_get_config; } @@ -161,7 +199,7 @@ static void virtio_9p_class_init(ObjectClass *klass, void *data) static const TypeInfo virtio_device_info = { .name = TYPE_VIRTIO_9P, .parent = TYPE_VIRTIO_DEVICE, - .instance_size = sizeof(V9fsState), + .instance_size = sizeof(V9fsVirtioState), .class_init = virtio_9p_class_init, }; diff --git a/qemu/hw/9pfs/virtio-9p.h b/qemu/hw/9pfs/virtio-9p.h index 2e7d48857..7f6d88553 100644 --- a/qemu/hw/9pfs/virtio-9p.h +++ b/qemu/hw/9pfs/virtio-9p.h @@ -1,394 +1,31 @@ #ifndef _QEMU_VIRTIO_9P_H #define _QEMU_VIRTIO_9P_H -#include <sys/types.h> -#include <dirent.h> -#include <sys/time.h> -#include <utime.h> -#include <sys/resource.h> -#include <glib.h> #include "standard-headers/linux/virtio_9p.h" #include "hw/virtio/virtio.h" -#include "hw/virtio/virtio-9p.h" -#include "fsdev/file-op-9p.h" -#include "fsdev/virtio-9p-marshal.h" -#include "qemu/thread.h" -#include "block/coroutine.h" +#include "9p.h" -enum { - P9_TLERROR = 6, - P9_RLERROR, - P9_TSTATFS = 8, - P9_RSTATFS, - P9_TLOPEN = 12, - P9_RLOPEN, - P9_TLCREATE = 14, - P9_RLCREATE, - P9_TSYMLINK = 16, - P9_RSYMLINK, - P9_TMKNOD = 18, - P9_RMKNOD, - P9_TRENAME = 20, - P9_RRENAME, - P9_TREADLINK = 22, - P9_RREADLINK, - P9_TGETATTR = 24, - P9_RGETATTR, - P9_TSETATTR = 26, - P9_RSETATTR, - P9_TXATTRWALK = 30, - P9_RXATTRWALK, - P9_TXATTRCREATE = 32, - P9_RXATTRCREATE, - P9_TREADDIR = 40, - P9_RREADDIR, - P9_TFSYNC = 50, - P9_RFSYNC, - P9_TLOCK = 52, - P9_RLOCK, - P9_TGETLOCK = 54, - P9_RGETLOCK, - P9_TLINK = 70, - P9_RLINK, - P9_TMKDIR = 72, - P9_RMKDIR, - P9_TRENAMEAT = 74, - P9_RRENAMEAT, - P9_TUNLINKAT = 76, - P9_RUNLINKAT, - P9_TVERSION = 100, - P9_RVERSION, - P9_TAUTH = 102, - P9_RAUTH, - P9_TATTACH = 104, - P9_RATTACH, - P9_TERROR = 106, - P9_RERROR, - P9_TFLUSH = 108, - P9_RFLUSH, - P9_TWALK = 110, - P9_RWALK, - P9_TOPEN = 112, - P9_ROPEN, - P9_TCREATE = 114, - P9_RCREATE, - P9_TREAD = 116, - P9_RREAD, - P9_TWRITE = 118, - P9_RWRITE, - P9_TCLUNK = 120, - P9_RCLUNK, - P9_TREMOVE = 122, - P9_RREMOVE, - P9_TSTAT = 124, - P9_RSTAT, - P9_TWSTAT = 126, - P9_RWSTAT, -}; - - -/* qid.types */ -enum { - P9_QTDIR = 0x80, - P9_QTAPPEND = 0x40, - P9_QTEXCL = 0x20, - P9_QTMOUNT = 0x10, - P9_QTAUTH = 0x08, - P9_QTTMP = 0x04, - P9_QTSYMLINK = 0x02, - P9_QTLINK = 0x01, - P9_QTFILE = 0x00, -}; - -enum p9_proto_version { - V9FS_PROTO_2000U = 0x01, - V9FS_PROTO_2000L = 0x02, -}; - -#define P9_NOTAG (u16)(~0) -#define P9_NOFID (u32)(~0) -#define P9_MAXWELEM 16 - -#define FID_REFERENCED 0x1 -#define FID_NON_RECLAIMABLE 0x2 -static inline char *rpath(FsContext *ctx, const char *path) -{ - return g_strdup_printf("%s/%s", ctx->fs_root, path); -} - -/* - * ample room for Twrite/Rread header - * size[4] Tread/Twrite tag[2] fid[4] offset[8] count[4] - */ -#define P9_IOHDRSZ 24 - -typedef struct V9fsPDU V9fsPDU; -struct V9fsState; - -struct V9fsPDU -{ - uint32_t size; - uint16_t tag; - uint8_t id; - uint8_t cancelled; - CoQueue complete; - VirtQueueElement elem; - struct V9fsState *s; - QLIST_ENTRY(V9fsPDU) next; -}; - - -/* FIXME - * 1) change user needs to set groups and stuff - */ - -#define MAX_REQ 128 -#define MAX_TAG_LEN 32 - -#define BUG_ON(cond) assert(!(cond)) - -typedef struct V9fsFidState V9fsFidState; - -enum { - P9_FID_NONE = 0, - P9_FID_FILE, - P9_FID_DIR, - P9_FID_XATTR, -}; - -typedef struct V9fsXattr -{ - int64_t copied_len; - int64_t len; - void *value; - V9fsString name; - int flags; -} V9fsXattr; - -/* - * Filled by fs driver on open and other - * calls. - */ -union V9fsFidOpenState { - int fd; - DIR *dir; - V9fsXattr xattr; - /* - * private pointer for fs drivers, that - * have its own internal representation of - * open files. - */ - void *private; -}; - -struct V9fsFidState -{ - int fid_type; - int32_t fid; - V9fsPath path; - V9fsFidOpenState fs; - V9fsFidOpenState fs_reclaim; - int flags; - int open_flags; - uid_t uid; - int ref; - int clunked; - V9fsFidState *next; - V9fsFidState *rclm_lst; -}; - -typedef struct V9fsState +typedef struct V9fsVirtioState { VirtIODevice parent_obj; VirtQueue *vq; - V9fsPDU pdus[MAX_REQ]; - QLIST_HEAD(, V9fsPDU) free_list; - QLIST_HEAD(, V9fsPDU) active_list; - V9fsFidState *fid_list; - FileOperations *ops; - FsContext ctx; - char *tag; size_t config_size; - enum p9_proto_version proto_version; - int32_t msize; - /* - * lock ensuring atomic path update - * on rename. - */ - CoRwlock rename_lock; - int32_t root_fid; - Error *migration_blocker; - V9fsConf fsconf; -} V9fsState; - -typedef struct V9fsStatState { - V9fsPDU *pdu; - size_t offset; - V9fsStat v9stat; - V9fsFidState *fidp; - struct stat stbuf; -} V9fsStatState; - -typedef struct V9fsOpenState { - V9fsPDU *pdu; - size_t offset; - int32_t mode; - V9fsFidState *fidp; - V9fsQID qid; - struct stat stbuf; - int iounit; -} V9fsOpenState; - -typedef struct V9fsReadState { - V9fsPDU *pdu; - size_t offset; - int32_t count; - int32_t total; - int64_t off; - V9fsFidState *fidp; - struct iovec iov[128]; /* FIXME: bad, bad, bad */ - struct iovec *sg; - off_t dir_pos; - struct dirent *dent; - struct stat stbuf; - V9fsString name; - V9fsStat v9stat; - int32_t len; - int32_t cnt; - int32_t max_count; -} V9fsReadState; - -typedef struct V9fsWriteState { - V9fsPDU *pdu; - size_t offset; - int32_t len; - int32_t count; - int32_t total; - int64_t off; - V9fsFidState *fidp; - struct iovec iov[128]; /* FIXME: bad, bad, bad */ - struct iovec *sg; - int cnt; -} V9fsWriteState; - -typedef struct V9fsMkState { - V9fsPDU *pdu; - size_t offset; - V9fsQID qid; - struct stat stbuf; - V9fsString name; - V9fsString fullname; -} V9fsMkState; - -/* 9p2000.L open flags */ -#define P9_DOTL_RDONLY 00000000 -#define P9_DOTL_WRONLY 00000001 -#define P9_DOTL_RDWR 00000002 -#define P9_DOTL_NOACCESS 00000003 -#define P9_DOTL_CREATE 00000100 -#define P9_DOTL_EXCL 00000200 -#define P9_DOTL_NOCTTY 00000400 -#define P9_DOTL_TRUNC 00001000 -#define P9_DOTL_APPEND 00002000 -#define P9_DOTL_NONBLOCK 00004000 -#define P9_DOTL_DSYNC 00010000 -#define P9_DOTL_FASYNC 00020000 -#define P9_DOTL_DIRECT 00040000 -#define P9_DOTL_LARGEFILE 00100000 -#define P9_DOTL_DIRECTORY 00200000 -#define P9_DOTL_NOFOLLOW 00400000 -#define P9_DOTL_NOATIME 01000000 -#define P9_DOTL_CLOEXEC 02000000 -#define P9_DOTL_SYNC 04000000 - -/* 9p2000.L at flags */ -#define P9_DOTL_AT_REMOVEDIR 0x200 - -/* 9P2000.L lock type */ -#define P9_LOCK_TYPE_RDLCK 0 -#define P9_LOCK_TYPE_WRLCK 1 -#define P9_LOCK_TYPE_UNLCK 2 - -#define P9_LOCK_SUCCESS 0 -#define P9_LOCK_BLOCKED 1 -#define P9_LOCK_ERROR 2 -#define P9_LOCK_GRACE 3 - -#define P9_LOCK_FLAGS_BLOCK 1 -#define P9_LOCK_FLAGS_RECLAIM 2 - -typedef struct V9fsFlock -{ - uint8_t type; - uint32_t flags; - uint64_t start; /* absolute offset */ - uint64_t length; - uint32_t proc_id; - V9fsString client_id; -} V9fsFlock; - -typedef struct V9fsGetlock -{ - uint8_t type; - uint64_t start; /* absolute offset */ - uint64_t length; - uint32_t proc_id; - V9fsString client_id; -} V9fsGetlock; - -extern int open_fd_hw; -extern int total_open_fd; - -size_t pdu_packunpack(void *addr, struct iovec *sg, int sg_count, - size_t offset, size_t size, int pack); - -static inline size_t do_pdu_unpack(void *dst, struct iovec *sg, int sg_count, - size_t offset, size_t size) -{ - return pdu_packunpack(dst, sg, sg_count, offset, size, 0); -} - -static inline void v9fs_path_write_lock(V9fsState *s) -{ - if (s->ctx.export_flags & V9FS_PATHNAME_FSCONTEXT) { - qemu_co_rwlock_wrlock(&s->rename_lock); - } -} - -static inline void v9fs_path_read_lock(V9fsState *s) -{ - if (s->ctx.export_flags & V9FS_PATHNAME_FSCONTEXT) { - qemu_co_rwlock_rdlock(&s->rename_lock); - } -} - -static inline void v9fs_path_unlock(V9fsState *s) -{ - if (s->ctx.export_flags & V9FS_PATHNAME_FSCONTEXT) { - qemu_co_rwlock_unlock(&s->rename_lock); - } -} - -static inline uint8_t v9fs_request_cancelled(V9fsPDU *pdu) -{ - return pdu->cancelled; -} + V9fsPDU pdus[MAX_REQ]; + VirtQueueElement *elems[MAX_REQ]; + V9fsState state; +} V9fsVirtioState; -extern void handle_9p_output(VirtIODevice *vdev, VirtQueue *vq); -extern void v9fs_reclaim_fd(V9fsPDU *pdu); -extern void v9fs_path_init(V9fsPath *path); -extern void v9fs_path_free(V9fsPath *path); -extern void v9fs_path_copy(V9fsPath *lhs, V9fsPath *rhs); -extern int v9fs_name_to_path(V9fsState *s, V9fsPath *dirpath, - const char *name, V9fsPath *path); +extern void virtio_9p_push_and_notify(V9fsPDU *pdu); -#define pdu_marshal(pdu, offset, fmt, args...) \ - v9fs_marshal(pdu->elem.in_sg, pdu->elem.in_num, offset, 1, fmt, ##args) -#define pdu_unmarshal(pdu, offset, fmt, args...) \ - v9fs_unmarshal(pdu->elem.out_sg, pdu->elem.out_num, offset, 1, fmt, ##args) +ssize_t virtio_pdu_vmarshal(V9fsPDU *pdu, size_t offset, + const char *fmt, va_list ap); +ssize_t virtio_pdu_vunmarshal(V9fsPDU *pdu, size_t offset, + const char *fmt, va_list ap); +void virtio_init_iov_from_pdu(V9fsPDU *pdu, struct iovec **piov, + unsigned int *pniov, bool is_write); #define TYPE_VIRTIO_9P "virtio-9p-device" #define VIRTIO_9P(obj) \ - OBJECT_CHECK(V9fsState, (obj), TYPE_VIRTIO_9P) + OBJECT_CHECK(V9fsVirtioState, (obj), TYPE_VIRTIO_9P) #endif |