Commit 022cae36551ba805bf82084047945b2901d75f36

Authored by Venkateswararao Jujjuri (JV)
Committed by Eric Van Hensbergen
1 parent 6752a1ebd1

[net/9p] Preparation and helper functions for zero copy

This patch prepares p9_fcall structure for zero copy. Added
fields send the payload buffer information to the transport layer.
In addition it adds a 'private' field for the transport layer to
store mapped/pinned page information so that it can be freed/unpinned
during req_done.

This patch also creates trans_common.[ch] to house helper functions.
It adds the following helper functions.

p9_release_req_pages - Release pages after the transaction.
p9_nr_pages - Return number of pages needed to accomodate the payload.
payload_gup - Translates user buffer into kernel pages.

Signed-off-by: Venkateswararao Jujjuri <jvrao@linux.vnet.ibm.com>
Signed-off-by: Eric Van Hensbergen <ericvh@gmail.com>

Showing 5 changed files with 139 additions and 0 deletions Side-by-side Diff

... ... @@ -689,6 +689,10 @@
689 689 * @tag: transaction id of the request
690 690 * @offset: used by marshalling routines to track currentposition in buffer
691 691 * @capacity: used by marshalling routines to track total capacity
  692 + * @pubuf: Payload user buffer given by the caller
  693 + * @pubuf: Payload kernel buffer given by the caller
  694 + * @pbuf_size: pubuf/pkbuf(only one will be !NULL) size to be read/write.
  695 + * @private: For transport layer's use.
692 696 * @sdata: payload
693 697 *
694 698 * &p9_fcall represents the structure for all 9P RPC
... ... @@ -705,6 +709,10 @@
705 709  
706 710 size_t offset;
707 711 size_t capacity;
  712 + char __user *pubuf;
  713 + char *pkbuf;
  714 + size_t pbuf_size;
  715 + void *private;
708 716  
709 717 uint8_t *sdata;
710 718 };
... ... @@ -9,6 +9,7 @@
9 9 util.o \
10 10 protocol.o \
11 11 trans_fd.o \
  12 + trans_common.o \
12 13  
13 14 9pnet_virtio-objs := \
14 15 trans_virtio.o \
... ... @@ -606,6 +606,10 @@
606 606 {
607 607 pdu->offset = 0;
608 608 pdu->size = 0;
  609 + pdu->private = NULL;
  610 + pdu->pubuf = NULL;
  611 + pdu->pkbuf = NULL;
  612 + pdu->pbuf_size = 0;
609 613 }
610 614  
611 615 int p9dirent_read(char *buf, int len, struct p9_dirent *dirent,
net/9p/trans_common.c
  1 +/*
  2 + * Copyright IBM Corporation, 2010
  3 + * Author Venkateswararao Jujjuri <jvrao@linux.vnet.ibm.com>
  4 + *
  5 + * This program is free software; you can redistribute it and/or modify it
  6 + * under the terms of version 2.1 of the GNU Lesser General Public License
  7 + * as published by the Free Software Foundation.
  8 + *
  9 + * This program is distributed in the hope that it would be useful, but
  10 + * WITHOUT ANY WARRANTY; without even the implied warranty of
  11 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  12 + *
  13 + */
  14 +
  15 +#include <linux/slab.h>
  16 +#include <linux/module.h>
  17 +#include <net/9p/9p.h>
  18 +#include <net/9p/client.h>
  19 +#include <linux/scatterlist.h>
  20 +#include "trans_common.h"
  21 +
  22 +/**
  23 + * p9_release_req_pages - Release pages after the transaction.
  24 + * @*private: PDU's private page of struct trans_rpage_info
  25 + */
  26 +void
  27 +p9_release_req_pages(struct trans_rpage_info *rpinfo)
  28 +{
  29 + int i = 0;
  30 +
  31 + while (rpinfo->rp_data[i] && rpinfo->rp_nr_pages--) {
  32 + put_page(rpinfo->rp_data[i]);
  33 + i++;
  34 + }
  35 +}
  36 +EXPORT_SYMBOL(p9_release_req_pages);
  37 +
  38 +/**
  39 + * p9_nr_pages - Return number of pages needed to accomodate the payload.
  40 + */
  41 +int
  42 +p9_nr_pages(struct p9_req_t *req)
  43 +{
  44 + int start_page, end_page;
  45 + start_page = (unsigned long long)req->tc->pubuf >> PAGE_SHIFT;
  46 + end_page = ((unsigned long long)req->tc->pubuf + req->tc->pbuf_size +
  47 + PAGE_SIZE - 1) >> PAGE_SHIFT;
  48 + return end_page - start_page;
  49 +}
  50 +EXPORT_SYMBOL(p9_nr_pages);
  51 +
  52 +/**
  53 + * payload_gup - Translates user buffer into kernel pages and
  54 + * pins them either for read/write through get_user_pages_fast().
  55 + * @req: Request to be sent to server.
  56 + * @pdata_off: data offset into the first page after translation (gup).
  57 + * @pdata_len: Total length of the IO. gup may not return requested # of pages.
  58 + * @nr_pages: number of pages to accomodate the payload
  59 + * @rw: Indicates if the pages are for read or write.
  60 + */
  61 +int
  62 +p9_payload_gup(struct p9_req_t *req, size_t *pdata_off, int *pdata_len,
  63 + int nr_pages, u8 rw)
  64 +{
  65 + uint32_t first_page_bytes = 0;
  66 + uint32_t pdata_mapped_pages;
  67 + struct trans_rpage_info *rpinfo;
  68 +
  69 + *pdata_off = (size_t)req->tc->pubuf & (PAGE_SIZE-1);
  70 +
  71 + if (*pdata_off)
  72 + first_page_bytes = min((PAGE_SIZE - *pdata_off),
  73 + req->tc->pbuf_size);
  74 +
  75 + rpinfo = req->tc->private;
  76 + pdata_mapped_pages = get_user_pages_fast((unsigned long)req->tc->pubuf,
  77 + nr_pages, rw, &rpinfo->rp_data[0]);
  78 +
  79 + if (pdata_mapped_pages < 0) {
  80 + printk(KERN_ERR "get_user_pages_fast failed:%d udata:%p"
  81 + "nr_pages:%d\n", pdata_mapped_pages,
  82 + req->tc->pubuf, nr_pages);
  83 + pdata_mapped_pages = 0;
  84 + return -EIO;
  85 + }
  86 + rpinfo->rp_nr_pages = pdata_mapped_pages;
  87 + if (*pdata_off) {
  88 + *pdata_len = first_page_bytes;
  89 + *pdata_len += min((req->tc->pbuf_size - *pdata_len),
  90 + ((size_t)pdata_mapped_pages - 1) << PAGE_SHIFT);
  91 + } else {
  92 + *pdata_len = min(req->tc->pbuf_size,
  93 + (size_t)pdata_mapped_pages << PAGE_SHIFT);
  94 + }
  95 + return 0;
  96 +}
  97 +EXPORT_SYMBOL(p9_payload_gup);
net/9p/trans_common.h
  1 +/*
  2 + * Copyright IBM Corporation, 2010
  3 + * Author Venkateswararao Jujjuri <jvrao@linux.vnet.ibm.com>
  4 + *
  5 + * This program is free software; you can redistribute it and/or modify it
  6 + * under the terms of version 2.1 of the GNU Lesser General Public License
  7 + * as published by the Free Software Foundation.
  8 + *
  9 + * This program is distributed in the hope that it would be useful, but
  10 + * WITHOUT ANY WARRANTY; without even the implied warranty of
  11 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  12 + *
  13 + */
  14 +
  15 +/**
  16 + * struct trans_rpage_info - To store mapped page information in PDU.
  17 + * @rp_alloc:Set if this structure is allocd, not a reuse unused space in pdu.
  18 + * @rp_nr_pages: Number of mapped pages
  19 + * @rp_data: Array of page pointers
  20 + */
  21 +struct trans_rpage_info {
  22 + u8 rp_alloc;
  23 + int rp_nr_pages;
  24 + struct page *rp_data[0];
  25 +};
  26 +
  27 +void p9_release_req_pages(struct trans_rpage_info *);
  28 +int p9_payload_gup(struct p9_req_t *, size_t *, int *, int, u8);
  29 +int p9_nr_pages(struct p9_req_t *);