Commit 8d987e5c75107ca7515fa19e857cfa24aab6ec8f

Authored by Eric Dumazet
Committed by David S. Miller
1 parent 67286640f6

net: avoid limits overflow

Robin Holt tried to boot a 16TB machine and found some limits were
reached : sysctl_tcp_mem[2], sysctl_udp_mem[2]

We can switch infrastructure to use long "instead" of "int", now
atomic_long_t primitives are available for free.

Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
Reported-by: Robin Holt <holt@sgi.com>
Reviewed-by: Robin Holt <holt@sgi.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: David S. Miller <davem@davemloft.net>

Showing 15 changed files with 40 additions and 38 deletions Side-by-side Diff

... ... @@ -225,7 +225,7 @@
225 225 extern int decnet_dr_count;
226 226 extern int decnet_no_fc_max_cwnd;
227 227  
228   -extern int sysctl_decnet_mem[3];
  228 +extern long sysctl_decnet_mem[3];
229 229 extern int sysctl_decnet_wmem[3];
230 230 extern int sysctl_decnet_rmem[3];
231 231  
... ... @@ -762,7 +762,7 @@
762 762  
763 763 /* Memory pressure */
764 764 void (*enter_memory_pressure)(struct sock *sk);
765   - atomic_t *memory_allocated; /* Current allocated memory. */
  765 + atomic_long_t *memory_allocated; /* Current allocated memory. */
766 766 struct percpu_counter *sockets_allocated; /* Current number of sockets. */
767 767 /*
768 768 * Pressure flag: try to collapse.
... ... @@ -771,7 +771,7 @@
771 771 * is strict, actions are advisory and have some latency.
772 772 */
773 773 int *memory_pressure;
774   - int *sysctl_mem;
  774 + long *sysctl_mem;
775 775 int *sysctl_wmem;
776 776 int *sysctl_rmem;
777 777 int max_header;
... ... @@ -224,7 +224,7 @@
224 224 extern int sysctl_tcp_reordering;
225 225 extern int sysctl_tcp_ecn;
226 226 extern int sysctl_tcp_dsack;
227   -extern int sysctl_tcp_mem[3];
  227 +extern long sysctl_tcp_mem[3];
228 228 extern int sysctl_tcp_wmem[3];
229 229 extern int sysctl_tcp_rmem[3];
230 230 extern int sysctl_tcp_app_win;
... ... @@ -247,7 +247,7 @@
247 247 extern int sysctl_tcp_thin_linear_timeouts;
248 248 extern int sysctl_tcp_thin_dupack;
249 249  
250   -extern atomic_t tcp_memory_allocated;
  250 +extern atomic_long_t tcp_memory_allocated;
251 251 extern struct percpu_counter tcp_sockets_allocated;
252 252 extern int tcp_memory_pressure;
253 253  
... ... @@ -280,7 +280,7 @@
280 280 }
281 281  
282 282 if (sk->sk_wmem_queued > SOCK_MIN_SNDBUF &&
283   - atomic_read(&tcp_memory_allocated) > sysctl_tcp_mem[2])
  283 + atomic_long_read(&tcp_memory_allocated) > sysctl_tcp_mem[2])
284 284 return true;
285 285 return false;
286 286 }
... ... @@ -105,10 +105,10 @@
105 105  
106 106 extern struct proto udp_prot;
107 107  
108   -extern atomic_t udp_memory_allocated;
  108 +extern atomic_long_t udp_memory_allocated;
109 109  
110 110 /* sysctl variables for udp */
111   -extern int sysctl_udp_mem[3];
  111 +extern long sysctl_udp_mem[3];
112 112 extern int sysctl_udp_rmem_min;
113 113 extern int sysctl_udp_wmem_min;
114 114  
... ... @@ -1653,10 +1653,10 @@
1653 1653 {
1654 1654 struct proto *prot = sk->sk_prot;
1655 1655 int amt = sk_mem_pages(size);
1656   - int allocated;
  1656 + long allocated;
1657 1657  
1658 1658 sk->sk_forward_alloc += amt * SK_MEM_QUANTUM;
1659   - allocated = atomic_add_return(amt, prot->memory_allocated);
  1659 + allocated = atomic_long_add_return(amt, prot->memory_allocated);
1660 1660  
1661 1661 /* Under limit. */
1662 1662 if (allocated <= prot->sysctl_mem[0]) {
... ... @@ -1714,7 +1714,7 @@
1714 1714  
1715 1715 /* Alas. Undo changes. */
1716 1716 sk->sk_forward_alloc -= amt * SK_MEM_QUANTUM;
1717   - atomic_sub(amt, prot->memory_allocated);
  1717 + atomic_long_sub(amt, prot->memory_allocated);
1718 1718 return 0;
1719 1719 }
1720 1720 EXPORT_SYMBOL(__sk_mem_schedule);
1721 1721  
... ... @@ -1727,12 +1727,12 @@
1727 1727 {
1728 1728 struct proto *prot = sk->sk_prot;
1729 1729  
1730   - atomic_sub(sk->sk_forward_alloc >> SK_MEM_QUANTUM_SHIFT,
  1730 + atomic_long_sub(sk->sk_forward_alloc >> SK_MEM_QUANTUM_SHIFT,
1731 1731 prot->memory_allocated);
1732 1732 sk->sk_forward_alloc &= SK_MEM_QUANTUM - 1;
1733 1733  
1734 1734 if (prot->memory_pressure && *prot->memory_pressure &&
1735   - (atomic_read(prot->memory_allocated) < prot->sysctl_mem[0]))
  1735 + (atomic_long_read(prot->memory_allocated) < prot->sysctl_mem[0]))
1736 1736 *prot->memory_pressure = 0;
1737 1737 }
1738 1738 EXPORT_SYMBOL(__sk_mem_reclaim);
1739 1739  
... ... @@ -2452,12 +2452,12 @@
2452 2452  
2453 2453 static void proto_seq_printf(struct seq_file *seq, struct proto *proto)
2454 2454 {
2455   - seq_printf(seq, "%-9s %4u %6d %6d %-3s %6u %-3s %-10s "
  2455 + seq_printf(seq, "%-9s %4u %6d %6ld %-3s %6u %-3s %-10s "
2456 2456 "%2c %2c %2c %2c %2c %2c %2c %2c %2c %2c %2c %2c %2c %2c %2c %2c %2c %2c %2c\n",
2457 2457 proto->name,
2458 2458 proto->obj_size,
2459 2459 sock_prot_inuse_get(seq_file_net(seq), proto),
2460   - proto->memory_allocated != NULL ? atomic_read(proto->memory_allocated) : -1,
  2460 + proto->memory_allocated != NULL ? atomic_long_read(proto->memory_allocated) : -1L,
2461 2461 proto->memory_pressure != NULL ? *proto->memory_pressure ? "yes" : "no" : "NI",
2462 2462 proto->max_header,
2463 2463 proto->slab == NULL ? "no" : "yes",
net/decnet/af_decnet.c
... ... @@ -155,7 +155,7 @@
155 155 static DEFINE_RWLOCK(dn_hash_lock);
156 156 static struct hlist_head dn_sk_hash[DN_SK_HASH_SIZE];
157 157 static struct hlist_head dn_wild_sk;
158   -static atomic_t decnet_memory_allocated;
  158 +static atomic_long_t decnet_memory_allocated;
159 159  
160 160 static int __dn_setsockopt(struct socket *sock, int level, int optname, char __user *optval, unsigned int optlen, int flags);
161 161 static int __dn_getsockopt(struct socket *sock, int level, int optname, char __user *optval, int __user *optlen, int flags);
net/decnet/sysctl_net_decnet.c
... ... @@ -38,7 +38,7 @@
38 38 int decnet_no_fc_max_cwnd = NSP_MIN_WINDOW;
39 39  
40 40 /* Reasonable defaults, I hope, based on tcp's defaults */
41   -int sysctl_decnet_mem[3] = { 768 << 3, 1024 << 3, 1536 << 3 };
  41 +long sysctl_decnet_mem[3] = { 768 << 3, 1024 << 3, 1536 << 3 };
42 42 int sysctl_decnet_wmem[3] = { 4 * 1024, 16 * 1024, 128 * 1024 };
43 43 int sysctl_decnet_rmem[3] = { 4 * 1024, 87380, 87380 * 2 };
44 44  
... ... @@ -324,7 +324,7 @@
324 324 .data = &sysctl_decnet_mem,
325 325 .maxlen = sizeof(sysctl_decnet_mem),
326 326 .mode = 0644,
327   - .proc_handler = proc_dointvec,
  327 + .proc_handler = proc_doulongvec_minmax
328 328 },
329 329 {
330 330 .procname = "decnet_rmem",
... ... @@ -59,13 +59,13 @@
59 59 local_bh_enable();
60 60  
61 61 socket_seq_show(seq);
62   - seq_printf(seq, "TCP: inuse %d orphan %d tw %d alloc %d mem %d\n",
  62 + seq_printf(seq, "TCP: inuse %d orphan %d tw %d alloc %d mem %ld\n",
63 63 sock_prot_inuse_get(net, &tcp_prot), orphans,
64 64 tcp_death_row.tw_count, sockets,
65   - atomic_read(&tcp_memory_allocated));
66   - seq_printf(seq, "UDP: inuse %d mem %d\n",
  65 + atomic_long_read(&tcp_memory_allocated));
  66 + seq_printf(seq, "UDP: inuse %d mem %ld\n",
67 67 sock_prot_inuse_get(net, &udp_prot),
68   - atomic_read(&udp_memory_allocated));
  68 + atomic_long_read(&udp_memory_allocated));
69 69 seq_printf(seq, "UDPLITE: inuse %d\n",
70 70 sock_prot_inuse_get(net, &udplite_prot));
71 71 seq_printf(seq, "RAW: inuse %d\n",
net/ipv4/sysctl_net_ipv4.c
... ... @@ -398,7 +398,7 @@
398 398 .data = &sysctl_tcp_mem,
399 399 .maxlen = sizeof(sysctl_tcp_mem),
400 400 .mode = 0644,
401   - .proc_handler = proc_dointvec
  401 + .proc_handler = proc_doulongvec_minmax
402 402 },
403 403 {
404 404 .procname = "tcp_wmem",
... ... @@ -602,8 +602,7 @@
602 602 .data = &sysctl_udp_mem,
603 603 .maxlen = sizeof(sysctl_udp_mem),
604 604 .mode = 0644,
605   - .proc_handler = proc_dointvec_minmax,
606   - .extra1 = &zero
  605 + .proc_handler = proc_doulongvec_minmax,
607 606 },
608 607 {
609 608 .procname = "udp_rmem_min",
... ... @@ -282,7 +282,7 @@
282 282 struct percpu_counter tcp_orphan_count;
283 283 EXPORT_SYMBOL_GPL(tcp_orphan_count);
284 284  
285   -int sysctl_tcp_mem[3] __read_mostly;
  285 +long sysctl_tcp_mem[3] __read_mostly;
286 286 int sysctl_tcp_wmem[3] __read_mostly;
287 287 int sysctl_tcp_rmem[3] __read_mostly;
288 288  
... ... @@ -290,7 +290,7 @@
290 290 EXPORT_SYMBOL(sysctl_tcp_rmem);
291 291 EXPORT_SYMBOL(sysctl_tcp_wmem);
292 292  
293   -atomic_t tcp_memory_allocated; /* Current allocated memory. */
  293 +atomic_long_t tcp_memory_allocated; /* Current allocated memory. */
294 294 EXPORT_SYMBOL(tcp_memory_allocated);
295 295  
296 296 /*
net/ipv4/tcp_input.c
... ... @@ -259,8 +259,11 @@
259 259 int sndmem = tcp_sk(sk)->rx_opt.mss_clamp + MAX_TCP_HEADER + 16 +
260 260 sizeof(struct sk_buff);
261 261  
262   - if (sk->sk_sndbuf < 3 * sndmem)
263   - sk->sk_sndbuf = min(3 * sndmem, sysctl_tcp_wmem[2]);
  262 + if (sk->sk_sndbuf < 3 * sndmem) {
  263 + sk->sk_sndbuf = 3 * sndmem;
  264 + if (sk->sk_sndbuf > sysctl_tcp_wmem[2])
  265 + sk->sk_sndbuf = sysctl_tcp_wmem[2];
  266 + }
264 267 }
265 268  
266 269 /* 2. Tuning advertised window (window_clamp, rcv_ssthresh)
... ... @@ -396,7 +399,7 @@
396 399 if (sk->sk_rcvbuf < sysctl_tcp_rmem[2] &&
397 400 !(sk->sk_userlocks & SOCK_RCVBUF_LOCK) &&
398 401 !tcp_memory_pressure &&
399   - atomic_read(&tcp_memory_allocated) < sysctl_tcp_mem[0]) {
  402 + atomic_long_read(&tcp_memory_allocated) < sysctl_tcp_mem[0]) {
400 403 sk->sk_rcvbuf = min(atomic_read(&sk->sk_rmem_alloc),
401 404 sysctl_tcp_rmem[2]);
402 405 }
... ... @@ -4861,7 +4864,7 @@
4861 4864 return 0;
4862 4865  
4863 4866 /* If we are under soft global TCP memory pressure, do not expand. */
4864   - if (atomic_read(&tcp_memory_allocated) >= sysctl_tcp_mem[0])
  4867 + if (atomic_long_read(&tcp_memory_allocated) >= sysctl_tcp_mem[0])
4865 4868 return 0;
4866 4869  
4867 4870 /* If we filled the congestion window, do not expand. */
... ... @@ -110,7 +110,7 @@
110 110 struct udp_table udp_table __read_mostly;
111 111 EXPORT_SYMBOL(udp_table);
112 112  
113   -int sysctl_udp_mem[3] __read_mostly;
  113 +long sysctl_udp_mem[3] __read_mostly;
114 114 EXPORT_SYMBOL(sysctl_udp_mem);
115 115  
116 116 int sysctl_udp_rmem_min __read_mostly;
... ... @@ -119,7 +119,7 @@
119 119 int sysctl_udp_wmem_min __read_mostly;
120 120 EXPORT_SYMBOL(sysctl_udp_wmem_min);
121 121  
122   -atomic_t udp_memory_allocated;
  122 +atomic_long_t udp_memory_allocated;
123 123 EXPORT_SYMBOL(udp_memory_allocated);
124 124  
125 125 #define MAX_UDP_PORTS 65536
... ... @@ -92,7 +92,7 @@
92 92 struct kmem_cache *sctp_chunk_cachep __read_mostly;
93 93 struct kmem_cache *sctp_bucket_cachep __read_mostly;
94 94  
95   -int sysctl_sctp_mem[3];
  95 +long sysctl_sctp_mem[3];
96 96 int sysctl_sctp_rmem[3];
97 97 int sysctl_sctp_wmem[3];
98 98  
... ... @@ -111,12 +111,12 @@
111 111 static char *sctp_hmac_alg = SCTP_COOKIE_HMAC_ALG;
112 112  
113 113 extern struct kmem_cache *sctp_bucket_cachep;
114   -extern int sysctl_sctp_mem[3];
  114 +extern long sysctl_sctp_mem[3];
115 115 extern int sysctl_sctp_rmem[3];
116 116 extern int sysctl_sctp_wmem[3];
117 117  
118 118 static int sctp_memory_pressure;
119   -static atomic_t sctp_memory_allocated;
  119 +static atomic_long_t sctp_memory_allocated;
120 120 struct percpu_counter sctp_sockets_allocated;
121 121  
122 122 static void sctp_enter_memory_pressure(struct sock *sk)
... ... @@ -54,7 +54,7 @@
54 54 static int addr_scope_max = 3; /* check sctp_scope_policy_t in include/net/sctp/constants.h for max entries */
55 55 static int rwnd_scale_max = 16;
56 56  
57   -extern int sysctl_sctp_mem[3];
  57 +extern long sysctl_sctp_mem[3];
58 58 extern int sysctl_sctp_rmem[3];
59 59 extern int sysctl_sctp_wmem[3];
60 60  
... ... @@ -203,7 +203,7 @@
203 203 .data = &sysctl_sctp_mem,
204 204 .maxlen = sizeof(sysctl_sctp_mem),
205 205 .mode = 0644,
206   - .proc_handler = proc_dointvec,
  206 + .proc_handler = proc_doulongvec_minmax
207 207 },
208 208 {
209 209 .procname = "sctp_rmem",