diff options
Diffstat (limited to 'net/sunrpc/xdr.c')
-rw-r--r-- | net/sunrpc/xdr.c | 16 |
1 files changed, 13 insertions, 3 deletions
diff --git a/net/sunrpc/xdr.c b/net/sunrpc/xdr.c index f86d1baa6302..65b268d39782 100644 --- a/net/sunrpc/xdr.c +++ b/net/sunrpc/xdr.c | |||
@@ -176,7 +176,7 @@ xdr_inline_pages(struct xdr_buf *xdr, unsigned int offset, | |||
176 | xdr->buflen += len; | 176 | xdr->buflen += len; |
177 | } | 177 | } |
178 | 178 | ||
179 | void | 179 | int |
180 | xdr_partial_copy_from_skb(struct xdr_buf *xdr, unsigned int base, | 180 | xdr_partial_copy_from_skb(struct xdr_buf *xdr, unsigned int base, |
181 | skb_reader_t *desc, | 181 | skb_reader_t *desc, |
182 | skb_read_actor_t copy_actor) | 182 | skb_read_actor_t copy_actor) |
@@ -190,7 +190,7 @@ xdr_partial_copy_from_skb(struct xdr_buf *xdr, unsigned int base, | |||
190 | len -= base; | 190 | len -= base; |
191 | ret = copy_actor(desc, (char *)xdr->head[0].iov_base + base, len); | 191 | ret = copy_actor(desc, (char *)xdr->head[0].iov_base + base, len); |
192 | if (ret != len || !desc->count) | 192 | if (ret != len || !desc->count) |
193 | return; | 193 | return 0; |
194 | base = 0; | 194 | base = 0; |
195 | } else | 195 | } else |
196 | base -= len; | 196 | base -= len; |
@@ -210,6 +210,14 @@ xdr_partial_copy_from_skb(struct xdr_buf *xdr, unsigned int base, | |||
210 | do { | 210 | do { |
211 | char *kaddr; | 211 | char *kaddr; |
212 | 212 | ||
213 | /* ACL likes to be lazy in allocating pages - ACLs | ||
214 | * are small by default but can get huge. */ | ||
215 | if (unlikely(*ppage == NULL)) { | ||
216 | *ppage = alloc_page(GFP_ATOMIC); | ||
217 | if (unlikely(*ppage == NULL)) | ||
218 | return -ENOMEM; | ||
219 | } | ||
220 | |||
213 | len = PAGE_CACHE_SIZE; | 221 | len = PAGE_CACHE_SIZE; |
214 | kaddr = kmap_atomic(*ppage, KM_SKB_SUNRPC_DATA); | 222 | kaddr = kmap_atomic(*ppage, KM_SKB_SUNRPC_DATA); |
215 | if (base) { | 223 | if (base) { |
@@ -226,13 +234,15 @@ xdr_partial_copy_from_skb(struct xdr_buf *xdr, unsigned int base, | |||
226 | flush_dcache_page(*ppage); | 234 | flush_dcache_page(*ppage); |
227 | kunmap_atomic(kaddr, KM_SKB_SUNRPC_DATA); | 235 | kunmap_atomic(kaddr, KM_SKB_SUNRPC_DATA); |
228 | if (ret != len || !desc->count) | 236 | if (ret != len || !desc->count) |
229 | return; | 237 | return 0; |
230 | ppage++; | 238 | ppage++; |
231 | } while ((pglen -= len) != 0); | 239 | } while ((pglen -= len) != 0); |
232 | copy_tail: | 240 | copy_tail: |
233 | len = xdr->tail[0].iov_len; | 241 | len = xdr->tail[0].iov_len; |
234 | if (base < len) | 242 | if (base < len) |
235 | copy_actor(desc, (char *)xdr->tail[0].iov_base + base, len - base); | 243 | copy_actor(desc, (char *)xdr->tail[0].iov_base + base, len - base); |
244 | |||
245 | return 0; | ||
236 | } | 246 | } |
237 | 247 | ||
238 | 248 | ||