From d61d5ef064409d30670291ba5c4ac2b1d22636bb Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Tue, 27 Apr 2010 15:13:20 -0700 Subject: [PATCH] --- yaml --- r: 194559 b: refs/heads/master c: c377411f2494a931ff7facdbb3a6839b1266bcf6 h: refs/heads/master i: 194557: cf5a34d4fcfdb11bcaaf64c0df4b42bbc4aad2f4 194555: 6329406ff2e3c6eae78331e2bb5d4a06852e50a0 194551: 882388019c65b538e5dd66cbce22c73d8f514139 194543: 20c24fbca1e8f028e2f74cba9fc6b86845502511 194527: 707fe74a628a8dad43ed281c5bdc40a0d12558c1 194495: 48db41640302ce245be06d62fe8fbb0e20ae71cf 194431: bfcaf5091c111b18294f0e5dd59224cb15596eea 194303: 74a32d666a067e1a1715da42f0c1dec058341339 194047: 012cb600ca78513c17e0414df71d4836b087dba1 193535: e2bc90748aa2eede4fb05a2b05f5182c2019b011 192511: 9325e2bfdab79e49b7c0cb495169b590fb8ee8d3 v: v3 --- [refs] | 2 +- trunk/include/net/sock.h | 13 +++++++++++-- trunk/net/core/sock.c | 5 ++++- trunk/net/ipv4/udp.c | 4 ++++ trunk/net/ipv6/udp.c | 8 ++++++++ trunk/net/sctp/socket.c | 3 --- 6 files changed, 28 insertions(+), 7 deletions(-) diff --git a/[refs] b/[refs] index 106eff9875e7..b339c858a694 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 6e7676c1a76aed6e957611d8d7a9e5592e23aeba +refs/heads/master: c377411f2494a931ff7facdbb3a6839b1266bcf6 diff --git a/trunk/include/net/sock.h b/trunk/include/net/sock.h index 07822280d953..cf12b1e61fa6 100644 --- a/trunk/include/net/sock.h +++ b/trunk/include/net/sock.h @@ -256,7 +256,6 @@ struct sock { struct sk_buff *head; struct sk_buff *tail; int len; - int limit; } sk_backlog; wait_queue_head_t *sk_sleep; struct dst_entry *sk_dst_cache; @@ -608,10 +607,20 @@ static inline void __sk_add_backlog(struct sock *sk, struct sk_buff *skb) skb->next = NULL; } +/* + * Take into account size of receive queue and backlog queue + */ +static inline bool sk_rcvqueues_full(const struct sock *sk, const struct sk_buff *skb) +{ + unsigned int qsize = sk->sk_backlog.len + atomic_read(&sk->sk_rmem_alloc); + + return qsize + skb->truesize > sk->sk_rcvbuf; +} + /* The per-socket spinlock must be held here. */ static inline __must_check int sk_add_backlog(struct sock *sk, struct sk_buff *skb) { - if (sk->sk_backlog.len >= max(sk->sk_backlog.limit, sk->sk_rcvbuf << 1)) + if (sk_rcvqueues_full(sk, skb)) return -ENOBUFS; __sk_add_backlog(sk, skb); diff --git a/trunk/net/core/sock.c b/trunk/net/core/sock.c index 58ebd146ce5a..51041759517e 100644 --- a/trunk/net/core/sock.c +++ b/trunk/net/core/sock.c @@ -327,6 +327,10 @@ int sk_receive_skb(struct sock *sk, struct sk_buff *skb, const int nested) skb->dev = NULL; + if (sk_rcvqueues_full(sk, skb)) { + atomic_inc(&sk->sk_drops); + goto discard_and_relse; + } if (nested) bh_lock_sock_nested(sk); else @@ -1885,7 +1889,6 @@ void sock_init_data(struct socket *sock, struct sock *sk) sk->sk_allocation = GFP_KERNEL; sk->sk_rcvbuf = sysctl_rmem_default; sk->sk_sndbuf = sysctl_wmem_default; - sk->sk_backlog.limit = sk->sk_rcvbuf << 1; sk->sk_state = TCP_CLOSE; sk_set_socket(sk, sock); diff --git a/trunk/net/ipv4/udp.c b/trunk/net/ipv4/udp.c index fa3d2874db41..63eb56b2d873 100644 --- a/trunk/net/ipv4/udp.c +++ b/trunk/net/ipv4/udp.c @@ -1372,6 +1372,10 @@ int udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) goto drop; } + + if (sk_rcvqueues_full(sk, skb)) + goto drop; + rc = 0; bh_lock_sock(sk); diff --git a/trunk/net/ipv6/udp.c b/trunk/net/ipv6/udp.c index 2850e35cee3d..3ead20ad9d07 100644 --- a/trunk/net/ipv6/udp.c +++ b/trunk/net/ipv6/udp.c @@ -584,6 +584,10 @@ static void flush_stack(struct sock **stack, unsigned int count, sk = stack[i]; if (skb1) { + if (sk_rcvqueues_full(sk, skb)) { + kfree_skb(skb1); + goto drop; + } bh_lock_sock(sk); if (!sock_owned_by_user(sk)) udpv6_queue_rcv_skb(sk, skb1); @@ -759,6 +763,10 @@ int __udp6_lib_rcv(struct sk_buff *skb, struct udp_table *udptable, /* deliver */ + if (sk_rcvqueues_full(sk, skb)) { + sock_put(sk); + goto discard; + } bh_lock_sock(sk); if (!sock_owned_by_user(sk)) udpv6_queue_rcv_skb(sk, skb); diff --git a/trunk/net/sctp/socket.c b/trunk/net/sctp/socket.c index f34adcca8a8c..13d8229f3a9c 100644 --- a/trunk/net/sctp/socket.c +++ b/trunk/net/sctp/socket.c @@ -3721,9 +3721,6 @@ SCTP_STATIC int sctp_init_sock(struct sock *sk) SCTP_DBG_OBJCNT_INC(sock); percpu_counter_inc(&sctp_sockets_allocated); - /* Set socket backlog limit. */ - sk->sk_backlog.limit = sysctl_sctp_rmem[1]; - local_bh_disable(); sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1); local_bh_enable();