summaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2017-01-05 10:53:57 +0000
committerPeter Maydell <peter.maydell@linaro.org>2017-01-05 10:53:57 +0000
commit9c904a7581d6e1bf693fe5cfe2d7cbf0a6009db6 (patch)
treecd2c1eee7930d497c79aaa63e7154922d5465f42 /hw
parent12597061b3fd71f8f97c18acf508241f290d55d5 (diff)
parenta37c07022b44e4fc29238deca7588406d081e6c2 (diff)
downloadqemu-9c904a7581d6e1bf693fe5cfe2d7cbf0a6009db6.zip
Merge remote-tracking branch 'remotes/gkurz/tags/for-upstream' into staging
- transport specific callbacks (for Xen) - fix crash (2.8 regression) - 9p functional tests # gpg: Signature made Tue 03 Jan 2017 17:30:58 GMT # gpg: using DSA key 0x02FC3AEB0101DBC2 # gpg: Good signature from "Greg Kurz <groug@kaod.org>" # gpg: aka "Greg Kurz <groug@free.fr>" # gpg: aka "Greg Kurz <gkurz@fr.ibm.com>" # gpg: aka "Greg Kurz <gkurz@linux.vnet.ibm.com>" # gpg: aka "Gregory Kurz (Groug) <groug@free.fr>" # gpg: aka "Gregory Kurz (Cimai Technology) <gkurz@cimai.com>" # gpg: aka "Gregory Kurz (Meiosys Technology) <gkurz@meiosys.com>" # gpg: WARNING: This key is not certified with a trusted signature! # gpg: There is no indication that the signature belongs to the owner. # Primary key fingerprint: 2BD4 3B44 535E C0A7 9894 DBA2 02FC 3AEB 0101 DBC2 * remotes/gkurz/tags/for-upstream: tests: virtio-9p: ".." cannot be used to walk out of the shared directory tests: virtio-9p: no slash in path elements during walk tests: virtio-9p: add walk operation test tests: virtio-9p: add attach operation test tests: virtio-9p: add version operation test 9pfs: fix P9_NOTAG and P9_NOFID macros tests: virtio-9p: code refactoring tests: virtio-9p: rename PCI configuration test 9pfs: fix crash when fsdev is missing 9pfs: introduce init_out/in_iov_from_pdu 9pfs: call v9fs_init_qiov_from_pdu before v9fs_pack 9pfs: introduce transport specific callbacks 9pfs: move pdus to V9fsState Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw')
-rw-r--r--hw/9pfs/9p.c78
-rw-r--r--hw/9pfs/9p.h26
-rw-r--r--hw/9pfs/virtio-9p-device.c46
-rw-r--r--hw/9pfs/virtio-9p.h10
4 files changed, 97 insertions, 63 deletions
diff --git a/hw/9pfs/9p.c b/hw/9pfs/9p.c
index faebd91f5f..fa58877570 100644
--- a/hw/9pfs/9p.c
+++ b/hw/9pfs/9p.c
@@ -47,7 +47,7 @@ ssize_t pdu_marshal(V9fsPDU *pdu, size_t offset, const char *fmt, ...)
va_list ap;
va_start(ap, fmt);
- ret = virtio_pdu_vmarshal(pdu, offset, fmt, ap);
+ ret = pdu->s->transport->pdu_vmarshal(pdu, offset, fmt, ap);
va_end(ap);
return ret;
@@ -59,7 +59,7 @@ ssize_t pdu_unmarshal(V9fsPDU *pdu, size_t offset, const char *fmt, ...)
va_list ap;
va_start(ap, fmt);
- ret = virtio_pdu_vunmarshal(pdu, offset, fmt, ap);
+ ret = pdu->s->transport->pdu_vunmarshal(pdu, offset, fmt, ap);
va_end(ap);
return ret;
@@ -67,7 +67,7 @@ ssize_t pdu_unmarshal(V9fsPDU *pdu, size_t offset, const char *fmt, ...)
static void pdu_push_and_notify(V9fsPDU *pdu)
{
- virtio_9p_push_and_notify(pdu);
+ pdu->s->transport->push_and_notify(pdu);
}
static int omode_to_uflags(int8_t mode)
@@ -1633,14 +1633,43 @@ out_nofid:
pdu_complete(pdu, err);
}
+/*
+ * Create a QEMUIOVector for a sub-region of PDU iovecs
+ *
+ * @qiov: uninitialized QEMUIOVector
+ * @skip: number of bytes to skip from beginning of PDU
+ * @size: number of bytes to include
+ * @is_write: true - write, false - read
+ *
+ * The resulting QEMUIOVector has heap-allocated iovecs and must be cleaned up
+ * with qemu_iovec_destroy().
+ */
+static void v9fs_init_qiov_from_pdu(QEMUIOVector *qiov, V9fsPDU *pdu,
+ size_t skip, size_t size,
+ bool is_write)
+{
+ QEMUIOVector elem;
+ struct iovec *iov;
+ unsigned int niov;
+
+ if (is_write) {
+ pdu->s->transport->init_out_iov_from_pdu(pdu, &iov, &niov);
+ } else {
+ pdu->s->transport->init_in_iov_from_pdu(pdu, &iov, &niov, size);
+ }
+
+ qemu_iovec_init_external(&elem, iov, niov);
+ qemu_iovec_init(qiov, niov);
+ qemu_iovec_concat(qiov, &elem, skip, size);
+}
+
static int v9fs_xattr_read(V9fsState *s, V9fsPDU *pdu, V9fsFidState *fidp,
uint64_t off, uint32_t max_count)
{
ssize_t err;
size_t offset = 7;
uint64_t read_count;
- V9fsVirtioState *v = container_of(s, V9fsVirtioState, state);
- VirtQueueElement *elem = v->elems[pdu->idx];
+ QEMUIOVector qiov_full;
if (fidp->fs.xattr.len < off) {
read_count = 0;
@@ -1656,9 +1685,11 @@ static int v9fs_xattr_read(V9fsState *s, V9fsPDU *pdu, V9fsFidState *fidp,
}
offset += err;
- err = v9fs_pack(elem->in_sg, elem->in_num, offset,
+ v9fs_init_qiov_from_pdu(&qiov_full, pdu, 0, read_count, false);
+ err = v9fs_pack(qiov_full.iov, qiov_full.niov, offset,
((char *)fidp->fs.xattr.value) + off,
read_count);
+ qemu_iovec_destroy(&qiov_full);
if (err < 0) {
return err;
}
@@ -1732,32 +1763,6 @@ static int coroutine_fn v9fs_do_readdir_with_stat(V9fsPDU *pdu,
return count;
}
-/*
- * Create a QEMUIOVector for a sub-region of PDU iovecs
- *
- * @qiov: uninitialized QEMUIOVector
- * @skip: number of bytes to skip from beginning of PDU
- * @size: number of bytes to include
- * @is_write: true - write, false - read
- *
- * The resulting QEMUIOVector has heap-allocated iovecs and must be cleaned up
- * with qemu_iovec_destroy().
- */
-static void v9fs_init_qiov_from_pdu(QEMUIOVector *qiov, V9fsPDU *pdu,
- size_t skip, size_t size,
- bool is_write)
-{
- QEMUIOVector elem;
- struct iovec *iov;
- unsigned int niov;
-
- virtio_init_iov_from_pdu(pdu, &iov, &niov, is_write);
-
- qemu_iovec_init_external(&elem, iov, niov);
- qemu_iovec_init(qiov, niov);
- qemu_iovec_concat(qiov, &elem, skip, size);
-}
-
static void coroutine_fn v9fs_read(void *opaque)
{
int32_t fid;
@@ -3440,7 +3445,6 @@ void pdu_submit(V9fsPDU *pdu)
/* Returns 0 on success, 1 on failure. */
int v9fs_device_realize_common(V9fsState *s, Error **errp)
{
- V9fsVirtioState *v = container_of(s, V9fsVirtioState, state);
int i, len;
struct stat stat;
FsDriverEntry *fse;
@@ -3451,9 +3455,9 @@ int v9fs_device_realize_common(V9fsState *s, Error **errp)
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;
+ QLIST_INSERT_HEAD(&s->free_list, &s->pdus[i], next);
+ s->pdus[i].s = s;
+ s->pdus[i].idx = i;
}
v9fs_path_init(&path);
@@ -3521,7 +3525,7 @@ int v9fs_device_realize_common(V9fsState *s, Error **errp)
rc = 0;
out:
if (rc) {
- if (s->ops->cleanup && s->ctx.private) {
+ if (s->ops && s->ops->cleanup && s->ctx.private) {
s->ops->cleanup(&s->ctx);
}
g_free(s->tag);
diff --git a/hw/9pfs/9p.h b/hw/9pfs/9p.h
index 3976b7fe3d..b7e836251e 100644
--- a/hw/9pfs/9p.h
+++ b/hw/9pfs/9p.h
@@ -99,8 +99,8 @@ enum p9_proto_version {
V9FS_PROTO_2000L = 0x02,
};
-#define P9_NOTAG (u16)(~0)
-#define P9_NOFID (u32)(~0)
+#define P9_NOTAG UINT16_MAX
+#define P9_NOFID UINT32_MAX
#define P9_MAXWELEM 16
#define FID_REFERENCED 0x1
@@ -229,6 +229,8 @@ typedef struct V9fsState
char *tag;
enum p9_proto_version proto_version;
int32_t msize;
+ V9fsPDU pdus[MAX_REQ];
+ const struct V9fsTransport *transport;
/*
* lock ensuring atomic path update
* on rename.
@@ -342,4 +344,24 @@ void pdu_free(V9fsPDU *pdu);
void pdu_submit(V9fsPDU *pdu);
void v9fs_reset(V9fsState *s);
+struct V9fsTransport {
+ ssize_t (*pdu_vmarshal)(V9fsPDU *pdu, size_t offset, const char *fmt,
+ va_list ap);
+ ssize_t (*pdu_vunmarshal)(V9fsPDU *pdu, size_t offset, const char *fmt,
+ va_list ap);
+ void (*init_in_iov_from_pdu)(V9fsPDU *pdu, struct iovec **piov,
+ unsigned int *pniov, size_t size);
+ void (*init_out_iov_from_pdu)(V9fsPDU *pdu, struct iovec **piov,
+ unsigned int *pniov);
+ void (*push_and_notify)(V9fsPDU *pdu);
+};
+
+static inline int v9fs_register_transport(V9fsState *s,
+ const struct V9fsTransport *t)
+{
+ assert(!s->transport);
+ s->transport = t;
+ return 0;
+}
+
#endif
diff --git a/hw/9pfs/virtio-9p-device.c b/hw/9pfs/virtio-9p-device.c
index 1782e4a227..27a4a32f5c 100644
--- a/hw/9pfs/virtio-9p-device.c
+++ b/hw/9pfs/virtio-9p-device.c
@@ -20,7 +20,9 @@
#include "hw/virtio/virtio-access.h"
#include "qemu/iov.h"
-void virtio_9p_push_and_notify(V9fsPDU *pdu)
+static const struct V9fsTransport virtio_9p_transport;
+
+static void virtio_9p_push_and_notify(V9fsPDU *pdu)
{
V9fsState *s = pdu->s;
V9fsVirtioState *v = container_of(s, V9fsVirtioState, state);
@@ -126,6 +128,7 @@ static void virtio_9p_device_realize(DeviceState *dev, Error **errp)
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);
+ v9fs_register_transport(s, &virtio_9p_transport);
out:
return;
@@ -148,8 +151,8 @@ static void virtio_9p_reset(VirtIODevice *vdev)
v9fs_reset(&v->state);
}
-ssize_t virtio_pdu_vmarshal(V9fsPDU *pdu, size_t offset,
- const char *fmt, va_list ap)
+static 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);
@@ -158,8 +161,8 @@ ssize_t virtio_pdu_vmarshal(V9fsPDU *pdu, size_t offset,
return v9fs_iov_vmarshal(elem->in_sg, elem->in_num, offset, 1, fmt, ap);
}
-ssize_t virtio_pdu_vunmarshal(V9fsPDU *pdu, size_t offset,
- const char *fmt, va_list ap)
+static 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);
@@ -168,22 +171,37 @@ ssize_t virtio_pdu_vunmarshal(V9fsPDU *pdu, size_t offset,
return v9fs_iov_vunmarshal(elem->out_sg, elem->out_num, offset, 1, fmt, ap);
}
-void virtio_init_iov_from_pdu(V9fsPDU *pdu, struct iovec **piov,
- unsigned int *pniov, bool is_write)
+/* The size parameter is used by other transports. Do not drop it. */
+static void virtio_init_in_iov_from_pdu(V9fsPDU *pdu, struct iovec **piov,
+ unsigned int *pniov, size_t size)
{
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;
- }
+ *piov = elem->in_sg;
+ *pniov = elem->in_num;
}
+static void virtio_init_out_iov_from_pdu(V9fsPDU *pdu, struct iovec **piov,
+ unsigned int *pniov)
+{
+ V9fsState *s = pdu->s;
+ V9fsVirtioState *v = container_of(s, V9fsVirtioState, state);
+ VirtQueueElement *elem = v->elems[pdu->idx];
+
+ *piov = elem->out_sg;
+ *pniov = elem->out_num;
+}
+
+static const struct V9fsTransport virtio_9p_transport = {
+ .pdu_vmarshal = virtio_pdu_vmarshal,
+ .pdu_vunmarshal = virtio_pdu_vunmarshal,
+ .init_in_iov_from_pdu = virtio_init_in_iov_from_pdu,
+ .init_out_iov_from_pdu = virtio_init_out_iov_from_pdu,
+ .push_and_notify = virtio_9p_push_and_notify,
+};
+
/* virtio-9p device */
static const VMStateDescription vmstate_virtio_9p = {
diff --git a/hw/9pfs/virtio-9p.h b/hw/9pfs/virtio-9p.h
index 25c47c7cb6..e763da2c02 100644
--- a/hw/9pfs/virtio-9p.h
+++ b/hw/9pfs/virtio-9p.h
@@ -10,20 +10,10 @@ typedef struct V9fsVirtioState
VirtIODevice parent_obj;
VirtQueue *vq;
size_t config_size;
- V9fsPDU pdus[MAX_REQ];
VirtQueueElement *elems[MAX_REQ];
V9fsState state;
} V9fsVirtioState;
-void virtio_9p_push_and_notify(V9fsPDU *pdu);
-
-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(V9fsVirtioState, (obj), TYPE_VIRTIO_9P)