net/mlx4_en: Fix mixed PFC and Global pause user control requests
[pandora-kernel.git] / net / ipv4 / udp.c
index 5a65eea..f64a1e5 100644 (file)
@@ -766,7 +766,7 @@ send:
 /*
  * Push out all pending data as one UDP datagram. Socket is locked.
  */
-static int udp_push_pending_frames(struct sock *sk)
+int udp_push_pending_frames(struct sock *sk)
 {
        struct udp_sock  *up = udp_sk(sk);
        struct inet_sock *inet = inet_sk(sk);
@@ -785,6 +785,7 @@ out:
        up->pending = 0;
        return err;
 }
+EXPORT_SYMBOL(udp_push_pending_frames);
 
 int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
                size_t len)
@@ -874,8 +875,10 @@ int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
                return err;
        if (msg->msg_controllen) {
                err = ip_cmsg_send(sock_net(sk), msg, &ipc);
-               if (err)
+               if (unlikely(err)) {
+                       kfree(ipc.opt);
                        return err;
+               }
                if (ipc.opt)
                        free = 1;
                connected = 0;
@@ -936,7 +939,7 @@ int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
                        err = PTR_ERR(rt);
                        rt = NULL;
                        if (err == -ENETUNREACH)
-                               IP_INC_STATS_BH(net, IPSTATS_MIB_OUTNOROUTES);
+                               IP_INC_STATS(net, IPSTATS_MIB_OUTNOROUTES);
                        goto out;
                }
 
@@ -1035,6 +1038,9 @@ int udp_sendpage(struct sock *sk, struct page *page, int offset,
        struct udp_sock *up = udp_sk(sk);
        int ret;
 
+       if (flags & MSG_SENDPAGE_NOTLAST)
+               flags |= MSG_MORE;
+
        if (!up->pending) {
                struct msghdr msg = {   .msg_flags = flags|MSG_MORE };
 
@@ -1168,16 +1174,11 @@ int udp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
        int peeked;
        int err;
        int is_udplite = IS_UDPLITE(sk);
+       bool checksum_valid = false;
        bool slow;
 
-       /*
-        *      Check any passed addresses
-        */
-       if (addr_len)
-               *addr_len = sizeof(*sin);
-
        if (flags & MSG_ERRQUEUE)
-               return ip_recv_error(sk, msg, len);
+               return ip_recv_error(sk, msg, len, addr_len);
 
 try_again:
        skb = __skb_recv_datagram(sk, flags | (noblock ? MSG_DONTWAIT : 0),
@@ -1199,11 +1200,12 @@ try_again:
         */
 
        if (copied < ulen || UDP_SKB_CB(skb)->partial_cov) {
-               if (udp_lib_checksum_complete(skb))
+               checksum_valid = !udp_lib_checksum_complete(skb);
+               if (!checksum_valid)
                        goto csum_copy_err;
        }
 
-       if (skb_csum_unnecessary(skb))
+       if (checksum_valid || skb_csum_unnecessary(skb))
                err = skb_copy_datagram_iovec(skb, sizeof(struct udphdr),
                                              msg->msg_iov, copied);
        else {
@@ -1230,6 +1232,7 @@ try_again:
                sin->sin_port = udp_hdr(skb)->source;
                sin->sin_addr.s_addr = ip_hdr(skb)->saddr;
                memset(sin->sin_zero, 0, sizeof(sin->sin_zero));
+               *addr_len = sizeof(*sin);
        }
        if (inet->cmsg_flags)
                ip_cmsg_recv(msg, skb);
@@ -1249,10 +1252,8 @@ csum_copy_err:
                UDP_INC_STATS_USER(sock_net(sk), UDP_MIB_INERRORS, is_udplite);
        unlock_sock_fast(sk, slow);
 
-       if (noblock)
-               return -EAGAIN;
-
-       /* starting over for a new packet */
+       /* starting over for a new packet, but check if we need to yield */
+       cond_resched();
        msg->msg_flags &= ~MSG_TRUNC;
        goto try_again;
 }