diff options
Diffstat (limited to 'net/sunrpc/xdr.c')
-rw-r--r-- | net/sunrpc/xdr.c | 177 |
1 files changed, 1 insertions, 176 deletions
diff --git a/net/sunrpc/xdr.c b/net/sunrpc/xdr.c index fde16f40a58..32df43372ee 100644 --- a/net/sunrpc/xdr.c +++ b/net/sunrpc/xdr.c | |||
@@ -6,15 +6,12 @@ | |||
6 | * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de> | 6 | * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de> |
7 | */ | 7 | */ |
8 | 8 | ||
9 | #include <linux/module.h> | ||
9 | #include <linux/types.h> | 10 | #include <linux/types.h> |
10 | #include <linux/socket.h> | ||
11 | #include <linux/string.h> | 11 | #include <linux/string.h> |
12 | #include <linux/kernel.h> | 12 | #include <linux/kernel.h> |
13 | #include <linux/pagemap.h> | 13 | #include <linux/pagemap.h> |
14 | #include <linux/errno.h> | 14 | #include <linux/errno.h> |
15 | #include <linux/in.h> | ||
16 | #include <linux/net.h> | ||
17 | #include <net/sock.h> | ||
18 | #include <linux/sunrpc/xdr.h> | 15 | #include <linux/sunrpc/xdr.h> |
19 | #include <linux/sunrpc/msg_prot.h> | 16 | #include <linux/sunrpc/msg_prot.h> |
20 | 17 | ||
@@ -176,178 +173,6 @@ xdr_inline_pages(struct xdr_buf *xdr, unsigned int offset, | |||
176 | xdr->buflen += len; | 173 | xdr->buflen += len; |
177 | } | 174 | } |
178 | 175 | ||
179 | ssize_t | ||
180 | xdr_partial_copy_from_skb(struct xdr_buf *xdr, unsigned int base, | ||
181 | skb_reader_t *desc, | ||
182 | skb_read_actor_t copy_actor) | ||
183 | { | ||
184 | struct page **ppage = xdr->pages; | ||
185 | unsigned int len, pglen = xdr->page_len; | ||
186 | ssize_t copied = 0; | ||
187 | int ret; | ||
188 | |||
189 | len = xdr->head[0].iov_len; | ||
190 | if (base < len) { | ||
191 | len -= base; | ||
192 | ret = copy_actor(desc, (char *)xdr->head[0].iov_base + base, len); | ||
193 | copied += ret; | ||
194 | if (ret != len || !desc->count) | ||
195 | goto out; | ||
196 | base = 0; | ||
197 | } else | ||
198 | base -= len; | ||
199 | |||
200 | if (pglen == 0) | ||
201 | goto copy_tail; | ||
202 | if (base >= pglen) { | ||
203 | base -= pglen; | ||
204 | goto copy_tail; | ||
205 | } | ||
206 | if (base || xdr->page_base) { | ||
207 | pglen -= base; | ||
208 | base += xdr->page_base; | ||
209 | ppage += base >> PAGE_CACHE_SHIFT; | ||
210 | base &= ~PAGE_CACHE_MASK; | ||
211 | } | ||
212 | do { | ||
213 | char *kaddr; | ||
214 | |||
215 | /* ACL likes to be lazy in allocating pages - ACLs | ||
216 | * are small by default but can get huge. */ | ||
217 | if (unlikely(*ppage == NULL)) { | ||
218 | *ppage = alloc_page(GFP_ATOMIC); | ||
219 | if (unlikely(*ppage == NULL)) { | ||
220 | if (copied == 0) | ||
221 | copied = -ENOMEM; | ||
222 | goto out; | ||
223 | } | ||
224 | } | ||
225 | |||
226 | len = PAGE_CACHE_SIZE; | ||
227 | kaddr = kmap_atomic(*ppage, KM_SKB_SUNRPC_DATA); | ||
228 | if (base) { | ||
229 | len -= base; | ||
230 | if (pglen < len) | ||
231 | len = pglen; | ||
232 | ret = copy_actor(desc, kaddr + base, len); | ||
233 | base = 0; | ||
234 | } else { | ||
235 | if (pglen < len) | ||
236 | len = pglen; | ||
237 | ret = copy_actor(desc, kaddr, len); | ||
238 | } | ||
239 | flush_dcache_page(*ppage); | ||
240 | kunmap_atomic(kaddr, KM_SKB_SUNRPC_DATA); | ||
241 | copied += ret; | ||
242 | if (ret != len || !desc->count) | ||
243 | goto out; | ||
244 | ppage++; | ||
245 | } while ((pglen -= len) != 0); | ||
246 | copy_tail: | ||
247 | len = xdr->tail[0].iov_len; | ||
248 | if (base < len) | ||
249 | copied += copy_actor(desc, (char *)xdr->tail[0].iov_base + base, len - base); | ||
250 | out: | ||
251 | return copied; | ||
252 | } | ||
253 | |||
254 | |||
255 | int | ||
256 | xdr_sendpages(struct socket *sock, struct sockaddr *addr, int addrlen, | ||
257 | struct xdr_buf *xdr, unsigned int base, int msgflags) | ||
258 | { | ||
259 | struct page **ppage = xdr->pages; | ||
260 | unsigned int len, pglen = xdr->page_len; | ||
261 | int err, ret = 0; | ||
262 | ssize_t (*sendpage)(struct socket *, struct page *, int, size_t, int); | ||
263 | |||
264 | len = xdr->head[0].iov_len; | ||
265 | if (base < len || (addr != NULL && base == 0)) { | ||
266 | struct kvec iov = { | ||
267 | .iov_base = xdr->head[0].iov_base + base, | ||
268 | .iov_len = len - base, | ||
269 | }; | ||
270 | struct msghdr msg = { | ||
271 | .msg_name = addr, | ||
272 | .msg_namelen = addrlen, | ||
273 | .msg_flags = msgflags, | ||
274 | }; | ||
275 | if (xdr->len > len) | ||
276 | msg.msg_flags |= MSG_MORE; | ||
277 | |||
278 | if (iov.iov_len != 0) | ||
279 | err = kernel_sendmsg(sock, &msg, &iov, 1, iov.iov_len); | ||
280 | else | ||
281 | err = kernel_sendmsg(sock, &msg, NULL, 0, 0); | ||
282 | if (ret == 0) | ||
283 | ret = err; | ||
284 | else if (err > 0) | ||
285 | ret += err; | ||
286 | if (err != iov.iov_len) | ||
287 | goto out; | ||
288 | base = 0; | ||
289 | } else | ||
290 | base -= len; | ||
291 | |||
292 | if (pglen == 0) | ||
293 | goto copy_tail; | ||
294 | if (base >= pglen) { | ||
295 | base -= pglen; | ||
296 | goto copy_tail; | ||
297 | } | ||
298 | if (base || xdr->page_base) { | ||
299 | pglen -= base; | ||
300 | base += xdr->page_base; | ||
301 | ppage += base >> PAGE_CACHE_SHIFT; | ||
302 | base &= ~PAGE_CACHE_MASK; | ||
303 | } | ||
304 | |||
305 | sendpage = sock->ops->sendpage ? : sock_no_sendpage; | ||
306 | do { | ||
307 | int flags = msgflags; | ||
308 | |||
309 | len = PAGE_CACHE_SIZE; | ||
310 | if (base) | ||
311 | len -= base; | ||
312 | if (pglen < len) | ||
313 | len = pglen; | ||
314 | |||
315 | if (pglen != len || xdr->tail[0].iov_len != 0) | ||
316 | flags |= MSG_MORE; | ||
317 | |||
318 | /* Hmm... We might be dealing with highmem pages */ | ||
319 | if (PageHighMem(*ppage)) | ||
320 | sendpage = sock_no_sendpage; | ||
321 | err = sendpage(sock, *ppage, base, len, flags); | ||
322 | if (ret == 0) | ||
323 | ret = err; | ||
324 | else if (err > 0) | ||
325 | ret += err; | ||
326 | if (err != len) | ||
327 | goto out; | ||
328 | base = 0; | ||
329 | ppage++; | ||
330 | } while ((pglen -= len) != 0); | ||
331 | copy_tail: | ||
332 | len = xdr->tail[0].iov_len; | ||
333 | if (base < len) { | ||
334 | struct kvec iov = { | ||
335 | .iov_base = xdr->tail[0].iov_base + base, | ||
336 | .iov_len = len - base, | ||
337 | }; | ||
338 | struct msghdr msg = { | ||
339 | .msg_flags = msgflags, | ||
340 | }; | ||
341 | err = kernel_sendmsg(sock, &msg, &iov, 1, iov.iov_len); | ||
342 | if (ret == 0) | ||
343 | ret = err; | ||
344 | else if (err > 0) | ||
345 | ret += err; | ||
346 | } | ||
347 | out: | ||
348 | return ret; | ||
349 | } | ||
350 | |||
351 | 176 | ||
352 | /* | 177 | /* |
353 | * Helper routines for doing 'memmove' like operations on a struct xdr_buf | 178 | * Helper routines for doing 'memmove' like operations on a struct xdr_buf |