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 | ||
