qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PULL 00/13] 9p patches 20170104
@ 2017-01-04  8:21 Greg Kurz
  2017-01-04  8:21 ` [Qemu-devel] [PULL 01/13] 9pfs: move pdus to V9fsState Greg Kurz
                   ` (13 more replies)
  0 siblings, 14 replies; 15+ messages in thread
From: Greg Kurz @ 2017-01-04  8:21 UTC (permalink / raw)
  To: qemu-devel; +Cc: Peter Maydell, Aneesh Kumar K.V, Greg Kurz

The following changes since commit dbe2b65566e76d3c3a0c3358285c0336ac61e757:

  Merge remote-tracking branch 'remotes/vivier/tags/m68k-for-2.9-pull-request' into staging (2016-12-28 17:11:11 +0000)

are available in the git repository at:

  https://github.com/gkurz/qemu.git tags/for-upstream

for you to fetch changes up to a37c07022b44e4fc29238deca7588406d081e6c2:

  tests: virtio-9p: ".." cannot be used to walk out of the shared directory (2017-01-03 17:28:44 +0100)

----------------------------------------------------------------
- transport specific callbacks (for Xen)
- fix crash (2.8 regression)
- 9p functional tests

----------------------------------------------------------------
Greg Kurz (9):
      9pfs: fix crash when fsdev is missing
      tests: virtio-9p: rename PCI configuration test
      tests: virtio-9p: code refactoring
      9pfs: fix P9_NOTAG and P9_NOFID macros
      tests: virtio-9p: add version operation test
      tests: virtio-9p: add attach operation test
      tests: virtio-9p: add walk operation test
      tests: virtio-9p: no slash in path elements during walk
      tests: virtio-9p: ".." cannot be used to walk out of the shared directory

Stefano Stabellini (4):
      9pfs: move pdus to V9fsState
      9pfs: introduce transport specific callbacks
      9pfs: call v9fs_init_qiov_from_pdu before v9fs_pack
      9pfs: introduce init_out/in_iov_from_pdu

 hw/9pfs/9p.c               |  78 ++++----
 hw/9pfs/9p.h               |  26 ++-
 hw/9pfs/virtio-9p-device.c |  46 +++--
 hw/9pfs/virtio-9p.h        |  10 -
 tests/virtio-9p-test.c     | 478 ++++++++++++++++++++++++++++++++++++++++-----
 5 files changed, 524 insertions(+), 114 deletions(-)
-- 
2.7.4

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [Qemu-devel] [PULL 01/13] 9pfs: move pdus to V9fsState
  2017-01-04  8:21 [Qemu-devel] [PULL 00/13] 9p patches 20170104 Greg Kurz
@ 2017-01-04  8:21 ` Greg Kurz
  2017-01-04  8:21 ` [Qemu-devel] [PULL 02/13] 9pfs: introduce transport specific callbacks Greg Kurz
                   ` (12 subsequent siblings)
  13 siblings, 0 replies; 15+ messages in thread
From: Greg Kurz @ 2017-01-04  8:21 UTC (permalink / raw)
  To: qemu-devel; +Cc: Peter Maydell, Aneesh Kumar K.V, Greg Kurz, Stefano Stabellini

From: Stefano Stabellini <sstabellini@kernel.org>

pdus are initialized and used in 9pfs common code. Move the array from
V9fsVirtioState to V9fsState.

Signed-off-by: Stefano Stabellini <sstabellini@kernel.org>
Reviewed-by: Greg Kurz <groug@kaod.org>
Signed-off-by: Greg Kurz <groug@kaod.org>
---
 hw/9pfs/9p.c        | 7 +++----
 hw/9pfs/9p.h        | 1 +
 hw/9pfs/virtio-9p.h | 1 -
 3 files changed, 4 insertions(+), 5 deletions(-)

diff --git a/hw/9pfs/9p.c b/hw/9pfs/9p.c
index faebd91f5fab..6bd364f6a0d1 100644
--- a/hw/9pfs/9p.c
+++ b/hw/9pfs/9p.c
@@ -3440,7 +3440,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 +3450,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);
diff --git a/hw/9pfs/9p.h b/hw/9pfs/9p.h
index 3976b7fe3dcd..07cee01abac3 100644
--- a/hw/9pfs/9p.h
+++ b/hw/9pfs/9p.h
@@ -229,6 +229,7 @@ typedef struct V9fsState
     char *tag;
     enum p9_proto_version proto_version;
     int32_t msize;
+    V9fsPDU pdus[MAX_REQ];
     /*
      * lock ensuring atomic path update
      * on rename.
diff --git a/hw/9pfs/virtio-9p.h b/hw/9pfs/virtio-9p.h
index 25c47c7cb6d6..52c4b9df51ca 100644
--- a/hw/9pfs/virtio-9p.h
+++ b/hw/9pfs/virtio-9p.h
@@ -10,7 +10,6 @@ typedef struct V9fsVirtioState
     VirtIODevice parent_obj;
     VirtQueue *vq;
     size_t config_size;
-    V9fsPDU pdus[MAX_REQ];
     VirtQueueElement *elems[MAX_REQ];
     V9fsState state;
 } V9fsVirtioState;
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [Qemu-devel] [PULL 02/13] 9pfs: introduce transport specific callbacks
  2017-01-04  8:21 [Qemu-devel] [PULL 00/13] 9p patches 20170104 Greg Kurz
  2017-01-04  8:21 ` [Qemu-devel] [PULL 01/13] 9pfs: move pdus to V9fsState Greg Kurz
@ 2017-01-04  8:21 ` Greg Kurz
  2017-01-04  8:21 ` [Qemu-devel] [PULL 03/13] 9pfs: call v9fs_init_qiov_from_pdu before v9fs_pack Greg Kurz
                   ` (11 subsequent siblings)
  13 siblings, 0 replies; 15+ messages in thread
From: Greg Kurz @ 2017-01-04  8:21 UTC (permalink / raw)
  To: qemu-devel; +Cc: Peter Maydell, Aneesh Kumar K.V, Greg Kurz, Stefano Stabellini

From: Stefano Stabellini <sstabellini@kernel.org>

Don't call virtio functions from 9pfs generic code, use generic function
callbacks instead.

Signed-off-by: Stefano Stabellini <sstabellini@kernel.org>
Reviewed-by: Greg Kurz <groug@kaod.org>
Signed-off-by: Greg Kurz <groug@kaod.org>
---
 hw/9pfs/9p.c               |  8 ++++----
 hw/9pfs/9p.h               | 19 +++++++++++++++++++
 hw/9pfs/virtio-9p-device.c | 24 +++++++++++++++++-------
 hw/9pfs/virtio-9p.h        |  9 ---------
 4 files changed, 40 insertions(+), 20 deletions(-)

diff --git a/hw/9pfs/9p.c b/hw/9pfs/9p.c
index 6bd364f6a0d1..3f5647aa5680 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)
@@ -1751,7 +1751,7 @@ static void v9fs_init_qiov_from_pdu(QEMUIOVector *qiov, V9fsPDU *pdu,
     struct iovec *iov;
     unsigned int niov;
 
-    virtio_init_iov_from_pdu(pdu, &iov, &niov, is_write);
+    pdu->s->transport->init_iov_from_pdu(pdu, &iov, &niov, is_write);
 
     qemu_iovec_init_external(&elem, iov, niov);
     qemu_iovec_init(qiov, niov);
diff --git a/hw/9pfs/9p.h b/hw/9pfs/9p.h
index 07cee01abac3..c8c9aa89093a 100644
--- a/hw/9pfs/9p.h
+++ b/hw/9pfs/9p.h
@@ -230,6 +230,7 @@ typedef struct V9fsState
     enum p9_proto_version proto_version;
     int32_t msize;
     V9fsPDU pdus[MAX_REQ];
+    const struct V9fsTransport *transport;
     /*
      * lock ensuring atomic path update
      * on rename.
@@ -343,4 +344,22 @@ 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_iov_from_pdu)(V9fsPDU *pdu, struct iovec **piov,
+                                     unsigned int *pniov, bool is_write);
+    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 1782e4a2277f..273425b9d136 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,8 +171,8 @@ 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)
+static 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);
@@ -184,6 +187,13 @@ void virtio_init_iov_from_pdu(V9fsPDU *pdu, struct iovec **piov,
     }
 }
 
+static const struct V9fsTransport virtio_9p_transport = {
+    .pdu_vmarshal = virtio_pdu_vmarshal,
+    .pdu_vunmarshal = virtio_pdu_vunmarshal,
+    .init_iov_from_pdu = virtio_init_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 52c4b9df51ca..e763da2c02bf 100644
--- a/hw/9pfs/virtio-9p.h
+++ b/hw/9pfs/virtio-9p.h
@@ -14,15 +14,6 @@ typedef struct V9fsVirtioState
     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)
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [Qemu-devel] [PULL 03/13] 9pfs: call v9fs_init_qiov_from_pdu before v9fs_pack
  2017-01-04  8:21 [Qemu-devel] [PULL 00/13] 9p patches 20170104 Greg Kurz
  2017-01-04  8:21 ` [Qemu-devel] [PULL 01/13] 9pfs: move pdus to V9fsState Greg Kurz
  2017-01-04  8:21 ` [Qemu-devel] [PULL 02/13] 9pfs: introduce transport specific callbacks Greg Kurz
@ 2017-01-04  8:21 ` Greg Kurz
  2017-01-04  8:21 ` [Qemu-devel] [PULL 04/13] 9pfs: introduce init_out/in_iov_from_pdu Greg Kurz
                   ` (10 subsequent siblings)
  13 siblings, 0 replies; 15+ messages in thread
From: Greg Kurz @ 2017-01-04  8:21 UTC (permalink / raw)
  To: qemu-devel; +Cc: Peter Maydell, Aneesh Kumar K.V, Greg Kurz, Stefano Stabellini

From: Stefano Stabellini <sstabellini@kernel.org>

v9fs_xattr_read should not access VirtQueueElement elems directly.
Move v9fs_init_qiov_from_pdu up in the file and call
v9fs_init_qiov_from_pdu before v9fs_pack. Use v9fs_pack on the new
iovec.

Signed-off-by: Stefano Stabellini <sstabellini@kernel.org>
Reviewed-by: Greg Kurz <groug@kaod.org>
Signed-off-by: Greg Kurz <groug@kaod.org>
---
 hw/9pfs/9p.c | 59 ++++++++++++++++++++++++++++++-----------------------------
 1 file changed, 30 insertions(+), 29 deletions(-)

diff --git a/hw/9pfs/9p.c b/hw/9pfs/9p.c
index 3f5647aa5680..f9acd632596f 100644
--- a/hw/9pfs/9p.c
+++ b/hw/9pfs/9p.c
@@ -1633,14 +1633,39 @@ 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;
+
+    pdu->s->transport->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 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 +1681,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 +1759,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;
-
-    pdu->s->transport->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;
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [Qemu-devel] [PULL 04/13] 9pfs: introduce init_out/in_iov_from_pdu
  2017-01-04  8:21 [Qemu-devel] [PULL 00/13] 9p patches 20170104 Greg Kurz
                   ` (2 preceding siblings ...)
  2017-01-04  8:21 ` [Qemu-devel] [PULL 03/13] 9pfs: call v9fs_init_qiov_from_pdu before v9fs_pack Greg Kurz
@ 2017-01-04  8:21 ` Greg Kurz
  2017-01-04  8:21 ` [Qemu-devel] [PULL 05/13] 9pfs: fix crash when fsdev is missing Greg Kurz
                   ` (9 subsequent siblings)
  13 siblings, 0 replies; 15+ messages in thread
From: Greg Kurz @ 2017-01-04  8:21 UTC (permalink / raw)
  To: qemu-devel; +Cc: Peter Maydell, Aneesh Kumar K.V, Greg Kurz, Stefano Stabellini

From: Stefano Stabellini <sstabellini@kernel.org>

Not all 9pfs transports share memory between request and response. For
those who don't, it is necessary to know how much memory is required in
the response.

Split the existing init_iov_from_pdu function in two:
init_out_iov_from_pdu (for writes) and init_in_iov_from_pdu (for reads).
init_in_iov_from_pdu takes an additional size parameter to specify the
memory required for the response message.

Signed-off-by: Stefano Stabellini <sstabellini@kernel.org>
Reviewed-by: Greg Kurz <groug@kaod.org>
Signed-off-by: Greg Kurz <groug@kaod.org>
---
 hw/9pfs/9p.c               |  6 +++++-
 hw/9pfs/9p.h               |  6 ++++--
 hw/9pfs/virtio-9p-device.c | 28 ++++++++++++++++++----------
 3 files changed, 27 insertions(+), 13 deletions(-)

diff --git a/hw/9pfs/9p.c b/hw/9pfs/9p.c
index f9acd632596f..97c2926aae50 100644
--- a/hw/9pfs/9p.c
+++ b/hw/9pfs/9p.c
@@ -1652,7 +1652,11 @@ static void v9fs_init_qiov_from_pdu(QEMUIOVector *qiov, V9fsPDU *pdu,
     struct iovec *iov;
     unsigned int niov;
 
-    pdu->s->transport->init_iov_from_pdu(pdu, &iov, &niov, is_write);
+    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);
diff --git a/hw/9pfs/9p.h b/hw/9pfs/9p.h
index c8c9aa89093a..4c4feafa2e97 100644
--- a/hw/9pfs/9p.h
+++ b/hw/9pfs/9p.h
@@ -349,8 +349,10 @@ struct V9fsTransport {
                                 va_list ap);
     ssize_t     (*pdu_vunmarshal)(V9fsPDU *pdu, size_t offset, const char *fmt,
                                   va_list ap);
-    void        (*init_iov_from_pdu)(V9fsPDU *pdu, struct iovec **piov,
-                                     unsigned int *pniov, bool is_write);
+    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);
 };
 
diff --git a/hw/9pfs/virtio-9p-device.c b/hw/9pfs/virtio-9p-device.c
index 273425b9d136..27a4a32f5c4c 100644
--- a/hw/9pfs/virtio-9p-device.c
+++ b/hw/9pfs/virtio-9p-device.c
@@ -171,26 +171,34 @@ static ssize_t virtio_pdu_vunmarshal(V9fsPDU *pdu, size_t offset,
     return v9fs_iov_vunmarshal(elem->out_sg, elem->out_num, offset, 1, fmt, ap);
 }
 
-static 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_iov_from_pdu = virtio_init_iov_from_pdu,
+    .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,
 };
 
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [Qemu-devel] [PULL 05/13] 9pfs: fix crash when fsdev is missing
  2017-01-04  8:21 [Qemu-devel] [PULL 00/13] 9p patches 20170104 Greg Kurz
                   ` (3 preceding siblings ...)
  2017-01-04  8:21 ` [Qemu-devel] [PULL 04/13] 9pfs: introduce init_out/in_iov_from_pdu Greg Kurz
@ 2017-01-04  8:21 ` Greg Kurz
  2017-01-04  8:21 ` [Qemu-devel] [PULL 06/13] tests: virtio-9p: rename PCI configuration test Greg Kurz
                   ` (8 subsequent siblings)
  13 siblings, 0 replies; 15+ messages in thread
From: Greg Kurz @ 2017-01-04  8:21 UTC (permalink / raw)
  To: qemu-devel; +Cc: Peter Maydell, Aneesh Kumar K.V, Greg Kurz

If the user passes -device virtio-9p without the corresponding -fsdev, QEMU
dereferences a NULL pointer and crashes.

This is a 2.8 regression introduced by commit 702dbcc274e2c.

Signed-off-by: Greg Kurz <groug@kaod.org>
Reviewed-by: Li Qiang <liq3ea@gmail.com>
---
 hw/9pfs/9p.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/9pfs/9p.c b/hw/9pfs/9p.c
index 97c2926aae50..fa58877570f6 100644
--- a/hw/9pfs/9p.c
+++ b/hw/9pfs/9p.c
@@ -3525,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);
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [Qemu-devel] [PULL 06/13] tests: virtio-9p: rename PCI configuration test
  2017-01-04  8:21 [Qemu-devel] [PULL 00/13] 9p patches 20170104 Greg Kurz
                   ` (4 preceding siblings ...)
  2017-01-04  8:21 ` [Qemu-devel] [PULL 05/13] 9pfs: fix crash when fsdev is missing Greg Kurz
@ 2017-01-04  8:21 ` Greg Kurz
  2017-01-04  8:21 ` [Qemu-devel] [PULL 07/13] tests: virtio-9p: code refactoring Greg Kurz
                   ` (7 subsequent siblings)
  13 siblings, 0 replies; 15+ messages in thread
From: Greg Kurz @ 2017-01-04  8:21 UTC (permalink / raw)
  To: qemu-devel; +Cc: Peter Maydell, Aneesh Kumar K.V, Greg Kurz

Signed-off-by: Greg Kurz <groug@kaod.org>
---
 tests/virtio-9p-test.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/tests/virtio-9p-test.c b/tests/virtio-9p-test.c
index 9c4f6cb40647..f458297f9ae1 100644
--- a/tests/virtio-9p-test.c
+++ b/tests/virtio-9p-test.c
@@ -92,7 +92,7 @@ static void qvirtio_9p_pci_free(QVirtIO9P *v9p)
     g_free(v9p);
 }
 
-static void pci_basic_config(void)
+static void pci_config(void)
 {
     QVirtIO9P *v9p;
     size_t tag_len;
@@ -121,7 +121,7 @@ int main(int argc, char **argv)
 {
     g_test_init(&argc, &argv, NULL);
     qtest_add_func("/virtio/9p/pci/nop", pci_nop);
-    qtest_add_func("/virtio/9p/pci/basic/configuration", pci_basic_config);
+    qtest_add_func("/virtio/9p/pci/config", pci_config);
 
     return g_test_run();
 }
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [Qemu-devel] [PULL 07/13] tests: virtio-9p: code refactoring
  2017-01-04  8:21 [Qemu-devel] [PULL 00/13] 9p patches 20170104 Greg Kurz
                   ` (5 preceding siblings ...)
  2017-01-04  8:21 ` [Qemu-devel] [PULL 06/13] tests: virtio-9p: rename PCI configuration test Greg Kurz
@ 2017-01-04  8:21 ` Greg Kurz
  2017-01-04  8:21 ` [Qemu-devel] [PULL 08/13] 9pfs: fix P9_NOTAG and P9_NOFID macros Greg Kurz
                   ` (6 subsequent siblings)
  13 siblings, 0 replies; 15+ messages in thread
From: Greg Kurz @ 2017-01-04  8:21 UTC (permalink / raw)
  To: qemu-devel; +Cc: Peter Maydell, Aneesh Kumar K.V, Greg Kurz

This moves the test_share static and the QOSState into the QVirtIO9P
structure, and put PCI related code in functions with a _pci_ name.

This will avoid code duplication in future tests, and allow to add
support for non-PCI platforms.

Signed-off-by: Greg Kurz <groug@kaod.org>
---
 tests/virtio-9p-test.c | 101 ++++++++++++++++++++++++-------------------------
 1 file changed, 50 insertions(+), 51 deletions(-)

diff --git a/tests/virtio-9p-test.c b/tests/virtio-9p-test.c
index f458297f9ae1..727316086337 100644
--- a/tests/virtio-9p-test.c
+++ b/tests/virtio-9p-test.c
@@ -18,59 +18,49 @@
 #include "standard-headers/linux/virtio_pci.h"
 
 static const char mount_tag[] = "qtest";
-static char *test_share;
 
+typedef struct {
+    QVirtioDevice *dev;
+    QOSState *qs;
+    QVirtQueue *vq;
+    char *test_share;
+} QVirtIO9P;
 
-static QOSState *qvirtio_9p_start(void)
+static QVirtIO9P *qvirtio_9p_start(const char *driver)
 {
     const char *arch = qtest_get_arch();
     const char *cmd = "-fsdev local,id=fsdev0,security_model=none,path=%s "
-                      "-device virtio-9p-pci,fsdev=fsdev0,mount_tag=%s";
+                      "-device %s,fsdev=fsdev0,mount_tag=%s";
+    QVirtIO9P *v9p = g_new0(QVirtIO9P, 1);
 
-    test_share = g_strdup("/tmp/qtest.XXXXXX");
-    g_assert_nonnull(mkdtemp(test_share));
+    v9p->test_share = g_strdup("/tmp/qtest.XXXXXX");
+    g_assert_nonnull(mkdtemp(v9p->test_share));
 
     if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) {
-        return qtest_pc_boot(cmd, test_share, mount_tag);
-    }
-    if (strcmp(arch, "ppc64") == 0) {
-        return qtest_spapr_boot(cmd, test_share, mount_tag);
+        v9p->qs = qtest_pc_boot(cmd, v9p->test_share, driver, mount_tag);
+    } else if (strcmp(arch, "ppc64") == 0) {
+        v9p->qs = qtest_spapr_boot(cmd, v9p->test_share, driver, mount_tag);
+    } else {
+        g_printerr("virtio-9p tests are only available on x86 or ppc64\n");
+        exit(EXIT_FAILURE);
     }
 
-    g_printerr("virtio-9p tests are only available on x86 or ppc64\n");
-    exit(EXIT_FAILURE);
-}
-
-static void qvirtio_9p_stop(QOSState *qs)
-{
-    qtest_shutdown(qs);
-    rmdir(test_share);
-    g_free(test_share);
+    return v9p;
 }
 
-static void pci_nop(void)
+static void qvirtio_9p_stop(QVirtIO9P *v9p)
 {
-    QOSState *qs;
-
-    qs = qvirtio_9p_start();
-    qvirtio_9p_stop(qs);
+    qtest_shutdown(v9p->qs);
+    rmdir(v9p->test_share);
+    g_free(v9p->test_share);
+    g_free(v9p);
 }
 
-typedef struct {
-    QVirtioDevice *dev;
-    QOSState *qs;
-    QVirtQueue *vq;
-} QVirtIO9P;
-
-static QVirtIO9P *qvirtio_9p_pci_init(QOSState *qs)
+static QVirtIO9P *qvirtio_9p_pci_start(void)
 {
-    QVirtIO9P *v9p;
-    QVirtioPCIDevice *dev;
-
-    v9p = g_new0(QVirtIO9P, 1);
-
-    v9p->qs = qs;
-    dev = qvirtio_pci_device_find(v9p->qs->pcibus, VIRTIO_ID_9P);
+    QVirtIO9P *v9p = qvirtio_9p_start("virtio-9p-pci");
+    QVirtioPCIDevice *dev = qvirtio_pci_device_find(v9p->qs->pcibus,
+                                                    VIRTIO_ID_9P);
     g_assert_nonnull(dev);
     g_assert_cmphex(dev->vdev.device_type, ==, VIRTIO_ID_9P);
     v9p->dev = (QVirtioDevice *) dev;
@@ -84,26 +74,20 @@ static QVirtIO9P *qvirtio_9p_pci_init(QOSState *qs)
     return v9p;
 }
 
-static void qvirtio_9p_pci_free(QVirtIO9P *v9p)
+static void qvirtio_9p_pci_stop(QVirtIO9P *v9p)
 {
     qvirtqueue_cleanup(v9p->dev->bus, v9p->vq, v9p->qs->alloc);
     qvirtio_pci_device_disable(container_of(v9p->dev, QVirtioPCIDevice, vdev));
     g_free(v9p->dev);
-    g_free(v9p);
+    qvirtio_9p_stop(v9p);
 }
 
-static void pci_config(void)
+static void pci_config(QVirtIO9P *v9p)
 {
-    QVirtIO9P *v9p;
-    size_t tag_len;
+    size_t tag_len = qvirtio_config_readw(v9p->dev, 0);
     char *tag;
     int i;
-    QOSState *qs;
-
-    qs = qvirtio_9p_start();
-    v9p = qvirtio_9p_pci_init(qs);
 
-    tag_len = qvirtio_config_readw(v9p->dev, 0);
     g_assert_cmpint(tag_len, ==, strlen(mount_tag));
 
     tag = g_malloc(tag_len);
@@ -112,16 +96,31 @@ static void pci_config(void)
     }
     g_assert_cmpmem(tag, tag_len, mount_tag, tag_len);
     g_free(tag);
+}
+
+typedef void (*v9fs_test_fn)(QVirtIO9P *v9p);
+
+static void v9fs_run_pci_test(gconstpointer data)
+{
+    v9fs_test_fn fn = data;
+    QVirtIO9P *v9p = qvirtio_9p_pci_start();
 
-    qvirtio_9p_pci_free(v9p);
-    qvirtio_9p_stop(qs);
+    if (fn) {
+        fn(v9p);
+    }
+    qvirtio_9p_pci_stop(v9p);
+}
+
+static void v9fs_qtest_pci_add(const char *path, v9fs_test_fn fn)
+{
+    qtest_add_data_func(path, fn, v9fs_run_pci_test);
 }
 
 int main(int argc, char **argv)
 {
     g_test_init(&argc, &argv, NULL);
-    qtest_add_func("/virtio/9p/pci/nop", pci_nop);
-    qtest_add_func("/virtio/9p/pci/config", pci_config);
+    v9fs_qtest_pci_add("/virtio/9p/pci/nop", NULL);
+    v9fs_qtest_pci_add("/virtio/9p/pci/config", pci_config);
 
     return g_test_run();
 }
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [Qemu-devel] [PULL 08/13] 9pfs: fix P9_NOTAG and P9_NOFID macros
  2017-01-04  8:21 [Qemu-devel] [PULL 00/13] 9p patches 20170104 Greg Kurz
                   ` (6 preceding siblings ...)
  2017-01-04  8:21 ` [Qemu-devel] [PULL 07/13] tests: virtio-9p: code refactoring Greg Kurz
@ 2017-01-04  8:21 ` Greg Kurz
  2017-01-04  8:21 ` [Qemu-devel] [PULL 09/13] tests: virtio-9p: add version operation test Greg Kurz
                   ` (5 subsequent siblings)
  13 siblings, 0 replies; 15+ messages in thread
From: Greg Kurz @ 2017-01-04  8:21 UTC (permalink / raw)
  To: qemu-devel; +Cc: Peter Maydell, Aneesh Kumar K.V, Greg Kurz

The u16 and u32 types don't exist in QEMU common headers. It never broke
build because these two macros aren't use by the current code, but this
is about to change with the future addition of functional tests for 9P.

Also, these should have enclosing parenthesis to be usable in any
syntactical situation.

As suggested by Eric Blake, let's use UINT16_MAX and UINT32_MAX to address
both issues.

Signed-off-by: Greg Kurz <groug@kaod.org>
---
 hw/9pfs/9p.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/hw/9pfs/9p.h b/hw/9pfs/9p.h
index 4c4feafa2e97..b7e836251e13 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
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [Qemu-devel] [PULL 09/13] tests: virtio-9p: add version operation test
  2017-01-04  8:21 [Qemu-devel] [PULL 00/13] 9p patches 20170104 Greg Kurz
                   ` (7 preceding siblings ...)
  2017-01-04  8:21 ` [Qemu-devel] [PULL 08/13] 9pfs: fix P9_NOTAG and P9_NOFID macros Greg Kurz
@ 2017-01-04  8:21 ` Greg Kurz
  2017-01-04  8:21 ` [Qemu-devel] [PULL 10/13] tests: virtio-9p: add attach " Greg Kurz
                   ` (4 subsequent siblings)
  13 siblings, 0 replies; 15+ messages in thread
From: Greg Kurz @ 2017-01-04  8:21 UTC (permalink / raw)
  To: qemu-devel; +Cc: Peter Maydell, Aneesh Kumar K.V, Greg Kurz

This patch lays the foundations to be able to test 9P operations and
provides a test for the version operation as a first example.

A 9P request is composed of a T-message sent by the client (guest) to the
server (QEMU), and a R-message sent by the server back to the client.

The following general calls are available to implement requests for any
9P operations:

v9fs_req_init(): allocates the request structure and the guest memory for
                 the T-message

v9fs_req_send(): allocates the guest memory for the R-message and sends the
                 T-message to QEMU

v9fs_req_recv(): waits for QEMU to answer and does some sanity checks on the
                 returned R-message header

v9fs_req_free(): releases the guest memory and the request structure

Helpers are provided, to be used by each specific 9P operation to copy data
to/from the guest memory.

The version operation is used to negotiate the 9P protocol version to be
used and the maximum buffer size for exchanged data. It is necessarily
the first message of a 9P session. For simplicity, the maximum buffer size
is hardcoded to 4k, which should be enough for functional tests.

The test simply advertises the "9P2000.L" version to QEMU and expects QEMU
to answer it is supported.

References:

http://man.cat-v.org/plan_9/5/intro
http://man.cat-v.org/plan_9/5/version

Signed-off-by: Greg Kurz <groug@kaod.org>
---
 tests/virtio-9p-test.c | 222 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 222 insertions(+)

diff --git a/tests/virtio-9p-test.c b/tests/virtio-9p-test.c
index 727316086337..b3ee956cbcb2 100644
--- a/tests/virtio-9p-test.c
+++ b/tests/virtio-9p-test.c
@@ -16,6 +16,7 @@
 #include "libqos/virtio-pci.h"
 #include "standard-headers/linux/virtio_ids.h"
 #include "standard-headers/linux/virtio_pci.h"
+#include "hw/9pfs/9p.h"
 
 static const char mount_tag[] = "qtest";
 
@@ -98,6 +99,226 @@ static void pci_config(QVirtIO9P *v9p)
     g_free(tag);
 }
 
+#define P9_MAX_SIZE 4096 /* Max size of a T-message or R-message */
+
+typedef struct {
+    QVirtIO9P *v9p;
+    uint16_t tag;
+    uint64_t t_msg;
+    uint32_t t_size;
+    uint64_t r_msg;
+    /* No r_size, it is hardcoded to P9_MAX_SIZE */
+    size_t t_off;
+    size_t r_off;
+} P9Req;
+
+static void v9fs_memwrite(P9Req *req, const void *addr, size_t len)
+{
+    memwrite(req->t_msg + req->t_off, addr, len);
+    req->t_off += len;
+}
+
+static void v9fs_memskip(P9Req *req, size_t len)
+{
+    req->r_off += len;
+}
+
+static void v9fs_memrewind(P9Req *req, size_t len)
+{
+    req->r_off -= len;
+}
+
+static void v9fs_memread(P9Req *req, void *addr, size_t len)
+{
+    memread(req->r_msg + req->r_off, addr, len);
+    req->r_off += len;
+}
+
+static void v9fs_uint16_write(P9Req *req, uint16_t val)
+{
+    uint16_t le_val = cpu_to_le16(val);
+
+    v9fs_memwrite(req, &le_val, 2);
+}
+
+static void v9fs_uint16_read(P9Req *req, uint16_t *val)
+{
+    v9fs_memread(req, val, 2);
+    le16_to_cpus(val);
+}
+
+static void v9fs_uint32_write(P9Req *req, uint32_t val)
+{
+    uint32_t le_val = cpu_to_le32(val);
+
+    v9fs_memwrite(req, &le_val, 4);
+}
+
+static void v9fs_uint32_read(P9Req *req, uint32_t *val)
+{
+    v9fs_memread(req, val, 4);
+    le32_to_cpus(val);
+}
+
+/* len[2] string[len] */
+static uint16_t v9fs_string_size(const char *string)
+{
+    size_t len = strlen(string);
+
+    g_assert_cmpint(len, <=, UINT16_MAX);
+
+    return 2 + len;
+}
+
+static void v9fs_string_write(P9Req *req, const char *string)
+{
+    int len = strlen(string);
+
+    g_assert_cmpint(len, <=, UINT16_MAX);
+
+    v9fs_uint16_write(req, (uint16_t) len);
+    v9fs_memwrite(req, string, len);
+}
+
+static void v9fs_string_read(P9Req *req, uint16_t *len, char **string)
+{
+    uint16_t local_len;
+
+    v9fs_uint16_read(req, &local_len);
+    if (len) {
+        *len = local_len;
+    }
+    if (string) {
+        *string = g_malloc(local_len);
+        v9fs_memread(req, *string, local_len);
+    } else {
+        v9fs_memskip(req, local_len);
+    }
+}
+
+ typedef struct {
+    uint32_t size;
+    uint8_t id;
+    uint16_t tag;
+} QEMU_PACKED P9Hdr;
+
+static P9Req *v9fs_req_init(QVirtIO9P *v9p, uint32_t size, uint8_t id,
+                            uint16_t tag)
+{
+    P9Req *req = g_new0(P9Req, 1);
+    uint32_t t_size = 7 + size; /* 9P header has well-known size of 7 bytes */
+    P9Hdr hdr = {
+        .size = cpu_to_le32(t_size),
+        .id = id,
+        .tag = cpu_to_le16(tag)
+    };
+
+    g_assert_cmpint(t_size, <=, P9_MAX_SIZE);
+
+    req->v9p = v9p;
+    req->t_size = t_size;
+    req->t_msg = guest_alloc(v9p->qs->alloc, req->t_size);
+    v9fs_memwrite(req, &hdr, 7);
+    req->tag = tag;
+    return req;
+}
+
+static void v9fs_req_send(P9Req *req)
+{
+    QVirtIO9P *v9p = req->v9p;
+    uint32_t free_head;
+
+    req->r_msg = guest_alloc(v9p->qs->alloc, P9_MAX_SIZE);
+    free_head = qvirtqueue_add(v9p->vq, req->t_msg, req->t_size, false, true);
+    qvirtqueue_add(v9p->vq, req->r_msg, P9_MAX_SIZE, true, false);
+    qvirtqueue_kick(v9p->dev, v9p->vq, free_head);
+    req->t_off = 0;
+}
+
+static void v9fs_req_recv(P9Req *req, uint8_t id)
+{
+    QVirtIO9P *v9p = req->v9p;
+    P9Hdr hdr;
+    int i;
+
+    for (i = 0; i < 10; i++) {
+        qvirtio_wait_queue_isr(v9p->dev, v9p->vq, 1000 * 1000);
+
+        v9fs_memread(req, &hdr, 7);
+        le32_to_cpus(&hdr.size);
+        le16_to_cpus(&hdr.tag);
+        if (hdr.size >= 7) {
+            break;
+        }
+        v9fs_memrewind(req, 7);
+    }
+
+    g_assert_cmpint(hdr.size, >=, 7);
+    g_assert_cmpint(hdr.size, <=, P9_MAX_SIZE);
+    g_assert_cmpint(hdr.tag, ==, req->tag);
+
+    if (hdr.id != id && hdr.id == P9_RLERROR) {
+        uint32_t err;
+        v9fs_uint32_read(req, &err);
+        g_printerr("Received Rlerror (%d) instead of Response %d\n", err, id);
+        g_assert_not_reached();
+    }
+    g_assert_cmpint(hdr.id, ==, id);
+}
+
+static void v9fs_req_free(P9Req *req)
+{
+    QVirtIO9P *v9p = req->v9p;
+
+    guest_free(v9p->qs->alloc, req->t_msg);
+    guest_free(v9p->qs->alloc, req->r_msg);
+    g_free(req);
+}
+
+/* size[4] Tversion tag[2] msize[4] version[s] */
+static P9Req *v9fs_tversion(QVirtIO9P *v9p, uint32_t msize, const char *version)
+{
+    P9Req *req = v9fs_req_init(v9p, 4 + v9fs_string_size(version), P9_TVERSION,
+                               P9_NOTAG);
+
+    v9fs_uint32_write(req, msize);
+    v9fs_string_write(req, version);
+    v9fs_req_send(req);
+    return req;
+}
+
+/* size[4] Rversion tag[2] msize[4] version[s] */
+static void v9fs_rversion(P9Req *req, uint16_t *len, char **version)
+{
+    uint32_t msize;
+
+    v9fs_req_recv(req, P9_RVERSION);
+    v9fs_uint32_read(req, &msize);
+
+    g_assert_cmpint(msize, ==, P9_MAX_SIZE);
+
+    if (len || version) {
+        v9fs_string_read(req, len, version);
+    }
+
+    v9fs_req_free(req);
+}
+
+static void fs_version(QVirtIO9P *v9p)
+{
+    const char *version = "9P2000.L";
+    uint16_t server_len;
+    char *server_version;
+    P9Req *req;
+
+    req = v9fs_tversion(v9p, P9_MAX_SIZE, version);
+    v9fs_rversion(req, &server_len, &server_version);
+
+    g_assert_cmpmem(server_version, server_len, version, strlen(version));
+
+    g_free(server_version);
+}
+
 typedef void (*v9fs_test_fn)(QVirtIO9P *v9p);
 
 static void v9fs_run_pci_test(gconstpointer data)
@@ -121,6 +342,7 @@ int main(int argc, char **argv)
     g_test_init(&argc, &argv, NULL);
     v9fs_qtest_pci_add("/virtio/9p/pci/nop", NULL);
     v9fs_qtest_pci_add("/virtio/9p/pci/config", pci_config);
+    v9fs_qtest_pci_add("/virtio/9p/pci/fs/version/basic", fs_version);
 
     return g_test_run();
 }
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [Qemu-devel] [PULL 10/13] tests: virtio-9p: add attach operation test
  2017-01-04  8:21 [Qemu-devel] [PULL 00/13] 9p patches 20170104 Greg Kurz
                   ` (8 preceding siblings ...)
  2017-01-04  8:21 ` [Qemu-devel] [PULL 09/13] tests: virtio-9p: add version operation test Greg Kurz
@ 2017-01-04  8:21 ` Greg Kurz
  2017-01-04  8:21 ` [Qemu-devel] [PULL 11/13] tests: virtio-9p: add walk " Greg Kurz
                   ` (3 subsequent siblings)
  13 siblings, 0 replies; 15+ messages in thread
From: Greg Kurz @ 2017-01-04  8:21 UTC (permalink / raw)
  To: qemu-devel; +Cc: Peter Maydell, Aneesh Kumar K.V, Greg Kurz

The attach operation is used to establish a connection between the
client and the server. After this, the client is able to access the
underlying filesystem and do I/O.

This test simply ensures the operation succeeds without error.

Reference:

http://man.cat-v.org/plan_9/5/attach

Signed-off-by: Greg Kurz <groug@kaod.org>
---
 tests/virtio-9p-test.c | 40 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 40 insertions(+)

diff --git a/tests/virtio-9p-test.c b/tests/virtio-9p-test.c
index b3ee956cbcb2..37a256ef4a59 100644
--- a/tests/virtio-9p-test.c
+++ b/tests/virtio-9p-test.c
@@ -25,6 +25,7 @@ typedef struct {
     QOSState *qs;
     QVirtQueue *vq;
     char *test_share;
+    uint16_t p9_req_tag;
 } QVirtIO9P;
 
 static QVirtIO9P *qvirtio_9p_start(const char *driver)
@@ -304,6 +305,35 @@ static void v9fs_rversion(P9Req *req, uint16_t *len, char **version)
     v9fs_req_free(req);
 }
 
+/* size[4] Tattach tag[2] fid[4] afid[4] uname[s] aname[s] n_uname[4] */
+static P9Req *v9fs_tattach(QVirtIO9P *v9p, uint32_t fid, uint32_t n_uname)
+{
+    const char *uname = ""; /* ignored by QEMU */
+    const char *aname = ""; /* ignored by QEMU */
+    P9Req *req = v9fs_req_init(v9p, 4 + 4 + 2 + 2 + 4, P9_TATTACH,
+                               ++(v9p->p9_req_tag));
+
+    v9fs_uint32_write(req, fid);
+    v9fs_uint32_write(req, P9_NOFID);
+    v9fs_string_write(req, uname);
+    v9fs_string_write(req, aname);
+    v9fs_uint32_write(req, n_uname);
+    v9fs_req_send(req);
+    return req;
+}
+
+typedef char v9fs_qid[13];
+
+/* size[4] Rattach tag[2] qid[13] */
+static void v9fs_rattach(P9Req *req, v9fs_qid *qid)
+{
+    v9fs_req_recv(req, P9_RATTACH);
+    if (qid) {
+        v9fs_memread(req, qid, 13);
+    }
+    v9fs_req_free(req);
+}
+
 static void fs_version(QVirtIO9P *v9p)
 {
     const char *version = "9P2000.L";
@@ -319,6 +349,15 @@ static void fs_version(QVirtIO9P *v9p)
     g_free(server_version);
 }
 
+static void fs_attach(QVirtIO9P *v9p)
+{
+    P9Req *req;
+
+    fs_version(v9p);
+    req = v9fs_tattach(v9p, 0, getuid());
+    v9fs_rattach(req, NULL);
+}
+
 typedef void (*v9fs_test_fn)(QVirtIO9P *v9p);
 
 static void v9fs_run_pci_test(gconstpointer data)
@@ -343,6 +382,7 @@ int main(int argc, char **argv)
     v9fs_qtest_pci_add("/virtio/9p/pci/nop", NULL);
     v9fs_qtest_pci_add("/virtio/9p/pci/config", pci_config);
     v9fs_qtest_pci_add("/virtio/9p/pci/fs/version/basic", fs_version);
+    v9fs_qtest_pci_add("/virtio/9p/pci/fs/attach/basic", fs_attach);
 
     return g_test_run();
 }
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [Qemu-devel] [PULL 11/13] tests: virtio-9p: add walk operation test
  2017-01-04  8:21 [Qemu-devel] [PULL 00/13] 9p patches 20170104 Greg Kurz
                   ` (9 preceding siblings ...)
  2017-01-04  8:21 ` [Qemu-devel] [PULL 10/13] tests: virtio-9p: add attach " Greg Kurz
@ 2017-01-04  8:21 ` Greg Kurz
  2017-01-04  8:21 ` [Qemu-devel] [PULL 12/13] tests: virtio-9p: no slash in path elements during walk Greg Kurz
                   ` (2 subsequent siblings)
  13 siblings, 0 replies; 15+ messages in thread
From: Greg Kurz @ 2017-01-04  8:21 UTC (permalink / raw)
  To: qemu-devel; +Cc: Peter Maydell, Aneesh Kumar K.V, Greg Kurz

The walk operation is used to traverse the directory tree and to associate
paths to fids. A single walk can be used to traverse up to P9_MAXWELEM path
elements at the same time.

The test creates a path with P9_MAXWELEM elements on the backend (à la
'mkdir -p') and issues a walk operation. The walk is expected to succeed
without error.

Reference:

http://man.cat-v.org/plan_9/5/walk

Signed-off-by: Greg Kurz <groug@kaod.org>
---
 tests/virtio-9p-test.c | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 70 insertions(+)

diff --git a/tests/virtio-9p-test.c b/tests/virtio-9p-test.c
index 37a256ef4a59..2deb7fbf92f1 100644
--- a/tests/virtio-9p-test.c
+++ b/tests/virtio-9p-test.c
@@ -334,6 +334,45 @@ static void v9fs_rattach(P9Req *req, v9fs_qid *qid)
     v9fs_req_free(req);
 }
 
+/* size[4] Twalk tag[2] fid[4] newfid[4] nwname[2] nwname*(wname[s]) */
+static P9Req *v9fs_twalk(QVirtIO9P *v9p, uint32_t fid, uint32_t newfid,
+                         uint16_t nwname, char *const wnames[])
+{
+    P9Req *req;
+    int i;
+    uint32_t size = 4 + 4 + 2;
+
+    for (i = 0; i < nwname; i++) {
+        size += v9fs_string_size(wnames[i]);
+    }
+    req = v9fs_req_init(v9p,  size, P9_TWALK, ++(v9p->p9_req_tag));
+    v9fs_uint32_write(req, fid);
+    v9fs_uint32_write(req, newfid);
+    v9fs_uint16_write(req, nwname);
+    for (i = 0; i < nwname; i++) {
+        v9fs_string_write(req, wnames[i]);
+    }
+    v9fs_req_send(req);
+    return req;
+}
+
+/* size[4] Rwalk tag[2] nwqid[2] nwqid*(wqid[13]) */
+static void v9fs_rwalk(P9Req *req, uint16_t *nwqid, v9fs_qid **wqid)
+{
+    uint16_t local_nwqid;
+
+    v9fs_req_recv(req, P9_RWALK);
+    v9fs_uint16_read(req, &local_nwqid);
+    if (nwqid) {
+        *nwqid = local_nwqid;
+    }
+    if (wqid) {
+        *wqid = g_malloc(local_nwqid * 13);
+        v9fs_memread(req, *wqid, local_nwqid * 13);
+    }
+    v9fs_req_free(req);
+}
+
 static void fs_version(QVirtIO9P *v9p)
 {
     const char *version = "9P2000.L";
@@ -358,6 +397,36 @@ static void fs_attach(QVirtIO9P *v9p)
     v9fs_rattach(req, NULL);
 }
 
+static void fs_walk(QVirtIO9P *v9p)
+{
+    char *wnames[P9_MAXWELEM], *paths[P9_MAXWELEM];
+    char *last_path = v9p->test_share;
+    uint16_t nwqid;
+    v9fs_qid *wqid;
+    int i;
+    P9Req *req;
+
+    for (i = 0; i < P9_MAXWELEM; i++) {
+        wnames[i] = g_strdup_printf("%s%d", __func__, i);
+        last_path = paths[i] = g_strdup_printf("%s/%s", last_path, wnames[i]);
+        g_assert(!mkdir(paths[i], 0700));
+    }
+
+    fs_attach(v9p);
+    req = v9fs_twalk(v9p, 0, 1, P9_MAXWELEM, wnames);
+    v9fs_rwalk(req, &nwqid, &wqid);
+
+    g_assert_cmpint(nwqid, ==, P9_MAXWELEM);
+
+    for (i = 0; i < P9_MAXWELEM; i++) {
+        rmdir(paths[P9_MAXWELEM - i - 1]);
+        g_free(paths[P9_MAXWELEM - i - 1]);
+        g_free(wnames[i]);
+    }
+
+    g_free(wqid);
+}
+
 typedef void (*v9fs_test_fn)(QVirtIO9P *v9p);
 
 static void v9fs_run_pci_test(gconstpointer data)
@@ -383,6 +452,7 @@ int main(int argc, char **argv)
     v9fs_qtest_pci_add("/virtio/9p/pci/config", pci_config);
     v9fs_qtest_pci_add("/virtio/9p/pci/fs/version/basic", fs_version);
     v9fs_qtest_pci_add("/virtio/9p/pci/fs/attach/basic", fs_attach);
+    v9fs_qtest_pci_add("/virtio/9p/pci/fs/walk/basic", fs_walk);
 
     return g_test_run();
 }
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [Qemu-devel] [PULL 12/13] tests: virtio-9p: no slash in path elements during walk
  2017-01-04  8:21 [Qemu-devel] [PULL 00/13] 9p patches 20170104 Greg Kurz
                   ` (10 preceding siblings ...)
  2017-01-04  8:21 ` [Qemu-devel] [PULL 11/13] tests: virtio-9p: add walk " Greg Kurz
@ 2017-01-04  8:21 ` Greg Kurz
  2017-01-04  8:21 ` [Qemu-devel] [PULL 13/13] tests: virtio-9p: ".." cannot be used to walk out of the shared directory Greg Kurz
  2017-01-05 12:44 ` [Qemu-devel] [PULL 00/13] 9p patches 20170104 Peter Maydell
  13 siblings, 0 replies; 15+ messages in thread
From: Greg Kurz @ 2017-01-04  8:21 UTC (permalink / raw)
  To: qemu-devel; +Cc: Peter Maydell, Aneesh Kumar K.V, Greg Kurz

The walk operation is expected to fail and to return ENOENT.

Signed-off-by: Greg Kurz <groug@kaod.org>
---
 tests/virtio-9p-test.c | 24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/tests/virtio-9p-test.c b/tests/virtio-9p-test.c
index 2deb7fbf92f1..83cb23b3afc7 100644
--- a/tests/virtio-9p-test.c
+++ b/tests/virtio-9p-test.c
@@ -276,6 +276,14 @@ static void v9fs_req_free(P9Req *req)
     g_free(req);
 }
 
+/* size[4] Rlerror tag[2] ecode[4] */
+static void v9fs_rlerror(P9Req *req, uint32_t *err)
+{
+    v9fs_req_recv(req, P9_RLERROR);
+    v9fs_uint32_read(req, err);
+    v9fs_req_free(req);
+}
+
 /* size[4] Tversion tag[2] msize[4] version[s] */
 static P9Req *v9fs_tversion(QVirtIO9P *v9p, uint32_t msize, const char *version)
 {
@@ -427,6 +435,21 @@ static void fs_walk(QVirtIO9P *v9p)
     g_free(wqid);
 }
 
+static void fs_walk_no_slash(QVirtIO9P *v9p)
+{
+    char *const wnames[] = { g_strdup(" /") };
+    P9Req *req;
+    uint32_t err;
+
+    fs_attach(v9p);
+    req = v9fs_twalk(v9p, 0, 1, 1, wnames);
+    v9fs_rlerror(req, &err);
+
+    g_assert_cmpint(err, ==, ENOENT);
+
+    g_free(wnames[0]);
+}
+
 typedef void (*v9fs_test_fn)(QVirtIO9P *v9p);
 
 static void v9fs_run_pci_test(gconstpointer data)
@@ -453,6 +476,7 @@ int main(int argc, char **argv)
     v9fs_qtest_pci_add("/virtio/9p/pci/fs/version/basic", fs_version);
     v9fs_qtest_pci_add("/virtio/9p/pci/fs/attach/basic", fs_attach);
     v9fs_qtest_pci_add("/virtio/9p/pci/fs/walk/basic", fs_walk);
+    v9fs_qtest_pci_add("/virtio/9p/pci/fs/walk/no_slash", fs_walk_no_slash);
 
     return g_test_run();
 }
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [Qemu-devel] [PULL 13/13] tests: virtio-9p: ".." cannot be used to walk out of the shared directory
  2017-01-04  8:21 [Qemu-devel] [PULL 00/13] 9p patches 20170104 Greg Kurz
                   ` (11 preceding siblings ...)
  2017-01-04  8:21 ` [Qemu-devel] [PULL 12/13] tests: virtio-9p: no slash in path elements during walk Greg Kurz
@ 2017-01-04  8:21 ` Greg Kurz
  2017-01-05 12:44 ` [Qemu-devel] [PULL 00/13] 9p patches 20170104 Peter Maydell
  13 siblings, 0 replies; 15+ messages in thread
From: Greg Kurz @ 2017-01-04  8:21 UTC (permalink / raw)
  To: qemu-devel; +Cc: Peter Maydell, Aneesh Kumar K.V, Greg Kurz

According to the 9P spec at http://man.cat-v.org/plan_9/5/intro, the
parent directory of the root directory of a server's tree is itself.
This test hence checks that the qid of the root directory as returned by
attach is the same as the qid of ".." when walking from the root directory.

Signed-off-by: Greg Kurz <groug@kaod.org>
---
 tests/virtio-9p-test.c | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)

diff --git a/tests/virtio-9p-test.c b/tests/virtio-9p-test.c
index 83cb23b3afc7..060407b20e39 100644
--- a/tests/virtio-9p-test.c
+++ b/tests/virtio-9p-test.c
@@ -450,6 +450,25 @@ static void fs_walk_no_slash(QVirtIO9P *v9p)
     g_free(wnames[0]);
 }
 
+static void fs_walk_dotdot(QVirtIO9P *v9p)
+{
+    char *const wnames[] = { g_strdup("..") };
+    v9fs_qid root_qid, *wqid;
+    P9Req *req;
+
+    fs_version(v9p);
+    req = v9fs_tattach(v9p, 0, getuid());
+    v9fs_rattach(req, &root_qid);
+
+    req = v9fs_twalk(v9p, 0, 1, 1, wnames);
+    v9fs_rwalk(req, NULL, &wqid); /* We now we'll get one qid */
+
+    g_assert_cmpmem(&root_qid, 13, wqid[0], 13);
+
+    g_free(wqid);
+    g_free(wnames[0]);
+}
+
 typedef void (*v9fs_test_fn)(QVirtIO9P *v9p);
 
 static void v9fs_run_pci_test(gconstpointer data)
@@ -477,6 +496,8 @@ int main(int argc, char **argv)
     v9fs_qtest_pci_add("/virtio/9p/pci/fs/attach/basic", fs_attach);
     v9fs_qtest_pci_add("/virtio/9p/pci/fs/walk/basic", fs_walk);
     v9fs_qtest_pci_add("/virtio/9p/pci/fs/walk/no_slash", fs_walk_no_slash);
+    v9fs_qtest_pci_add("/virtio/9p/pci/fs/walk/dotdot_from_root",
+                       fs_walk_dotdot);
 
     return g_test_run();
 }
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* Re: [Qemu-devel] [PULL 00/13] 9p patches 20170104
  2017-01-04  8:21 [Qemu-devel] [PULL 00/13] 9p patches 20170104 Greg Kurz
                   ` (12 preceding siblings ...)
  2017-01-04  8:21 ` [Qemu-devel] [PULL 13/13] tests: virtio-9p: ".." cannot be used to walk out of the shared directory Greg Kurz
@ 2017-01-05 12:44 ` Peter Maydell
  13 siblings, 0 replies; 15+ messages in thread
From: Peter Maydell @ 2017-01-05 12:44 UTC (permalink / raw)
  To: Greg Kurz; +Cc: QEMU Developers, Aneesh Kumar K.V

On 4 January 2017 at 08:21, Greg Kurz <groug@kaod.org> wrote:
> The following changes since commit dbe2b65566e76d3c3a0c3358285c0336ac61e757:
>
>   Merge remote-tracking branch 'remotes/vivier/tags/m68k-for-2.9-pull-request' into staging (2016-12-28 17:11:11 +0000)
>
> are available in the git repository at:
>
>   https://github.com/gkurz/qemu.git tags/for-upstream
>
> for you to fetch changes up to a37c07022b44e4fc29238deca7588406d081e6c2:
>
>   tests: virtio-9p: ".." cannot be used to walk out of the shared directory (2017-01-03 17:28:44 +0100)
>
> ----------------------------------------------------------------
> - transport specific callbacks (for Xen)
> - fix crash (2.8 regression)
> - 9p functional tests
>
> ----------------------------------------------------------------

Applied, thanks.

-- PMM

^ permalink raw reply	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2017-01-05 12:44 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-01-04  8:21 [Qemu-devel] [PULL 00/13] 9p patches 20170104 Greg Kurz
2017-01-04  8:21 ` [Qemu-devel] [PULL 01/13] 9pfs: move pdus to V9fsState Greg Kurz
2017-01-04  8:21 ` [Qemu-devel] [PULL 02/13] 9pfs: introduce transport specific callbacks Greg Kurz
2017-01-04  8:21 ` [Qemu-devel] [PULL 03/13] 9pfs: call v9fs_init_qiov_from_pdu before v9fs_pack Greg Kurz
2017-01-04  8:21 ` [Qemu-devel] [PULL 04/13] 9pfs: introduce init_out/in_iov_from_pdu Greg Kurz
2017-01-04  8:21 ` [Qemu-devel] [PULL 05/13] 9pfs: fix crash when fsdev is missing Greg Kurz
2017-01-04  8:21 ` [Qemu-devel] [PULL 06/13] tests: virtio-9p: rename PCI configuration test Greg Kurz
2017-01-04  8:21 ` [Qemu-devel] [PULL 07/13] tests: virtio-9p: code refactoring Greg Kurz
2017-01-04  8:21 ` [Qemu-devel] [PULL 08/13] 9pfs: fix P9_NOTAG and P9_NOFID macros Greg Kurz
2017-01-04  8:21 ` [Qemu-devel] [PULL 09/13] tests: virtio-9p: add version operation test Greg Kurz
2017-01-04  8:21 ` [Qemu-devel] [PULL 10/13] tests: virtio-9p: add attach " Greg Kurz
2017-01-04  8:21 ` [Qemu-devel] [PULL 11/13] tests: virtio-9p: add walk " Greg Kurz
2017-01-04  8:21 ` [Qemu-devel] [PULL 12/13] tests: virtio-9p: no slash in path elements during walk Greg Kurz
2017-01-04  8:21 ` [Qemu-devel] [PULL 13/13] tests: virtio-9p: ".." cannot be used to walk out of the shared directory Greg Kurz
2017-01-05 12:44 ` [Qemu-devel] [PULL 00/13] 9p patches 20170104 Peter Maydell

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).