summaryrefslogtreecommitdiffstats
path: root/net/kcm
diff options
context:
space:
mode:
authorTom Herbert <tom@herbertland.com>2016-03-07 17:11:09 -0500
committerDavid S. Miller <davem@davemloft.net>2016-03-09 16:36:15 -0500
commitf29698fc6b3a45a5c6147eca8379f38be8232117 (patch)
treefaad89f5af8cda7df1eb6b5a447fffcacf9a8d68 /net/kcm
parent91687355b92735e5f247ed163b3b0b4d14c3cab6 (diff)
kcm: Sendpage support
Implement kcm_sendpage. Set in sendpage to kcm_sendpage in both dgram and seqpacket ops. Signed-off-by: Tom Herbert <tom@herbertland.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/kcm')
-rw-r--r--net/kcm/kcmsock.c147
1 files changed, 145 insertions, 2 deletions
diff --git a/net/kcm/kcmsock.c b/net/kcm/kcmsock.c
index 982ea5f77bfc..9ac24995691c 100644
--- a/net/kcm/kcmsock.c
+++ b/net/kcm/kcmsock.c
@@ -990,6 +990,149 @@ static void kcm_push(struct kcm_sock *kcm)
990 kcm_write_msgs(kcm); 990 kcm_write_msgs(kcm);
991} 991}
992 992
993static ssize_t kcm_sendpage(struct socket *sock, struct page *page,
994 int offset, size_t size, int flags)
995
996{
997 struct sock *sk = sock->sk;
998 struct kcm_sock *kcm = kcm_sk(sk);
999 struct sk_buff *skb = NULL, *head = NULL;
1000 long timeo = sock_sndtimeo(sk, flags & MSG_DONTWAIT);
1001 bool eor;
1002 int err = 0;
1003 int i;
1004
1005 if (flags & MSG_SENDPAGE_NOTLAST)
1006 flags |= MSG_MORE;
1007
1008 /* No MSG_EOR from splice, only look at MSG_MORE */
1009 eor = !(flags & MSG_MORE);
1010
1011 lock_sock(sk);
1012
1013 sk_clear_bit(SOCKWQ_ASYNC_NOSPACE, sk);
1014
1015 err = -EPIPE;
1016 if (sk->sk_err)
1017 goto out_error;
1018
1019 if (kcm->seq_skb) {
1020 /* Previously opened message */
1021 head = kcm->seq_skb;
1022 skb = kcm_tx_msg(head)->last_skb;
1023 i = skb_shinfo(skb)->nr_frags;
1024
1025 if (skb_can_coalesce(skb, i, page, offset)) {
1026 skb_frag_size_add(&skb_shinfo(skb)->frags[i - 1], size);
1027 skb_shinfo(skb)->tx_flags |= SKBTX_SHARED_FRAG;
1028 goto coalesced;
1029 }
1030
1031 if (i >= MAX_SKB_FRAGS) {
1032 struct sk_buff *tskb;
1033
1034 tskb = alloc_skb(0, sk->sk_allocation);
1035 while (!tskb) {
1036 kcm_push(kcm);
1037 err = sk_stream_wait_memory(sk, &timeo);
1038 if (err)
1039 goto out_error;
1040 }
1041
1042 if (head == skb)
1043 skb_shinfo(head)->frag_list = tskb;
1044 else
1045 skb->next = tskb;
1046
1047 skb = tskb;
1048 skb->ip_summed = CHECKSUM_UNNECESSARY;
1049 i = 0;
1050 }
1051 } else {
1052 /* Call the sk_stream functions to manage the sndbuf mem. */
1053 if (!sk_stream_memory_free(sk)) {
1054 kcm_push(kcm);
1055 set_bit(SOCK_NOSPACE, &sk->sk_socket->flags);
1056 err = sk_stream_wait_memory(sk, &timeo);
1057 if (err)
1058 goto out_error;
1059 }
1060
1061 head = alloc_skb(0, sk->sk_allocation);
1062 while (!head) {
1063 kcm_push(kcm);
1064 err = sk_stream_wait_memory(sk, &timeo);
1065 if (err)
1066 goto out_error;
1067 }
1068
1069 skb = head;
1070 i = 0;
1071 }
1072
1073 get_page(page);
1074 skb_fill_page_desc(skb, i, page, offset, size);
1075 skb_shinfo(skb)->tx_flags |= SKBTX_SHARED_FRAG;
1076
1077coalesced:
1078 skb->len += size;
1079 skb->data_len += size;
1080 skb->truesize += size;
1081 sk->sk_wmem_queued += size;
1082 sk_mem_charge(sk, size);
1083
1084 if (head != skb) {
1085 head->len += size;
1086 head->data_len += size;
1087 head->truesize += size;
1088 }
1089
1090 if (eor) {
1091 bool not_busy = skb_queue_empty(&sk->sk_write_queue);
1092
1093 /* Message complete, queue it on send buffer */
1094 __skb_queue_tail(&sk->sk_write_queue, head);
1095 kcm->seq_skb = NULL;
1096 KCM_STATS_INCR(kcm->stats.tx_msgs);
1097
1098 if (flags & MSG_BATCH) {
1099 kcm->tx_wait_more = true;
1100 } else if (kcm->tx_wait_more || not_busy) {
1101 err = kcm_write_msgs(kcm);
1102 if (err < 0) {
1103 /* We got a hard error in write_msgs but have
1104 * already queued this message. Report an error
1105 * in the socket, but don't affect return value
1106 * from sendmsg
1107 */
1108 pr_warn("KCM: Hard failure on kcm_write_msgs\n");
1109 report_csk_error(&kcm->sk, -err);
1110 }
1111 }
1112 } else {
1113 /* Message not complete, save state */
1114 kcm->seq_skb = head;
1115 kcm_tx_msg(head)->last_skb = skb;
1116 }
1117
1118 KCM_STATS_ADD(kcm->stats.tx_bytes, size);
1119
1120 release_sock(sk);
1121 return size;
1122
1123out_error:
1124 kcm_push(kcm);
1125
1126 err = sk_stream_error(sk, flags, err);
1127
1128 /* make sure we wake any epoll edge trigger waiter */
1129 if (unlikely(skb_queue_len(&sk->sk_write_queue) == 0 && err == -EAGAIN))
1130 sk->sk_write_space(sk);
1131
1132 release_sock(sk);
1133 return err;
1134}
1135
993static int kcm_sendmsg(struct socket *sock, struct msghdr *msg, size_t len) 1136static int kcm_sendmsg(struct socket *sock, struct msghdr *msg, size_t len)
994{ 1137{
995 struct sock *sk = sock->sk; 1138 struct sock *sk = sock->sk;
@@ -1995,7 +2138,7 @@ static const struct proto_ops kcm_dgram_ops = {
1995 .sendmsg = kcm_sendmsg, 2138 .sendmsg = kcm_sendmsg,
1996 .recvmsg = kcm_recvmsg, 2139 .recvmsg = kcm_recvmsg,
1997 .mmap = sock_no_mmap, 2140 .mmap = sock_no_mmap,
1998 .sendpage = sock_no_sendpage, 2141 .sendpage = kcm_sendpage,
1999}; 2142};
2000 2143
2001static const struct proto_ops kcm_seqpacket_ops = { 2144static const struct proto_ops kcm_seqpacket_ops = {
@@ -2016,7 +2159,7 @@ static const struct proto_ops kcm_seqpacket_ops = {
2016 .sendmsg = kcm_sendmsg, 2159 .sendmsg = kcm_sendmsg,
2017 .recvmsg = kcm_recvmsg, 2160 .recvmsg = kcm_recvmsg,
2018 .mmap = sock_no_mmap, 2161 .mmap = sock_no_mmap,
2019 .sendpage = sock_no_sendpage, 2162 .sendpage = kcm_sendpage,
2020 .splice_read = kcm_splice_read, 2163 .splice_read = kcm_splice_read,
2021}; 2164};
2022 2165