return rm;
}
-int rds_message_copy_from_user(struct rds_message *rm, struct iov_iter *from,
- bool zcopy)
+int rds_message_zcopy_from_user(struct rds_message *rm, struct iov_iter *from)
{
- unsigned long to_copy, nbytes;
unsigned long sg_off;
struct scatterlist *sg;
int ret = 0;
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));
sg = rm->data.op_sg;
sg_off = 0; /* Dear gcc, sg->page will be null from kzalloc. */
- if (zcopy) {
- int total_copied = 0;
- struct sk_buff *skb;
-
- skb = alloc_skb(0, GFP_KERNEL);
- if (!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;
+ skb = alloc_skb(0, GFP_KERNEL);
+ if (!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;
+
+ copied = iov_iter_get_pages(from, &pages, PAGE_SIZE,
+ 1, &start);
+ if (copied < 0) {
+ struct mmpin *mmp;
+ 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;
}
- while (iov_iter_count(from)) {
- struct page *pages;
- size_t start;
- ssize_t copied;
-
- copied = iov_iter_get_pages(from, &pages, PAGE_SIZE,
- 1, &start);
- if (copied < 0) {
- struct mmpin *mmp;
- 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;
+ 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:
- consume_skb(skb);
- rm->data.op_mmp_znotifier = NULL;
- return ret;
- } /* zcopy */
+ consume_skb(skb);
+ rm->data.op_mmp_znotifier = NULL;
+ return ret;
+}
+
+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)) {
if (!sg_page(sg)) {