]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
rds: UNDO reverts done for rebase code to compile with Linux 4.1 APIs
authorMukesh Kacker <mukesh.kacker@oracle.com>
Sun, 19 Apr 2015 22:26:19 +0000 (15:26 -0700)
committerMukesh Kacker <mukesh.kacker@oracle.com>
Wed, 8 Jul 2015 20:12:42 +0000 (13:12 -0700)
Commit 163377dd82f2d81809aabe736a2e0ea515055a69 does reverts
to common ancestor of upstream and UEK2 to rebase UEK2 patches
for net/rds. This commit undoes reverts needed to compile to
Linux 4.0 APIs.

UNDO Revert "net: Replace get_cpu_var through this_cpu_ptr" for net/rds
This commit does UNDO of revert of commit 903ceff7ca7b4d80c083a80ee5163b74e9fa359f for net/rds.

UNDO Revert "rds: switch ->inc_copy_to_user() to passing iov_iter"
This commit does UNDO of revert of commit c310e72c89926e06138e4881f21e4c8da3e7ef18

UNDO Revert of "rds: switch rds_message_copy_from_user() to iov_iter"
This commit does UNDO of revert of commit 083735f4b01b703184c0e11c2e384b2c60a8aea4.

UNDO Revert "put iov_iter into msghdr" for net/rds
This commit does UNDO of revert of commit c0371da6047abd261bc483c744dbc7d81a116172 for net/rds

UNDO Revert "net: introduce helper macro for_each_cmsghdr" for net/rds
This commit does UNDO of revert of commit f95b414edb18de59940dcebbefb49cf25c6d505c for net/rds

UNDO Revert "rds: Fix min() warning in rds_message_inc_copy_to_user()"
This commit does UNDO of revert of commit 6ff4a8ad4b6eae5171754fb60418bc81834aa09b.

UNDO Revert "rds: Make rds_message_copy_from_user() return 0 on success."
This commit does UNDO of revert of commit d0a47d32724bf0765b8768086ef1a7a6d074a7a0.

UNDO Revert "net: Remove iocb argument from sendmsg and recvmsg" for net/rds
This commit does UNDO of revert of commit 1b784140474e4fc94281a49e96c67d29df0efbde for net/rds.

These commits were reverted earlier to rebase unmodified UEK2 RDS code
(UNDO needed to compile to new Linux 4.1 kernel APIs - changed *after* Linux 3.18)

Signed-off-by: Mukesh Kacker <mukesh.kacker@oracle.com>
net/rds/ib.h
net/rds/ib_rdma.c
net/rds/ib_recv.c
net/rds/iw.h
net/rds/iw_recv.c
net/rds/message.c
net/rds/rds.h
net/rds/recv.c
net/rds/send.c
net/rds/tcp.h
net/rds/tcp_recv.c

index 8799ddb371739679316940809fb86dc467611cc1..44092f905beba5ebf71146552b2b8786a5c3da92 100644 (file)
@@ -492,8 +492,7 @@ int rds_ib_recv_alloc_caches(struct rds_ib_connection *ic);
 void rds_ib_recv_free_caches(struct rds_ib_connection *ic);
 void rds_ib_recv_refill(struct rds_connection *conn, int prefill, gfp_t gfp);
 void rds_ib_inc_free(struct rds_incoming *inc);
-int rds_ib_inc_copy_to_user(struct rds_incoming *inc, struct iovec *iov,
-                            size_t size);
+int rds_ib_inc_copy_to_user(struct rds_incoming *inc, struct iov_iter *to);
 void rds_ib_recv_cqe_handler(struct rds_ib_connection *ic,
                            struct ib_wc *wc,
                            struct rds_ib_ack_state *state);
index 1ac02fdb90a52743f4c6d4f0678fd1c30c645949..3cac288e4530b0afbf2f7831e42ed53dcfd1a1e6 100644 (file)
@@ -288,7 +288,7 @@ static inline struct rds_ib_mr *rds_ib_reuse_fmr(struct rds_ib_mr_pool *pool)
        unsigned long *flag;
 
        preempt_disable();
-       flag = &__get_cpu_var(clean_list_grace);
+       flag = this_cpu_ptr(&clean_list_grace);
        set_bit(CLEAN_LIST_BUSY_BIT, flag);
        ret = xlist_del_head(&pool->clean_list);
        if (ret)
index a22d9097081e50203ee9092871e97a094113f94d..40fdd665c7a81a835d70d83618b5ca2079ae9e3e 100644 (file)
@@ -704,15 +704,12 @@ static struct list_head *rds_ib_recv_cache_get(struct rds_ib_refill_cache *cache
        return head;
 }
 
-int rds_ib_inc_copy_to_user(struct rds_incoming *inc, struct iovec *first_iov,
-                           size_t size)
+int rds_ib_inc_copy_to_user(struct rds_incoming *inc, struct iov_iter *to)
 {
        struct rds_ib_incoming *ibinc;
        struct rds_page_frag *frag;
-       struct iovec *iov = first_iov;
        unsigned long to_copy;
        unsigned long frag_off = 0;
-       unsigned long iov_off = 0;
        int copied = 0;
        int ret;
        u32 len;
@@ -721,37 +718,25 @@ int rds_ib_inc_copy_to_user(struct rds_incoming *inc, struct iovec *first_iov,
        frag = list_entry(ibinc->ii_frags.next, struct rds_page_frag, f_item);
        len = be32_to_cpu(inc->i_hdr.h_len);
 
-       while (copied < size && copied < len) {
+       while (iov_iter_count(to) && copied < len) {
                if (frag_off == RDS_FRAG_SIZE) {
                        frag = list_entry(frag->f_item.next,
                                          struct rds_page_frag, f_item);
                        frag_off = 0;
                }
-               while (iov_off == iov->iov_len) {
-                       iov_off = 0;
-                       iov++;
-               }
-
-               to_copy = min(iov->iov_len - iov_off, RDS_FRAG_SIZE - frag_off);
-               to_copy = min_t(size_t, to_copy, size - copied);
+               to_copy = min_t(unsigned long, iov_iter_count(to),
+                               RDS_FRAG_SIZE - frag_off);
                to_copy = min_t(unsigned long, to_copy, len - copied);
 
-               rdsdebug("%lu bytes to user [%p, %zu] + %lu from frag "
-                        "[%p, %u] + %lu\n",
-                        to_copy, iov->iov_base, iov->iov_len, iov_off,
-                        sg_page(&frag->f_sg), frag->f_sg.offset, frag_off);
-
                /* XXX needs + offset for multiple recvs per page */
-               ret = rds_page_copy_to_user(sg_page(&frag->f_sg),
-                                           frag->f_sg.offset + frag_off,
-                                           iov->iov_base + iov_off,
-                                           to_copy);
-               if (ret) {
-                       copied = ret;
-                       break;
-               }
+               rds_stats_add(s_copy_to_user, to_copy);
+               ret = copy_page_to_iter(sg_page(&frag->f_sg),
+                                       frag->f_sg.offset + frag_off,
+                                       to_copy,
+                                       to);
+               if (ret != to_copy)
+                       return -EFAULT;
 
-               iov_off += to_copy;
                frag_off += to_copy;
                copied += to_copy;
        }
index 1e59190809c25be56c6eb0012afb3daa5f532a7a..8d57cf7cfde11ccc82e0625bb7d1d80cf0d3502b 100644 (file)
@@ -327,8 +327,7 @@ int rds_iw_recv(struct rds_connection *conn);
 int rds_iw_recv_refill(struct rds_connection *conn, gfp_t kptr_gfp,
                       gfp_t page_gfp, int prefill);
 void rds_iw_inc_free(struct rds_incoming *inc);
-int rds_iw_inc_copy_to_user(struct rds_incoming *inc, struct iovec *iov,
-                            size_t size);
+int rds_iw_inc_copy_to_user(struct rds_incoming *inc, struct iov_iter *to);
 void rds_iw_recv_cq_comp_handler(struct ib_cq *cq, void *context);
 void rds_iw_recv_tasklet_fn(unsigned long data);
 void rds_iw_recv_init_ring(struct rds_iw_connection *ic);
index b1b3aa66c30d0f804ac6a5508eb848d81466dbbc..545fb526f77b111b085843e3aa691985b185ce48 100644 (file)
@@ -302,15 +302,12 @@ void rds_iw_inc_free(struct rds_incoming *inc)
        BUG_ON(atomic_read(&rds_iw_allocation) < 0);
 }
 
-int rds_iw_inc_copy_to_user(struct rds_incoming *inc, struct iovec *first_iov,
-                           size_t size)
+int rds_iw_inc_copy_to_user(struct rds_incoming *inc, struct iov_iter *to)
 {
        struct rds_iw_incoming *iwinc;
        struct rds_page_frag *frag;
-       struct iovec *iov = first_iov;
        unsigned long to_copy;
        unsigned long frag_off = 0;
-       unsigned long iov_off = 0;
        int copied = 0;
        int ret;
        u32 len;
@@ -319,37 +316,25 @@ int rds_iw_inc_copy_to_user(struct rds_incoming *inc, struct iovec *first_iov,
        frag = list_entry(iwinc->ii_frags.next, struct rds_page_frag, f_item);
        len = be32_to_cpu(inc->i_hdr.h_len);
 
-       while (copied < size && copied < len) {
+       while (iov_iter_count(to) && copied < len) {
                if (frag_off == RDS_FRAG_SIZE) {
                        frag = list_entry(frag->f_item.next,
                                          struct rds_page_frag, f_item);
                        frag_off = 0;
                }
-               while (iov_off == iov->iov_len) {
-                       iov_off = 0;
-                       iov++;
-               }
-
-               to_copy = min(iov->iov_len - iov_off, RDS_FRAG_SIZE - frag_off);
-               to_copy = min_t(size_t, to_copy, size - copied);
+               to_copy = min_t(unsigned long, iov_iter_count(to),
+                               RDS_FRAG_SIZE - frag_off);
                to_copy = min_t(unsigned long, to_copy, len - copied);
 
-               rdsdebug("%lu bytes to user [%p, %zu] + %lu from frag "
-                        "[%p, %lu] + %lu\n",
-                        to_copy, iov->iov_base, iov->iov_len, iov_off,
-                        frag->f_page, frag->f_offset, frag_off);
-
                /* XXX needs + offset for multiple recvs per page */
-               ret = rds_page_copy_to_user(frag->f_page,
-                                           frag->f_offset + frag_off,
-                                           iov->iov_base + iov_off,
-                                           to_copy);
-               if (ret) {
-                       copied = ret;
-                       break;
-               }
+               rds_stats_add(s_copy_to_user, to_copy);
+               ret = copy_page_to_iter(frag->f_page,
+                                       frag->f_offset + frag_off,
+                                       to_copy,
+                                       to);
+               if (ret != to_copy)
+                       return -EFAULT;
 
-               iov_off += to_copy;
                frag_off += to_copy;
                copied += to_copy;
        }
index 4ed85e11cca89e5df0a2a1529e8811eb797a624f..587f87b9dc1b1eed69287c3f28314976dfc7efb4 100644 (file)
@@ -276,75 +276,54 @@ struct rds_message *rds_message_map_pages(unsigned long *page_addrs, unsigned in
        return rm;
 }
 
-int rds_message_copy_from_user(struct rds_message *rm, struct iovec *first_iov,
-                                              size_t total_len)
+int rds_message_copy_from_user(struct rds_message *rm, struct iov_iter *from)
 {
-       unsigned long to_copy;
-       unsigned long iov_off;
+       unsigned long to_copy, nbytes;
        unsigned long sg_off;
-       struct iovec *iov;
        struct scatterlist *sg;
        int ret = 0;
 
-       rm->m_inc.i_hdr.h_len = cpu_to_be32(total_len);
+       rm->m_inc.i_hdr.h_len = cpu_to_be32(iov_iter_count(from));
 
        /*
         * now allocate and copy in the data payload.
         */
        sg = rm->data.op_sg;
-       iov = first_iov;
-       iov_off = 0;
        sg_off = 0; /* Dear gcc, sg->page will be null from kzalloc. */
 
-       while (total_len) {
+       while (iov_iter_count(from)) {
                if (!sg_page(sg)) {
-                       ret = rds_page_remainder_alloc(sg, total_len,
+                       ret = rds_page_remainder_alloc(sg, iov_iter_count(from),
                                                       GFP_HIGHUSER);
                        if (ret)
-                               goto out;
+                               return ret;
                        rm->data.op_nents++;
                        sg_off = 0;
                }
 
-               while (iov_off == iov->iov_len) {
-                       iov_off = 0;
-                       iov++;
-               }
-
-               to_copy = min(iov->iov_len - iov_off, sg->length - sg_off);
-               to_copy = min_t(size_t, to_copy, total_len);
-
-               rdsdebug("copying %lu bytes from user iov [%p, %zu] + %lu to "
-                        "sg [%p, %u, %u] + %lu\n",
-                        to_copy, iov->iov_base, iov->iov_len, iov_off,
-                        (void *)sg_page(sg), sg->offset, sg->length, sg_off);
+               to_copy = min_t(unsigned long, iov_iter_count(from),
+                               sg->length - sg_off);
 
-               ret = rds_page_copy_from_user(sg_page(sg), sg->offset + sg_off,
-                                             iov->iov_base + iov_off,
-                                             to_copy);
-               if (ret)
-                       goto out;
+               rds_stats_add(s_copy_from_user, to_copy);
+               nbytes = copy_page_from_iter(sg_page(sg), sg->offset + sg_off,
+                                            to_copy, from);
+               if (nbytes != to_copy)
+                       return -EFAULT;
 
-               iov_off += to_copy;
-               total_len -= to_copy;
                sg_off += to_copy;
 
                if (sg_off == sg->length)
                        sg++;
        }
 
-out:
        return ret;
 }
 
-int rds_message_inc_copy_to_user(struct rds_incoming *inc,
-                                struct iovec *first_iov, size_t size)
+int rds_message_inc_copy_to_user(struct rds_incoming *inc, struct iov_iter *to)
 {
        struct rds_message *rm;
-       struct iovec *iov;
        struct scatterlist *sg;
        unsigned long to_copy;
-       unsigned long iov_off;
        unsigned long vec_off;
        int copied;
        int ret;
@@ -353,36 +332,21 @@ int rds_message_inc_copy_to_user(struct rds_incoming *inc,
        rm = container_of(inc, struct rds_message, m_inc);
        len = be32_to_cpu(rm->m_inc.i_hdr.h_len);
 
-       iov = first_iov;
-       iov_off = 0;
        sg = rm->data.op_sg;
        vec_off = 0;
        copied = 0;
 
-       while (copied < size && copied < len) {
-               while (iov_off == iov->iov_len) {
-                       iov_off = 0;
-                       iov++;
-               }
-
-               to_copy = min(iov->iov_len - iov_off, sg->length - vec_off);
-               to_copy = min_t(size_t, to_copy, size - copied);
+       while (iov_iter_count(to) && copied < len) {
+               to_copy = min_t(unsigned long, iov_iter_count(to),
+                               sg->length - vec_off);
                to_copy = min_t(unsigned long, to_copy, len - copied);
 
-               rdsdebug("copying %lu bytes to user iov [%p, %zu] + %lu to "
-                        "sg [%p, %u, %u] + %lu\n",
-                        to_copy, iov->iov_base, iov->iov_len, iov_off,
-                        sg_page(sg), sg->offset, sg->length, vec_off);
-
-               ret = rds_page_copy_to_user(sg_page(sg), sg->offset + vec_off,
-                                           iov->iov_base + iov_off,
-                                           to_copy);
-               if (ret) {
-                       copied = ret;
-                       break;
-               }
+               rds_stats_add(s_copy_to_user, to_copy);
+               ret = copy_page_to_iter(sg_page(sg), sg->offset + vec_off,
+                                       to_copy, to);
+               if (ret != to_copy)
+                       return -EFAULT;
 
-               iov_off += to_copy;
                vec_off += to_copy;
                copied += to_copy;
 
index 6c44c38f3467b2db012cd87e04f9d8ba62daaa32..4716e239d5ecb18c411370d5651741be9446091a 100644 (file)
@@ -457,8 +457,7 @@ struct rds_transport {
        int (*xmit_rdma)(struct rds_connection *conn, struct rm_rdma_op *op);
        int (*xmit_atomic)(struct rds_connection *conn, struct rm_atomic_op *op);
        int (*recv)(struct rds_connection *conn);
-       int (*inc_copy_to_user)(struct rds_incoming *inc, struct iovec *iov,
-                               size_t size);
+       int (*inc_copy_to_user)(struct rds_incoming *inc, struct iov_iter *to);
        void (*inc_free)(struct rds_incoming *inc);
 
        int (*cm_handle_connect)(struct rdma_cm_id *cm_id,
@@ -696,8 +695,7 @@ rds_conn_connecting(struct rds_connection *conn)
 /* message.c */
 struct rds_message *rds_message_alloc(unsigned int nents, gfp_t gfp);
 struct scatterlist *rds_message_alloc_sgs(struct rds_message *rm, int nents);
-int rds_message_copy_from_user(struct rds_message *rm, struct iovec *first_iov,
-                                              size_t total_len);
+int rds_message_copy_from_user(struct rds_message *rm, struct iov_iter *from);
 struct rds_message *rds_message_map_pages(unsigned long *page_addrs, unsigned int total_len);
 void rds_message_populate_header(struct rds_header *hdr, __be16 sport,
                                 __be16 dport, u64 seq);
@@ -708,8 +706,7 @@ int rds_message_next_extension(struct rds_header *hdr,
 int rds_message_add_version_extension(struct rds_header *hdr, unsigned int version);
 int rds_message_get_version_extension(struct rds_header *hdr, unsigned int *version);
 int rds_message_add_rdma_dest_extension(struct rds_header *hdr, u32 r_key, u32 offset);
-int rds_message_inc_copy_to_user(struct rds_incoming *inc,
-                                struct iovec *first_iov, size_t size);
+int rds_message_inc_copy_to_user(struct rds_incoming *inc, struct iov_iter *to);
 void rds_message_inc_free(struct rds_incoming *inc);
 void rds_message_addref(struct rds_message *rm);
 void rds_message_put(struct rds_message *rm);
@@ -747,8 +744,8 @@ void rds_inc_addref(struct rds_incoming *inc);
 void rds_inc_put(struct rds_incoming *inc);
 void rds_recv_incoming(struct rds_connection *conn, __be32 saddr, __be32 daddr,
                       struct rds_incoming *inc, gfp_t gfp);
-int rds_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg,
-               size_t size, int msg_flags);
+int rds_recvmsg(struct socket *sock, struct msghdr *msg, size_t size,
+               int msg_flags);
 void rds_clear_recv_queue(struct rds_sock *rs);
 int rds_notify_queue_get(struct rds_sock *rs, struct msghdr *msg);
 void rds_inc_info_copy(struct rds_incoming *inc,
@@ -756,8 +753,7 @@ void rds_inc_info_copy(struct rds_incoming *inc,
                       __be32 saddr, __be32 daddr, int flip);
 
 /* send.c */
-int rds_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg,
-               size_t payload_len);
+int rds_sendmsg(struct socket *sock, struct msghdr *msg, size_t payload_len);
 void rds_send_reset(struct rds_connection *conn);
 int rds_send_xmit(struct rds_connection *conn);
 struct sockaddr_in;
index cd25beb6870174c89398a18cc8b338d7a8e46c12..ba6e420e08ceb169460a468eaee3e5f160eab67e 100644 (file)
@@ -413,8 +413,8 @@ static int rds_cmsg_recv(struct rds_incoming *inc, struct msghdr *msg)
        return 0;
 }
 
-int rds_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg,
-               size_t size, int msg_flags)
+int rds_recvmsg(struct socket *sock, struct msghdr *msg, size_t size,
+               int msg_flags)
 {
        struct sock *sk = sock->sk;
        struct rds_sock *rs = rds_sk_to_rs(sk);
@@ -432,6 +432,7 @@ int rds_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg,
                goto out;
 
        while (1) {
+               struct iov_iter save;
                /* If there are pending notifications, do those - and nothing else */
                if (!list_empty(&rs->rs_notify_queue)) {
                        ret = rds_notify_queue_get(rs, msg);
@@ -468,8 +469,8 @@ int rds_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg,
                rdsdebug("copying inc %p from %pI4:%u to user\n", inc,
                         &inc->i_conn->c_faddr,
                         ntohs(inc->i_hdr.h_sport));
-               ret = inc->i_conn->c_trans->inc_copy_to_user(inc, msg->msg_iov,
-                                                            size);
+               save = msg->msg_iter;
+               ret = inc->i_conn->c_trans->inc_copy_to_user(inc, &msg->msg_iter);
                if (ret < 0)
                        break;
 
@@ -482,6 +483,7 @@ int rds_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg,
                        rds_inc_put(inc);
                        inc = NULL;
                        rds_stats_inc(s_recv_deliver_raced);
+                       msg->msg_iter = save;
                        continue;
                }
 
index f1408f39cbe96162bd7ee057396969b6944efe0e..0ac3ce9bbddd226a0246e10551c12d8087c54872 100644 (file)
@@ -1049,7 +1049,7 @@ static int rds_rm_size(struct msghdr *msg, int data_len)
        int cmsg_groups = 0;
        int retval;
 
-       for (cmsg = CMSG_FIRSTHDR(msg); cmsg; cmsg = CMSG_NXTHDR(msg, cmsg)) {
+       for_each_cmsghdr(cmsg, msg) {
                if (!CMSG_OK(msg, cmsg))
                        return -EINVAL;
 
@@ -1124,7 +1124,7 @@ static int rds_cmsg_send(struct rds_sock *rs, struct rds_message *rm,
        struct cmsghdr *cmsg;
        int ret = 0;
 
-       for (cmsg = CMSG_FIRSTHDR(msg); cmsg; cmsg = CMSG_NXTHDR(msg, cmsg)) {
+       for_each_cmsghdr(cmsg, msg) {
                if (!CMSG_OK(msg, cmsg))
                        return -EINVAL;
 
@@ -1173,8 +1173,7 @@ struct user_hdr {
        u8      op;
 };
 
-int rds_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg,
-               size_t payload_len)
+int rds_sendmsg(struct socket *sock, struct msghdr *msg, size_t payload_len)
 {
        struct sock *sk = sock->sk;
        struct rds_sock *rs = rds_sk_to_rs(sk);
@@ -1233,7 +1232,7 @@ int rds_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg,
        /* Attach data to the rm */
        if (payload_len) {
                rm->data.op_sg = rds_message_alloc_sgs(rm, ceil(payload_len, PAGE_SIZE));
-               ret = rds_message_copy_from_user(rm, msg->msg_iov, payload_len);
+               ret = rds_message_copy_from_user(rm, &msg->msg_iter);
                if (ret)
                        goto out;
        }
index 8b1975b54a02e0c5c40f306cf4bd07fa20ea14a1..750987d0af5dc43943c437470ba9bf2d1b720bd9 100644 (file)
@@ -71,8 +71,7 @@ void rds_tcp_recv_exit(void);
 void rds_tcp_data_ready(struct sock *sk);
 int rds_tcp_recv(struct rds_connection *conn);
 void rds_tcp_inc_free(struct rds_incoming *inc);
-int rds_tcp_inc_copy_to_user(struct rds_incoming *inc, struct iovec *iov,
-                            size_t size);
+int rds_tcp_inc_copy_to_user(struct rds_incoming *inc, struct iov_iter *to);
 
 /* tcp_send.c */
 void rds_tcp_xmit_prepare(struct rds_connection *conn);
index 7cbe929153c8b63323ccf11f3b6a7545f31fd48a..f941f60963f9a4ad31158b412aad5ea030b25804 100644 (file)
@@ -58,50 +58,30 @@ void rds_tcp_inc_free(struct rds_incoming *inc)
 /*
  * this is pretty lame, but, whatever.
  */
-int rds_tcp_inc_copy_to_user(struct rds_incoming *inc, struct iovec *first_iov,
-                            size_t size)
+int rds_tcp_inc_copy_to_user(struct rds_incoming *inc, struct iov_iter *to)
 {
        struct rds_tcp_incoming *tinc;
-       struct iovec *iov, tmp;
        struct sk_buff *skb;
-       unsigned long to_copy, skb_off;
        int ret = 0;
 
-       if (size == 0)
+       if (!iov_iter_count(to))
                goto out;
 
        tinc = container_of(inc, struct rds_tcp_incoming, ti_inc);
-       iov = first_iov;
-       tmp = *iov;
 
        skb_queue_walk(&tinc->ti_skb_list, skb) {
-               skb_off = 0;
-               while (skb_off < skb->len) {
-                       while (tmp.iov_len == 0) {
-                               iov++;
-                               tmp = *iov;
-                       }
-
-                       to_copy = min(tmp.iov_len, size);
+               unsigned long to_copy, skb_off;
+               for (skb_off = 0; skb_off < skb->len; skb_off += to_copy) {
+                       to_copy = iov_iter_count(to);
                        to_copy = min(to_copy, skb->len - skb_off);
 
-                       rdsdebug("ret %d size %zu skb %p skb_off %lu "
-                                "skblen %d iov_base %p iov_len %zu cpy %lu\n",
-                                ret, size, skb, skb_off, skb->len,
-                                tmp.iov_base, tmp.iov_len, to_copy);
-
-                       /* modifies tmp as it copies */
-                       if (skb_copy_datagram_iovec(skb, skb_off, &tmp,
-                                                   to_copy)) {
-                               ret = -EFAULT;
-                               goto out;
-                       }
+                       if (skb_copy_datagram_iter(skb, skb_off, to, to_copy))
+                               return -EFAULT;
 
                        rds_stats_add(s_copy_to_user, to_copy);
-                       size -= to_copy;
                        ret += to_copy;
-                       skb_off += to_copy;
-                       if (size == 0)
+
+                       if (!iov_iter_count(to))
                                goto out;
                }
        }