diff options
Diffstat (limited to 'net/rds/iw_recv.c')
-rw-r--r-- | net/rds/iw_recv.c | 37 |
1 files changed, 11 insertions, 26 deletions
diff --git a/net/rds/iw_recv.c b/net/rds/iw_recv.c index aa8bf6786008..a66d1794b2d0 100644 --- a/net/rds/iw_recv.c +++ b/net/rds/iw_recv.c | |||
@@ -303,15 +303,12 @@ void rds_iw_inc_free(struct rds_incoming *inc) | |||
303 | BUG_ON(atomic_read(&rds_iw_allocation) < 0); | 303 | BUG_ON(atomic_read(&rds_iw_allocation) < 0); |
304 | } | 304 | } |
305 | 305 | ||
306 | int rds_iw_inc_copy_to_user(struct rds_incoming *inc, struct iovec *first_iov, | 306 | int rds_iw_inc_copy_to_user(struct rds_incoming *inc, struct iov_iter *to) |
307 | size_t size) | ||
308 | { | 307 | { |
309 | struct rds_iw_incoming *iwinc; | 308 | struct rds_iw_incoming *iwinc; |
310 | struct rds_page_frag *frag; | 309 | struct rds_page_frag *frag; |
311 | struct iovec *iov = first_iov; | ||
312 | unsigned long to_copy; | 310 | unsigned long to_copy; |
313 | unsigned long frag_off = 0; | 311 | unsigned long frag_off = 0; |
314 | unsigned long iov_off = 0; | ||
315 | int copied = 0; | 312 | int copied = 0; |
316 | int ret; | 313 | int ret; |
317 | u32 len; | 314 | u32 len; |
@@ -320,37 +317,25 @@ int rds_iw_inc_copy_to_user(struct rds_incoming *inc, struct iovec *first_iov, | |||
320 | frag = list_entry(iwinc->ii_frags.next, struct rds_page_frag, f_item); | 317 | frag = list_entry(iwinc->ii_frags.next, struct rds_page_frag, f_item); |
321 | len = be32_to_cpu(inc->i_hdr.h_len); | 318 | len = be32_to_cpu(inc->i_hdr.h_len); |
322 | 319 | ||
323 | while (copied < size && copied < len) { | 320 | while (iov_iter_count(to) && copied < len) { |
324 | if (frag_off == RDS_FRAG_SIZE) { | 321 | if (frag_off == RDS_FRAG_SIZE) { |
325 | frag = list_entry(frag->f_item.next, | 322 | frag = list_entry(frag->f_item.next, |
326 | struct rds_page_frag, f_item); | 323 | struct rds_page_frag, f_item); |
327 | frag_off = 0; | 324 | frag_off = 0; |
328 | } | 325 | } |
329 | while (iov_off == iov->iov_len) { | 326 | to_copy = min_t(unsigned long, iov_iter_count(to), |
330 | iov_off = 0; | 327 | RDS_FRAG_SIZE - frag_off); |
331 | iov++; | ||
332 | } | ||
333 | |||
334 | to_copy = min(iov->iov_len - iov_off, RDS_FRAG_SIZE - frag_off); | ||
335 | to_copy = min_t(size_t, to_copy, size - copied); | ||
336 | to_copy = min_t(unsigned long, to_copy, len - copied); | 328 | to_copy = min_t(unsigned long, to_copy, len - copied); |
337 | 329 | ||
338 | rdsdebug("%lu bytes to user [%p, %zu] + %lu from frag " | ||
339 | "[%p, %lu] + %lu\n", | ||
340 | to_copy, iov->iov_base, iov->iov_len, iov_off, | ||
341 | frag->f_page, frag->f_offset, frag_off); | ||
342 | |||
343 | /* XXX needs + offset for multiple recvs per page */ | 330 | /* XXX needs + offset for multiple recvs per page */ |
344 | ret = rds_page_copy_to_user(frag->f_page, | 331 | rds_stats_add(s_copy_to_user, to_copy); |
345 | frag->f_offset + frag_off, | 332 | ret = copy_page_to_iter(frag->f_page, |
346 | iov->iov_base + iov_off, | 333 | frag->f_offset + frag_off, |
347 | to_copy); | 334 | to_copy, |
348 | if (ret) { | 335 | to); |
349 | copied = ret; | 336 | if (ret != to_copy) |
350 | break; | 337 | return -EFAULT; |
351 | } | ||
352 | 338 | ||
353 | iov_off += to_copy; | ||
354 | frag_off += to_copy; | 339 | frag_off += to_copy; |
355 | copied += to_copy; | 340 | copied += to_copy; |
356 | } | 341 | } |