aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2014-11-24 18:17:55 -0500
committerAl Viro <viro@zeniv.linux.org.uk>2014-12-09 16:29:10 -0500
commite5a4b0bb803b39a36478451eae53a880d2663d5b (patch)
tree2e7c71032ede136c8e8f975bf7a79a692df76535
parent17836394e578b8d6475ecdb309ad1356bbcf37a2 (diff)
switch memcpy_to_msg() and skb_copy{,_and_csum}_datagram_msg() to primitives
... making both non-draining. That means that tcp_recvmsg() becomes non-draining. And _that_ would break iscsit_do_rx_data() unless we a) make sure tcp_recvmsg() is uniformly non-draining (it is) b) make sure it copes with arbitrary (including shifted) iov_iter (it does, all it uses is iov_iter primitives) c) make iscsit_do_rx_data() initialize ->msg_iter only once. Fortunately, (c) is doable with minimal work and we are rid of one the two places where kernel send/recvmsg users would be unhappy with non-draining behaviour. Actually, that makes all but one of ->recvmsg() instances iov_iter-clean. The exception is skcipher_recvmsg() and it also isn't hard to convert to primitives (iov_iter_get_pages() is needed there). That'll wait a bit - there's some interplay with ->sendmsg() path for that one. Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r--drivers/target/iscsi/iscsi_target_util.c12
-rw-r--r--include/linux/skbuff.h16
-rw-r--r--net/core/datagram.c54
3 files changed, 28 insertions, 54 deletions
diff --git a/drivers/target/iscsi/iscsi_target_util.c b/drivers/target/iscsi/iscsi_target_util.c
index ce87ce9bdb9c..7c6a95bcb35e 100644
--- a/drivers/target/iscsi/iscsi_target_util.c
+++ b/drivers/target/iscsi/iscsi_target_util.c
@@ -1326,21 +1326,19 @@ static int iscsit_do_rx_data(
1326 struct iscsi_conn *conn, 1326 struct iscsi_conn *conn,
1327 struct iscsi_data_count *count) 1327 struct iscsi_data_count *count)
1328{ 1328{
1329 int data = count->data_length, rx_loop = 0, total_rx = 0, iov_len; 1329 int data = count->data_length, rx_loop = 0, total_rx = 0;
1330 struct kvec *iov_p;
1331 struct msghdr msg; 1330 struct msghdr msg;
1332 1331
1333 if (!conn || !conn->sock || !conn->conn_ops) 1332 if (!conn || !conn->sock || !conn->conn_ops)
1334 return -1; 1333 return -1;
1335 1334
1336 memset(&msg, 0, sizeof(struct msghdr)); 1335 memset(&msg, 0, sizeof(struct msghdr));
1337 1336 iov_iter_kvec(&msg.msg_iter, READ | ITER_KVEC,
1338 iov_p = count->iov; 1337 count->iov, count->iov_count, data);
1339 iov_len = count->iov_count;
1340 1338
1341 while (total_rx < data) { 1339 while (total_rx < data) {
1342 rx_loop = kernel_recvmsg(conn->sock, &msg, iov_p, iov_len, 1340 rx_loop = sock_recvmsg(conn->sock, &msg,
1343 (data - total_rx), MSG_WAITALL); 1341 (data - total_rx), MSG_WAITALL);
1344 if (rx_loop <= 0) { 1342 if (rx_loop <= 0) {
1345 pr_debug("rx_loop: %d total_rx: %d\n", 1343 pr_debug("rx_loop: %d total_rx: %d\n",
1346 rx_loop, total_rx); 1344 rx_loop, total_rx);
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 52cf1bdac0d8..4902f2df90c8 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -2651,17 +2651,10 @@ int skb_copy_datagram_iter(const struct sk_buff *from, int offset,
2651static inline int skb_copy_datagram_msg(const struct sk_buff *from, int offset, 2651static inline int skb_copy_datagram_msg(const struct sk_buff *from, int offset,
2652 struct msghdr *msg, int size) 2652 struct msghdr *msg, int size)
2653{ 2653{
2654 /* XXX: stripping const */ 2654 return skb_copy_datagram_iter(from, offset, &msg->msg_iter, size);
2655 return skb_copy_datagram_iovec(from, offset, (struct iovec *)msg->msg_iter.iov, size);
2656}
2657int skb_copy_and_csum_datagram_iovec(struct sk_buff *skb, int hlen,
2658 struct iovec *iov);
2659static inline int skb_copy_and_csum_datagram_msg(struct sk_buff *skb, int hlen,
2660 struct msghdr *msg)
2661{
2662 /* XXX: stripping const */
2663 return skb_copy_and_csum_datagram_iovec(skb, hlen, (struct iovec *)msg->msg_iter.iov);
2664} 2655}
2656int skb_copy_and_csum_datagram_msg(struct sk_buff *skb, int hlen,
2657 struct msghdr *msg);
2665int skb_copy_datagram_from_iter(struct sk_buff *skb, int offset, 2658int skb_copy_datagram_from_iter(struct sk_buff *skb, int offset,
2666 struct iov_iter *from, int len); 2659 struct iov_iter *from, int len);
2667int zerocopy_sg_from_iter(struct sk_buff *skb, struct iov_iter *frm); 2660int zerocopy_sg_from_iter(struct sk_buff *skb, struct iov_iter *frm);
@@ -2697,8 +2690,7 @@ static inline int memcpy_from_msg(void *data, struct msghdr *msg, int len)
2697 2690
2698static inline int memcpy_to_msg(struct msghdr *msg, void *data, int len) 2691static inline int memcpy_to_msg(struct msghdr *msg, void *data, int len)
2699{ 2692{
2700 /* XXX: stripping const */ 2693 return copy_to_iter(data, len, &msg->msg_iter) == len ? 0 : -EFAULT;
2701 return memcpy_toiovec((struct iovec *)msg->msg_iter.iov, data, len);
2702} 2694}
2703 2695
2704struct skb_checksum_ops { 2696struct skb_checksum_ops {
diff --git a/net/core/datagram.c b/net/core/datagram.c
index b6e303b0f01f..41075ed6bb52 100644
--- a/net/core/datagram.c
+++ b/net/core/datagram.c
@@ -615,27 +615,25 @@ int zerocopy_sg_from_iter(struct sk_buff *skb, struct iov_iter *from)
615EXPORT_SYMBOL(zerocopy_sg_from_iter); 615EXPORT_SYMBOL(zerocopy_sg_from_iter);
616 616
617static int skb_copy_and_csum_datagram(const struct sk_buff *skb, int offset, 617static int skb_copy_and_csum_datagram(const struct sk_buff *skb, int offset,
618 u8 __user *to, int len, 618 struct iov_iter *to, int len,
619 __wsum *csump) 619 __wsum *csump)
620{ 620{
621 int start = skb_headlen(skb); 621 int start = skb_headlen(skb);
622 int i, copy = start - offset; 622 int i, copy = start - offset;
623 struct sk_buff *frag_iter; 623 struct sk_buff *frag_iter;
624 int pos = 0; 624 int pos = 0;
625 int n;
625 626
626 /* Copy header. */ 627 /* Copy header. */
627 if (copy > 0) { 628 if (copy > 0) {
628 int err = 0;
629 if (copy > len) 629 if (copy > len)
630 copy = len; 630 copy = len;
631 *csump = csum_and_copy_to_user(skb->data + offset, to, copy, 631 n = csum_and_copy_to_iter(skb->data + offset, copy, csump, to);
632 *csump, &err); 632 if (n != copy)
633 if (err)
634 goto fault; 633 goto fault;
635 if ((len -= copy) == 0) 634 if ((len -= copy) == 0)
636 return 0; 635 return 0;
637 offset += copy; 636 offset += copy;
638 to += copy;
639 pos = copy; 637 pos = copy;
640 } 638 }
641 639
@@ -647,26 +645,22 @@ static int skb_copy_and_csum_datagram(const struct sk_buff *skb, int offset,
647 645
648 end = start + skb_frag_size(frag); 646 end = start + skb_frag_size(frag);
649 if ((copy = end - offset) > 0) { 647 if ((copy = end - offset) > 0) {
650 __wsum csum2; 648 __wsum csum2 = 0;
651 int err = 0;
652 u8 *vaddr;
653 struct page *page = skb_frag_page(frag); 649 struct page *page = skb_frag_page(frag);
650 u8 *vaddr = kmap(page);
654 651
655 if (copy > len) 652 if (copy > len)
656 copy = len; 653 copy = len;
657 vaddr = kmap(page); 654 n = csum_and_copy_to_iter(vaddr + frag->page_offset +
658 csum2 = csum_and_copy_to_user(vaddr + 655 offset - start, copy,
659 frag->page_offset + 656 &csum2, to);
660 offset - start,
661 to, copy, 0, &err);
662 kunmap(page); 657 kunmap(page);
663 if (err) 658 if (n != copy)
664 goto fault; 659 goto fault;
665 *csump = csum_block_add(*csump, csum2, pos); 660 *csump = csum_block_add(*csump, csum2, pos);
666 if (!(len -= copy)) 661 if (!(len -= copy))
667 return 0; 662 return 0;
668 offset += copy; 663 offset += copy;
669 to += copy;
670 pos += copy; 664 pos += copy;
671 } 665 }
672 start = end; 666 start = end;
@@ -691,7 +685,6 @@ static int skb_copy_and_csum_datagram(const struct sk_buff *skb, int offset,
691 if ((len -= copy) == 0) 685 if ((len -= copy) == 0)
692 return 0; 686 return 0;
693 offset += copy; 687 offset += copy;
694 to += copy;
695 pos += copy; 688 pos += copy;
696 } 689 }
697 start = end; 690 start = end;
@@ -744,20 +737,19 @@ __sum16 __skb_checksum_complete(struct sk_buff *skb)
744EXPORT_SYMBOL(__skb_checksum_complete); 737EXPORT_SYMBOL(__skb_checksum_complete);
745 738
746/** 739/**
747 * skb_copy_and_csum_datagram_iovec - Copy and checksum skb to user iovec. 740 * skb_copy_and_csum_datagram_msg - Copy and checksum skb to user iovec.
748 * @skb: skbuff 741 * @skb: skbuff
749 * @hlen: hardware length 742 * @hlen: hardware length
750 * @iov: io vector 743 * @msg: destination
751 * 744 *
752 * Caller _must_ check that skb will fit to this iovec. 745 * Caller _must_ check that skb will fit to this iovec.
753 * 746 *
754 * Returns: 0 - success. 747 * Returns: 0 - success.
755 * -EINVAL - checksum failure. 748 * -EINVAL - checksum failure.
756 * -EFAULT - fault during copy. Beware, in this case iovec 749 * -EFAULT - fault during copy.
757 * can be modified!
758 */ 750 */
759int skb_copy_and_csum_datagram_iovec(struct sk_buff *skb, 751int skb_copy_and_csum_datagram_msg(struct sk_buff *skb,
760 int hlen, struct iovec *iov) 752 int hlen, struct msghdr *msg)
761{ 753{
762 __wsum csum; 754 __wsum csum;
763 int chunk = skb->len - hlen; 755 int chunk = skb->len - hlen;
@@ -765,28 +757,20 @@ int skb_copy_and_csum_datagram_iovec(struct sk_buff *skb,
765 if (!chunk) 757 if (!chunk)
766 return 0; 758 return 0;
767 759
768 /* Skip filled elements. 760 if (iov_iter_count(&msg->msg_iter) < chunk) {
769 * Pretty silly, look at memcpy_toiovec, though 8)
770 */
771 while (!iov->iov_len)
772 iov++;
773
774 if (iov->iov_len < chunk) {
775 if (__skb_checksum_complete(skb)) 761 if (__skb_checksum_complete(skb))
776 goto csum_error; 762 goto csum_error;
777 if (skb_copy_datagram_iovec(skb, hlen, iov, chunk)) 763 if (skb_copy_datagram_msg(skb, hlen, msg, chunk))
778 goto fault; 764 goto fault;
779 } else { 765 } else {
780 csum = csum_partial(skb->data, hlen, skb->csum); 766 csum = csum_partial(skb->data, hlen, skb->csum);
781 if (skb_copy_and_csum_datagram(skb, hlen, iov->iov_base, 767 if (skb_copy_and_csum_datagram(skb, hlen, &msg->msg_iter,
782 chunk, &csum)) 768 chunk, &csum))
783 goto fault; 769 goto fault;
784 if (csum_fold(csum)) 770 if (csum_fold(csum))
785 goto csum_error; 771 goto csum_error;
786 if (unlikely(skb->ip_summed == CHECKSUM_COMPLETE)) 772 if (unlikely(skb->ip_summed == CHECKSUM_COMPLETE))
787 netdev_rx_csum_fault(skb->dev); 773 netdev_rx_csum_fault(skb->dev);
788 iov->iov_len -= chunk;
789 iov->iov_base += chunk;
790 } 774 }
791 return 0; 775 return 0;
792csum_error: 776csum_error:
@@ -794,7 +778,7 @@ csum_error:
794fault: 778fault:
795 return -EFAULT; 779 return -EFAULT;
796} 780}
797EXPORT_SYMBOL(skb_copy_and_csum_datagram_iovec); 781EXPORT_SYMBOL(skb_copy_and_csum_datagram_msg);
798 782
799/** 783/**
800 * datagram_poll - generic datagram poll 784 * datagram_poll - generic datagram poll