rds: refactor zcopy code into rds_message_zcopy_from_user

Move the large block of code predicated on zcopy from
rds_message_copy_from_user into a new function,
rds_message_zcopy_from_user()

Signed-off-by: Sowmini Varadhan <sowmini.varadhan@oracle.com>
Acked-by: Willem de Bruijn <willemb@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Sowmini Varadhan 2018-03-06 07:22:33 -08:00 committed by David S. Miller
parent c33b3b9fcf
commit d40a126b16

View File

@ -333,14 +333,14 @@ struct rds_message *rds_message_map_pages(unsigned long *page_addrs, unsigned in
return rm; return rm;
} }
int rds_message_copy_from_user(struct rds_message *rm, struct iov_iter *from, int rds_message_zcopy_from_user(struct rds_message *rm, struct iov_iter *from)
bool zcopy)
{ {
unsigned long to_copy, nbytes;
unsigned long sg_off; unsigned long sg_off;
struct scatterlist *sg; struct scatterlist *sg;
int ret = 0; int ret = 0;
int length = iov_iter_count(from); int length = iov_iter_count(from);
int total_copied = 0;
struct sk_buff *skb;
rm->m_inc.i_hdr.h_len = cpu_to_be32(iov_iter_count(from)); rm->m_inc.i_hdr.h_len = cpu_to_be32(iov_iter_count(from));
@ -350,54 +350,66 @@ int rds_message_copy_from_user(struct rds_message *rm, struct iov_iter *from,
sg = rm->data.op_sg; sg = rm->data.op_sg;
sg_off = 0; /* Dear gcc, sg->page will be null from kzalloc. */ sg_off = 0; /* Dear gcc, sg->page will be null from kzalloc. */
if (zcopy) { skb = alloc_skb(0, GFP_KERNEL);
int total_copied = 0; if (!skb)
struct sk_buff *skb; return -ENOMEM;
BUILD_BUG_ON(sizeof(skb->cb) < max_t(int, sizeof(struct rds_znotifier),
sizeof(struct rds_zcopy_cookies)));
rm->data.op_mmp_znotifier = RDS_ZCOPY_SKB(skb);
if (mm_account_pinned_pages(&rm->data.op_mmp_znotifier->z_mmp,
length)) {
ret = -ENOMEM;
goto err;
}
while (iov_iter_count(from)) {
struct page *pages;
size_t start;
ssize_t copied;
skb = alloc_skb(0, GFP_KERNEL); copied = iov_iter_get_pages(from, &pages, PAGE_SIZE,
if (!skb) 1, &start);
return -ENOMEM; if (copied < 0) {
BUILD_BUG_ON(sizeof(skb->cb) < struct mmpin *mmp;
max_t(int, sizeof(struct rds_znotifier), int i;
sizeof(struct rds_zcopy_cookies)));
rm->data.op_mmp_znotifier = RDS_ZCOPY_SKB(skb); for (i = 0; i < rm->data.op_nents; i++)
if (mm_account_pinned_pages(&rm->data.op_mmp_znotifier->z_mmp, put_page(sg_page(&rm->data.op_sg[i]));
length)) { mmp = &rm->data.op_mmp_znotifier->z_mmp;
ret = -ENOMEM; mm_unaccount_pinned_pages(mmp);
ret = -EFAULT;
goto err; goto err;
} }
while (iov_iter_count(from)) { total_copied += copied;
struct page *pages; iov_iter_advance(from, copied);
size_t start; length -= copied;
ssize_t copied; sg_set_page(sg, pages, copied, start);
rm->data.op_nents++;
copied = iov_iter_get_pages(from, &pages, PAGE_SIZE, sg++;
1, &start); }
if (copied < 0) { WARN_ON_ONCE(length != 0);
struct mmpin *mmp; return ret;
int i;
for (i = 0; i < rm->data.op_nents; i++)
put_page(sg_page(&rm->data.op_sg[i]));
mmp = &rm->data.op_mmp_znotifier->z_mmp;
mm_unaccount_pinned_pages(mmp);
ret = -EFAULT;
goto err;
}
total_copied += copied;
iov_iter_advance(from, copied);
length -= copied;
sg_set_page(sg, pages, copied, start);
rm->data.op_nents++;
sg++;
}
WARN_ON_ONCE(length != 0);
return ret;
err: err:
consume_skb(skb); consume_skb(skb);
rm->data.op_mmp_znotifier = NULL; rm->data.op_mmp_znotifier = NULL;
return ret; return ret;
} /* zcopy */ }
int rds_message_copy_from_user(struct rds_message *rm, struct iov_iter *from,
bool zcopy)
{
unsigned long to_copy, nbytes;
unsigned long sg_off;
struct scatterlist *sg;
int ret = 0;
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;
sg_off = 0; /* Dear gcc, sg->page will be null from kzalloc. */
if (zcopy)
return rds_message_zcopy_from_user(rm, from);
while (iov_iter_count(from)) { while (iov_iter_count(from)) {
if (!sg_page(sg)) { if (!sg_page(sg)) {