forked from Minki/linux
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:
parent
c33b3b9fcf
commit
d40a126b16
@ -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)) {
|
||||||
|
Loading…
Reference in New Issue
Block a user