aboutsummaryrefslogtreecommitdiffstats
path: root/net/rds/iw_recv.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/rds/iw_recv.c')
-rw-r--r--net/rds/iw_recv.c37
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
306int rds_iw_inc_copy_to_user(struct rds_incoming *inc, struct iovec *first_iov, 306int 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 }