rds: switch ->inc_copy_to_user() to passing iov_iter

instances get considerably simpler from that...

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
Al Viro 2014-11-20 09:21:14 -05:00
parent 7424ce6506
commit c310e72c89
9 changed files with 47 additions and 120 deletions

View File

@ -316,8 +316,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_free_caches(struct rds_ib_connection *ic);
void rds_ib_recv_refill(struct rds_connection *conn, int prefill); void rds_ib_recv_refill(struct rds_connection *conn, int prefill);
void rds_ib_inc_free(struct rds_incoming *inc); void rds_ib_inc_free(struct rds_incoming *inc);
int rds_ib_inc_copy_to_user(struct rds_incoming *inc, struct iovec *iov, int rds_ib_inc_copy_to_user(struct rds_incoming *inc, struct iov_iter *to);
size_t size);
void rds_ib_recv_cq_comp_handler(struct ib_cq *cq, void *context); void rds_ib_recv_cq_comp_handler(struct ib_cq *cq, void *context);
void rds_ib_recv_tasklet_fn(unsigned long data); void rds_ib_recv_tasklet_fn(unsigned long data);
void rds_ib_recv_init_ring(struct rds_ib_connection *ic); void rds_ib_recv_init_ring(struct rds_ib_connection *ic);

View File

@ -472,15 +472,12 @@ static struct list_head *rds_ib_recv_cache_get(struct rds_ib_refill_cache *cache
return head; return head;
} }
int rds_ib_inc_copy_to_user(struct rds_incoming *inc, struct iovec *first_iov, int rds_ib_inc_copy_to_user(struct rds_incoming *inc, struct iov_iter *to)
size_t size)
{ {
struct rds_ib_incoming *ibinc; struct rds_ib_incoming *ibinc;
struct rds_page_frag *frag; struct rds_page_frag *frag;
struct iovec *iov = first_iov;
unsigned long to_copy; unsigned long to_copy;
unsigned long frag_off = 0; unsigned long frag_off = 0;
unsigned long iov_off = 0;
int copied = 0; int copied = 0;
int ret; int ret;
u32 len; u32 len;
@ -489,37 +486,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); frag = list_entry(ibinc->ii_frags.next, struct rds_page_frag, f_item);
len = be32_to_cpu(inc->i_hdr.h_len); 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) { if (frag_off == RDS_FRAG_SIZE) {
frag = list_entry(frag->f_item.next, frag = list_entry(frag->f_item.next,
struct rds_page_frag, f_item); struct rds_page_frag, f_item);
frag_off = 0; frag_off = 0;
} }
while (iov_off == iov->iov_len) { to_copy = min_t(unsigned long, iov_iter_count(to),
iov_off = 0; RDS_FRAG_SIZE - frag_off);
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, to_copy, len - copied); 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 */ /* XXX needs + offset for multiple recvs per page */
ret = rds_page_copy_to_user(sg_page(&frag->f_sg), rds_stats_add(s_copy_to_user, to_copy);
frag->f_sg.offset + frag_off, ret = copy_page_to_iter(sg_page(&frag->f_sg),
iov->iov_base + iov_off, frag->f_sg.offset + frag_off,
to_copy); to_copy,
if (ret) { to);
copied = ret; if (ret != to_copy)
break; return -EFAULT;
}
iov_off += to_copy;
frag_off += to_copy; frag_off += to_copy;
copied += to_copy; copied += to_copy;
} }

View File

@ -325,8 +325,7 @@ int rds_iw_recv(struct rds_connection *conn);
int rds_iw_recv_refill(struct rds_connection *conn, gfp_t kptr_gfp, int rds_iw_recv_refill(struct rds_connection *conn, gfp_t kptr_gfp,
gfp_t page_gfp, int prefill); gfp_t page_gfp, int prefill);
void rds_iw_inc_free(struct rds_incoming *inc); void rds_iw_inc_free(struct rds_incoming *inc);
int rds_iw_inc_copy_to_user(struct rds_incoming *inc, struct iovec *iov, int rds_iw_inc_copy_to_user(struct rds_incoming *inc, struct iov_iter *to);
size_t size);
void rds_iw_recv_cq_comp_handler(struct ib_cq *cq, void *context); 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_tasklet_fn(unsigned long data);
void rds_iw_recv_init_ring(struct rds_iw_connection *ic); void rds_iw_recv_init_ring(struct rds_iw_connection *ic);

View File

@ -303,15 +303,12 @@ void rds_iw_inc_free(struct rds_incoming *inc)
BUG_ON(atomic_read(&rds_iw_allocation) < 0); BUG_ON(atomic_read(&rds_iw_allocation) < 0);
} }
int rds_iw_inc_copy_to_user(struct rds_incoming *inc, struct iovec *first_iov, int rds_iw_inc_copy_to_user(struct rds_incoming *inc, struct iov_iter *to)
size_t size)
{ {
struct rds_iw_incoming *iwinc; struct rds_iw_incoming *iwinc;
struct rds_page_frag *frag; struct rds_page_frag *frag;
struct iovec *iov = first_iov;
unsigned long to_copy; unsigned long to_copy;
unsigned long frag_off = 0; unsigned long frag_off = 0;
unsigned long iov_off = 0;
int copied = 0; int copied = 0;
int ret; int ret;
u32 len; u32 len;
@ -320,37 +317,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); frag = list_entry(iwinc->ii_frags.next, struct rds_page_frag, f_item);
len = be32_to_cpu(inc->i_hdr.h_len); 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) { if (frag_off == RDS_FRAG_SIZE) {
frag = list_entry(frag->f_item.next, frag = list_entry(frag->f_item.next,
struct rds_page_frag, f_item); struct rds_page_frag, f_item);
frag_off = 0; frag_off = 0;
} }
while (iov_off == iov->iov_len) { to_copy = min_t(unsigned long, iov_iter_count(to),
iov_off = 0; RDS_FRAG_SIZE - frag_off);
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, to_copy, len - copied); 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 */ /* XXX needs + offset for multiple recvs per page */
ret = rds_page_copy_to_user(frag->f_page, rds_stats_add(s_copy_to_user, to_copy);
frag->f_offset + frag_off, ret = copy_page_to_iter(frag->f_page,
iov->iov_base + iov_off, frag->f_offset + frag_off,
to_copy); to_copy,
if (ret) { to);
copied = ret; if (ret != to_copy)
break; return -EFAULT;
}
iov_off += to_copy;
frag_off += to_copy; frag_off += to_copy;
copied += to_copy; copied += to_copy;
} }

View File

@ -325,14 +325,11 @@ out:
return ret; return ret;
} }
int rds_message_inc_copy_to_user(struct rds_incoming *inc, int rds_message_inc_copy_to_user(struct rds_incoming *inc, struct iov_iter *to)
struct iovec *first_iov, size_t size)
{ {
struct rds_message *rm; struct rds_message *rm;
struct iovec *iov;
struct scatterlist *sg; struct scatterlist *sg;
unsigned long to_copy; unsigned long to_copy;
unsigned long iov_off;
unsigned long vec_off; unsigned long vec_off;
int copied; int copied;
int ret; int ret;
@ -341,36 +338,20 @@ int rds_message_inc_copy_to_user(struct rds_incoming *inc,
rm = container_of(inc, struct rds_message, m_inc); rm = container_of(inc, struct rds_message, m_inc);
len = be32_to_cpu(rm->m_inc.i_hdr.h_len); len = be32_to_cpu(rm->m_inc.i_hdr.h_len);
iov = first_iov;
iov_off = 0;
sg = rm->data.op_sg; sg = rm->data.op_sg;
vec_off = 0; vec_off = 0;
copied = 0; copied = 0;
while (copied < size && copied < len) { while (iov_iter_count(to) && copied < len) {
while (iov_off == iov->iov_len) { to_copy = min(iov_iter_count(to), sg->length - vec_off);
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);
to_copy = min_t(unsigned long, to_copy, len - copied); to_copy = min_t(unsigned long, to_copy, len - copied);
rdsdebug("copying %lu bytes to user iov [%p, %zu] + %lu to " rds_stats_add(s_copy_to_user, to_copy);
"sg [%p, %u, %u] + %lu\n", ret = copy_page_to_iter(sg_page(sg), sg->offset + vec_off,
to_copy, iov->iov_base, iov->iov_len, iov_off, to_copy, to);
sg_page(sg), sg->offset, sg->length, vec_off); if (ret != to_copy)
return -EFAULT;
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;
}
iov_off += to_copy;
vec_off += to_copy; vec_off += to_copy;
copied += to_copy; copied += to_copy;

View File

@ -431,8 +431,7 @@ struct rds_transport {
int (*xmit_rdma)(struct rds_connection *conn, struct rm_rdma_op *op); 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 (*xmit_atomic)(struct rds_connection *conn, struct rm_atomic_op *op);
int (*recv)(struct rds_connection *conn); int (*recv)(struct rds_connection *conn);
int (*inc_copy_to_user)(struct rds_incoming *inc, struct iovec *iov, int (*inc_copy_to_user)(struct rds_incoming *inc, struct iov_iter *to);
size_t size);
void (*inc_free)(struct rds_incoming *inc); void (*inc_free)(struct rds_incoming *inc);
int (*cm_handle_connect)(struct rdma_cm_id *cm_id, int (*cm_handle_connect)(struct rdma_cm_id *cm_id,
@ -667,8 +666,7 @@ int rds_message_add_extension(struct rds_header *hdr,
int rds_message_next_extension(struct rds_header *hdr, int rds_message_next_extension(struct rds_header *hdr,
unsigned int *pos, void *buf, unsigned int *buflen); unsigned int *pos, void *buf, unsigned int *buflen);
int rds_message_add_rdma_dest_extension(struct rds_header *hdr, u32 r_key, u32 offset); 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, int rds_message_inc_copy_to_user(struct rds_incoming *inc, struct iov_iter *to);
struct iovec *first_iov, size_t size);
void rds_message_inc_free(struct rds_incoming *inc); void rds_message_inc_free(struct rds_incoming *inc);
void rds_message_addref(struct rds_message *rm); void rds_message_addref(struct rds_message *rm);
void rds_message_put(struct rds_message *rm); void rds_message_put(struct rds_message *rm);

View File

@ -404,6 +404,7 @@ int rds_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg,
int ret = 0, nonblock = msg_flags & MSG_DONTWAIT; int ret = 0, nonblock = msg_flags & MSG_DONTWAIT;
DECLARE_SOCKADDR(struct sockaddr_in *, sin, msg->msg_name); DECLARE_SOCKADDR(struct sockaddr_in *, sin, msg->msg_name);
struct rds_incoming *inc = NULL; struct rds_incoming *inc = NULL;
struct iov_iter to;
/* udp_recvmsg()->sock_recvtimeo() gets away without locking too.. */ /* udp_recvmsg()->sock_recvtimeo() gets away without locking too.. */
timeo = sock_rcvtimeo(sk, nonblock); timeo = sock_rcvtimeo(sk, nonblock);
@ -449,8 +450,8 @@ int rds_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg,
rdsdebug("copying inc %p from %pI4:%u to user\n", inc, rdsdebug("copying inc %p from %pI4:%u to user\n", inc,
&inc->i_conn->c_faddr, &inc->i_conn->c_faddr,
ntohs(inc->i_hdr.h_sport)); ntohs(inc->i_hdr.h_sport));
ret = inc->i_conn->c_trans->inc_copy_to_user(inc, msg->msg_iov, iov_iter_init(&to, READ, msg->msg_iov, msg->msg_iovlen, size);
size); ret = inc->i_conn->c_trans->inc_copy_to_user(inc, &to);
if (ret < 0) if (ret < 0)
break; break;

View File

@ -69,8 +69,7 @@ void rds_tcp_recv_exit(void);
void rds_tcp_data_ready(struct sock *sk); void rds_tcp_data_ready(struct sock *sk);
int rds_tcp_recv(struct rds_connection *conn); int rds_tcp_recv(struct rds_connection *conn);
void rds_tcp_inc_free(struct rds_incoming *inc); void rds_tcp_inc_free(struct rds_incoming *inc);
int rds_tcp_inc_copy_to_user(struct rds_incoming *inc, struct iovec *iov, int rds_tcp_inc_copy_to_user(struct rds_incoming *inc, struct iov_iter *to);
size_t size);
/* tcp_send.c */ /* tcp_send.c */
void rds_tcp_xmit_prepare(struct rds_connection *conn); void rds_tcp_xmit_prepare(struct rds_connection *conn);

View File

@ -59,50 +59,30 @@ void rds_tcp_inc_free(struct rds_incoming *inc)
/* /*
* this is pretty lame, but, whatever. * this is pretty lame, but, whatever.
*/ */
int rds_tcp_inc_copy_to_user(struct rds_incoming *inc, struct iovec *first_iov, int rds_tcp_inc_copy_to_user(struct rds_incoming *inc, struct iov_iter *to)
size_t size)
{ {
struct rds_tcp_incoming *tinc; struct rds_tcp_incoming *tinc;
struct iovec *iov, tmp;
struct sk_buff *skb; struct sk_buff *skb;
unsigned long to_copy, skb_off;
int ret = 0; int ret = 0;
if (size == 0) if (!iov_iter_count(to))
goto out; goto out;
tinc = container_of(inc, struct rds_tcp_incoming, ti_inc); tinc = container_of(inc, struct rds_tcp_incoming, ti_inc);
iov = first_iov;
tmp = *iov;
skb_queue_walk(&tinc->ti_skb_list, skb) { skb_queue_walk(&tinc->ti_skb_list, skb) {
skb_off = 0; unsigned long to_copy, skb_off;
while (skb_off < skb->len) { for (skb_off = 0; skb_off < skb->len; skb_off += to_copy) {
while (tmp.iov_len == 0) { to_copy = iov_iter_count(to);
iov++;
tmp = *iov;
}
to_copy = min(tmp.iov_len, size);
to_copy = min(to_copy, skb->len - skb_off); to_copy = min(to_copy, skb->len - skb_off);
rdsdebug("ret %d size %zu skb %p skb_off %lu " if (skb_copy_datagram_iter(skb, skb_off, to, to_copy))
"skblen %d iov_base %p iov_len %zu cpy %lu\n", return -EFAULT;
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;
}
rds_stats_add(s_copy_to_user, to_copy); rds_stats_add(s_copy_to_user, to_copy);
size -= to_copy;
ret += to_copy; ret += to_copy;
skb_off += to_copy;
if (size == 0) if (!iov_iter_count(to))
goto out; goto out;
} }
} }