On 2/6/2011 11:21 PM, Venkateswararao Jujjuri (JV) wrote: > Signed-off-by: Venkateswararao Jujjuri <jvrao@xxxxxxxxxxxxxxxxxx> > --- > 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 <linux/scatterlist.h> > #include <linux/virtio.h> > #include <linux/virtio_9p.h> > +#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) { -- To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html