diff mbox

[5/5] tools/kvm/9p: Simplify the handler

Message ID 1308419348-31934-5-git-send-email-aneesh.kumar@linux.vnet.ibm.com (mailing list archive)
State New, archived
Headers show

Commit Message

Aneesh Kumar K.V June 18, 2011, 5:49 p.m. UTC
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
---
 tools/kvm/include/net/9p/9p.h |    1 -
 tools/kvm/virtio/9p.c         |  261 +++++++++++++++++++++++------------------
 2 files changed, 147 insertions(+), 115 deletions(-)

Comments

Sasha Levin June 18, 2011, 6:51 p.m. UTC | #1
On Sat, 2011-06-18 at 23:19 +0530, Aneesh Kumar K.V wrote:
> Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
> ---
>  tools/kvm/include/net/9p/9p.h |    1 -
>  tools/kvm/virtio/9p.c         |  261 +++++++++++++++++++++++------------------
>  2 files changed, 147 insertions(+), 115 deletions(-)

After applying the patches (within a 9p mounted dir):

 # mkdir new_dir
 # cp 10MB new_dir/
cp: cannot create regular file `new_dir/10MB': No such file or directory

> diff --git a/tools/kvm/include/net/9p/9p.h b/tools/kvm/include/net/9p/9p.h
> index cc11592..61ecff3 100644
> --- a/tools/kvm/include/net/9p/9p.h
> +++ b/tools/kvm/include/net/9p/9p.h
> @@ -635,7 +635,6 @@ struct p9_twrite {
>  	u32 fid;
>  	u64 offset;
>  	u32 count;
> -	u8 *data;
>  };
>  
>  struct p9_rwrite {
> diff --git a/tools/kvm/virtio/9p.c b/tools/kvm/virtio/9p.c
> index ef2fbaf..f2b9299 100644
> --- a/tools/kvm/virtio/9p.c
> +++ b/tools/kvm/virtio/9p.c
> @@ -67,6 +67,15 @@ struct p9_dev {
>  	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,
>  			      const char *path, char *abs_path)
> @@ -184,12 +193,12 @@ static void set_p9msg_hdr(struct p9_msg *msg, u32 size, u8 cmd, u16 tag)
>  	};
>  }
>  
> -static bool virtio_p9_version(struct p9_dev *p9dev, struct p9_msg *msg,
> -			      u32 len, struct iovec *iov,
> -			      int outiovcnt, int iniovcnt, u32 *outlen)
> +static bool virtio_p9_version(struct p9_dev *p9dev,
> +			      struct p9_pdu *pdu, u32 *outlen)
>  {
> -	struct p9_msg *outmsg = iov[0].iov_base;
> -	struct p9_rversion *rversion = (struct p9_rversion *)outmsg->msg;
> +	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);
> @@ -197,35 +206,35 @@ static bool virtio_p9_version(struct p9_dev *p9dev, struct p9_msg *msg,
>  
>  	*outlen = VIRTIO_P9_HDR_LEN +
>  		rversion->version.len + sizeof(u16) + sizeof(u32);
> -	set_p9msg_hdr(outmsg, *outlen, P9_RVERSION, msg->tag);
> +	set_p9msg_hdr(inmsg, *outlen, P9_RVERSION, outmsg->tag);
>  
>  	return true;
>  }
>  
> -static bool virtio_p9_clunk(struct p9_dev *p9dev, struct p9_msg *msg,
> -			    u32 len, struct iovec *iov,
> -			    int outiovcnt, int iniovcnt, u32 *outlen)
> +static bool virtio_p9_clunk(struct p9_dev *p9dev,
> +			    struct p9_pdu *pdu, u32 *outlen)
>  {
> -	struct p9_msg *outmsg = iov[0].iov_base;
> -	struct p9_tclunk *tclunk = (struct p9_tclunk *)msg->msg;
> +	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;
>  
>  	close_fid(p9dev, tclunk->fid);
>  
>  	*outlen = VIRTIO_P9_HDR_LEN;
> -	set_p9msg_hdr(outmsg, *outlen, P9_RCLUNK, msg->tag);
> +	set_p9msg_hdr(inmsg, *outlen, P9_RCLUNK, outmsg->tag);
>  
>  	return true;
>  }
>  
> -static bool virtio_p9_open(struct p9_dev *p9dev, struct p9_msg *msg,
> -			   u32 len, struct iovec *iov,
> -			   int outiovcnt, int iniovcnt, u32 *outlen)
> +static bool virtio_p9_open(struct p9_dev *p9dev,
> +			   struct p9_pdu *pdu, u32 *outlen)
>  {
> -	struct p9_msg *outmsg	= iov[0].iov_base;
> -	struct p9_topen *topen	= (struct p9_topen *)msg->msg;
> -	struct p9_ropen *ropen	= (struct p9_ropen *)outmsg->msg;
> -	struct p9_fid *new_fid	= &p9dev->fids[topen->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];
>  
>  	if (lstat(new_fid->abs_path, &st) < 0)
>  		return false;
> @@ -239,28 +248,29 @@ static bool virtio_p9_open(struct p9_dev *p9dev, struct p9_msg *msg,
>  		new_fid->fd	= open(new_fid->abs_path, omode2uflags(topen->mode));
>  
>  	*outlen = VIRTIO_P9_HDR_LEN + sizeof(*ropen);
> -	set_p9msg_hdr(outmsg, *outlen, P9_ROPEN, msg->tag);
> +	set_p9msg_hdr(inmsg, *outlen, P9_ROPEN, outmsg->tag);
>  
>  	return true;
>  }
>  
> -static bool virtio_p9_create(struct p9_dev *p9dev, struct p9_msg *msg,
> -			     u32 len, struct iovec *iov,
> -			     int outiovcnt, int iniovcnt, u32 *outlen)
> +static bool virtio_p9_create(struct p9_dev *p9dev,
> +			     struct p9_pdu *pdu, u32 *outlen)
>  {
> -	struct p9_msg *outmsg		= iov[0].iov_base;
> -	struct p9_tcreate *tcreate	= (struct p9_tcreate *)msg->msg;
> -	struct p9_rcreate *rcreate	= (struct p9_rcreate *)outmsg->msg;
> -	struct p9_fid *fid		= &p9dev->fids[tcreate->fid];
> -	struct stat st;
>  	u8 mode;
>  	u32 perm;
> +	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 *)msg + msg->size - 1);
> -	perm = *(u32 *)((u8 *)msg + msg->size - 5);
> +	mode = *((u8 *)outmsg + outmsg->size - 1);
> +	perm = *(u32 *)((u8 *)outmsg + outmsg->size - 5);
>  
>  	sprintf(fid->path, "%s/%.*s", fid->path, tcreate->name.len, (char *)&tcreate->name.str);
>  
> @@ -280,21 +290,22 @@ static bool virtio_p9_create(struct p9_dev *p9dev, struct p9_msg *msg,
>  	st2qid(&st, &rcreate->qid);
>  
>  	*outlen = VIRTIO_P9_HDR_LEN + sizeof(*rcreate);
> -	set_p9msg_hdr(outmsg, *outlen, P9_RCREATE, msg->tag);
> +	set_p9msg_hdr(inmsg, *outlen, P9_RCREATE, outmsg->tag);
>  
>  	return true;
>  }
>  
> -static bool virtio_p9_walk(struct p9_dev *p9dev, struct p9_msg *msg,
> -			   u32 len, struct iovec *iov,
> -			   int outiovcnt, int iniovcnt, u32 *outlen)
> +static bool virtio_p9_walk(struct p9_dev *p9dev,
> +			   struct p9_pdu *pdu, u32 *outlen)
>  {
> -	struct p9_msg *outmsg	= iov[0].iov_base;
> -	struct p9_twalk *twalk	= (struct p9_twalk *)msg->msg;
> -	struct p9_rwalk *rwalk	= (struct p9_rwalk *)outmsg->msg;
> +	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];
> -	u8 i;
> +
>  
>  	rwalk->nwqid = 0;
>  	if (twalk->nwname) {
> @@ -306,7 +317,8 @@ static bool virtio_p9_walk(struct p9_dev *p9dev, struct p9_msg *msg,
>  			struct stat st;
>  
>  			/* 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,
> +				str->len, (char *)&str->str);
>  
>  			if (lstat(rel_to_abs(p9dev, tmp, full_path), &st) < 0)
>  				break;
> @@ -323,22 +335,23 @@ static bool virtio_p9_walk(struct p9_dev *p9dev, struct p9_msg *msg,
>  		new_fid->fid	= twalk->newfid;
>  	}
>  
> -	*outlen = VIRTIO_P9_HDR_LEN + sizeof(u16) + sizeof(struct p9_qid) * rwalk->nwqid;
> -	set_p9msg_hdr(outmsg, *outlen, P9_RWALK, msg->tag);
> +	*outlen = VIRTIO_P9_HDR_LEN + sizeof(u16) +
> +		sizeof(struct p9_qid)*rwalk->nwqid;
> +	set_p9msg_hdr(inmsg, *outlen, P9_RWALK, outmsg->tag);
>  
>  	return true;
>  }
>  
> -static bool virtio_p9_attach(struct p9_dev *p9dev, struct p9_msg *msg,
> -			     u32 len, struct iovec *iov,
> -			     int outiovcnt, int iniovcnt, u32 *outlen)
> +static bool virtio_p9_attach(struct p9_dev *p9dev,
> +			     struct p9_pdu *pdu, u32 *outlen)
>  {
> -	struct p9_msg *outmsg = iov[0].iov_base;
> -	struct p9_rattach *rattach = (struct p9_rattach *)outmsg->msg;
> -	struct p9_tattach *tattach = (struct p9_tattach *)msg->msg;
> +	u32 i;
>  	struct stat st;
>  	struct p9_fid *fid;
> -	u32 i;
> +	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;
>  
>  	/* Reset everything */
>  	for (i = 0; i < VIRTIO_P9_MAX_FID; i++)
> @@ -355,7 +368,7 @@ static bool virtio_p9_attach(struct p9_dev *p9dev, struct p9_msg *msg,
>  	strcpy(fid->path, "/");
>  
>  	*outlen = VIRTIO_P9_HDR_LEN + sizeof(*rattach);
> -	set_p9msg_hdr(outmsg, *outlen, P9_RATTACH, msg->tag);
> +	set_p9msg_hdr(inmsg, *outlen, P9_RATTACH, outmsg->tag);
>  
>  	return true;
>  }
> @@ -400,14 +413,14 @@ static u32 virtio_p9_fill_stat(struct p9_dev *p9dev, const char *name,
>  	return rstat->stat.size + sizeof(u16);
>  }
>  
> -static bool virtio_p9_read(struct p9_dev *p9dev, struct p9_msg *msg,
> -			   u32 len, struct iovec *iov,
> -			   int outiovcnt, int iniovcnt, u32 *outlen)
> +static bool virtio_p9_read(struct p9_dev *p9dev,
> +			   struct p9_pdu *pdu, u32 *outlen)
>  {
> -	struct p9_msg *outmsg	= iov[0].iov_base;
> -	struct p9_tread *tread	= (struct p9_tread *)msg->msg;
> -	struct p9_rread *rread	= (struct p9_rread *)outmsg->msg;
> -	struct p9_rstat *rstat	= (struct p9_rstat *)iov[1].iov_base;
> +	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];
>  	struct stat st;
>  
> @@ -429,29 +442,30 @@ static bool virtio_p9_read(struct p9_dev *p9dev, struct p9_msg *msg,
>  			cur = readdir(fid->dir);
>  		}
>  	} else {
> -		iov[0].iov_base += VIRTIO_P9_HDR_LEN + sizeof(u32);
> -		iov[0].iov_len -= VIRTIO_P9_HDR_LEN + sizeof(u32);
> -		rread->count = preadv(fid->fd, iov, iniovcnt, tread->offset);
> +		pdu->in_iov[0].iov_base += VIRTIO_P9_HDR_LEN + sizeof(u32);
> +		pdu->in_iov[0].iov_len -= VIRTIO_P9_HDR_LEN + sizeof(u32);
> +		rread->count = preadv(fid->fd, pdu->in_iov,
> +				      pdu->in_iov_cnt, tread->offset);
>  		if (rread->count > tread->count)
>  			rread->count = tread->count;
>  	}
>  
>  	*outlen = VIRTIO_P9_HDR_LEN + sizeof(u32) + rread->count;
> -	set_p9msg_hdr(outmsg, *outlen, P9_RREAD, msg->tag);
> +	set_p9msg_hdr(inmsg, *outlen, P9_RREAD, outmsg->tag);
>  
>  	return true;
>  }
>  
> -static bool virtio_p9_stat(struct p9_dev *p9dev, struct p9_msg *msg,
> -			   u32 len, struct iovec *iov,
> -			   int outiovcnt, int iniovcnt, u32 *outlen)
> +static bool virtio_p9_stat(struct p9_dev *p9dev,
> +			   struct p9_pdu *pdu, u32 *outlen)
>  {
> -	struct p9_msg *outmsg = iov[0].iov_base;
> -	struct p9_tstat *tstat = (struct p9_tstat *)msg->msg;
> -	struct p9_rstat *rstat = (struct p9_rstat *)(outmsg->msg + sizeof(u16));
> +	u32 ret;
>  	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];
> -	u32 ret;
>  
>  	if (lstat(fid->abs_path, &st) < 0)
>  		return false;
> @@ -459,19 +473,20 @@ static bool virtio_p9_stat(struct p9_dev *p9dev, struct p9_msg *msg,
>  	ret = virtio_p9_fill_stat(p9dev, fid->path, &st, rstat);
>  
>  	*outlen = VIRTIO_P9_HDR_LEN + ret + sizeof(u16);
> -	set_p9msg_hdr(outmsg, *outlen, P9_RSTAT, msg->tag);
> +	set_p9msg_hdr(inmsg, *outlen, P9_RSTAT, outmsg->tag);
>  	return true;
>  }
>  
> -static bool virtio_p9_wstat(struct p9_dev *p9dev, struct p9_msg *msg,
> -			    u32 len, struct iovec *iov,
> -			    int outiovcnt, int iniovcnt, u32 *outlen)
> +static bool virtio_p9_wstat(struct p9_dev *p9dev,
> +			    struct p9_pdu *pdu, u32 *outlen)
>  {
> -	struct p9_msg *outmsg = iov[0].iov_base;
> -	struct p9_twstat *twstat = (struct p9_twstat *)msg->msg;
> +	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];
> -	int res = 0;
> +
>  
>  	if (twstat->stat.length != -1UL)
>  		res = ftruncate(fid->fd, twstat->stat.length);
> @@ -497,17 +512,17 @@ static bool virtio_p9_wstat(struct p9_dev *p9dev, struct p9_msg *msg,
>  	}
>  
>  	*outlen = VIRTIO_P9_HDR_LEN;
> -	set_p9msg_hdr(outmsg, *outlen, P9_RWSTAT, msg->tag);
> +	set_p9msg_hdr(inmsg, *outlen, P9_RWSTAT, outmsg->tag);
>  
>  	return res == 0;
>  }
>  
> -static bool virtio_p9_remove(struct p9_dev *p9dev, struct p9_msg *msg,
> -			     u32 len, struct iovec *iov,
> -			     int outiovcnt, int iniovcnt, u32 *outlen)
> +static bool virtio_p9_remove(struct p9_dev *p9dev,
> +			     struct p9_pdu *pdu, u32 *outlen)
>  {
> -	struct p9_msg *outmsg = iov[0].iov_base;
> -	struct p9_tremove *tremove = (struct p9_tremove *)msg->msg;
> +	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];
>  
>  	close_fid(p9dev, tremove->fid);
> @@ -517,39 +532,32 @@ static bool virtio_p9_remove(struct p9_dev *p9dev, struct p9_msg *msg,
>  		unlink(fid->abs_path);
>  
>  	*outlen = VIRTIO_P9_HDR_LEN;
> -	set_p9msg_hdr(outmsg, *outlen, P9_RREMOVE, msg->tag);
> +	set_p9msg_hdr(inmsg, *outlen, P9_RREMOVE, outmsg->tag);
>  	return true;
>  }
>  
> -static bool virtio_p9_write(struct p9_dev *p9dev, struct p9_msg *msg,
> -			    u32 len, struct iovec *iov,
> -			    int outiovcnt, int iniovcnt, u32 *outlen)
> +static bool virtio_p9_write(struct p9_dev *p9dev,
> +			    struct p9_pdu *pdu, u32 *outlen)
>  {
> -	struct p9_msg *outmsg;
> -	struct p9_rwrite *rwrite;
> -	struct p9_twrite *twrite = (struct p9_twrite *)msg->msg;
> +	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];
>  
> -	if (outiovcnt == 1) {
> -		outmsg = iov[0].iov_base;
> -		rwrite = (struct p9_rwrite *)outmsg->msg;
> -		rwrite->count = pwrite(fid->fd, &twrite->data,
> -				       twrite->count, twrite->offset);
> -	} else {
> -		outmsg = iov[2].iov_base;
> -		rwrite = (struct p9_rwrite *)outmsg->msg;
> -		rwrite->count = pwrite(fid->fd, iov[1].iov_base,
> -				       twrite->count, twrite->offset);
> -	}
> +
> +	pdu->out_iov[0].iov_base += (sizeof(*outmsg) + sizeof(*twrite));
> +	pdu->out_iov[0].iov_len -= (sizeof(*outmsg) + sizeof(*twrite));
> +	rwrite->count = pwritev(fid->fd, pdu->out_iov,
> +				pdu->out_iov_cnt, twrite->offset);
>  	*outlen = VIRTIO_P9_HDR_LEN + sizeof(u32);
> -	set_p9msg_hdr(outmsg, *outlen, P9_RWRITE, msg->tag);
> +	set_p9msg_hdr(inmsg, *outlen, P9_RWRITE, outmsg->tag);
>  
>  	return true;
>  }
>  
> -typedef bool p9_handler(struct p9_dev *p9dev, struct p9_msg *msg,
> -			u32 len, struct iovec *iov,
> -			int outiovcnt, int iniovcnt, u32 *outlen);
> +typedef bool p9_handler(struct p9_dev *p9dev,
> +			struct p9_pdu *pdu, u32 *outlen);
>  
>  static p9_handler *virtio_9p_handler [] = {
>  	[P9_TVERSION] = virtio_p9_version,
> @@ -565,30 +573,55 @@ static p9_handler *virtio_9p_handler [] = {
>  	[P9_TWRITE]   =	virtio_p9_write,
>  };
>  
> +static struct p9_pdu *virtio_p9_pdu_init(struct kvm *kvm, struct virt_queue *vq)
> +{
> +	struct p9_pdu *pdu = calloc(1, sizeof(*pdu));
> +	if (!pdu)
> +		return NULL;
> +
> +	pdu->queue_head  = virt_queue__get_inout_iov(kvm, vq, pdu->in_iov,
> +						     pdu->out_iov,
> +						     &pdu->in_iov_cnt,
> +						     &pdu->out_iov_cnt);
> +	return pdu;
> +}
> +
> +static u8 virtio_p9_get_cmd(struct p9_pdu *pdu)
> +{
> +	struct p9_msg *msg;
> +	/*
> +	 * we can peek directly into pdu for a u8
> +	 * value. The host endianess won't be an issue
> +	 */
> +	msg = pdu->out_iov[0].iov_base;
> +	return msg->cmd;
> +}
> +
>  static bool virtio_p9_do_io_request(struct kvm *kvm, struct p9_dev_job *job)
>  {
> +	u8 cmd;
>  	u32 len = 0;
> -	u16 out, in, head;
> -	struct p9_msg *msg;
>  	p9_handler *handler;
> -	struct virt_queue *vq;
>  	struct p9_dev *p9dev;
> -	struct iovec iov[VIRTQUEUE_NUM];
> +	struct virt_queue *vq;
> +	struct p9_pdu *p9pdu;
>  
>  	vq = job->vq;
>  	p9dev = job->p9dev;
> -	head  = virt_queue__get_iov(vq, iov, &out, &in, kvm);
> -	msg   = iov[0].iov_base;
>  
> -	if (msg->cmd >= ARRAY_SIZE(virtio_9p_handler) ||
> -	    !virtio_9p_handler[msg->cmd]) {
> -		printf("Unsupported P9 message type: %u\n", msg->cmd);
> +	p9pdu = virtio_p9_pdu_init(kvm, vq);
> +	cmd = virtio_p9_get_cmd(p9pdu);
> +
> +	if (cmd >= ARRAY_SIZE(virtio_9p_handler) ||
> +	    !virtio_9p_handler[cmd]) {
> +		printf("Unsupported P9 message type: %u\n", cmd);
>  
>  	} else {
> -		handler = virtio_9p_handler[msg->cmd];
> -		handler(p9dev, msg, iov[0].iov_len, iov+1, out, in, &len);
> +		handler = virtio_9p_handler[cmd];
> +		handler(p9dev, p9pdu, &len);
>  	}
> -	virt_queue__set_used_elem(vq, head, len);
> +	virt_queue__set_used_elem(vq, p9pdu->queue_head, len);
> +	free(p9pdu);
>  	return true;
>  }
>
Aneesh Kumar K.V June 19, 2011, 5:13 a.m. UTC | #2
On Sat, 18 Jun 2011 14:51:34 -0400, Sasha Levin <levinsasha928@gmail.com> wrote:
> On Sat, 2011-06-18 at 23:19 +0530, Aneesh Kumar K.V wrote:
> > Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
> > ---
> >  tools/kvm/include/net/9p/9p.h |    1 -
> >  tools/kvm/virtio/9p.c         |  261 +++++++++++++++++++++++------------------
> >  2 files changed, 147 insertions(+), 115 deletions(-)
> 
> After applying the patches (within a 9p mounted dir):
> 
>  # mkdir new_dir
>  # cp 10MB new_dir/
> cp: cannot create regular file `new_dir/10MB': No such file or directory
> 

works fine here

sh-2.05b# ls -al 10M
-rwxr-xr-x    1 4294967294 4294967294 10485760 Jun 19  2011 10M
sh-2.05b# mkdir new_dir
sh-2.05b# cp 10M new_dir/
sh-2.05b# 

Can you check the before and after behaviour with the patch ?

-aneesh
--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Sasha Levin June 19, 2011, 6:41 a.m. UTC | #3
On Sun, 2011-06-19 at 10:43 +0530, Aneesh Kumar K.V wrote:
> On Sat, 18 Jun 2011 14:51:34 -0400, Sasha Levin <levinsasha928@gmail.com> wrote:
> > On Sat, 2011-06-18 at 23:19 +0530, Aneesh Kumar K.V wrote:
> > > Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
> > > ---
> > >  tools/kvm/include/net/9p/9p.h |    1 -
> > >  tools/kvm/virtio/9p.c         |  261 +++++++++++++++++++++++------------------
> > >  2 files changed, 147 insertions(+), 115 deletions(-)
> > 
> > After applying the patches (within a 9p mounted dir):
> > 
> >  # mkdir new_dir
> >  # cp 10MB new_dir/
> > cp: cannot create regular file `new_dir/10MB': No such file or directory
> > 
> 
> works fine here
> 
> sh-2.05b# ls -al 10M
> -rwxr-xr-x    1 4294967294 4294967294 10485760 Jun 19  2011 10M
> sh-2.05b# mkdir new_dir
> sh-2.05b# cp 10M new_dir/
> sh-2.05b# 
> 
> Can you check the before and after behaviour with the patch ?

It works ok before the patch here.

I've added debug to the mount command, looks like it was caused due to
patch 4/5 (the removal of one u16) - the host didn't quite like it :)
diff mbox

Patch

diff --git a/tools/kvm/include/net/9p/9p.h b/tools/kvm/include/net/9p/9p.h
index cc11592..61ecff3 100644
--- a/tools/kvm/include/net/9p/9p.h
+++ b/tools/kvm/include/net/9p/9p.h
@@ -635,7 +635,6 @@  struct p9_twrite {
 	u32 fid;
 	u64 offset;
 	u32 count;
-	u8 *data;
 };
 
 struct p9_rwrite {
diff --git a/tools/kvm/virtio/9p.c b/tools/kvm/virtio/9p.c
index ef2fbaf..f2b9299 100644
--- a/tools/kvm/virtio/9p.c
+++ b/tools/kvm/virtio/9p.c
@@ -67,6 +67,15 @@  struct p9_dev {
 	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,
 			      const char *path, char *abs_path)
@@ -184,12 +193,12 @@  static void set_p9msg_hdr(struct p9_msg *msg, u32 size, u8 cmd, u16 tag)
 	};
 }
 
-static bool virtio_p9_version(struct p9_dev *p9dev, struct p9_msg *msg,
-			      u32 len, struct iovec *iov,
-			      int outiovcnt, int iniovcnt, u32 *outlen)
+static bool virtio_p9_version(struct p9_dev *p9dev,
+			      struct p9_pdu *pdu, u32 *outlen)
 {
-	struct p9_msg *outmsg = iov[0].iov_base;
-	struct p9_rversion *rversion = (struct p9_rversion *)outmsg->msg;
+	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);
@@ -197,35 +206,35 @@  static bool virtio_p9_version(struct p9_dev *p9dev, struct p9_msg *msg,
 
 	*outlen = VIRTIO_P9_HDR_LEN +
 		rversion->version.len + sizeof(u16) + sizeof(u32);
-	set_p9msg_hdr(outmsg, *outlen, P9_RVERSION, msg->tag);
+	set_p9msg_hdr(inmsg, *outlen, P9_RVERSION, outmsg->tag);
 
 	return true;
 }
 
-static bool virtio_p9_clunk(struct p9_dev *p9dev, struct p9_msg *msg,
-			    u32 len, struct iovec *iov,
-			    int outiovcnt, int iniovcnt, u32 *outlen)
+static bool virtio_p9_clunk(struct p9_dev *p9dev,
+			    struct p9_pdu *pdu, u32 *outlen)
 {
-	struct p9_msg *outmsg = iov[0].iov_base;
-	struct p9_tclunk *tclunk = (struct p9_tclunk *)msg->msg;
+	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;
 
 	close_fid(p9dev, tclunk->fid);
 
 	*outlen = VIRTIO_P9_HDR_LEN;
-	set_p9msg_hdr(outmsg, *outlen, P9_RCLUNK, msg->tag);
+	set_p9msg_hdr(inmsg, *outlen, P9_RCLUNK, outmsg->tag);
 
 	return true;
 }
 
-static bool virtio_p9_open(struct p9_dev *p9dev, struct p9_msg *msg,
-			   u32 len, struct iovec *iov,
-			   int outiovcnt, int iniovcnt, u32 *outlen)
+static bool virtio_p9_open(struct p9_dev *p9dev,
+			   struct p9_pdu *pdu, u32 *outlen)
 {
-	struct p9_msg *outmsg	= iov[0].iov_base;
-	struct p9_topen *topen	= (struct p9_topen *)msg->msg;
-	struct p9_ropen *ropen	= (struct p9_ropen *)outmsg->msg;
-	struct p9_fid *new_fid	= &p9dev->fids[topen->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];
 
 	if (lstat(new_fid->abs_path, &st) < 0)
 		return false;
@@ -239,28 +248,29 @@  static bool virtio_p9_open(struct p9_dev *p9dev, struct p9_msg *msg,
 		new_fid->fd	= open(new_fid->abs_path, omode2uflags(topen->mode));
 
 	*outlen = VIRTIO_P9_HDR_LEN + sizeof(*ropen);
-	set_p9msg_hdr(outmsg, *outlen, P9_ROPEN, msg->tag);
+	set_p9msg_hdr(inmsg, *outlen, P9_ROPEN, outmsg->tag);
 
 	return true;
 }
 
-static bool virtio_p9_create(struct p9_dev *p9dev, struct p9_msg *msg,
-			     u32 len, struct iovec *iov,
-			     int outiovcnt, int iniovcnt, u32 *outlen)
+static bool virtio_p9_create(struct p9_dev *p9dev,
+			     struct p9_pdu *pdu, u32 *outlen)
 {
-	struct p9_msg *outmsg		= iov[0].iov_base;
-	struct p9_tcreate *tcreate	= (struct p9_tcreate *)msg->msg;
-	struct p9_rcreate *rcreate	= (struct p9_rcreate *)outmsg->msg;
-	struct p9_fid *fid		= &p9dev->fids[tcreate->fid];
-	struct stat st;
 	u8 mode;
 	u32 perm;
+	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 *)msg + msg->size - 1);
-	perm = *(u32 *)((u8 *)msg + msg->size - 5);
+	mode = *((u8 *)outmsg + outmsg->size - 1);
+	perm = *(u32 *)((u8 *)outmsg + outmsg->size - 5);
 
 	sprintf(fid->path, "%s/%.*s", fid->path, tcreate->name.len, (char *)&tcreate->name.str);
 
@@ -280,21 +290,22 @@  static bool virtio_p9_create(struct p9_dev *p9dev, struct p9_msg *msg,
 	st2qid(&st, &rcreate->qid);
 
 	*outlen = VIRTIO_P9_HDR_LEN + sizeof(*rcreate);
-	set_p9msg_hdr(outmsg, *outlen, P9_RCREATE, msg->tag);
+	set_p9msg_hdr(inmsg, *outlen, P9_RCREATE, outmsg->tag);
 
 	return true;
 }
 
-static bool virtio_p9_walk(struct p9_dev *p9dev, struct p9_msg *msg,
-			   u32 len, struct iovec *iov,
-			   int outiovcnt, int iniovcnt, u32 *outlen)
+static bool virtio_p9_walk(struct p9_dev *p9dev,
+			   struct p9_pdu *pdu, u32 *outlen)
 {
-	struct p9_msg *outmsg	= iov[0].iov_base;
-	struct p9_twalk *twalk	= (struct p9_twalk *)msg->msg;
-	struct p9_rwalk *rwalk	= (struct p9_rwalk *)outmsg->msg;
+	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];
-	u8 i;
+
 
 	rwalk->nwqid = 0;
 	if (twalk->nwname) {
@@ -306,7 +317,8 @@  static bool virtio_p9_walk(struct p9_dev *p9dev, struct p9_msg *msg,
 			struct stat st;
 
 			/* 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,
+				str->len, (char *)&str->str);
 
 			if (lstat(rel_to_abs(p9dev, tmp, full_path), &st) < 0)
 				break;
@@ -323,22 +335,23 @@  static bool virtio_p9_walk(struct p9_dev *p9dev, struct p9_msg *msg,
 		new_fid->fid	= twalk->newfid;
 	}
 
-	*outlen = VIRTIO_P9_HDR_LEN + sizeof(u16) + sizeof(struct p9_qid) * rwalk->nwqid;
-	set_p9msg_hdr(outmsg, *outlen, P9_RWALK, msg->tag);
+	*outlen = VIRTIO_P9_HDR_LEN + sizeof(u16) +
+		sizeof(struct p9_qid)*rwalk->nwqid;
+	set_p9msg_hdr(inmsg, *outlen, P9_RWALK, outmsg->tag);
 
 	return true;
 }
 
-static bool virtio_p9_attach(struct p9_dev *p9dev, struct p9_msg *msg,
-			     u32 len, struct iovec *iov,
-			     int outiovcnt, int iniovcnt, u32 *outlen)
+static bool virtio_p9_attach(struct p9_dev *p9dev,
+			     struct p9_pdu *pdu, u32 *outlen)
 {
-	struct p9_msg *outmsg = iov[0].iov_base;
-	struct p9_rattach *rattach = (struct p9_rattach *)outmsg->msg;
-	struct p9_tattach *tattach = (struct p9_tattach *)msg->msg;
+	u32 i;
 	struct stat st;
 	struct p9_fid *fid;
-	u32 i;
+	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;
 
 	/* Reset everything */
 	for (i = 0; i < VIRTIO_P9_MAX_FID; i++)
@@ -355,7 +368,7 @@  static bool virtio_p9_attach(struct p9_dev *p9dev, struct p9_msg *msg,
 	strcpy(fid->path, "/");
 
 	*outlen = VIRTIO_P9_HDR_LEN + sizeof(*rattach);
-	set_p9msg_hdr(outmsg, *outlen, P9_RATTACH, msg->tag);
+	set_p9msg_hdr(inmsg, *outlen, P9_RATTACH, outmsg->tag);
 
 	return true;
 }
@@ -400,14 +413,14 @@  static u32 virtio_p9_fill_stat(struct p9_dev *p9dev, const char *name,
 	return rstat->stat.size + sizeof(u16);
 }
 
-static bool virtio_p9_read(struct p9_dev *p9dev, struct p9_msg *msg,
-			   u32 len, struct iovec *iov,
-			   int outiovcnt, int iniovcnt, u32 *outlen)
+static bool virtio_p9_read(struct p9_dev *p9dev,
+			   struct p9_pdu *pdu, u32 *outlen)
 {
-	struct p9_msg *outmsg	= iov[0].iov_base;
-	struct p9_tread *tread	= (struct p9_tread *)msg->msg;
-	struct p9_rread *rread	= (struct p9_rread *)outmsg->msg;
-	struct p9_rstat *rstat	= (struct p9_rstat *)iov[1].iov_base;
+	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];
 	struct stat st;
 
@@ -429,29 +442,30 @@  static bool virtio_p9_read(struct p9_dev *p9dev, struct p9_msg *msg,
 			cur = readdir(fid->dir);
 		}
 	} else {
-		iov[0].iov_base += VIRTIO_P9_HDR_LEN + sizeof(u32);
-		iov[0].iov_len -= VIRTIO_P9_HDR_LEN + sizeof(u32);
-		rread->count = preadv(fid->fd, iov, iniovcnt, tread->offset);
+		pdu->in_iov[0].iov_base += VIRTIO_P9_HDR_LEN + sizeof(u32);
+		pdu->in_iov[0].iov_len -= VIRTIO_P9_HDR_LEN + sizeof(u32);
+		rread->count = preadv(fid->fd, pdu->in_iov,
+				      pdu->in_iov_cnt, tread->offset);
 		if (rread->count > tread->count)
 			rread->count = tread->count;
 	}
 
 	*outlen = VIRTIO_P9_HDR_LEN + sizeof(u32) + rread->count;
-	set_p9msg_hdr(outmsg, *outlen, P9_RREAD, msg->tag);
+	set_p9msg_hdr(inmsg, *outlen, P9_RREAD, outmsg->tag);
 
 	return true;
 }
 
-static bool virtio_p9_stat(struct p9_dev *p9dev, struct p9_msg *msg,
-			   u32 len, struct iovec *iov,
-			   int outiovcnt, int iniovcnt, u32 *outlen)
+static bool virtio_p9_stat(struct p9_dev *p9dev,
+			   struct p9_pdu *pdu, u32 *outlen)
 {
-	struct p9_msg *outmsg = iov[0].iov_base;
-	struct p9_tstat *tstat = (struct p9_tstat *)msg->msg;
-	struct p9_rstat *rstat = (struct p9_rstat *)(outmsg->msg + sizeof(u16));
+	u32 ret;
 	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];
-	u32 ret;
 
 	if (lstat(fid->abs_path, &st) < 0)
 		return false;
@@ -459,19 +473,20 @@  static bool virtio_p9_stat(struct p9_dev *p9dev, struct p9_msg *msg,
 	ret = virtio_p9_fill_stat(p9dev, fid->path, &st, rstat);
 
 	*outlen = VIRTIO_P9_HDR_LEN + ret + sizeof(u16);
-	set_p9msg_hdr(outmsg, *outlen, P9_RSTAT, msg->tag);
+	set_p9msg_hdr(inmsg, *outlen, P9_RSTAT, outmsg->tag);
 	return true;
 }
 
-static bool virtio_p9_wstat(struct p9_dev *p9dev, struct p9_msg *msg,
-			    u32 len, struct iovec *iov,
-			    int outiovcnt, int iniovcnt, u32 *outlen)
+static bool virtio_p9_wstat(struct p9_dev *p9dev,
+			    struct p9_pdu *pdu, u32 *outlen)
 {
-	struct p9_msg *outmsg = iov[0].iov_base;
-	struct p9_twstat *twstat = (struct p9_twstat *)msg->msg;
+	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];
-	int res = 0;
+
 
 	if (twstat->stat.length != -1UL)
 		res = ftruncate(fid->fd, twstat->stat.length);
@@ -497,17 +512,17 @@  static bool virtio_p9_wstat(struct p9_dev *p9dev, struct p9_msg *msg,
 	}
 
 	*outlen = VIRTIO_P9_HDR_LEN;
-	set_p9msg_hdr(outmsg, *outlen, P9_RWSTAT, msg->tag);
+	set_p9msg_hdr(inmsg, *outlen, P9_RWSTAT, outmsg->tag);
 
 	return res == 0;
 }
 
-static bool virtio_p9_remove(struct p9_dev *p9dev, struct p9_msg *msg,
-			     u32 len, struct iovec *iov,
-			     int outiovcnt, int iniovcnt, u32 *outlen)
+static bool virtio_p9_remove(struct p9_dev *p9dev,
+			     struct p9_pdu *pdu, u32 *outlen)
 {
-	struct p9_msg *outmsg = iov[0].iov_base;
-	struct p9_tremove *tremove = (struct p9_tremove *)msg->msg;
+	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];
 
 	close_fid(p9dev, tremove->fid);
@@ -517,39 +532,32 @@  static bool virtio_p9_remove(struct p9_dev *p9dev, struct p9_msg *msg,
 		unlink(fid->abs_path);
 
 	*outlen = VIRTIO_P9_HDR_LEN;
-	set_p9msg_hdr(outmsg, *outlen, P9_RREMOVE, msg->tag);
+	set_p9msg_hdr(inmsg, *outlen, P9_RREMOVE, outmsg->tag);
 	return true;
 }
 
-static bool virtio_p9_write(struct p9_dev *p9dev, struct p9_msg *msg,
-			    u32 len, struct iovec *iov,
-			    int outiovcnt, int iniovcnt, u32 *outlen)
+static bool virtio_p9_write(struct p9_dev *p9dev,
+			    struct p9_pdu *pdu, u32 *outlen)
 {
-	struct p9_msg *outmsg;
-	struct p9_rwrite *rwrite;
-	struct p9_twrite *twrite = (struct p9_twrite *)msg->msg;
+	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];
 
-	if (outiovcnt == 1) {
-		outmsg = iov[0].iov_base;
-		rwrite = (struct p9_rwrite *)outmsg->msg;
-		rwrite->count = pwrite(fid->fd, &twrite->data,
-				       twrite->count, twrite->offset);
-	} else {
-		outmsg = iov[2].iov_base;
-		rwrite = (struct p9_rwrite *)outmsg->msg;
-		rwrite->count = pwrite(fid->fd, iov[1].iov_base,
-				       twrite->count, twrite->offset);
-	}
+
+	pdu->out_iov[0].iov_base += (sizeof(*outmsg) + sizeof(*twrite));
+	pdu->out_iov[0].iov_len -= (sizeof(*outmsg) + sizeof(*twrite));
+	rwrite->count = pwritev(fid->fd, pdu->out_iov,
+				pdu->out_iov_cnt, twrite->offset);
 	*outlen = VIRTIO_P9_HDR_LEN + sizeof(u32);
-	set_p9msg_hdr(outmsg, *outlen, P9_RWRITE, msg->tag);
+	set_p9msg_hdr(inmsg, *outlen, P9_RWRITE, outmsg->tag);
 
 	return true;
 }
 
-typedef bool p9_handler(struct p9_dev *p9dev, struct p9_msg *msg,
-			u32 len, struct iovec *iov,
-			int outiovcnt, int iniovcnt, u32 *outlen);
+typedef bool p9_handler(struct p9_dev *p9dev,
+			struct p9_pdu *pdu, u32 *outlen);
 
 static p9_handler *virtio_9p_handler [] = {
 	[P9_TVERSION] = virtio_p9_version,
@@ -565,30 +573,55 @@  static p9_handler *virtio_9p_handler [] = {
 	[P9_TWRITE]   =	virtio_p9_write,
 };
 
+static struct p9_pdu *virtio_p9_pdu_init(struct kvm *kvm, struct virt_queue *vq)
+{
+	struct p9_pdu *pdu = calloc(1, sizeof(*pdu));
+	if (!pdu)
+		return NULL;
+
+	pdu->queue_head  = virt_queue__get_inout_iov(kvm, vq, pdu->in_iov,
+						     pdu->out_iov,
+						     &pdu->in_iov_cnt,
+						     &pdu->out_iov_cnt);
+	return pdu;
+}
+
+static u8 virtio_p9_get_cmd(struct p9_pdu *pdu)
+{
+	struct p9_msg *msg;
+	/*
+	 * we can peek directly into pdu for a u8
+	 * value. The host endianess won't be an issue
+	 */
+	msg = pdu->out_iov[0].iov_base;
+	return msg->cmd;
+}
+
 static bool virtio_p9_do_io_request(struct kvm *kvm, struct p9_dev_job *job)
 {
+	u8 cmd;
 	u32 len = 0;
-	u16 out, in, head;
-	struct p9_msg *msg;
 	p9_handler *handler;
-	struct virt_queue *vq;
 	struct p9_dev *p9dev;
-	struct iovec iov[VIRTQUEUE_NUM];
+	struct virt_queue *vq;
+	struct p9_pdu *p9pdu;
 
 	vq = job->vq;
 	p9dev = job->p9dev;
-	head  = virt_queue__get_iov(vq, iov, &out, &in, kvm);
-	msg   = iov[0].iov_base;
 
-	if (msg->cmd >= ARRAY_SIZE(virtio_9p_handler) ||
-	    !virtio_9p_handler[msg->cmd]) {
-		printf("Unsupported P9 message type: %u\n", msg->cmd);
+	p9pdu = virtio_p9_pdu_init(kvm, vq);
+	cmd = virtio_p9_get_cmd(p9pdu);
+
+	if (cmd >= ARRAY_SIZE(virtio_9p_handler) ||
+	    !virtio_9p_handler[cmd]) {
+		printf("Unsupported P9 message type: %u\n", cmd);
 
 	} else {
-		handler = virtio_9p_handler[msg->cmd];
-		handler(p9dev, msg, iov[0].iov_len, iov+1, out, in, &len);
+		handler = virtio_9p_handler[cmd];
+		handler(p9dev, p9pdu, &len);
 	}
-	virt_queue__set_used_elem(vq, head, len);
+	virt_queue__set_used_elem(vq, p9pdu->queue_head, len);
+	free(p9pdu);
 	return true;
 }