summaryrefslogtreecommitdiffstats
path: root/qemu/hw/9pfs
diff options
context:
space:
mode:
authorJosé Pekkarinen <jose.pekkarinen@nokia.com>2016-05-18 13:18:31 +0300
committerJosé Pekkarinen <jose.pekkarinen@nokia.com>2016-05-18 13:42:15 +0300
commit437fd90c0250dee670290f9b714253671a990160 (patch)
treeb871786c360704244a07411c69fb58da9ead4a06 /qemu/hw/9pfs
parent5bbd6fe9b8bab2a93e548c5a53b032d1939eec05 (diff)
These changes are the raw update to qemu-2.6.
Collission happened in the following patches: migration: do cleanup operation after completion(738df5b9) Bug fix.(1750c932f86) kvmclock: add a new function to update env->tsc.(b52baab2) The code provided by the patches was already in the upstreamed version. Change-Id: I3cc11841a6a76ae20887b2e245710199e1ea7f9a Signed-off-by: José Pekkarinen <jose.pekkarinen@nokia.com>
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.h324
-rw-r--r--qemu/hw/9pfs/Makefile.objs14
-rw-r--r--qemu/hw/9pfs/codir.c5
-rw-r--r--qemu/hw/9pfs/cofile.c5
-rw-r--r--qemu/hw/9pfs/cofs.c5
-rw-r--r--qemu/hw/9pfs/coth.c42
-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.c5
-rw-r--r--qemu/hw/9pfs/virtio-9p-coth.c82
-rw-r--r--qemu/hw/9pfs/virtio-9p-device.c212
-rw-r--r--qemu/hw/9pfs/virtio-9p.h391
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