* [PATCH] tools/kvm/9p: Add encode/decode routines for protocol data
@ 2011-06-21 10:20 Aneesh Kumar K.V
2011-06-24 13:47 ` Sasha Levin
0 siblings, 1 reply; 5+ messages in thread
From: Aneesh Kumar K.V @ 2011-06-21 10:20 UTC (permalink / raw)
To: penberg, levinsasha928; +Cc: kvm, Aneesh Kumar K.V
The protocol data is in little-endian format.
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
---
tools/kvm/Makefile | 1 +
tools/kvm/include/kvm/virtio-9p.h | 81 ++++++-
tools/kvm/virtio/9p-pdu.c | 237 ++++++++++++++++++
tools/kvm/virtio/9p.c | 477 ++++++++++++++++---------------------
4 files changed, 526 insertions(+), 270 deletions(-)
create mode 100644 tools/kvm/virtio/9p-pdu.c
diff --git a/tools/kvm/Makefile b/tools/kvm/Makefile
index d368c22..559fefc 100644
--- a/tools/kvm/Makefile
+++ b/tools/kvm/Makefile
@@ -57,6 +57,7 @@ OBJS += util/parse-options.o
OBJS += util/rbtree-interval.o
OBJS += util/strbuf.o
OBJS += virtio/9p.o
+OBJS += virtio/9p-pdu.o
OBJS += hw/vesa.o
OBJS += hw/i8042.o
diff --git a/tools/kvm/include/kvm/virtio-9p.h b/tools/kvm/include/kvm/virtio-9p.h
index d99bf96..55f963b 100644
--- a/tools/kvm/include/kvm/virtio-9p.h
+++ b/tools/kvm/include/kvm/virtio-9p.h
@@ -1,8 +1,87 @@
#ifndef KVM__VIRTIO_9P_H
#define KVM__VIRTIO_9P_H
+#include "kvm/virtio-pci-dev.h"
+#include "kvm/virtio.h"
+#include "kvm/ioport.h"
+#include "kvm/mutex.h"
+#include "kvm/util.h"
+#include "kvm/kvm.h"
+#include "kvm/pci.h"
+#include "kvm/threadpool.h"
+#include "kvm/irq.h"
+#include "kvm/ioeventfd.h"
+
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <pthread.h>
+#include <dirent.h>
+
+#include <linux/virtio_ring.h>
+#include <linux/virtio_9p.h>
+#include <net/9p/9p.h>
+
+#define NUM_VIRT_QUEUES 1
+#define VIRTQUEUE_NUM 128
+#define VIRTIO_P9_DEFAULT_TAG "kvm_9p"
+#define VIRTIO_P9_HDR_LEN (sizeof(u32)+sizeof(u8)+sizeof(u16))
+#define VIRTIO_P9_MAX_FID 128
+#define VIRTIO_P9_VERSION "9P2000"
+#define MAX_TAG_LEN 32
+
+
+struct p9_msg {
+ u32 size;
+ u8 cmd;
+ u16 tag;
+ u8 msg[0];
+} __attribute__((packed));
+
+struct p9_fid {
+ u32 fid;
+ u8 is_dir;
+ char abs_path[PATH_MAX];
+ char *path;
+ DIR *dir;
+ int fd;
+};
+
+struct p9_dev_job {
+ struct virt_queue *vq;
+ struct p9_dev *p9dev;
+ void *job_id;
+};
+
+struct p9_dev {
+ u8 status;
+ u8 isr;
+ u16 config_vector;
+ u32 features;
+ struct virtio_9p_config *config;
+ u16 base_addr;
+
+ /* virtio queue */
+ u16 queue_selector;
+ struct virt_queue vqs[NUM_VIRT_QUEUES];
+ struct p9_dev_job jobs[NUM_VIRT_QUEUES];
+ struct p9_fid fids[VIRTIO_P9_MAX_FID];
+ char root_dir[PATH_MAX];
+ struct pci_device_header pci_hdr;
+};
+
+struct p9_pdu {
+ u32 queue_head;
+ size_t read_offset;
+ size_t write_offset;
+ u16 out_iov_cnt;
+ u16 in_iov_cnt;
+ struct iovec in_iov[VIRTQUEUE_NUM];
+ struct iovec out_iov[VIRTQUEUE_NUM];
+};
struct kvm;
void virtio_9p__init(struct kvm *kvm, const char *root, const char *tag_name);
-
+int virtio_p9_pdu_readf(struct p9_pdu *pdu, const char *fmt, ...);
+int virtio_p9_pdu_writef(struct p9_pdu *pdu, const char *fmt, ...);
#endif
diff --git a/tools/kvm/virtio/9p-pdu.c b/tools/kvm/virtio/9p-pdu.c
new file mode 100644
index 0000000..da9f263
--- /dev/null
+++ b/tools/kvm/virtio/9p-pdu.c
@@ -0,0 +1,237 @@
+#include "kvm/virtio-9p.h"
+
+#include <endian.h>
+
+static void virtio_p9_pdu_read(struct p9_pdu *pdu, void *data, size_t size)
+{
+ size_t len;
+ int i, copied = 0;
+ u16 iov_cnt = pdu->out_iov_cnt;
+ size_t offset = pdu->read_offset;
+ struct iovec *iov = pdu->out_iov;
+
+ for (i = 0; i < iov_cnt && size; i++) {
+ if (offset >= iov[i].iov_len) {
+ offset -= iov[i].iov_len;
+ continue;
+ } else {
+ len = MIN(iov[i].iov_len - offset, size);
+ memcpy(data, iov[i].iov_base + offset, len);
+ size -= len;
+ data += len;
+ offset = 0;
+ copied += len;
+ }
+ }
+ pdu->read_offset += copied;
+}
+
+static void virtio_p9_pdu_write(struct p9_pdu *pdu,
+ const void *data, size_t size)
+{
+ size_t len;
+ int i, copied = 0;
+ u16 iov_cnt = pdu->in_iov_cnt;
+ size_t offset = pdu->write_offset;
+ struct iovec *iov = pdu->in_iov;
+
+ for (i = 0; i < iov_cnt && size; i++) {
+ if (offset >= iov[i].iov_len) {
+ offset -= iov[i].iov_len;
+ continue;
+ } else {
+ len = MIN(iov[i].iov_len - offset, size);
+ memcpy(iov[i].iov_base + offset, data, len);
+ size -= len;
+ data += len;
+ offset = 0;
+ copied += len;
+ }
+ }
+ pdu->write_offset += copied;
+}
+
+static void virtio_p9_wstat_free(struct p9_wstat *stbuf)
+{
+ free(stbuf->name);
+ free(stbuf->uid);
+ free(stbuf->gid);
+ free(stbuf->muid);
+}
+
+static int virtio_p9_decode(struct p9_pdu *pdu, const char *fmt, va_list ap)
+{
+ int retval = 0;
+ const char *ptr;
+
+ for (ptr = fmt; *ptr; ptr++) {
+ switch (*ptr) {
+ case 'b':
+ {
+ int8_t *val = va_arg(ap, int8_t *);
+ virtio_p9_pdu_read(pdu, val, sizeof(*val));
+ }
+ break;
+ case 'w':
+ {
+ int16_t le_val;
+ int16_t *val = va_arg(ap, int16_t *);
+ virtio_p9_pdu_read(pdu, &le_val, sizeof(le_val));
+ *val = le16toh(le_val);
+ }
+ break;
+ case 'd':
+ {
+ int32_t le_val;
+ int32_t *val = va_arg(ap, int32_t *);
+ virtio_p9_pdu_read(pdu, &le_val, sizeof(le_val));
+ *val = le32toh(le_val);
+ }
+ break;
+ case 'q':
+ {
+ int64_t le_val;
+ int64_t *val = va_arg(ap, int64_t *);
+ virtio_p9_pdu_read(pdu, &le_val, sizeof(le_val));
+ *val = le64toh(le_val);
+ }
+ break;
+ case 's':
+ {
+ int16_t len;
+ char **str = va_arg(ap, char **);
+
+ virtio_p9_pdu_readf(pdu, "w", &len);
+ *str = malloc(len + 1);
+ if (*str == NULL) {
+ retval = ENOMEM;
+ break;
+ }
+ virtio_p9_pdu_read(pdu, *str, len);
+ (*str)[len] = 0;
+ }
+ break;
+ case 'Q':
+ {
+ struct p9_qid *qid = va_arg(ap, struct p9_qid *);
+ retval = virtio_p9_pdu_readf(pdu, "bdq",
+ &qid->type, &qid->version,
+ &qid->path);
+ }
+ break;
+ case 'S':
+ {
+ struct p9_wstat *stbuf = va_arg(ap, struct p9_wstat *);
+ memset(stbuf, 0, sizeof(struct p9_wstat));
+ stbuf->n_uid = stbuf->n_gid = stbuf->n_muid = -1;
+ retval = virtio_p9_pdu_readf(pdu, "wwdQdddqssss",
+ &stbuf->size, &stbuf->type,
+ &stbuf->dev, &stbuf->qid,
+ &stbuf->mode, &stbuf->atime,
+ &stbuf->mtime, &stbuf->length,
+ &stbuf->name, &stbuf->uid,
+ &stbuf->gid, &stbuf->muid);
+ if (retval)
+ virtio_p9_wstat_free(stbuf);
+ }
+ break;
+ default:
+ retval = EINVAL;
+ break;
+ }
+ }
+ return retval;
+}
+
+static int virtio_p9_pdu_encode(struct p9_pdu *pdu, const char *fmt, va_list ap)
+{
+ int retval = 0;
+ const char *ptr;
+
+ for (ptr = fmt; *ptr; ptr++) {
+ switch (*ptr) {
+ case 'b':
+ {
+ int8_t val = va_arg(ap, int);
+ virtio_p9_pdu_write(pdu, &val, sizeof(val));
+ }
+ break;
+ case 'w':
+ {
+ int16_t val = htole16(va_arg(ap, int));
+ virtio_p9_pdu_write(pdu, &val, sizeof(val));
+ }
+ break;
+ case 'd':
+ {
+ int32_t val = htole32(va_arg(ap, int32_t));
+ virtio_p9_pdu_write(pdu, &val, sizeof(val));
+ }
+ break;
+ case 'q':
+ {
+ int64_t val = htole64(va_arg(ap, int64_t));
+ virtio_p9_pdu_write(pdu, &val, sizeof(val));
+ }
+ break;
+ case 's':
+ {
+ uint16_t len = 0;
+ const char *s = va_arg(ap, char *);
+ if (s)
+ len = MIN(strlen(s), USHRT_MAX);
+ virtio_p9_pdu_writef(pdu, "w", len);
+ virtio_p9_pdu_write(pdu, s, len);
+ }
+ break;
+ case 'Q':
+ {
+ struct p9_qid *qid = va_arg(ap, struct p9_qid *);
+ retval = virtio_p9_pdu_writef(pdu, "bdq",
+ qid->type, qid->version,
+ qid->path);
+ }
+ break;
+ case 'S':
+ {
+ struct p9_wstat *stbuf = va_arg(ap, struct p9_wstat *);
+ retval = virtio_p9_pdu_writef(pdu, "wwdQdddqssss",
+ stbuf->size, stbuf->type,
+ stbuf->dev, &stbuf->qid,
+ stbuf->mode, stbuf->atime,
+ stbuf->mtime, stbuf->length,
+ stbuf->name, stbuf->uid,
+ stbuf->gid, stbuf->muid);
+ }
+ break;
+ default:
+ retval = EINVAL;
+ break;
+ }
+ }
+ return retval;
+}
+
+int virtio_p9_pdu_readf(struct p9_pdu *pdu, const char *fmt, ...)
+{
+ int ret;
+ va_list ap;
+
+ va_start(ap, fmt);
+ ret = virtio_p9_decode(pdu, fmt, ap);
+ va_end(ap);
+
+ return ret;
+}
+
+int virtio_p9_pdu_writef(struct p9_pdu *pdu, const char *fmt, ...)
+{
+ int ret;
+ va_list ap;
+
+ va_start(ap, fmt);
+ ret = virtio_p9_pdu_encode(pdu, fmt, ap);
+ va_end(ap);
+
+ return ret;
+}
diff --git a/tools/kvm/virtio/9p.c b/tools/kvm/virtio/9p.c
index d2d738d..7bc6c95 100644
--- a/tools/kvm/virtio/9p.c
+++ b/tools/kvm/virtio/9p.c
@@ -1,81 +1,4 @@
#include "kvm/virtio-9p.h"
-#include "kvm/virtio-pci-dev.h"
-#include "kvm/virtio.h"
-#include "kvm/ioport.h"
-#include "kvm/mutex.h"
-#include "kvm/util.h"
-#include "kvm/kvm.h"
-#include "kvm/pci.h"
-#include "kvm/threadpool.h"
-#include "kvm/irq.h"
-#include "kvm/ioeventfd.h"
-
-#include <fcntl.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <pthread.h>
-#include <dirent.h>
-
-#include <linux/virtio_ring.h>
-#include <linux/virtio_9p.h>
-#include <net/9p/9p.h>
-
-#define NUM_VIRT_QUEUES 1
-#define VIRTQUEUE_NUM 128
-#define VIRTIO_P9_DEFAULT_TAG "kvm_9p"
-#define VIRTIO_P9_HDR_LEN (sizeof(u32)+sizeof(u8)+sizeof(u16))
-#define VIRTIO_P9_MAX_FID 128
-#define VIRTIO_P9_VERSION "9P2000"
-#define MAX_TAG_LEN 32
-
-
-struct p9_msg {
- u32 size;
- u8 cmd;
- u16 tag;
- u8 msg[0];
-} __attribute__((packed));
-
-struct p9_fid {
- u32 fid;
- u8 is_dir;
- char abs_path[PATH_MAX];
- char *path;
- DIR *dir;
- int fd;
-};
-
-struct p9_dev_job {
- struct virt_queue *vq;
- struct p9_dev *p9dev;
- void *job_id;
-};
-
-struct p9_dev {
- u8 status;
- u8 isr;
- u16 config_vector;
- u32 features;
- struct virtio_9p_config *config;
- u16 base_addr;
-
- /* virtio queue */
- u16 queue_selector;
- struct virt_queue vqs[NUM_VIRT_QUEUES];
- struct p9_dev_job jobs[NUM_VIRT_QUEUES];
- struct p9_fid fids[VIRTIO_P9_MAX_FID];
- char root_dir[PATH_MAX];
- struct pci_device_header pci_hdr;
-};
-
-struct p9_pdu {
- u32 queue_head;
- int offset;
- u16 out_iov_cnt;
- u16 in_iov_cnt;
- struct iovec in_iov[VIRTQUEUE_NUM];
- struct iovec out_iov[VIRTQUEUE_NUM];
-};
/* Warning: Immediately use value returned from this function */
static const char *rel_to_abs(struct p9_dev *p9dev,
@@ -185,13 +108,16 @@ static void close_fid(struct p9_dev *p9dev, u32 fid)
}
}
-static void set_p9msg_hdr(struct p9_msg *msg, u32 size, u8 cmd, u16 tag)
+static void virtio_p9_set_reply_header(struct p9_pdu *pdu, u32 size)
{
- *msg = (struct p9_msg) {
- .size = size,
- .tag = tag,
- .cmd = cmd,
- };
+ u8 cmd;
+ u16 tag;
+
+ pdu->read_offset = sizeof(u32);
+ virtio_p9_pdu_readf(pdu, "bw", &cmd, &tag);
+ pdu->write_offset = 0;
+ /* cmd + 1 is the reply message */
+ virtio_p9_pdu_writef(pdu, "dbw", size, cmd + 1, tag);
}
static u16 virtio_p9_update_iov_cnt(struct iovec iov[], u32 count, int iov_cnt)
@@ -213,67 +139,61 @@ static u16 virtio_p9_update_iov_cnt(struct iovec iov[], u32 count, int iov_cnt)
static void virtio_p9_error_reply(struct p9_dev *p9dev,
struct p9_pdu *pdu, int err, u32 *outlen)
{
+ u16 tag;
char *err_str;
- struct p9_msg *inmsg = pdu->in_iov[0].iov_base;
- struct p9_msg *outmsg = pdu->out_iov[0].iov_base;
- struct p9_rerror *rerror = (struct p9_rerror *)inmsg->msg;
err_str = strerror(err);
- rerror->error.len = strlen(err_str);
- memcpy(&rerror->error.str, err_str, rerror->error.len);
+ pdu->write_offset = VIRTIO_P9_HDR_LEN;
+ virtio_p9_pdu_writef(pdu, "s", err_str);
+ *outlen = pdu->write_offset;
+
+ pdu->read_offset = sizeof(u32) + sizeof(u8);
+ virtio_p9_pdu_readf(pdu, "w", &tag);
- *outlen = VIRTIO_P9_HDR_LEN + rerror->error.len + sizeof(u16);
- set_p9msg_hdr(inmsg, *outlen, P9_RERROR, outmsg->tag);
+ pdu->write_offset = 0;
+ virtio_p9_pdu_writef(pdu, "dbw", *outlen, P9_RERROR, tag);
}
static void virtio_p9_version(struct p9_dev *p9dev,
struct p9_pdu *pdu, u32 *outlen)
{
- struct p9_msg *inmsg = pdu->in_iov[0].iov_base;
- struct p9_msg *outmsg = pdu->out_iov[0].iov_base;
- struct p9_rversion *rversion = (struct p9_rversion *)inmsg->msg;
-
- rversion->msize = 4096;
- rversion->version.len = strlen(VIRTIO_P9_VERSION);
- memcpy(&rversion->version.str, VIRTIO_P9_VERSION, rversion->version.len);
-
- *outlen = VIRTIO_P9_HDR_LEN +
- rversion->version.len + sizeof(u16) + sizeof(u32);
- set_p9msg_hdr(inmsg, *outlen, P9_RVERSION, outmsg->tag);
+ virtio_p9_pdu_writef(pdu, "ds", 4096, VIRTIO_P9_VERSION);
+ *outlen = pdu->write_offset;
+ virtio_p9_set_reply_header(pdu, *outlen);
return;
}
static void virtio_p9_clunk(struct p9_dev *p9dev,
struct p9_pdu *pdu, u32 *outlen)
{
- struct p9_msg *inmsg = pdu->in_iov[0].iov_base;
- struct p9_msg *outmsg = pdu->out_iov[0].iov_base;
- struct p9_tclunk *tclunk = (struct p9_tclunk *)outmsg->msg;
+ u32 fid;
- close_fid(p9dev, tclunk->fid);
-
- *outlen = VIRTIO_P9_HDR_LEN;
- set_p9msg_hdr(inmsg, *outlen, P9_RCLUNK, outmsg->tag);
+ virtio_p9_pdu_readf(pdu, "d", &fid);
+ close_fid(p9dev, fid);
+ *outlen = pdu->write_offset;
+ virtio_p9_set_reply_header(pdu, *outlen);
return;
}
static void virtio_p9_open(struct p9_dev *p9dev,
struct p9_pdu *pdu, u32 *outlen)
{
+ u8 mode;
+ u32 fid;
struct stat st;
- struct p9_msg *inmsg = pdu->in_iov[0].iov_base;
- struct p9_msg *outmsg = pdu->out_iov[0].iov_base;
- struct p9_topen *topen = (struct p9_topen *)outmsg->msg;
- struct p9_ropen *ropen = (struct p9_ropen *)inmsg->msg;
- struct p9_fid *new_fid = &p9dev->fids[topen->fid];
+ struct p9_qid qid;
+ struct p9_fid *new_fid;
+
+
+ virtio_p9_pdu_readf(pdu, "db", &fid, &mode);
+ new_fid = &p9dev->fids[fid];
if (lstat(new_fid->abs_path, &st) < 0)
goto err_out;
- st2qid(&st, &ropen->qid);
- ropen->iounit = 0;
+ st2qid(&st, &qid);
if (new_fid->is_dir) {
new_fid->dir = opendir(new_fid->abs_path);
@@ -281,12 +201,14 @@ static void virtio_p9_open(struct p9_dev *p9dev,
goto err_out;
} else {
new_fid->fd = open(new_fid->abs_path,
- omode2uflags(topen->mode) | O_NOFOLLOW);
+ omode2uflags(mode) | O_NOFOLLOW);
if (new_fid->fd < 0)
goto err_out;
}
- *outlen = VIRTIO_P9_HDR_LEN + sizeof(*ropen);
- set_p9msg_hdr(inmsg, *outlen, P9_ROPEN, outmsg->tag);
+ virtio_p9_pdu_writef(pdu, "Qd", &qid, 0);
+
+ *outlen = pdu->write_offset;
+ virtio_p9_set_reply_header(pdu, *outlen);
return;
err_out:
virtio_p9_error_reply(p9dev, pdu, errno, outlen);
@@ -298,39 +220,33 @@ static void virtio_p9_create(struct p9_dev *p9dev,
{
u8 mode;
u32 perm;
+ char *name;
+ u32 fid_val;
struct stat st;
- struct p9_msg *inmsg = pdu->in_iov[0].iov_base;
- struct p9_msg *outmsg = pdu->out_iov[0].iov_base;
- struct p9_tcreate *tcreate = (struct p9_tcreate *)outmsg->msg;
- struct p9_rcreate *rcreate = (struct p9_rcreate *)inmsg->msg;
- struct p9_fid *fid = &p9dev->fids[tcreate->fid];
-
-
- rcreate->iounit = 0;
-
- /* Get last byte of the variable length struct */
- mode = *((u8 *)outmsg + outmsg->size - 1);
- perm = *(u32 *)((u8 *)outmsg + outmsg->size - 5);
+ struct p9_qid qid;
+ struct p9_fid *fid;
- sprintf(fid->path, "%s/%.*s", fid->path, tcreate->name.len, (char *)&tcreate->name.str);
+ virtio_p9_pdu_readf(pdu, "dsdb", &fid_val, &name, &perm, &mode);
+ fid = &p9dev->fids[fid_val];
- close_fid(p9dev, tcreate->fid);
+ sprintf(fid->path, "%s/%.*s", fid->path, strlen(name), name);
+ close_fid(p9dev, fid_val);
if (perm & P9_DMDIR) {
mkdir(fid->abs_path, perm & 0xFFFF);
fid->dir = opendir(fid->abs_path);
fid->is_dir = 1;
} else {
- fid->fd = open(fid->abs_path, omode2uflags(mode) | O_CREAT, 0777);
+ fid->fd = open(fid->abs_path,
+ omode2uflags(mode) | O_CREAT, 0777);
}
-
if (lstat(fid->abs_path, &st) < 0)
goto err_out;
- st2qid(&st, &rcreate->qid);
-
- *outlen = VIRTIO_P9_HDR_LEN + sizeof(*rcreate);
- set_p9msg_hdr(inmsg, *outlen, P9_RCREATE, outmsg->tag);
+ st2qid(&st, &qid);
+ virtio_p9_pdu_writef(pdu, "Qd", &qid, 0);
+ *outlen = pdu->write_offset;
+ virtio_p9_set_reply_header(pdu, *outlen);
return;
err_out:
virtio_p9_error_reply(p9dev, pdu, errno, outlen);
@@ -341,45 +257,57 @@ static void virtio_p9_walk(struct p9_dev *p9dev,
struct p9_pdu *pdu, u32 *outlen)
{
u8 i;
- struct p9_msg *inmsg = pdu->in_iov[0].iov_base;
- struct p9_msg *outmsg = pdu->out_iov[0].iov_base;
- struct p9_twalk *twalk = (struct p9_twalk *)outmsg->msg;
- struct p9_rwalk *rwalk = (struct p9_rwalk *)inmsg->msg;
- struct p9_str *str = twalk->wnames;
- struct p9_fid *new_fid = &p9dev->fids[twalk->newfid];
+ u16 nwqid;
+ char *str;
+ u16 nwname;
+ u32 fid_val;
+ u32 newfid_val;
+ struct p9_qid wqid;
+ struct p9_fid *new_fid;
+
+ virtio_p9_pdu_readf(pdu, "ddw", &fid_val, &newfid_val, &nwname);
+ new_fid = &p9dev->fids[newfid_val];
- rwalk->nwqid = 0;
- if (twalk->nwname) {
- struct p9_fid *fid = &p9dev->fids[twalk->fid];
+ nwqid = 0;
+ if (nwname) {
+ struct p9_fid *fid = &p9dev->fids[fid_val];
- for (i = 0; i < twalk->nwname; i++) {
+ /* skip the space for count */
+ pdu->write_offset += sizeof(u16);
+ for (i = 0; i < nwname; i++) {
+ struct stat st;
char tmp[PATH_MAX] = {0};
char full_path[PATH_MAX];
- struct stat st;
+
+ virtio_p9_pdu_readf(pdu, "s", &str);
/* Format the new path we're 'walk'ing into */
- sprintf(tmp, "%s/%.*s", fid->path,
- str->len, (char *)&str->str);
+ sprintf(tmp, "%s/%.*s", fid->path, strlen(str), str);
if (lstat(rel_to_abs(p9dev, tmp, full_path), &st) < 0)
goto err_out;
- st2qid(&st, &rwalk->wqids[i]);
+ st2qid(&st, &wqid);
new_fid->is_dir = S_ISDIR(st.st_mode);
strcpy(new_fid->path, tmp);
- new_fid->fid = twalk->newfid;
- rwalk->nwqid++;
+ new_fid->fid = newfid_val;
+ nwqid++;
+ virtio_p9_pdu_writef(pdu, "Q", &wqid);
}
} else {
- new_fid->is_dir = p9dev->fids[twalk->fid].is_dir;
- strcpy(new_fid->path, p9dev->fids[twalk->fid].path);
- new_fid->fid = twalk->newfid;
+ /*
+ * update write_offset so our outlen get correct value
+ */
+ pdu->write_offset += sizeof(u16);
+ new_fid->is_dir = p9dev->fids[fid_val].is_dir;
+ strcpy(new_fid->path, p9dev->fids[fid_val].path);
+ new_fid->fid = newfid_val;
}
-
- *outlen = VIRTIO_P9_HDR_LEN + sizeof(u16) +
- sizeof(struct p9_qid)*rwalk->nwqid;
- set_p9msg_hdr(inmsg, *outlen, P9_RWALK, outmsg->tag);
+ *outlen = pdu->write_offset;
+ pdu->write_offset = VIRTIO_P9_HDR_LEN;
+ virtio_p9_pdu_writef(pdu, "d", nwqid);
+ virtio_p9_set_reply_header(pdu, *outlen);
return;
err_out:
virtio_p9_error_reply(p9dev, pdu, errno, outlen);
@@ -390,12 +318,15 @@ static void virtio_p9_attach(struct p9_dev *p9dev,
struct p9_pdu *pdu, u32 *outlen)
{
u32 i;
+ u32 fid_val;
+ u32 afid;
+ char *uname;
+ char *aname;
struct stat st;
+ struct p9_qid qid;
struct p9_fid *fid;
- struct p9_msg *inmsg = pdu->in_iov[0].iov_base;
- struct p9_msg *outmsg = pdu->out_iov[0].iov_base;
- struct p9_rattach *rattach = (struct p9_rattach *)inmsg->msg;
- struct p9_tattach *tattach = (struct p9_tattach *)outmsg->msg;
+
+ virtio_p9_pdu_readf(pdu, "ddss", &fid_val, &afid, &uname, &aname);
/* Reset everything */
for (i = 0; i < VIRTIO_P9_MAX_FID; i++)
@@ -404,103 +335,106 @@ static void virtio_p9_attach(struct p9_dev *p9dev,
if (lstat(p9dev->root_dir, &st) < 0)
goto err_out;
- st2qid(&st, &rattach->qid);
+ st2qid(&st, &qid);
- fid = &p9dev->fids[tattach->fid];
- fid->fid = tattach->fid;
+ fid = &p9dev->fids[fid_val];
+ fid->fid = fid_val;
fid->is_dir = 1;
strcpy(fid->path, "/");
- *outlen = VIRTIO_P9_HDR_LEN + sizeof(*rattach);
- set_p9msg_hdr(inmsg, *outlen, P9_RATTACH, outmsg->tag);
+ virtio_p9_pdu_writef(pdu, "Q", &qid);
+ *outlen = pdu->write_offset;
+ virtio_p9_set_reply_header(pdu, *outlen);
return;
err_out:
virtio_p9_error_reply(p9dev, pdu, errno, outlen);
return;
}
-static u32 virtio_p9_fill_stat(struct p9_dev *p9dev, const char *name,
- struct stat *st, struct p9_rstat *rstat)
+static void virtio_p9_fill_stat(struct p9_dev *p9dev, const char *name,
+ struct stat *st, struct p9_wstat *wstat)
{
- struct p9_str *str;
-
- rstat->stat.type = 0;
- rstat->stat.dev = 0;
- st2qid(st, &rstat->stat.qid);
- rstat->stat.mode = st->st_mode;
- rstat->stat.length = st->st_size;
+ wstat->type = 0;
+ wstat->dev = 0;
+ st2qid(st, &wstat->qid);
+ wstat->mode = st->st_mode;
+ wstat->length = st->st_size;
if (S_ISDIR(st->st_mode)) {
- rstat->stat.length = 0;
- rstat->stat.mode |= P9_DMDIR;
+ wstat->length = 0;
+ wstat->mode |= P9_DMDIR;
}
- rstat->stat.atime = st->st_atime;
- rstat->stat.mtime = st->st_mtime;
-
- str = (struct p9_str *)&rstat->stat.name;
- str->len = strlen(name);
- memcpy(&str->str, name, str->len);
- str = (void *)str + str->len + sizeof(u16);
-
- /* TODO: Pass usernames to the client */
- str->len = 0;
- str = (void *)str + sizeof(u16);
- str->len = 0;
- str = (void *)str + sizeof(u16);
- str->len = 0;
- str = (void *)str + sizeof(u16);
-
- /*
- * We subtract a u16 here because rstat->size
- * doesn't include rstat->size itself
- */
- rstat->stat.size = (void *)str - (void *)&rstat->stat - sizeof(u16);
-
- return rstat->stat.size + sizeof(u16);
+ wstat->atime = st->st_atime;
+ wstat->mtime = st->st_mtime;
+
+ wstat->name = strdup(name);
+ wstat->uid = NULL;
+ wstat->gid = NULL;
+ wstat->muid = NULL;
+
+ /* NOTE: size shouldn't include its own length */
+ /* size[2] type[2] dev[4] qid[13] */
+ /* mode[4] atime[4] mtime[4] length[8]*/
+ /* name[s] uid[s] gid[s] muid[s] */
+ wstat->size = 2+4+13+4+4+4+8+2+2+2+2;
+ if (wstat->name)
+ wstat->size += strlen(wstat->name);
}
static void virtio_p9_read(struct p9_dev *p9dev,
struct p9_pdu *pdu, u32 *outlen)
{
- struct p9_msg *inmsg = pdu->in_iov[0].iov_base;
- struct p9_msg *outmsg = pdu->out_iov[0].iov_base;
- struct p9_tread *tread = (struct p9_tread *)outmsg->msg;
- struct p9_rread *rread = (struct p9_rread *)inmsg->msg;
- struct p9_rstat *rstat = (struct p9_rstat *)pdu->in_iov[1].iov_base;
- struct p9_fid *fid = &p9dev->fids[tread->fid];
+ u64 offset;
+ u32 fid_val;
+ u32 count, rcount;
struct stat st;
+ struct p9_fid *fid;
+ struct p9_wstat wstat;
- rread->count = 0;
-
+ rcount = 0;
+ virtio_p9_pdu_readf(pdu, "dqd", &fid_val, &offset, &count);
+ fid = &p9dev->fids[fid_val];
if (fid->is_dir) {
/* If reading a dir, fill the buffer with p9_stat entries */
- struct dirent *cur = readdir(fid->dir);
char full_path[PATH_MAX];
+ struct dirent *cur = readdir(fid->dir);
+ /* Skip the space for writing count */
+ pdu->write_offset += sizeof(u32);
while (cur) {
u32 read;
lstat(rel_to_abs(p9dev, cur->d_name, full_path), &st);
- read = virtio_p9_fill_stat(p9dev, cur->d_name,
- &st, rstat);
- rread->count += read;
- rstat = (void *)rstat + read;
+ virtio_p9_fill_stat(p9dev, cur->d_name, &st, &wstat);
+
+ read = pdu->write_offset;
+ virtio_p9_pdu_writef(pdu, "S", &wstat);
+ rcount += pdu->write_offset - read;
+
cur = readdir(fid->dir);
}
} else {
pdu->in_iov[0].iov_base += VIRTIO_P9_HDR_LEN + sizeof(u32);
pdu->in_iov[0].iov_len -= VIRTIO_P9_HDR_LEN + sizeof(u32);
pdu->in_iov_cnt = virtio_p9_update_iov_cnt(pdu->in_iov,
- tread->count,
- pdu->in_iov_cnt);
- rread->count = preadv(fid->fd, pdu->in_iov,
- pdu->in_iov_cnt, tread->offset);
- if (rread->count > tread->count)
- rread->count = tread->count;
- }
+ count,
+ pdu->in_iov_cnt);
+ rcount = preadv(fid->fd, pdu->in_iov,
+ pdu->in_iov_cnt, offset);
+ if (rcount > count)
+ rcount = count;
+ /*
+ * Update the iov_base back, so that rest of
+ * pdu_writef works correctly.
+ */
+ pdu->in_iov[0].iov_base -= VIRTIO_P9_HDR_LEN + sizeof(u32);
+ pdu->in_iov[0].iov_len += VIRTIO_P9_HDR_LEN + sizeof(u32);
- *outlen = VIRTIO_P9_HDR_LEN + sizeof(u32) + rread->count;
- set_p9msg_hdr(inmsg, *outlen, P9_RREAD, outmsg->tag);
+ }
+ pdu->write_offset = VIRTIO_P9_HDR_LEN;
+ virtio_p9_pdu_writef(pdu, "d", rcount);
+ *outlen = pdu->write_offset + rcount;
+ virtio_p9_set_reply_header(pdu, *outlen);
return;
}
@@ -508,21 +442,21 @@ static void virtio_p9_read(struct p9_dev *p9dev,
static void virtio_p9_stat(struct p9_dev *p9dev,
struct p9_pdu *pdu, u32 *outlen)
{
- u32 ret;
+ u32 fid_val;
struct stat st;
- struct p9_msg *inmsg = pdu->in_iov[0].iov_base;
- struct p9_msg *outmsg = pdu->out_iov[0].iov_base;
- struct p9_tstat *tstat = (struct p9_tstat *)outmsg->msg;
- struct p9_rstat *rstat = (struct p9_rstat *)(inmsg->msg + sizeof(u16));
- struct p9_fid *fid = &p9dev->fids[tstat->fid];
+ struct p9_fid *fid;
+ struct p9_wstat wstat;
+ virtio_p9_pdu_readf(pdu, "d", &fid_val);
+ fid = &p9dev->fids[fid_val];
if (lstat(fid->abs_path, &st) < 0)
goto err_out;
- ret = virtio_p9_fill_stat(p9dev, fid->path, &st, rstat);
+ virtio_p9_fill_stat(p9dev, fid->path, &st, &wstat);
- *outlen = VIRTIO_P9_HDR_LEN + ret + sizeof(u16);
- set_p9msg_hdr(inmsg, *outlen, P9_RSTAT, outmsg->tag);
+ virtio_p9_pdu_writef(pdu, "wS", 0, &wstat);
+ *outlen = pdu->write_offset;
+ virtio_p9_set_reply_header(pdu, *outlen);
return;
err_out:
virtio_p9_error_reply(p9dev, pdu, errno, outlen);
@@ -533,21 +467,21 @@ static void virtio_p9_wstat(struct p9_dev *p9dev,
struct p9_pdu *pdu, u32 *outlen)
{
int res = 0;
- struct p9_str *str;
- struct p9_msg *inmsg = pdu->in_iov[0].iov_base;
- struct p9_msg *outmsg = pdu->out_iov[0].iov_base;
- struct p9_twstat *twstat = (struct p9_twstat *)outmsg->msg;
- struct p9_fid *fid = &p9dev->fids[twstat->fid];
+ u32 fid_val;
+ u16 unused;
+ struct p9_fid *fid;
+ struct p9_wstat wstat;
+ virtio_p9_pdu_readf(pdu, "dwS", &fid_val, &unused, &wstat);
+ fid = &p9dev->fids[fid_val];
- if (twstat->stat.length != -1UL)
- res = ftruncate(fid->fd, twstat->stat.length);
+ if (wstat.length != -1UL)
+ res = ftruncate(fid->fd, wstat.length);
- if (twstat->stat.mode != -1U)
- chmod(fid->abs_path, twstat->stat.mode & 0xFFFF);
+ if (wstat.mode != -1U)
+ chmod(fid->abs_path, wstat.mode & 0xFFFF);
- str = (void *)&twstat->stat.name + sizeof(u16);
- if (str->len > 0) {
+ if (strlen(wstat.name) > 0) {
char new_name[PATH_MAX] = {0};
char full_path[PATH_MAX];
char *last_dir = strrchr(fid->path, '/');
@@ -556,57 +490,59 @@ static void virtio_p9_wstat(struct p9_dev *p9dev,
if (last_dir)
strncpy(new_name, fid->path, last_dir - fid->path + 1);
- memcpy(new_name + strlen(new_name), &str->str, str->len);
+ memcpy(new_name + strlen(new_name),
+ wstat.name, strlen(wstat.name));
/* fid is reused for the new file */
rename(fid->abs_path, rel_to_abs(p9dev, new_name, full_path));
sprintf(fid->path, "%s", new_name);
}
-
*outlen = VIRTIO_P9_HDR_LEN;
- set_p9msg_hdr(inmsg, *outlen, P9_RWSTAT, outmsg->tag);
-
+ virtio_p9_set_reply_header(pdu, *outlen);
return;
}
static void virtio_p9_remove(struct p9_dev *p9dev,
struct p9_pdu *pdu, u32 *outlen)
{
- struct p9_msg *inmsg = pdu->in_iov[0].iov_base;
- struct p9_msg *outmsg = pdu->out_iov[0].iov_base;
- struct p9_tremove *tremove = (struct p9_tremove *)outmsg->msg;
- struct p9_fid *fid = &p9dev->fids[tremove->fid];
+ u32 fid_val;
+ struct p9_fid *fid;
- close_fid(p9dev, tremove->fid);
+ virtio_p9_pdu_readf(pdu, "d", &fid_val);
+ fid = &p9dev->fids[fid_val];
+ close_fid(p9dev, fid_val);
if (fid->is_dir)
rmdir(fid->abs_path);
else
unlink(fid->abs_path);
*outlen = VIRTIO_P9_HDR_LEN;
- set_p9msg_hdr(inmsg, *outlen, P9_RREMOVE, outmsg->tag);
+ virtio_p9_set_reply_header(pdu, *outlen);
return;
}
static void virtio_p9_write(struct p9_dev *p9dev,
struct p9_pdu *pdu, u32 *outlen)
{
- struct p9_msg *inmsg = pdu->in_iov[0].iov_base;
- struct p9_msg *outmsg = pdu->out_iov[0].iov_base;
- struct p9_twrite *twrite = (struct p9_twrite *)outmsg->msg;
- struct p9_rwrite *rwrite = (struct p9_rwrite *)inmsg->msg;
- struct p9_fid *fid = &p9dev->fids[twrite->fid];
+ u64 offset;
+ u32 fid_val;
+ u32 count, rcount;
+ struct p9_fid *fid;
+ virtio_p9_pdu_readf(pdu, "dqd", &fid_val, &offset, &count);
+ fid = &p9dev->fids[fid_val];
- pdu->out_iov[0].iov_base += (sizeof(*outmsg) + sizeof(*twrite));
- pdu->out_iov[0].iov_len -= (sizeof(*outmsg) + sizeof(*twrite));
- pdu->out_iov_cnt = virtio_p9_update_iov_cnt(pdu->out_iov, twrite->count,
+ /* Adjust the iovec to skip the header and meta data */
+ pdu->out_iov[0].iov_base += (sizeof(struct p9_msg) +
+ sizeof(struct p9_twrite));
+ pdu->out_iov[0].iov_len -= (sizeof(struct p9_msg) +
+ sizeof(struct p9_twrite));
+ pdu->out_iov_cnt = virtio_p9_update_iov_cnt(pdu->out_iov, count,
pdu->out_iov_cnt);
- rwrite->count = pwritev(fid->fd, pdu->out_iov,
- pdu->out_iov_cnt, twrite->offset);
- *outlen = VIRTIO_P9_HDR_LEN + sizeof(u32);
- set_p9msg_hdr(inmsg, *outlen, P9_RWRITE, outmsg->tag);
-
+ rcount = pwritev(fid->fd, pdu->out_iov, pdu->out_iov_cnt, offset);
+ virtio_p9_pdu_writef(pdu, "d", rcount);
+ *outlen = pdu->write_offset;
+ virtio_p9_set_reply_header(pdu, *outlen);
return;
}
@@ -633,6 +569,9 @@ static struct p9_pdu *virtio_p9_pdu_init(struct kvm *kvm, struct virt_queue *vq)
if (!pdu)
return NULL;
+ /* skip the pdu header p9_msg */
+ pdu->read_offset = VIRTIO_P9_HDR_LEN;
+ pdu->write_offset = VIRTIO_P9_HDR_LEN;
pdu->queue_head = virt_queue__get_inout_iov(kvm, vq, pdu->in_iov,
pdu->out_iov,
&pdu->in_iov_cnt,
--
1.7.4.1
^ permalink raw reply related [flat|nested] 5+ messages in thread* Re: [PATCH] tools/kvm/9p: Add encode/decode routines for protocol data
2011-06-21 10:20 [PATCH] tools/kvm/9p: Add encode/decode routines for protocol data Aneesh Kumar K.V
@ 2011-06-24 13:47 ` Sasha Levin
2011-06-24 16:00 ` Aneesh Kumar K.V
0 siblings, 1 reply; 5+ messages in thread
From: Sasha Levin @ 2011-06-24 13:47 UTC (permalink / raw)
To: Aneesh Kumar K.V; +Cc: penberg, kvm
On Tue, 2011-06-21 at 15:50 +0530, Aneesh Kumar K.V wrote:
> The protocol data is in little-endian format.
>
> Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
> ---
> tools/kvm/Makefile | 1 +
> tools/kvm/include/kvm/virtio-9p.h | 81 ++++++-
> tools/kvm/virtio/9p-pdu.c | 237 ++++++++++++++++++
> tools/kvm/virtio/9p.c | 477 ++++++++++++++++---------------------
> 4 files changed, 526 insertions(+), 270 deletions(-)
> create mode 100644 tools/kvm/virtio/9p-pdu.c
I'm seeing this when trying to build after this patch:
cc1: warnings being treated as errors
virtio/9p.c: In function 'virtio_p9_create':
virtio/9p.c:232:2: error: field precision should have type 'int', but
argument 4 has type 'size_t'
virtio/9p.c: In function 'virtio_p9_walk':
virtio/9p.c:286:4: error: field precision should have type 'int', but
argument 4 has type 'size_t'
make: *** [virtio/9p.o] Error 1
> diff --git a/tools/kvm/Makefile b/tools/kvm/Makefile
> index d368c22..559fefc 100644
> --- a/tools/kvm/Makefile
> +++ b/tools/kvm/Makefile
> @@ -57,6 +57,7 @@ OBJS += util/parse-options.o
> OBJS += util/rbtree-interval.o
> OBJS += util/strbuf.o
> OBJS += virtio/9p.o
> +OBJS += virtio/9p-pdu.o
> OBJS += hw/vesa.o
> OBJS += hw/i8042.o
>
> diff --git a/tools/kvm/include/kvm/virtio-9p.h b/tools/kvm/include/kvm/virtio-9p.h
> index d99bf96..55f963b 100644
> --- a/tools/kvm/include/kvm/virtio-9p.h
> +++ b/tools/kvm/include/kvm/virtio-9p.h
> @@ -1,8 +1,87 @@
> #ifndef KVM__VIRTIO_9P_H
> #define KVM__VIRTIO_9P_H
> +#include "kvm/virtio-pci-dev.h"
> +#include "kvm/virtio.h"
> +#include "kvm/ioport.h"
> +#include "kvm/mutex.h"
> +#include "kvm/util.h"
> +#include "kvm/kvm.h"
> +#include "kvm/pci.h"
> +#include "kvm/threadpool.h"
> +#include "kvm/irq.h"
> +#include "kvm/ioeventfd.h"
> +
> +#include <fcntl.h>
> +#include <sys/types.h>
> +#include <sys/stat.h>
> +#include <pthread.h>
> +#include <dirent.h>
> +
> +#include <linux/virtio_ring.h>
> +#include <linux/virtio_9p.h>
> +#include <net/9p/9p.h>
> +
> +#define NUM_VIRT_QUEUES 1
> +#define VIRTQUEUE_NUM 128
> +#define VIRTIO_P9_DEFAULT_TAG "kvm_9p"
> +#define VIRTIO_P9_HDR_LEN (sizeof(u32)+sizeof(u8)+sizeof(u16))
> +#define VIRTIO_P9_MAX_FID 128
> +#define VIRTIO_P9_VERSION "9P2000"
> +#define MAX_TAG_LEN 32
> +
> +
> +struct p9_msg {
> + u32 size;
> + u8 cmd;
> + u16 tag;
> + u8 msg[0];
> +} __attribute__((packed));
> +
> +struct p9_fid {
> + u32 fid;
> + u8 is_dir;
> + char abs_path[PATH_MAX];
> + char *path;
> + DIR *dir;
> + int fd;
> +};
> +
> +struct p9_dev_job {
> + struct virt_queue *vq;
> + struct p9_dev *p9dev;
> + void *job_id;
> +};
> +
This struct isn't vertically aligned with the rest of the file.
> +struct p9_dev {
> + u8 status;
> + u8 isr;
> + u16 config_vector;
> + u32 features;
> + struct virtio_9p_config *config;
> + u16 base_addr;
> +
> + /* virtio queue */
> + u16 queue_selector;
> + struct virt_queue vqs[NUM_VIRT_QUEUES];
> + struct p9_dev_job jobs[NUM_VIRT_QUEUES];
> + struct p9_fid fids[VIRTIO_P9_MAX_FID];
> + char root_dir[PATH_MAX];
> + struct pci_device_header pci_hdr;
> +};
> +
> +struct p9_pdu {
> + u32 queue_head;
> + size_t read_offset;
> + size_t write_offset;
> + u16 out_iov_cnt;
> + u16 in_iov_cnt;
> + struct iovec in_iov[VIRTQUEUE_NUM];
> + struct iovec out_iov[VIRTQUEUE_NUM];
> +};
This struct is just isn't vertically aligned.
> struct kvm;
>
> void virtio_9p__init(struct kvm *kvm, const char *root, const char *tag_name);
> -
> +int virtio_p9_pdu_readf(struct p9_pdu *pdu, const char *fmt, ...);
> +int virtio_p9_pdu_writef(struct p9_pdu *pdu, const char *fmt, ...);
> #endif
> diff --git a/tools/kvm/virtio/9p-pdu.c b/tools/kvm/virtio/9p-pdu.c
> new file mode 100644
> index 0000000..da9f263
> --- /dev/null
> +++ b/tools/kvm/virtio/9p-pdu.c
> @@ -0,0 +1,237 @@
> +#include "kvm/virtio-9p.h"
> +
> +#include <endian.h>
> +
> +static void virtio_p9_pdu_read(struct p9_pdu *pdu, void *data, size_t size)
> +{
> + size_t len;
> + int i, copied = 0;
> + u16 iov_cnt = pdu->out_iov_cnt;
> + size_t offset = pdu->read_offset;
> + struct iovec *iov = pdu->out_iov;
> +
> + for (i = 0; i < iov_cnt && size; i++) {
> + if (offset >= iov[i].iov_len) {
> + offset -= iov[i].iov_len;
> + continue;
> + } else {
> + len = MIN(iov[i].iov_len - offset, size);
> + memcpy(data, iov[i].iov_base + offset, len);
> + size -= len;
> + data += len;
> + offset = 0;
> + copied += len;
> + }
> + }
> + pdu->read_offset += copied;
> +}
> +
> +static void virtio_p9_pdu_write(struct p9_pdu *pdu,
> + const void *data, size_t size)
> +{
> + size_t len;
> + int i, copied = 0;
> + u16 iov_cnt = pdu->in_iov_cnt;
> + size_t offset = pdu->write_offset;
> + struct iovec *iov = pdu->in_iov;
> +
> + for (i = 0; i < iov_cnt && size; i++) {
> + if (offset >= iov[i].iov_len) {
> + offset -= iov[i].iov_len;
> + continue;
> + } else {
> + len = MIN(iov[i].iov_len - offset, size);
> + memcpy(iov[i].iov_base + offset, data, len);
> + size -= len;
> + data += len;
> + offset = 0;
> + copied += len;
> + }
> + }
> + pdu->write_offset += copied;
> +}
> +
Just wondering here, can we use pipes (read/write/vmsplice) instead of a
scatter-gather list?
--
Sasha.
^ permalink raw reply [flat|nested] 5+ messages in thread* Re: [PATCH] tools/kvm/9p: Add encode/decode routines for protocol data
2011-06-24 13:47 ` Sasha Levin
@ 2011-06-24 16:00 ` Aneesh Kumar K.V
2011-06-24 23:26 ` Sasha Levin
0 siblings, 1 reply; 5+ messages in thread
From: Aneesh Kumar K.V @ 2011-06-24 16:00 UTC (permalink / raw)
To: Sasha Levin; +Cc: penberg, kvm
On Fri, 24 Jun 2011 09:47:18 -0400, Sasha Levin <levinsasha928@gmail.com> wrote:
> On Tue, 2011-06-21 at 15:50 +0530, Aneesh Kumar K.V wrote:
> > The protocol data is in little-endian format.
> >
> > Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
> > ---
> > tools/kvm/Makefile | 1 +
> > tools/kvm/include/kvm/virtio-9p.h | 81 ++++++-
> > tools/kvm/virtio/9p-pdu.c | 237 ++++++++++++++++++
> > tools/kvm/virtio/9p.c | 477 ++++++++++++++++---------------------
> > 4 files changed, 526 insertions(+), 270 deletions(-)
> > create mode 100644 tools/kvm/virtio/9p-pdu.c
>
> I'm seeing this when trying to build after this patch:
>
> cc1: warnings being treated as errors
> virtio/9p.c: In function 'virtio_p9_create':
> virtio/9p.c:232:2: error: field precision should have type 'int', but
> argument 4 has type 'size_t'
> virtio/9p.c: In function 'virtio_p9_walk':
> virtio/9p.c:286:4: error: field precision should have type 'int', but
> argument 4 has type 'size_t'
> make: *** [virtio/9p.o] Error 1
Updated the patch to fix the error
- sprintf(fid->path, "%s/%.*s", fid->path, strlen(name), name);
+ sprintf(fid->path, "%s/%.*s", fid->path, (int)strlen(name), name);
>
> > diff --git a/tools/kvm/Makefile b/tools/kvm/Makefile
> > index d368c22..559fefc 100644
> > --- a/tools/kvm/Makefile
> > +++ b/tools/kvm/Makefile
> > @@ -57,6 +57,7 @@ OBJS += util/parse-options.o
> > OBJS += util/rbtree-interval.o
> > OBJS += util/strbuf.o
> > OBJS += virtio/9p.o
> > +OBJS += virtio/9p-pdu.o
> > OBJS += hw/vesa.o
> > OBJS += hw/i8042.o
> >
> > diff --git a/tools/kvm/include/kvm/virtio-9p.h b/tools/kvm/include/kvm/virtio-9p.h
> > index d99bf96..55f963b 100644
> > --- a/tools/kvm/include/kvm/virtio-9p.h
> > +++ b/tools/kvm/include/kvm/virtio-9p.h
> > @@ -1,8 +1,87 @@
> > #ifndef KVM__VIRTIO_9P_H
> > #define KVM__VIRTIO_9P_H
> > +#include "kvm/virtio-pci-dev.h"
> > +#include "kvm/virtio.h"
> > +#include "kvm/ioport.h"
> > +#include "kvm/mutex.h"
> > +#include "kvm/util.h"
> > +#include "kvm/kvm.h"
> > +#include "kvm/pci.h"
> > +#include "kvm/threadpool.h"
> > +#include "kvm/irq.h"
> > +#include "kvm/ioeventfd.h"
> > +
> > +#include <fcntl.h>
> > +#include <sys/types.h>
> > +#include <sys/stat.h>
> > +#include <pthread.h>
> > +#include <dirent.h>
> > +
> > +#include <linux/virtio_ring.h>
> > +#include <linux/virtio_9p.h>
> > +#include <net/9p/9p.h>
> > +
> > +#define NUM_VIRT_QUEUES 1
> > +#define VIRTQUEUE_NUM 128
> > +#define VIRTIO_P9_DEFAULT_TAG "kvm_9p"
> > +#define VIRTIO_P9_HDR_LEN (sizeof(u32)+sizeof(u8)+sizeof(u16))
> > +#define VIRTIO_P9_MAX_FID 128
> > +#define VIRTIO_P9_VERSION "9P2000"
> > +#define MAX_TAG_LEN 32
> > +
> > +
> > +struct p9_msg {
> > + u32 size;
> > + u8 cmd;
> > + u16 tag;
> > + u8 msg[0];
> > +} __attribute__((packed));
> > +
> > +struct p9_fid {
> > + u32 fid;
> > + u8 is_dir;
> > + char abs_path[PATH_MAX];
> > + char *path;
> > + DIR *dir;
> > + int fd;
> > +};
> > +
> > +struct p9_dev_job {
> > + struct virt_queue *vq;
> > + struct p9_dev *p9dev;
> > + void *job_id;
> > +};
> > +
>
> This struct isn't vertically aligned with the rest of the file.
Update the patch to align them. But Do we really need to add those many
whitespace ?. Other part of kernel doesn't follow that coding style.
>
> > +struct p9_dev {
> > + u8 status;
> > + u8 isr;
> > + u16 config_vector;
> > + u32 features;
> > + struct virtio_9p_config *config;
> > + u16 base_addr;
> > +
> > + /* virtio queue */
> > + u16 queue_selector;
> > + struct virt_queue vqs[NUM_VIRT_QUEUES];
> > + struct p9_dev_job jobs[NUM_VIRT_QUEUES];
> > + struct p9_fid fids[VIRTIO_P9_MAX_FID];
> > + char root_dir[PATH_MAX];
> > + struct pci_device_header pci_hdr;
> > +};
> > +
> > +struct p9_pdu {
> > + u32 queue_head;
> > + size_t read_offset;
> > + size_t write_offset;
> > + u16 out_iov_cnt;
> > + u16 in_iov_cnt;
> > + struct iovec in_iov[VIRTQUEUE_NUM];
> > + struct iovec out_iov[VIRTQUEUE_NUM];
> > +};
>
> This struct is just isn't vertically aligned.
>
> > struct kvm;
> >
> > void virtio_9p__init(struct kvm *kvm, const char *root, const char *tag_name);
> > -
> > +int virtio_p9_pdu_readf(struct p9_pdu *pdu, const char *fmt, ...);
> > +int virtio_p9_pdu_writef(struct p9_pdu *pdu, const char *fmt, ...);
> > #endif
> > diff --git a/tools/kvm/virtio/9p-pdu.c b/tools/kvm/virtio/9p-pdu.c
> > new file mode 100644
> > index 0000000..da9f263
> > --- /dev/null
> > +++ b/tools/kvm/virtio/9p-pdu.c
> > @@ -0,0 +1,237 @@
> > +#include "kvm/virtio-9p.h"
> > +
> > +#include <endian.h>
> > +
> > +static void virtio_p9_pdu_read(struct p9_pdu *pdu, void *data, size_t size)
> > +{
> > + size_t len;
> > + int i, copied = 0;
> > + u16 iov_cnt = pdu->out_iov_cnt;
> > + size_t offset = pdu->read_offset;
> > + struct iovec *iov = pdu->out_iov;
> > +
> > + for (i = 0; i < iov_cnt && size; i++) {
> > + if (offset >= iov[i].iov_len) {
> > + offset -= iov[i].iov_len;
> > + continue;
> > + } else {
> > + len = MIN(iov[i].iov_len - offset, size);
> > + memcpy(data, iov[i].iov_base + offset, len);
> > + size -= len;
> > + data += len;
> > + offset = 0;
> > + copied += len;
> > + }
> > + }
> > + pdu->read_offset += copied;
> > +}
> > +
> > +static void virtio_p9_pdu_write(struct p9_pdu *pdu,
> > + const void *data, size_t size)
> > +{
> > + size_t len;
> > + int i, copied = 0;
> > + u16 iov_cnt = pdu->in_iov_cnt;
> > + size_t offset = pdu->write_offset;
> > + struct iovec *iov = pdu->in_iov;
> > +
> > + for (i = 0; i < iov_cnt && size; i++) {
> > + if (offset >= iov[i].iov_len) {
> > + offset -= iov[i].iov_len;
> > + continue;
> > + } else {
> > + len = MIN(iov[i].iov_len - offset, size);
> > + memcpy(iov[i].iov_base + offset, data, len);
> > + size -= len;
> > + data += len;
> > + offset = 0;
> > + copied += len;
> > + }
> > + }
> > + pdu->write_offset += copied;
> > +}
> > +
>
> Just wondering here, can we use pipes (read/write/vmsplice) instead of a
> scatter-gather list?
Can you elaborate on this. The function is to encode/decode data out of
protocol buffer.
-aneesh
^ permalink raw reply [flat|nested] 5+ messages in thread* Re: [PATCH] tools/kvm/9p: Add encode/decode routines for protocol data
2011-06-24 16:00 ` Aneesh Kumar K.V
@ 2011-06-24 23:26 ` Sasha Levin
2011-06-28 6:39 ` Aneesh Kumar K.V
0 siblings, 1 reply; 5+ messages in thread
From: Sasha Levin @ 2011-06-24 23:26 UTC (permalink / raw)
To: Aneesh Kumar K.V; +Cc: penberg, kvm
On Fri, 2011-06-24 at 21:30 +0530, Aneesh Kumar K.V wrote:
> On Fri, 24 Jun 2011 09:47:18 -0400, Sasha Levin <levinsasha928@gmail.com> wrote:
> > On Tue, 2011-06-21 at 15:50 +0530, Aneesh Kumar K.V wrote:
> > > +static void virtio_p9_pdu_read(struct p9_pdu *pdu, void *data, size_t size)
> > > +{
> > > + size_t len;
> > > + int i, copied = 0;
> > > + u16 iov_cnt = pdu->out_iov_cnt;
> > > + size_t offset = pdu->read_offset;
> > > + struct iovec *iov = pdu->out_iov;
> > > +
> > > + for (i = 0; i < iov_cnt && size; i++) {
> > > + if (offset >= iov[i].iov_len) {
> > > + offset -= iov[i].iov_len;
> > > + continue;
> > > + } else {
> > > + len = MIN(iov[i].iov_len - offset, size);
> > > + memcpy(data, iov[i].iov_base + offset, len);
> > > + size -= len;
> > > + data += len;
> > > + offset = 0;
> > > + copied += len;
> > > + }
> > > + }
> > > + pdu->read_offset += copied;
> > > +}
> > > +
> > > +static void virtio_p9_pdu_write(struct p9_pdu *pdu,
> > > + const void *data, size_t size)
> > > +{
> > > + size_t len;
> > > + int i, copied = 0;
> > > + u16 iov_cnt = pdu->in_iov_cnt;
> > > + size_t offset = pdu->write_offset;
> > > + struct iovec *iov = pdu->in_iov;
> > > +
> > > + for (i = 0; i < iov_cnt && size; i++) {
> > > + if (offset >= iov[i].iov_len) {
> > > + offset -= iov[i].iov_len;
> > > + continue;
> > > + } else {
> > > + len = MIN(iov[i].iov_len - offset, size);
> > > + memcpy(iov[i].iov_base + offset, data, len);
> > > + size -= len;
> > > + data += len;
> > > + offset = 0;
> > > + copied += len;
> > > + }
> > > + }
> > > + pdu->write_offset += copied;
> > > +}
> > > +
> >
> > Just wondering here, can we use pipes (read/write/vmsplice) instead of a
> > scatter-gather list?
>
> Can you elaborate on this. The function is to encode/decode data out of
> protocol buffer.
I was just thinking about storing the data in a pipe instead of a
scatter-gather list.
This would turn virtio_p9_pdu_read() into a simple wrapper for read()
from a pipe and virtio_p9_pdu_write() into a wrapper for write().
Something like this:
void virtio_9p__init(struct kvm *kvm, const char *root, const char
*tag_name)
{
[...]
pipe(p9_pipe);
[...]
}
static void virtio_p9_pdu_read(struct p9_pdu *pdu, void *data, size_t
size)
{
read(p9_pipe[0], data, size);
}
static void virtio_p9_pdu_write(struct p9_pdu *pdu, const void *data,
size_t size)
{
write(p9_pipe[1], data, size);
}
--
Sasha.
^ permalink raw reply [flat|nested] 5+ messages in thread* Re: [PATCH] tools/kvm/9p: Add encode/decode routines for protocol data
2011-06-24 23:26 ` Sasha Levin
@ 2011-06-28 6:39 ` Aneesh Kumar K.V
0 siblings, 0 replies; 5+ messages in thread
From: Aneesh Kumar K.V @ 2011-06-28 6:39 UTC (permalink / raw)
To: Sasha Levin; +Cc: penberg, kvm
On Fri, 24 Jun 2011 19:26:48 -0400, Sasha Levin <levinsasha928@gmail.com> wrote:
> On Fri, 2011-06-24 at 21:30 +0530, Aneesh Kumar K.V wrote:
> > On Fri, 24 Jun 2011 09:47:18 -0400, Sasha Levin <levinsasha928@gmail.com> wrote:
> > > On Tue, 2011-06-21 at 15:50 +0530, Aneesh Kumar K.V wrote:
> > > > +static void virtio_p9_pdu_read(struct p9_pdu *pdu, void *data, size_t size)
> > > > +{
> > > > + size_t len;
> > > > + int i, copied = 0;
> > > > + u16 iov_cnt = pdu->out_iov_cnt;
> > > > + size_t offset = pdu->read_offset;
> > > > + struct iovec *iov = pdu->out_iov;
> > > > +
> > > > + for (i = 0; i < iov_cnt && size; i++) {
> > > > + if (offset >= iov[i].iov_len) {
> > > > + offset -= iov[i].iov_len;
> > > > + continue;
> > > > + } else {
> > > > + len = MIN(iov[i].iov_len - offset, size);
> > > > + memcpy(data, iov[i].iov_base + offset, len);
> > > > + size -= len;
> > > > + data += len;
> > > > + offset = 0;
> > > > + copied += len;
> > > > + }
> > > > + }
> > > > + pdu->read_offset += copied;
> > > > +}
> > > > +
> > > > +static void virtio_p9_pdu_write(struct p9_pdu *pdu,
> > > > + const void *data, size_t size)
> > > > +{
> > > > + size_t len;
> > > > + int i, copied = 0;
> > > > + u16 iov_cnt = pdu->in_iov_cnt;
> > > > + size_t offset = pdu->write_offset;
> > > > + struct iovec *iov = pdu->in_iov;
> > > > +
> > > > + for (i = 0; i < iov_cnt && size; i++) {
> > > > + if (offset >= iov[i].iov_len) {
> > > > + offset -= iov[i].iov_len;
> > > > + continue;
> > > > + } else {
> > > > + len = MIN(iov[i].iov_len - offset, size);
> > > > + memcpy(iov[i].iov_base + offset, data, len);
> > > > + size -= len;
> > > > + data += len;
> > > > + offset = 0;
> > > > + copied += len;
> > > > + }
> > > > + }
> > > > + pdu->write_offset += copied;
> > > > +}
> > > > +
> > >
> > > Just wondering here, can we use pipes (read/write/vmsplice) instead of a
> > > scatter-gather list?
> >
> > Can you elaborate on this. The function is to encode/decode data out of
> > protocol buffer.
>
> I was just thinking about storing the data in a pipe instead of a
> scatter-gather list.
We are building that scatter-gather list from vring. I am not clear
how to push that to pipe ? ie we have iovec in vring and how do i
store that to a pipe ?
>
> This would turn virtio_p9_pdu_read() into a simple wrapper for read()
> from a pipe and virtio_p9_pdu_write() into a wrapper for write().
>
> Something like this:
>
> void virtio_9p__init(struct kvm *kvm, const char *root, const char
> *tag_name)
> {
> [...]
> pipe(p9_pipe);
> [...]
> }
>
> static void virtio_p9_pdu_read(struct p9_pdu *pdu, void *data, size_t
> size)
> {
> read(p9_pipe[0], data, size);
> }
>
> static void virtio_p9_pdu_write(struct p9_pdu *pdu, const void *data,
> size_t size)
> {
> write(p9_pipe[1], data, size);
> }
>
But why ? what we currently have is a simple memcpy, why replace that
with syscall read/write ?
-aneesh
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2011-06-28 6:39 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-06-21 10:20 [PATCH] tools/kvm/9p: Add encode/decode routines for protocol data Aneesh Kumar K.V
2011-06-24 13:47 ` Sasha Levin
2011-06-24 16:00 ` Aneesh Kumar K.V
2011-06-24 23:26 ` Sasha Levin
2011-06-28 6:39 ` Aneesh Kumar K.V
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox