diff options
36 files changed, 88 insertions, 21 deletions
diff --git a/arch/alpha/include/asm/socket.h b/arch/alpha/include/asm/socket.h index 26773e3246e2..06edfefc3373 100644 --- a/arch/alpha/include/asm/socket.h +++ b/arch/alpha/include/asm/socket.h | |||
@@ -67,6 +67,8 @@ | |||
67 | #define SO_TIMESTAMPING 37 | 67 | #define SO_TIMESTAMPING 37 |
68 | #define SCM_TIMESTAMPING SO_TIMESTAMPING | 68 | #define SCM_TIMESTAMPING SO_TIMESTAMPING |
69 | 69 | ||
70 | #define SO_RXQ_OVFL 40 | ||
71 | |||
70 | /* O_NONBLOCK clashes with the bits used for socket types. Therefore we | 72 | /* O_NONBLOCK clashes with the bits used for socket types. Therefore we |
71 | * have to define SOCK_NONBLOCK to a different value here. | 73 | * have to define SOCK_NONBLOCK to a different value here. |
72 | */ | 74 | */ |
diff --git a/arch/arm/include/asm/socket.h b/arch/arm/include/asm/socket.h index 92ac61d294fd..90ffd04b8e74 100644 --- a/arch/arm/include/asm/socket.h +++ b/arch/arm/include/asm/socket.h | |||
@@ -60,4 +60,6 @@ | |||
60 | #define SO_PROTOCOL 38 | 60 | #define SO_PROTOCOL 38 |
61 | #define SO_DOMAIN 39 | 61 | #define SO_DOMAIN 39 |
62 | 62 | ||
63 | #define SO_RXQ_OVFL 40 | ||
64 | |||
63 | #endif /* _ASM_SOCKET_H */ | 65 | #endif /* _ASM_SOCKET_H */ |
diff --git a/arch/avr32/include/asm/socket.h b/arch/avr32/include/asm/socket.h index fe863f9794d5..c8d1fae49476 100644 --- a/arch/avr32/include/asm/socket.h +++ b/arch/avr32/include/asm/socket.h | |||
@@ -60,4 +60,6 @@ | |||
60 | #define SO_PROTOCOL 38 | 60 | #define SO_PROTOCOL 38 |
61 | #define SO_DOMAIN 39 | 61 | #define SO_DOMAIN 39 |
62 | 62 | ||
63 | #define SO_RXQ_OVFL 40 | ||
64 | |||
63 | #endif /* __ASM_AVR32_SOCKET_H */ | 65 | #endif /* __ASM_AVR32_SOCKET_H */ |
diff --git a/arch/cris/include/asm/socket.h b/arch/cris/include/asm/socket.h index 45ec49bdb7b1..1a4a61909ca8 100644 --- a/arch/cris/include/asm/socket.h +++ b/arch/cris/include/asm/socket.h | |||
@@ -62,6 +62,8 @@ | |||
62 | #define SO_PROTOCOL 38 | 62 | #define SO_PROTOCOL 38 |
63 | #define SO_DOMAIN 39 | 63 | #define SO_DOMAIN 39 |
64 | 64 | ||
65 | #define SO_RXQ_OVFL 40 | ||
66 | |||
65 | #endif /* _ASM_SOCKET_H */ | 67 | #endif /* _ASM_SOCKET_H */ |
66 | 68 | ||
67 | 69 | ||
diff --git a/arch/frv/include/asm/socket.h b/arch/frv/include/asm/socket.h index 2dea726095c2..a6b26880c1ec 100644 --- a/arch/frv/include/asm/socket.h +++ b/arch/frv/include/asm/socket.h | |||
@@ -60,5 +60,7 @@ | |||
60 | #define SO_PROTOCOL 38 | 60 | #define SO_PROTOCOL 38 |
61 | #define SO_DOMAIN 39 | 61 | #define SO_DOMAIN 39 |
62 | 62 | ||
63 | #define SO_RXQ_OVFL 40 | ||
64 | |||
63 | #endif /* _ASM_SOCKET_H */ | 65 | #endif /* _ASM_SOCKET_H */ |
64 | 66 | ||
diff --git a/arch/h8300/include/asm/socket.h b/arch/h8300/include/asm/socket.h index 1547f01c8e22..04c0f4596eb5 100644 --- a/arch/h8300/include/asm/socket.h +++ b/arch/h8300/include/asm/socket.h | |||
@@ -60,4 +60,6 @@ | |||
60 | #define SO_PROTOCOL 38 | 60 | #define SO_PROTOCOL 38 |
61 | #define SO_DOMAIN 39 | 61 | #define SO_DOMAIN 39 |
62 | 62 | ||
63 | #define SO_RXQ_OVFL 40 | ||
64 | |||
63 | #endif /* _ASM_SOCKET_H */ | 65 | #endif /* _ASM_SOCKET_H */ |
diff --git a/arch/ia64/include/asm/socket.h b/arch/ia64/include/asm/socket.h index 0b0d5ff062e5..51427eaa51ba 100644 --- a/arch/ia64/include/asm/socket.h +++ b/arch/ia64/include/asm/socket.h | |||
@@ -69,4 +69,6 @@ | |||
69 | #define SO_PROTOCOL 38 | 69 | #define SO_PROTOCOL 38 |
70 | #define SO_DOMAIN 39 | 70 | #define SO_DOMAIN 39 |
71 | 71 | ||
72 | #define SO_RXQ_OVFL 40 | ||
73 | |||
72 | #endif /* _ASM_IA64_SOCKET_H */ | 74 | #endif /* _ASM_IA64_SOCKET_H */ |
diff --git a/arch/m32r/include/asm/socket.h b/arch/m32r/include/asm/socket.h index 3390a864f224..469787c30098 100644 --- a/arch/m32r/include/asm/socket.h +++ b/arch/m32r/include/asm/socket.h | |||
@@ -60,4 +60,6 @@ | |||
60 | #define SO_PROTOCOL 38 | 60 | #define SO_PROTOCOL 38 |
61 | #define SO_DOMAIN 39 | 61 | #define SO_DOMAIN 39 |
62 | 62 | ||
63 | #define SO_RXQ_OVFL 40 | ||
64 | |||
63 | #endif /* _ASM_M32R_SOCKET_H */ | 65 | #endif /* _ASM_M32R_SOCKET_H */ |
diff --git a/arch/m68k/include/asm/socket.h b/arch/m68k/include/asm/socket.h index eee01cce921b..9bf49c87d954 100644 --- a/arch/m68k/include/asm/socket.h +++ b/arch/m68k/include/asm/socket.h | |||
@@ -60,4 +60,6 @@ | |||
60 | #define SO_PROTOCOL 38 | 60 | #define SO_PROTOCOL 38 |
61 | #define SO_DOMAIN 39 | 61 | #define SO_DOMAIN 39 |
62 | 62 | ||
63 | #define SO_RXQ_OVFL 40 | ||
64 | |||
63 | #endif /* _ASM_SOCKET_H */ | 65 | #endif /* _ASM_SOCKET_H */ |
diff --git a/arch/mips/include/asm/socket.h b/arch/mips/include/asm/socket.h index ae05accd9fe4..9de5190f2487 100644 --- a/arch/mips/include/asm/socket.h +++ b/arch/mips/include/asm/socket.h | |||
@@ -80,6 +80,8 @@ To add: #define SO_REUSEPORT 0x0200 /* Allow local address and port reuse. */ | |||
80 | #define SO_TIMESTAMPING 37 | 80 | #define SO_TIMESTAMPING 37 |
81 | #define SCM_TIMESTAMPING SO_TIMESTAMPING | 81 | #define SCM_TIMESTAMPING SO_TIMESTAMPING |
82 | 82 | ||
83 | #define SO_RXQ_OVFL 40 | ||
84 | |||
83 | #ifdef __KERNEL__ | 85 | #ifdef __KERNEL__ |
84 | 86 | ||
85 | /** sock_type - Socket types | 87 | /** sock_type - Socket types |
diff --git a/arch/mn10300/include/asm/socket.h b/arch/mn10300/include/asm/socket.h index 4df75af29d76..4e60c4281288 100644 --- a/arch/mn10300/include/asm/socket.h +++ b/arch/mn10300/include/asm/socket.h | |||
@@ -60,4 +60,6 @@ | |||
60 | #define SO_PROTOCOL 38 | 60 | #define SO_PROTOCOL 38 |
61 | #define SO_DOMAIN 39 | 61 | #define SO_DOMAIN 39 |
62 | 62 | ||
63 | #define SO_RXQ_OVFL 40 | ||
64 | |||
63 | #endif /* _ASM_SOCKET_H */ | 65 | #endif /* _ASM_SOCKET_H */ |
diff --git a/arch/parisc/include/asm/socket.h b/arch/parisc/include/asm/socket.h index 960b1e5d8e16..225b7d6a1a0a 100644 --- a/arch/parisc/include/asm/socket.h +++ b/arch/parisc/include/asm/socket.h | |||
@@ -59,6 +59,8 @@ | |||
59 | #define SO_TIMESTAMPING 0x4020 | 59 | #define SO_TIMESTAMPING 0x4020 |
60 | #define SCM_TIMESTAMPING SO_TIMESTAMPING | 60 | #define SCM_TIMESTAMPING SO_TIMESTAMPING |
61 | 61 | ||
62 | #define SO_RXQ_OVFL 0x4021 | ||
63 | |||
62 | /* O_NONBLOCK clashes with the bits used for socket types. Therefore we | 64 | /* O_NONBLOCK clashes with the bits used for socket types. Therefore we |
63 | * have to define SOCK_NONBLOCK to a different value here. | 65 | * have to define SOCK_NONBLOCK to a different value here. |
64 | */ | 66 | */ |
diff --git a/arch/powerpc/include/asm/socket.h b/arch/powerpc/include/asm/socket.h index 3ab8b3e6feb0..866f7606da68 100644 --- a/arch/powerpc/include/asm/socket.h +++ b/arch/powerpc/include/asm/socket.h | |||
@@ -67,4 +67,6 @@ | |||
67 | #define SO_PROTOCOL 38 | 67 | #define SO_PROTOCOL 38 |
68 | #define SO_DOMAIN 39 | 68 | #define SO_DOMAIN 39 |
69 | 69 | ||
70 | #define SO_RXQ_OVFL 40 | ||
71 | |||
70 | #endif /* _ASM_POWERPC_SOCKET_H */ | 72 | #endif /* _ASM_POWERPC_SOCKET_H */ |
diff --git a/arch/s390/include/asm/socket.h b/arch/s390/include/asm/socket.h index e42df89a0b85..fdff1e995c73 100644 --- a/arch/s390/include/asm/socket.h +++ b/arch/s390/include/asm/socket.h | |||
@@ -68,4 +68,6 @@ | |||
68 | #define SO_PROTOCOL 38 | 68 | #define SO_PROTOCOL 38 |
69 | #define SO_DOMAIN 39 | 69 | #define SO_DOMAIN 39 |
70 | 70 | ||
71 | #define SO_RXQ_OVFL 40 | ||
72 | |||
71 | #endif /* _ASM_SOCKET_H */ | 73 | #endif /* _ASM_SOCKET_H */ |
diff --git a/arch/sparc/include/asm/socket.h b/arch/sparc/include/asm/socket.h index 3a5ae3d12088..9d3fefcff2f5 100644 --- a/arch/sparc/include/asm/socket.h +++ b/arch/sparc/include/asm/socket.h | |||
@@ -56,6 +56,8 @@ | |||
56 | #define SO_TIMESTAMPING 0x0023 | 56 | #define SO_TIMESTAMPING 0x0023 |
57 | #define SCM_TIMESTAMPING SO_TIMESTAMPING | 57 | #define SCM_TIMESTAMPING SO_TIMESTAMPING |
58 | 58 | ||
59 | #define SO_RXQ_OVFL 0x0024 | ||
60 | |||
59 | /* Security levels - as per NRL IPv6 - don't actually do anything */ | 61 | /* Security levels - as per NRL IPv6 - don't actually do anything */ |
60 | #define SO_SECURITY_AUTHENTICATION 0x5001 | 62 | #define SO_SECURITY_AUTHENTICATION 0x5001 |
61 | #define SO_SECURITY_ENCRYPTION_TRANSPORT 0x5002 | 63 | #define SO_SECURITY_ENCRYPTION_TRANSPORT 0x5002 |
diff --git a/arch/xtensa/include/asm/socket.h b/arch/xtensa/include/asm/socket.h index beb3a6bdb61d..cbdf2ffaacff 100644 --- a/arch/xtensa/include/asm/socket.h +++ b/arch/xtensa/include/asm/socket.h | |||
@@ -71,4 +71,6 @@ | |||
71 | #define SO_PROTOCOL 38 | 71 | #define SO_PROTOCOL 38 |
72 | #define SO_DOMAIN 39 | 72 | #define SO_DOMAIN 39 |
73 | 73 | ||
74 | #define SO_RXQ_OVFL 40 | ||
75 | |||
74 | #endif /* _XTENSA_SOCKET_H */ | 76 | #endif /* _XTENSA_SOCKET_H */ |
diff --git a/include/asm-generic/socket.h b/include/asm-generic/socket.h index 538991cef6f0..9a6115e7cf63 100644 --- a/include/asm-generic/socket.h +++ b/include/asm-generic/socket.h | |||
@@ -63,4 +63,5 @@ | |||
63 | #define SO_PROTOCOL 38 | 63 | #define SO_PROTOCOL 38 |
64 | #define SO_DOMAIN 39 | 64 | #define SO_DOMAIN 39 |
65 | 65 | ||
66 | #define SO_RXQ_OVFL 40 | ||
66 | #endif /* __ASM_GENERIC_SOCKET_H */ | 67 | #endif /* __ASM_GENERIC_SOCKET_H */ |
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index df7b23ac66e6..8c866b5cb97b 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h | |||
@@ -389,8 +389,10 @@ struct sk_buff { | |||
389 | #ifdef CONFIG_NETWORK_SECMARK | 389 | #ifdef CONFIG_NETWORK_SECMARK |
390 | __u32 secmark; | 390 | __u32 secmark; |
391 | #endif | 391 | #endif |
392 | 392 | union { | |
393 | __u32 mark; | 393 | __u32 mark; |
394 | __u32 dropcount; | ||
395 | }; | ||
394 | 396 | ||
395 | __u16 vlan_tci; | 397 | __u16 vlan_tci; |
396 | 398 | ||
diff --git a/include/net/sock.h b/include/net/sock.h index 98398bdec57d..10669b01eeab 100644 --- a/include/net/sock.h +++ b/include/net/sock.h | |||
@@ -505,6 +505,7 @@ enum sock_flags { | |||
505 | SOCK_TIMESTAMPING_RAW_HARDWARE, /* %SOF_TIMESTAMPING_RAW_HARDWARE */ | 505 | SOCK_TIMESTAMPING_RAW_HARDWARE, /* %SOF_TIMESTAMPING_RAW_HARDWARE */ |
506 | SOCK_TIMESTAMPING_SYS_HARDWARE, /* %SOF_TIMESTAMPING_SYS_HARDWARE */ | 506 | SOCK_TIMESTAMPING_SYS_HARDWARE, /* %SOF_TIMESTAMPING_SYS_HARDWARE */ |
507 | SOCK_FASYNC, /* fasync() active */ | 507 | SOCK_FASYNC, /* fasync() active */ |
508 | SOCK_RXQ_OVFL, | ||
508 | }; | 509 | }; |
509 | 510 | ||
510 | static inline void sock_copy_flags(struct sock *nsk, struct sock *osk) | 511 | static inline void sock_copy_flags(struct sock *nsk, struct sock *osk) |
@@ -1493,6 +1494,8 @@ sock_recv_timestamp(struct msghdr *msg, struct sock *sk, struct sk_buff *skb) | |||
1493 | sk->sk_stamp = kt; | 1494 | sk->sk_stamp = kt; |
1494 | } | 1495 | } |
1495 | 1496 | ||
1497 | extern void sock_recv_ts_and_drops(struct msghdr *msg, struct sock *sk, struct sk_buff *skb); | ||
1498 | |||
1496 | /** | 1499 | /** |
1497 | * sock_tx_timestamp - checks whether the outgoing packet is to be time stamped | 1500 | * sock_tx_timestamp - checks whether the outgoing packet is to be time stamped |
1498 | * @msg: outgoing packet | 1501 | * @msg: outgoing packet |
diff --git a/net/atm/common.c b/net/atm/common.c index 950bd16d2383..d61e051e0a3f 100644 --- a/net/atm/common.c +++ b/net/atm/common.c | |||
@@ -496,7 +496,7 @@ int vcc_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, | |||
496 | error = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied); | 496 | error = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied); |
497 | if (error) | 497 | if (error) |
498 | return error; | 498 | return error; |
499 | sock_recv_timestamp(msg, sk, skb); | 499 | sock_recv_ts_and_drops(msg, sk, skb); |
500 | pr_debug("RcvM %d -= %d\n", atomic_read(&sk->sk_rmem_alloc), skb->truesize); | 500 | pr_debug("RcvM %d -= %d\n", atomic_read(&sk->sk_rmem_alloc), skb->truesize); |
501 | atm_return(vcc, skb->truesize); | 501 | atm_return(vcc, skb->truesize); |
502 | skb_free_datagram(sk, skb); | 502 | skb_free_datagram(sk, skb); |
diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c index 1f6e49c1cde8..399e59c9c6cb 100644 --- a/net/bluetooth/af_bluetooth.c +++ b/net/bluetooth/af_bluetooth.c | |||
@@ -257,7 +257,7 @@ int bt_sock_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
257 | skb_reset_transport_header(skb); | 257 | skb_reset_transport_header(skb); |
258 | err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied); | 258 | err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied); |
259 | if (err == 0) | 259 | if (err == 0) |
260 | sock_recv_timestamp(msg, sk, skb); | 260 | sock_recv_ts_and_drops(msg, sk, skb); |
261 | 261 | ||
262 | skb_free_datagram(sk, skb); | 262 | skb_free_datagram(sk, skb); |
263 | 263 | ||
diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c index c70786503850..d3bfc1b0afb1 100644 --- a/net/bluetooth/rfcomm/sock.c +++ b/net/bluetooth/rfcomm/sock.c | |||
@@ -703,7 +703,7 @@ static int rfcomm_sock_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
703 | copied += chunk; | 703 | copied += chunk; |
704 | size -= chunk; | 704 | size -= chunk; |
705 | 705 | ||
706 | sock_recv_timestamp(msg, sk, skb); | 706 | sock_recv_ts_and_drops(msg, sk, skb); |
707 | 707 | ||
708 | if (!(flags & MSG_PEEK)) { | 708 | if (!(flags & MSG_PEEK)) { |
709 | atomic_sub(chunk, &sk->sk_rmem_alloc); | 709 | atomic_sub(chunk, &sk->sk_rmem_alloc); |
diff --git a/net/can/bcm.c b/net/can/bcm.c index 597da4f8f888..2f47039c79dd 100644 --- a/net/can/bcm.c +++ b/net/can/bcm.c | |||
@@ -1534,7 +1534,7 @@ static int bcm_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
1534 | return err; | 1534 | return err; |
1535 | } | 1535 | } |
1536 | 1536 | ||
1537 | sock_recv_timestamp(msg, sk, skb); | 1537 | sock_recv_ts_and_drops(msg, sk, skb); |
1538 | 1538 | ||
1539 | if (msg->msg_name) { | 1539 | if (msg->msg_name) { |
1540 | msg->msg_namelen = sizeof(struct sockaddr_can); | 1540 | msg->msg_namelen = sizeof(struct sockaddr_can); |
diff --git a/net/can/raw.c b/net/can/raw.c index b5e897922d32..962fc9f1d0c7 100644 --- a/net/can/raw.c +++ b/net/can/raw.c | |||
@@ -702,7 +702,7 @@ static int raw_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
702 | return err; | 702 | return err; |
703 | } | 703 | } |
704 | 704 | ||
705 | sock_recv_timestamp(msg, sk, skb); | 705 | sock_recv_ts_and_drops(msg, sk, skb); |
706 | 706 | ||
707 | if (msg->msg_name) { | 707 | if (msg->msg_name) { |
708 | msg->msg_namelen = sizeof(struct sockaddr_can); | 708 | msg->msg_namelen = sizeof(struct sockaddr_can); |
diff --git a/net/core/sock.c b/net/core/sock.c index 7626b6aacd68..43ca2c995393 100644 --- a/net/core/sock.c +++ b/net/core/sock.c | |||
@@ -276,6 +276,8 @@ int sock_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) | |||
276 | { | 276 | { |
277 | int err = 0; | 277 | int err = 0; |
278 | int skb_len; | 278 | int skb_len; |
279 | unsigned long flags; | ||
280 | struct sk_buff_head *list = &sk->sk_receive_queue; | ||
279 | 281 | ||
280 | /* Cast sk->rcvbuf to unsigned... It's pointless, but reduces | 282 | /* Cast sk->rcvbuf to unsigned... It's pointless, but reduces |
281 | number of warnings when compiling with -W --ANK | 283 | number of warnings when compiling with -W --ANK |
@@ -305,7 +307,10 @@ int sock_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) | |||
305 | */ | 307 | */ |
306 | skb_len = skb->len; | 308 | skb_len = skb->len; |
307 | 309 | ||
308 | skb_queue_tail(&sk->sk_receive_queue, skb); | 310 | spin_lock_irqsave(&list->lock, flags); |
311 | skb->dropcount = atomic_read(&sk->sk_drops); | ||
312 | __skb_queue_tail(list, skb); | ||
313 | spin_unlock_irqrestore(&list->lock, flags); | ||
309 | 314 | ||
310 | if (!sock_flag(sk, SOCK_DEAD)) | 315 | if (!sock_flag(sk, SOCK_DEAD)) |
311 | sk->sk_data_ready(sk, skb_len); | 316 | sk->sk_data_ready(sk, skb_len); |
@@ -702,6 +707,12 @@ set_rcvbuf: | |||
702 | 707 | ||
703 | /* We implement the SO_SNDLOWAT etc to | 708 | /* We implement the SO_SNDLOWAT etc to |
704 | not be settable (1003.1g 5.3) */ | 709 | not be settable (1003.1g 5.3) */ |
710 | case SO_RXQ_OVFL: | ||
711 | if (valbool) | ||
712 | sock_set_flag(sk, SOCK_RXQ_OVFL); | ||
713 | else | ||
714 | sock_reset_flag(sk, SOCK_RXQ_OVFL); | ||
715 | break; | ||
705 | default: | 716 | default: |
706 | ret = -ENOPROTOOPT; | 717 | ret = -ENOPROTOOPT; |
707 | break; | 718 | break; |
@@ -901,6 +912,10 @@ int sock_getsockopt(struct socket *sock, int level, int optname, | |||
901 | v.val = sk->sk_mark; | 912 | v.val = sk->sk_mark; |
902 | break; | 913 | break; |
903 | 914 | ||
915 | case SO_RXQ_OVFL: | ||
916 | v.val = !!sock_flag(sk, SOCK_RXQ_OVFL); | ||
917 | break; | ||
918 | |||
904 | default: | 919 | default: |
905 | return -ENOPROTOOPT; | 920 | return -ENOPROTOOPT; |
906 | } | 921 | } |
diff --git a/net/ieee802154/dgram.c b/net/ieee802154/dgram.c index a413b1bf4465..25ad956a39d8 100644 --- a/net/ieee802154/dgram.c +++ b/net/ieee802154/dgram.c | |||
@@ -303,7 +303,7 @@ static int dgram_recvmsg(struct kiocb *iocb, struct sock *sk, | |||
303 | if (err) | 303 | if (err) |
304 | goto done; | 304 | goto done; |
305 | 305 | ||
306 | sock_recv_timestamp(msg, sk, skb); | 306 | sock_recv_ts_and_drops(msg, sk, skb); |
307 | 307 | ||
308 | if (flags & MSG_TRUNC) | 308 | if (flags & MSG_TRUNC) |
309 | copied = skb->len; | 309 | copied = skb->len; |
diff --git a/net/ieee802154/raw.c b/net/ieee802154/raw.c index 30e74eee07d6..769c8d138fc3 100644 --- a/net/ieee802154/raw.c +++ b/net/ieee802154/raw.c | |||
@@ -191,7 +191,7 @@ static int raw_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, | |||
191 | if (err) | 191 | if (err) |
192 | goto done; | 192 | goto done; |
193 | 193 | ||
194 | sock_recv_timestamp(msg, sk, skb); | 194 | sock_recv_ts_and_drops(msg, sk, skb); |
195 | 195 | ||
196 | if (flags & MSG_TRUNC) | 196 | if (flags & MSG_TRUNC) |
197 | copied = skb->len; | 197 | copied = skb->len; |
diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c index 757c9171e7c2..f18172b07611 100644 --- a/net/ipv4/raw.c +++ b/net/ipv4/raw.c | |||
@@ -682,7 +682,7 @@ static int raw_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, | |||
682 | if (err) | 682 | if (err) |
683 | goto done; | 683 | goto done; |
684 | 684 | ||
685 | sock_recv_timestamp(msg, sk, skb); | 685 | sock_recv_ts_and_drops(msg, sk, skb); |
686 | 686 | ||
687 | /* Copy the address. */ | 687 | /* Copy the address. */ |
688 | if (sin) { | 688 | if (sin) { |
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 194bcdc6d9fc..71e5353b30c8 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c | |||
@@ -955,7 +955,7 @@ try_again: | |||
955 | UDP_INC_STATS_USER(sock_net(sk), | 955 | UDP_INC_STATS_USER(sock_net(sk), |
956 | UDP_MIB_INDATAGRAMS, is_udplite); | 956 | UDP_MIB_INDATAGRAMS, is_udplite); |
957 | 957 | ||
958 | sock_recv_timestamp(msg, sk, skb); | 958 | sock_recv_ts_and_drops(msg, sk, skb); |
959 | 959 | ||
960 | /* Copy the address. */ | 960 | /* Copy the address. */ |
961 | if (sin) { | 961 | if (sin) { |
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index 4f24570b0869..d8375bc7f2d5 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c | |||
@@ -497,7 +497,7 @@ static int rawv6_recvmsg(struct kiocb *iocb, struct sock *sk, | |||
497 | sin6->sin6_scope_id = IP6CB(skb)->iif; | 497 | sin6->sin6_scope_id = IP6CB(skb)->iif; |
498 | } | 498 | } |
499 | 499 | ||
500 | sock_recv_timestamp(msg, sk, skb); | 500 | sock_recv_ts_and_drops(msg, sk, skb); |
501 | 501 | ||
502 | if (np->rxopt.all) | 502 | if (np->rxopt.all) |
503 | datagram_recv_ctl(sk, msg, skb); | 503 | datagram_recv_ctl(sk, msg, skb); |
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index ff778c172ef2..1f8e2afa4490 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c | |||
@@ -252,7 +252,7 @@ try_again: | |||
252 | UDP_MIB_INDATAGRAMS, is_udplite); | 252 | UDP_MIB_INDATAGRAMS, is_udplite); |
253 | } | 253 | } |
254 | 254 | ||
255 | sock_recv_timestamp(msg, sk, skb); | 255 | sock_recv_ts_and_drops(msg, sk, skb); |
256 | 256 | ||
257 | /* Copy the address. */ | 257 | /* Copy the address. */ |
258 | if (msg->msg_name) { | 258 | if (msg->msg_name) { |
diff --git a/net/key/af_key.c b/net/key/af_key.c index c078ae6e975b..472f6594184a 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c | |||
@@ -3606,7 +3606,7 @@ static int pfkey_recvmsg(struct kiocb *kiocb, | |||
3606 | if (err) | 3606 | if (err) |
3607 | goto out_free; | 3607 | goto out_free; |
3608 | 3608 | ||
3609 | sock_recv_timestamp(msg, sk, skb); | 3609 | sock_recv_ts_and_drops(msg, sk, skb); |
3610 | 3610 | ||
3611 | err = (flags & MSG_TRUNC) ? skb->len : copied; | 3611 | err = (flags & MSG_TRUNC) ? skb->len : copied; |
3612 | 3612 | ||
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index f87ed4803c11..bf3a2954cd4d 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c | |||
@@ -627,15 +627,14 @@ static int packet_rcv(struct sk_buff *skb, struct net_device *dev, | |||
627 | 627 | ||
628 | spin_lock(&sk->sk_receive_queue.lock); | 628 | spin_lock(&sk->sk_receive_queue.lock); |
629 | po->stats.tp_packets++; | 629 | po->stats.tp_packets++; |
630 | skb->dropcount = atomic_read(&sk->sk_drops); | ||
630 | __skb_queue_tail(&sk->sk_receive_queue, skb); | 631 | __skb_queue_tail(&sk->sk_receive_queue, skb); |
631 | spin_unlock(&sk->sk_receive_queue.lock); | 632 | spin_unlock(&sk->sk_receive_queue.lock); |
632 | sk->sk_data_ready(sk, skb->len); | 633 | sk->sk_data_ready(sk, skb->len); |
633 | return 0; | 634 | return 0; |
634 | 635 | ||
635 | drop_n_acct: | 636 | drop_n_acct: |
636 | spin_lock(&sk->sk_receive_queue.lock); | 637 | po->stats.tp_drops = atomic_inc_return(&sk->sk_drops); |
637 | po->stats.tp_drops++; | ||
638 | spin_unlock(&sk->sk_receive_queue.lock); | ||
639 | 638 | ||
640 | drop_n_restore: | 639 | drop_n_restore: |
641 | if (skb_head != skb->data && skb_shared(skb)) { | 640 | if (skb_head != skb->data && skb_shared(skb)) { |
@@ -1478,7 +1477,7 @@ static int packet_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
1478 | if (err) | 1477 | if (err) |
1479 | goto out_free; | 1478 | goto out_free; |
1480 | 1479 | ||
1481 | sock_recv_timestamp(msg, sk, skb); | 1480 | sock_recv_ts_and_drops(msg, sk, skb); |
1482 | 1481 | ||
1483 | if (msg->msg_name) | 1482 | if (msg->msg_name) |
1484 | memcpy(msg->msg_name, &PACKET_SKB_CB(skb)->sa, | 1483 | memcpy(msg->msg_name, &PACKET_SKB_CB(skb)->sa, |
diff --git a/net/rxrpc/ar-recvmsg.c b/net/rxrpc/ar-recvmsg.c index a39bf97f8830..60c2b94e6b54 100644 --- a/net/rxrpc/ar-recvmsg.c +++ b/net/rxrpc/ar-recvmsg.c | |||
@@ -146,7 +146,7 @@ int rxrpc_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
146 | memcpy(msg->msg_name, | 146 | memcpy(msg->msg_name, |
147 | &call->conn->trans->peer->srx, | 147 | &call->conn->trans->peer->srx, |
148 | sizeof(call->conn->trans->peer->srx)); | 148 | sizeof(call->conn->trans->peer->srx)); |
149 | sock_recv_timestamp(msg, &rx->sk, skb); | 149 | sock_recv_ts_and_drops(msg, &rx->sk, skb); |
150 | } | 150 | } |
151 | 151 | ||
152 | /* receive the message */ | 152 | /* receive the message */ |
diff --git a/net/sctp/socket.c b/net/sctp/socket.c index c8d05758661d..0970e92c6acd 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c | |||
@@ -1958,7 +1958,7 @@ SCTP_STATIC int sctp_recvmsg(struct kiocb *iocb, struct sock *sk, | |||
1958 | if (err) | 1958 | if (err) |
1959 | goto out_free; | 1959 | goto out_free; |
1960 | 1960 | ||
1961 | sock_recv_timestamp(msg, sk, skb); | 1961 | sock_recv_ts_and_drops(msg, sk, skb); |
1962 | if (sctp_ulpevent_is_notification(event)) { | 1962 | if (sctp_ulpevent_is_notification(event)) { |
1963 | msg->msg_flags |= MSG_NOTIFICATION; | 1963 | msg->msg_flags |= MSG_NOTIFICATION; |
1964 | sp->pf->event_msgname(event, msg->msg_name, addr_len); | 1964 | sp->pf->event_msgname(event, msg->msg_name, addr_len); |
diff --git a/net/socket.c b/net/socket.c index 954f3381cc8a..807935693846 100644 --- a/net/socket.c +++ b/net/socket.c | |||
@@ -668,6 +668,21 @@ void __sock_recv_timestamp(struct msghdr *msg, struct sock *sk, | |||
668 | 668 | ||
669 | EXPORT_SYMBOL_GPL(__sock_recv_timestamp); | 669 | EXPORT_SYMBOL_GPL(__sock_recv_timestamp); |
670 | 670 | ||
671 | inline void sock_recv_drops(struct msghdr *msg, struct sock *sk, struct sk_buff *skb) | ||
672 | { | ||
673 | if (sock_flag(sk, SOCK_RXQ_OVFL) && skb && skb->dropcount) | ||
674 | put_cmsg(msg, SOL_SOCKET, SO_RXQ_OVFL, | ||
675 | sizeof(__u32), &skb->dropcount); | ||
676 | } | ||
677 | |||
678 | void sock_recv_ts_and_drops(struct msghdr *msg, struct sock *sk, | ||
679 | struct sk_buff *skb) | ||
680 | { | ||
681 | sock_recv_timestamp(msg, sk, skb); | ||
682 | sock_recv_drops(msg, sk, skb); | ||
683 | } | ||
684 | EXPORT_SYMBOL_GPL(sock_recv_ts_and_drops); | ||
685 | |||
671 | static inline int __sock_recvmsg(struct kiocb *iocb, struct socket *sock, | 686 | static inline int __sock_recvmsg(struct kiocb *iocb, struct socket *sock, |
672 | struct msghdr *msg, size_t size, int flags) | 687 | struct msghdr *msg, size_t size, int flags) |
673 | { | 688 | { |