Skip to content

Commit e5a4b0b

Browse files
author
Al Viro
committed
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>
1 parent 1783639 commit e5a4b0b

File tree

3 files changed

+28
-54
lines changed

3 files changed

+28
-54
lines changed

drivers/target/iscsi/iscsi_target_util.c

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1326,21 +1326,19 @@ static int iscsit_do_rx_data(
13261326
struct iscsi_conn *conn,
13271327
struct iscsi_data_count *count)
13281328
{
1329-
int data = count->data_length, rx_loop = 0, total_rx = 0, iov_len;
1330-
struct kvec *iov_p;
1329+
int data = count->data_length, rx_loop = 0, total_rx = 0;
13311330
struct msghdr msg;
13321331

13331332
if (!conn || !conn->sock || !conn->conn_ops)
13341333
return -1;
13351334

13361335
memset(&msg, 0, sizeof(struct msghdr));
1337-
1338-
iov_p = count->iov;
1339-
iov_len = count->iov_count;
1336+
iov_iter_kvec(&msg.msg_iter, READ | ITER_KVEC,
1337+
count->iov, count->iov_count, data);
13401338

13411339
while (total_rx < data) {
1342-
rx_loop = kernel_recvmsg(conn->sock, &msg, iov_p, iov_len,
1343-
(data - total_rx), MSG_WAITALL);
1340+
rx_loop = sock_recvmsg(conn->sock, &msg,
1341+
(data - total_rx), MSG_WAITALL);
13441342
if (rx_loop <= 0) {
13451343
pr_debug("rx_loop: %d total_rx: %d\n",
13461344
rx_loop, total_rx);

include/linux/skbuff.h

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2651,17 +2651,10 @@ int skb_copy_datagram_iter(const struct sk_buff *from, int offset,
26512651
static inline int skb_copy_datagram_msg(const struct sk_buff *from, int offset,
26522652
struct msghdr *msg, int size)
26532653
{
2654-
/* XXX: stripping const */
2655-
return skb_copy_datagram_iovec(from, offset, (struct iovec *)msg->msg_iter.iov, size);
2656-
}
2657-
int skb_copy_and_csum_datagram_iovec(struct sk_buff *skb, int hlen,
2658-
struct iovec *iov);
2659-
static 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);
2654+
return skb_copy_datagram_iter(from, offset, &msg->msg_iter, size);
26642655
}
2656+
int skb_copy_and_csum_datagram_msg(struct sk_buff *skb, int hlen,
2657+
struct msghdr *msg);
26652658
int skb_copy_datagram_from_iter(struct sk_buff *skb, int offset,
26662659
struct iov_iter *from, int len);
26672660
int 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)
26972690

26982691
static inline int memcpy_to_msg(struct msghdr *msg, void *data, int len)
26992692
{
2700-
/* XXX: stripping const */
2701-
return memcpy_toiovec((struct iovec *)msg->msg_iter.iov, data, len);
2693+
return copy_to_iter(data, len, &msg->msg_iter) == len ? 0 : -EFAULT;
27022694
}
27032695

27042696
struct skb_checksum_ops {

net/core/datagram.c

Lines changed: 19 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -615,27 +615,25 @@ int zerocopy_sg_from_iter(struct sk_buff *skb, struct iov_iter *from)
615615
EXPORT_SYMBOL(zerocopy_sg_from_iter);
616616

617617
static 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,
619619
__wsum *csump)
620620
{
621621
int start = skb_headlen(skb);
622622
int i, copy = start - offset;
623623
struct sk_buff *frag_iter;
624624
int pos = 0;
625+
int n;
625626

626627
/* Copy header. */
627628
if (copy > 0) {
628-
int err = 0;
629629
if (copy > len)
630630
copy = len;
631-
*csump = csum_and_copy_to_user(skb->data + offset, to, copy,
632-
*csump, &err);
633-
if (err)
631+
n = csum_and_copy_to_iter(skb->data + offset, copy, csump, to);
632+
if (n != copy)
634633
goto fault;
635634
if ((len -= copy) == 0)
636635
return 0;
637636
offset += copy;
638-
to += copy;
639637
pos = copy;
640638
}
641639

@@ -647,26 +645,22 @@ static int skb_copy_and_csum_datagram(const struct sk_buff *skb, int offset,
647645

648646
end = start + skb_frag_size(frag);
649647
if ((copy = end - offset) > 0) {
650-
__wsum csum2;
651-
int err = 0;
652-
u8 *vaddr;
648+
__wsum csum2 = 0;
653649
struct page *page = skb_frag_page(frag);
650+
u8 *vaddr = kmap(page);
654651

655652
if (copy > len)
656653
copy = len;
657-
vaddr = kmap(page);
658-
csum2 = csum_and_copy_to_user(vaddr +
659-
frag->page_offset +
660-
offset - start,
661-
to, copy, 0, &err);
654+
n = csum_and_copy_to_iter(vaddr + frag->page_offset +
655+
offset - start, copy,
656+
&csum2, to);
662657
kunmap(page);
663-
if (err)
658+
if (n != copy)
664659
goto fault;
665660
*csump = csum_block_add(*csump, csum2, pos);
666661
if (!(len -= copy))
667662
return 0;
668663
offset += copy;
669-
to += copy;
670664
pos += copy;
671665
}
672666
start = end;
@@ -691,7 +685,6 @@ static int skb_copy_and_csum_datagram(const struct sk_buff *skb, int offset,
691685
if ((len -= copy) == 0)
692686
return 0;
693687
offset += copy;
694-
to += copy;
695688
pos += copy;
696689
}
697690
start = end;
@@ -744,57 +737,48 @@ __sum16 __skb_checksum_complete(struct sk_buff *skb)
744737
EXPORT_SYMBOL(__skb_checksum_complete);
745738

746739
/**
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.
748741
* @skb: skbuff
749742
* @hlen: hardware length
750-
* @iov: io vector
743+
* @msg: destination
751744
*
752745
* Caller _must_ check that skb will fit to this iovec.
753746
*
754747
* Returns: 0 - success.
755748
* -EINVAL - checksum failure.
756-
* -EFAULT - fault during copy. Beware, in this case iovec
757-
* can be modified!
749+
* -EFAULT - fault during copy.
758750
*/
759-
int skb_copy_and_csum_datagram_iovec(struct sk_buff *skb,
760-
int hlen, struct iovec *iov)
751+
int skb_copy_and_csum_datagram_msg(struct sk_buff *skb,
752+
int hlen, struct msghdr *msg)
761753
{
762754
__wsum csum;
763755
int chunk = skb->len - hlen;
764756

765757
if (!chunk)
766758
return 0;
767759

768-
/* Skip filled elements.
769-
* Pretty silly, look at memcpy_toiovec, though 8)
770-
*/
771-
while (!iov->iov_len)
772-
iov++;
773-
774-
if (iov->iov_len < chunk) {
760+
if (iov_iter_count(&msg->msg_iter) < chunk) {
775761
if (__skb_checksum_complete(skb))
776762
goto csum_error;
777-
if (skb_copy_datagram_iovec(skb, hlen, iov, chunk))
763+
if (skb_copy_datagram_msg(skb, hlen, msg, chunk))
778764
goto fault;
779765
} else {
780766
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,
782768
chunk, &csum))
783769
goto fault;
784770
if (csum_fold(csum))
785771
goto csum_error;
786772
if (unlikely(skb->ip_summed == CHECKSUM_COMPLETE))
787773
netdev_rx_csum_fault(skb->dev);
788-
iov->iov_len -= chunk;
789-
iov->iov_base += chunk;
790774
}
791775
return 0;
792776
csum_error:
793777
return -EINVAL;
794778
fault:
795779
return -EFAULT;
796780
}
797-
EXPORT_SYMBOL(skb_copy_and_csum_datagram_iovec);
781+
EXPORT_SYMBOL(skb_copy_and_csum_datagram_msg);
798782

799783
/**
800784
* datagram_poll - generic datagram poll

0 commit comments

Comments
 (0)