From mboxrd@z Thu Jan 1 00:00:00 1970 From: "Venkateswararao Jujjuri (JV)" Subject: [RFC] [PATCH 4/7] [net/9p] Add gup/zero_copy support to VirtIO transport layer. Date: Sun, 06 Feb 2011 22:56:55 -0800 Message-ID: <4D4F97B7.8060104@linux.vnet.ibm.com> References: <1297063283-2180-1-git-send-email-jvrao@linux.vnet.ibm.com> <1297063283-2180-5-git-send-email-jvrao@linux.vnet.ibm.com> Mime-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit Cc: v9fs-developer@lists.sourceforge.net, linux-fsdevel@vger.kernel.org To: "Venkateswararao Jujjuri (JV)" Return-path: Received: from e35.co.us.ibm.com ([32.97.110.153]:60045 "EHLO e35.co.us.ibm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752239Ab1BGG5A (ORCPT ); Mon, 7 Feb 2011 01:57:00 -0500 Received: from d03relay02.boulder.ibm.com (d03relay02.boulder.ibm.com [9.17.195.227]) by e35.co.us.ibm.com (8.14.4/8.13.1) with ESMTP id p176grQd015354 for ; Sun, 6 Feb 2011 23:42:53 -0700 Received: from d03av02.boulder.ibm.com (d03av02.boulder.ibm.com [9.17.195.168]) by d03relay02.boulder.ibm.com (8.13.8/8.13.8/NCO v9.1) with ESMTP id p176uxiV230346 for ; Sun, 6 Feb 2011 23:56:59 -0700 Received: from d03av02.boulder.ibm.com (loopback [127.0.0.1]) by d03av02.boulder.ibm.com (8.14.4/8.13.1/NCO v10.0 AVout) with ESMTP id p176uxlb025672 for ; Sun, 6 Feb 2011 23:56:59 -0700 In-Reply-To: <1297063283-2180-5-git-send-email-jvrao@linux.vnet.ibm.com> Sender: linux-fsdevel-owner@vger.kernel.org List-ID: On 2/6/2011 11:21 PM, Venkateswararao Jujjuri (JV) wrote: > Signed-off-by: Venkateswararao Jujjuri > --- > net/9p/trans_virtio.c | 85 +++++++++++++++++++++++++++++++++++++++++++++--- > 1 files changed, 79 insertions(+), 6 deletions(-) > > diff --git a/net/9p/trans_virtio.c b/net/9p/trans_virtio.c > index c8f3f72..607f064 100644 > --- a/net/9p/trans_virtio.c > +++ b/net/9p/trans_virtio.c > @@ -45,6 +45,7 @@ > #include > #include > #include > +#include "trans_common.h" > > #define VIRTQUEUE_NUM 128 > > @@ -155,6 +156,12 @@ static void req_done(struct virtqueue *vq) > rc->tag); > req = p9_tag_lookup(chan->client, rc->tag); > req->status = REQ_STATUS_RCVD; > + if (req->tc->private) { > + /*Release pages */ > + p9_release_req_pages(req->tc->private); > + kfree(req->tc->private); > + req->tc->private = NULL; > + } > p9_client_cb(chan->client, req); > } else { > spin_unlock_irqrestore(&chan->lock, flags); > @@ -202,6 +209,30 @@ static int p9_virtio_cancel(struct p9_client *client, struct p9_req_t *req) > return 1; > } > > +static int > +pack_sg_list_p(struct scatterlist *sg, int start, int limit, size_t pdata_off, > + struct page **pdata, int count) > +{ > + int s; > + int i = 0; > + int index = start; > + > + if (pdata_off) { > + s = min((int)(PAGE_SIZE - pdata_off), count); > + sg_set_page(&sg[index++], pdata[i++], s, pdata_off); > + count -= s; > + } > + > + while (count) { > + BUG_ON(index > limit); > + s = min((int)PAGE_SIZE, count); > + sg_set_page(&sg[index++], pdata[i++], s, 0); > + count -= s; > + } > + > + return index-start; > +} > + > /** > * p9_virtio_request - issue a request > * @client: client instance issuing the request > @@ -212,22 +243,64 @@ static int p9_virtio_cancel(struct p9_client *client, struct p9_req_t *req) > static int > p9_virtio_request(struct p9_client *client, struct p9_req_t *req) > { > - int in, out; > + int in, out, inp, outp; > struct virtio_chan *chan = client->trans; > char *rdata = (char *)req->rc+sizeof(struct p9_fcall); > unsigned long flags; > - int err; > + size_t pdata_off=0; > + virtio_rpage_info_t *rpinfo; > + int err, pdata_len=0; > > P9_DPRINTK(P9_DEBUG_TRANS, "9p debug: virtio request\n"); > > req_retry: > req->status = REQ_STATUS_SENT; > > + if (req->tc->pbuf_size && > + (req->tc->pbuf && !segment_eq(get_fs(), KERNEL_DS))) { > + err = payload_gup(req, &pdata_off, &pdata_len, > + req->tc->id == P9_TREAD ? 1 : 0 ); > + if (err < 0) > + return err; > + } > + rpinfo = (virtio_rpage_info_t *)req->tc->private; > + > spin_lock_irqsave(&chan->lock, flags); > - out = pack_sg_list(chan->sg, 0, VIRTQUEUE_NUM, req->tc->sdata, > - req->tc->size); > - in = pack_sg_list(chan->sg, out, VIRTQUEUE_NUM-out, rdata, > - client->msize); > + > + /* Handle out VirtIO ring buffers */ > + if (req->tc->pbuf_size && (req->tc->id == P9_TWRITE)) { > + /* We have additional write payload buffer to take care */ > + out = pack_sg_list(chan->sg, 0, VIRTQUEUE_NUM, req->tc->sdata, > + req->tc->size); > + outp = pack_sg_list_p(chan->sg, out, VIRTQUEUE_NUM, > + pdata_off, rpinfo->vp_data, pdata_len); > + out += outp; > + } else { > + out = pack_sg_list(chan->sg, 0, VIRTQUEUE_NUM, req->tc->sdata, > + req->tc->size); > + } > + > + /* Handle in VirtIO ring buffers */ > + if (req->tc->pbuf_size && (req->tc->id == P9_TREAD)) { > + /* We have additional Read payload buffer to take care */ > + inp = pack_sg_list(chan->sg, out, VIRTQUEUE_NUM, rdata, 11); > + /* > + * Running executables in the filesystem may result in > + * a read request with kernel buffer as opposed to user buffer. > + */ > + if (req->tc->pbuf && !segment_eq(get_fs(), KERNEL_DS)) { > + in = pack_sg_list_p(chan->sg, out+inp, VIRTQUEUE_NUM, > + pdata_off, rpinfo->vp_data, pdata_len); > + } else { > + in = pack_sg_list(chan->sg, out, VIRTQUEUE_NUM, > + (char *)req->tc->pbuf, > + req->tc->pbuf_size); > + } > + in += inp; > + } else { > + in = pack_sg_list(chan->sg, out, VIRTQUEUE_NUM, rdata, > + client->msize); > + } > > err = virtqueue_add_buf(chan->vq, chan->sg, out, in, req->tc); > if (err < 0) {