diff options
author | Eric Dumazet <dada1@cosmosbay.com> | 2008-11-26 00:16:35 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-11-26 00:16:35 -0500 |
commit | 1748376b6626acf59c24e9592ac67b3fe2a0e026 (patch) | |
tree | 65a28205daf1ca92e31389440764fc407365014e | |
parent | c1b56878fb68e9c14070939ea4537ad4db79ffae (diff) |
net: Use a percpu_counter for sockets_allocated
Instead of using one atomic_t per protocol, use a percpu_counter
for "sockets_allocated", to reduce cache line contention on
heavy duty network servers.
Note : We revert commit (248969ae31e1b3276fc4399d67ce29a5d81e6fd9
net: af_unix can make unix_nr_socks visbile in /proc),
since it is not anymore used after sock_prot_inuse_add() addition
Signed-off-by: Eric Dumazet <dada1@cosmosbay.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | include/net/sctp/sctp.h | 1 | ||||
-rw-r--r-- | include/net/sock.h | 2 | ||||
-rw-r--r-- | include/net/tcp.h | 2 | ||||
-rw-r--r-- | net/core/sock.c | 10 | ||||
-rw-r--r-- | net/ipv4/proc.c | 3 | ||||
-rw-r--r-- | net/ipv4/tcp.c | 8 | ||||
-rw-r--r-- | net/ipv4/tcp_ipv4.c | 4 | ||||
-rw-r--r-- | net/ipv6/tcp_ipv6.c | 2 | ||||
-rw-r--r-- | net/sctp/protocol.c | 6 | ||||
-rw-r--r-- | net/sctp/socket.c | 6 | ||||
-rw-r--r-- | net/unix/af_unix.c | 1 |
11 files changed, 29 insertions, 16 deletions
diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h index 23797506f593..bbb7742195b0 100644 --- a/include/net/sctp/sctp.h +++ b/include/net/sctp/sctp.h | |||
@@ -138,6 +138,7 @@ void sctp_write_space(struct sock *sk); | |||
138 | unsigned int sctp_poll(struct file *file, struct socket *sock, | 138 | unsigned int sctp_poll(struct file *file, struct socket *sock, |
139 | poll_table *wait); | 139 | poll_table *wait); |
140 | void sctp_sock_rfree(struct sk_buff *skb); | 140 | void sctp_sock_rfree(struct sk_buff *skb); |
141 | extern struct percpu_counter sctp_sockets_allocated; | ||
141 | 142 | ||
142 | /* | 143 | /* |
143 | * sctp/primitive.c | 144 | * sctp/primitive.c |
diff --git a/include/net/sock.h b/include/net/sock.h index 00cd486d362f..a2a3890959c4 100644 --- a/include/net/sock.h +++ b/include/net/sock.h | |||
@@ -649,7 +649,7 @@ struct proto { | |||
649 | /* Memory pressure */ | 649 | /* Memory pressure */ |
650 | void (*enter_memory_pressure)(struct sock *sk); | 650 | void (*enter_memory_pressure)(struct sock *sk); |
651 | atomic_t *memory_allocated; /* Current allocated memory. */ | 651 | atomic_t *memory_allocated; /* Current allocated memory. */ |
652 | atomic_t *sockets_allocated; /* Current number of sockets. */ | 652 | struct percpu_counter *sockets_allocated; /* Current number of sockets. */ |
653 | /* | 653 | /* |
654 | * Pressure flag: try to collapse. | 654 | * Pressure flag: try to collapse. |
655 | * Technical note: it is used by multiple contexts non atomically. | 655 | * Technical note: it is used by multiple contexts non atomically. |
diff --git a/include/net/tcp.h b/include/net/tcp.h index e8ae90a8c35e..cbca3b8a133d 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h | |||
@@ -238,7 +238,7 @@ extern int sysctl_tcp_slow_start_after_idle; | |||
238 | extern int sysctl_tcp_max_ssthresh; | 238 | extern int sysctl_tcp_max_ssthresh; |
239 | 239 | ||
240 | extern atomic_t tcp_memory_allocated; | 240 | extern atomic_t tcp_memory_allocated; |
241 | extern atomic_t tcp_sockets_allocated; | 241 | extern struct percpu_counter tcp_sockets_allocated; |
242 | extern int tcp_memory_pressure; | 242 | extern int tcp_memory_pressure; |
243 | 243 | ||
244 | /* | 244 | /* |
diff --git a/net/core/sock.c b/net/core/sock.c index a4e840e5a053..7a081b647bf9 100644 --- a/net/core/sock.c +++ b/net/core/sock.c | |||
@@ -1071,7 +1071,7 @@ struct sock *sk_clone(const struct sock *sk, const gfp_t priority) | |||
1071 | newsk->sk_sleep = NULL; | 1071 | newsk->sk_sleep = NULL; |
1072 | 1072 | ||
1073 | if (newsk->sk_prot->sockets_allocated) | 1073 | if (newsk->sk_prot->sockets_allocated) |
1074 | atomic_inc(newsk->sk_prot->sockets_allocated); | 1074 | percpu_counter_inc(newsk->sk_prot->sockets_allocated); |
1075 | } | 1075 | } |
1076 | out: | 1076 | out: |
1077 | return newsk; | 1077 | return newsk; |
@@ -1463,8 +1463,12 @@ int __sk_mem_schedule(struct sock *sk, int size, int kind) | |||
1463 | } | 1463 | } |
1464 | 1464 | ||
1465 | if (prot->memory_pressure) { | 1465 | if (prot->memory_pressure) { |
1466 | if (!*prot->memory_pressure || | 1466 | int alloc; |
1467 | prot->sysctl_mem[2] > atomic_read(prot->sockets_allocated) * | 1467 | |
1468 | if (!*prot->memory_pressure) | ||
1469 | return 1; | ||
1470 | alloc = percpu_counter_read_positive(prot->sockets_allocated); | ||
1471 | if (prot->sysctl_mem[2] > alloc * | ||
1468 | sk_mem_pages(sk->sk_wmem_queued + | 1472 | sk_mem_pages(sk->sk_wmem_queued + |
1469 | atomic_read(&sk->sk_rmem_alloc) + | 1473 | atomic_read(&sk->sk_rmem_alloc) + |
1470 | sk->sk_forward_alloc)) | 1474 | sk->sk_forward_alloc)) |
diff --git a/net/ipv4/proc.c b/net/ipv4/proc.c index 731789bb499f..4944b47ad628 100644 --- a/net/ipv4/proc.c +++ b/net/ipv4/proc.c | |||
@@ -55,7 +55,8 @@ static int sockstat_seq_show(struct seq_file *seq, void *v) | |||
55 | seq_printf(seq, "TCP: inuse %d orphan %d tw %d alloc %d mem %d\n", | 55 | seq_printf(seq, "TCP: inuse %d orphan %d tw %d alloc %d mem %d\n", |
56 | sock_prot_inuse_get(net, &tcp_prot), | 56 | sock_prot_inuse_get(net, &tcp_prot), |
57 | atomic_read(&tcp_orphan_count), | 57 | atomic_read(&tcp_orphan_count), |
58 | tcp_death_row.tw_count, atomic_read(&tcp_sockets_allocated), | 58 | tcp_death_row.tw_count, |
59 | (int)percpu_counter_sum_positive(&tcp_sockets_allocated), | ||
59 | atomic_read(&tcp_memory_allocated)); | 60 | atomic_read(&tcp_memory_allocated)); |
60 | seq_printf(seq, "UDP: inuse %d mem %d\n", | 61 | seq_printf(seq, "UDP: inuse %d mem %d\n", |
61 | sock_prot_inuse_get(net, &udp_prot), | 62 | sock_prot_inuse_get(net, &udp_prot), |
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 044224a341eb..e6fade9ebf62 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c | |||
@@ -290,9 +290,12 @@ EXPORT_SYMBOL(sysctl_tcp_rmem); | |||
290 | EXPORT_SYMBOL(sysctl_tcp_wmem); | 290 | EXPORT_SYMBOL(sysctl_tcp_wmem); |
291 | 291 | ||
292 | atomic_t tcp_memory_allocated; /* Current allocated memory. */ | 292 | atomic_t tcp_memory_allocated; /* Current allocated memory. */ |
293 | atomic_t tcp_sockets_allocated; /* Current number of TCP sockets. */ | ||
294 | |||
295 | EXPORT_SYMBOL(tcp_memory_allocated); | 293 | EXPORT_SYMBOL(tcp_memory_allocated); |
294 | |||
295 | /* | ||
296 | * Current number of TCP sockets. | ||
297 | */ | ||
298 | struct percpu_counter tcp_sockets_allocated; | ||
296 | EXPORT_SYMBOL(tcp_sockets_allocated); | 299 | EXPORT_SYMBOL(tcp_sockets_allocated); |
297 | 300 | ||
298 | /* | 301 | /* |
@@ -2685,6 +2688,7 @@ void __init tcp_init(void) | |||
2685 | 2688 | ||
2686 | BUILD_BUG_ON(sizeof(struct tcp_skb_cb) > sizeof(skb->cb)); | 2689 | BUILD_BUG_ON(sizeof(struct tcp_skb_cb) > sizeof(skb->cb)); |
2687 | 2690 | ||
2691 | percpu_counter_init(&tcp_sockets_allocated, 0); | ||
2688 | tcp_hashinfo.bind_bucket_cachep = | 2692 | tcp_hashinfo.bind_bucket_cachep = |
2689 | kmem_cache_create("tcp_bind_bucket", | 2693 | kmem_cache_create("tcp_bind_bucket", |
2690 | sizeof(struct inet_bind_bucket), 0, | 2694 | sizeof(struct inet_bind_bucket), 0, |
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index cab2458f86fd..26b9030747cc 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c | |||
@@ -1797,7 +1797,7 @@ static int tcp_v4_init_sock(struct sock *sk) | |||
1797 | sk->sk_sndbuf = sysctl_tcp_wmem[1]; | 1797 | sk->sk_sndbuf = sysctl_tcp_wmem[1]; |
1798 | sk->sk_rcvbuf = sysctl_tcp_rmem[1]; | 1798 | sk->sk_rcvbuf = sysctl_tcp_rmem[1]; |
1799 | 1799 | ||
1800 | atomic_inc(&tcp_sockets_allocated); | 1800 | percpu_counter_inc(&tcp_sockets_allocated); |
1801 | 1801 | ||
1802 | return 0; | 1802 | return 0; |
1803 | } | 1803 | } |
@@ -1845,7 +1845,7 @@ void tcp_v4_destroy_sock(struct sock *sk) | |||
1845 | sk->sk_sndmsg_page = NULL; | 1845 | sk->sk_sndmsg_page = NULL; |
1846 | } | 1846 | } |
1847 | 1847 | ||
1848 | atomic_dec(&tcp_sockets_allocated); | 1848 | percpu_counter_dec(&tcp_sockets_allocated); |
1849 | } | 1849 | } |
1850 | 1850 | ||
1851 | EXPORT_SYMBOL(tcp_v4_destroy_sock); | 1851 | EXPORT_SYMBOL(tcp_v4_destroy_sock); |
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index f259c9671f3e..8702b06cb60a 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c | |||
@@ -1830,7 +1830,7 @@ static int tcp_v6_init_sock(struct sock *sk) | |||
1830 | sk->sk_sndbuf = sysctl_tcp_wmem[1]; | 1830 | sk->sk_sndbuf = sysctl_tcp_wmem[1]; |
1831 | sk->sk_rcvbuf = sysctl_tcp_rmem[1]; | 1831 | sk->sk_rcvbuf = sysctl_tcp_rmem[1]; |
1832 | 1832 | ||
1833 | atomic_inc(&tcp_sockets_allocated); | 1833 | percpu_counter_inc(&tcp_sockets_allocated); |
1834 | 1834 | ||
1835 | return 0; | 1835 | return 0; |
1836 | } | 1836 | } |
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index a8ca743241ee..d5ea232c9126 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c | |||
@@ -102,6 +102,8 @@ struct sock *sctp_get_ctl_sock(void) | |||
102 | /* Set up the proc fs entry for the SCTP protocol. */ | 102 | /* Set up the proc fs entry for the SCTP protocol. */ |
103 | static __init int sctp_proc_init(void) | 103 | static __init int sctp_proc_init(void) |
104 | { | 104 | { |
105 | if (percpu_counter_init(&sctp_sockets_allocated, 0)) | ||
106 | goto out_nomem; | ||
105 | #ifdef CONFIG_PROC_FS | 107 | #ifdef CONFIG_PROC_FS |
106 | if (!proc_net_sctp) { | 108 | if (!proc_net_sctp) { |
107 | struct proc_dir_entry *ent; | 109 | struct proc_dir_entry *ent; |
@@ -110,7 +112,7 @@ static __init int sctp_proc_init(void) | |||
110 | ent->owner = THIS_MODULE; | 112 | ent->owner = THIS_MODULE; |
111 | proc_net_sctp = ent; | 113 | proc_net_sctp = ent; |
112 | } else | 114 | } else |
113 | goto out_nomem; | 115 | goto out_free_percpu; |
114 | } | 116 | } |
115 | 117 | ||
116 | if (sctp_snmp_proc_init()) | 118 | if (sctp_snmp_proc_init()) |
@@ -135,6 +137,8 @@ out_snmp_proc_init: | |||
135 | proc_net_sctp = NULL; | 137 | proc_net_sctp = NULL; |
136 | remove_proc_entry("sctp", init_net.proc_net); | 138 | remove_proc_entry("sctp", init_net.proc_net); |
137 | } | 139 | } |
140 | out_free_percpu: | ||
141 | percpu_counter_destroy(&sctp_sockets_allocated); | ||
138 | out_nomem: | 142 | out_nomem: |
139 | return -ENOMEM; | 143 | return -ENOMEM; |
140 | #else | 144 | #else |
diff --git a/net/sctp/socket.c b/net/sctp/socket.c index ba81fe3ccab8..a2de585888d0 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c | |||
@@ -114,7 +114,7 @@ extern int sysctl_sctp_wmem[3]; | |||
114 | 114 | ||
115 | static int sctp_memory_pressure; | 115 | static int sctp_memory_pressure; |
116 | static atomic_t sctp_memory_allocated; | 116 | static atomic_t sctp_memory_allocated; |
117 | static atomic_t sctp_sockets_allocated; | 117 | struct percpu_counter sctp_sockets_allocated; |
118 | 118 | ||
119 | static void sctp_enter_memory_pressure(struct sock *sk) | 119 | static void sctp_enter_memory_pressure(struct sock *sk) |
120 | { | 120 | { |
@@ -3613,7 +3613,7 @@ SCTP_STATIC int sctp_init_sock(struct sock *sk) | |||
3613 | sp->hmac = NULL; | 3613 | sp->hmac = NULL; |
3614 | 3614 | ||
3615 | SCTP_DBG_OBJCNT_INC(sock); | 3615 | SCTP_DBG_OBJCNT_INC(sock); |
3616 | atomic_inc(&sctp_sockets_allocated); | 3616 | percpu_counter_inc(&sctp_sockets_allocated); |
3617 | 3617 | ||
3618 | local_bh_disable(); | 3618 | local_bh_disable(); |
3619 | sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1); | 3619 | sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1); |
@@ -3632,7 +3632,7 @@ SCTP_STATIC void sctp_destroy_sock(struct sock *sk) | |||
3632 | /* Release our hold on the endpoint. */ | 3632 | /* Release our hold on the endpoint. */ |
3633 | ep = sctp_sk(sk)->ep; | 3633 | ep = sctp_sk(sk)->ep; |
3634 | sctp_endpoint_free(ep); | 3634 | sctp_endpoint_free(ep); |
3635 | atomic_dec(&sctp_sockets_allocated); | 3635 | percpu_counter_dec(&sctp_sockets_allocated); |
3636 | local_bh_disable(); | 3636 | local_bh_disable(); |
3637 | sock_prot_inuse_add(sock_net(sk), sk->sk_prot, -1); | 3637 | sock_prot_inuse_add(sock_net(sk), sk->sk_prot, -1); |
3638 | local_bh_enable(); | 3638 | local_bh_enable(); |
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index 3a35a6e8bf91..5aaf23e43f1d 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c | |||
@@ -571,7 +571,6 @@ static const struct proto_ops unix_seqpacket_ops = { | |||
571 | static struct proto unix_proto = { | 571 | static struct proto unix_proto = { |
572 | .name = "UNIX", | 572 | .name = "UNIX", |
573 | .owner = THIS_MODULE, | 573 | .owner = THIS_MODULE, |
574 | .sockets_allocated = &unix_nr_socks, | ||
575 | .obj_size = sizeof(struct unix_sock), | 574 | .obj_size = sizeof(struct unix_sock), |
576 | }; | 575 | }; |
577 | 576 | ||