Commit 022cae36551ba805bf82084047945b2901d75f36
Committed by
Eric Van Hensbergen
1 parent
6752a1ebd1
Exists in
master
and in
7 other branches
[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
include/net/9p/9p.h
... | ... | @@ -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 | }; |
net/9p/Makefile
net/9p/protocol.c
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 *); |