diff options
author | Eric Dumazet <dada1@cosmosbay.com> | 2008-10-08 17:18:04 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-10-08 17:18:04 -0400 |
commit | 3c689b7320ae6f20dba6a8b71806a6c6fd604ee8 (patch) | |
tree | f9417dbd9f4aca952a1aba3e9a0f2a5a6e088dcd | |
parent | 9088c5609584684149f3fb5b065aa7f18dcb03ff (diff) |
inet: cleanup of local_port_range
I noticed sysctl_local_port_range[] and its associated seqlock
sysctl_local_port_range_lock were on separate cache lines.
Moreover, sysctl_local_port_range[] was close to unrelated
variables, highly modified, leading to cache misses.
Moving these two variables in a structure can help data
locality and moving this structure to read_mostly section
helps sharing of this data among cpus.
Cleanup of extern declarations (moved in include file where
they belong), and use of inet_get_local_port_range()
accessor instead of direct access to ports values.
Signed-off-by: Eric Dumazet <dada1@cosmosbay.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | include/net/ip.h | 4 | ||||
-rw-r--r-- | net/ipv4/inet_connection_sock.c | 16 | ||||
-rw-r--r-- | net/ipv4/sysctl_net_ipv4.c | 23 |
3 files changed, 23 insertions, 20 deletions
diff --git a/include/net/ip.h b/include/net/ip.h index d678ea3d474a..1cbccaf0de3f 100644 --- a/include/net/ip.h +++ b/include/net/ip.h | |||
@@ -178,6 +178,10 @@ extern unsigned long snmp_fold_field(void *mib[], int offt); | |||
178 | extern int snmp_mib_init(void *ptr[2], size_t mibsize); | 178 | extern int snmp_mib_init(void *ptr[2], size_t mibsize); |
179 | extern void snmp_mib_free(void *ptr[2]); | 179 | extern void snmp_mib_free(void *ptr[2]); |
180 | 180 | ||
181 | extern struct local_ports { | ||
182 | seqlock_t lock; | ||
183 | int range[2]; | ||
184 | } sysctl_local_ports; | ||
181 | extern void inet_get_local_port_range(int *low, int *high); | 185 | extern void inet_get_local_port_range(int *low, int *high); |
182 | 186 | ||
183 | extern int sysctl_ip_default_ttl; | 187 | extern int sysctl_ip_default_ttl; |
diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c index 21fcc5a9045f..bd1278a2d828 100644 --- a/net/ipv4/inet_connection_sock.c +++ b/net/ipv4/inet_connection_sock.c | |||
@@ -30,20 +30,22 @@ EXPORT_SYMBOL(inet_csk_timer_bug_msg); | |||
30 | #endif | 30 | #endif |
31 | 31 | ||
32 | /* | 32 | /* |
33 | * This array holds the first and last local port number. | 33 | * This struct holds the first and last local port number. |
34 | */ | 34 | */ |
35 | int sysctl_local_port_range[2] = { 32768, 61000 }; | 35 | struct local_ports sysctl_local_ports __read_mostly = { |
36 | DEFINE_SEQLOCK(sysctl_port_range_lock); | 36 | .lock = SEQLOCK_UNLOCKED, |
37 | .range = { 32768, 61000 }, | ||
38 | }; | ||
37 | 39 | ||
38 | void inet_get_local_port_range(int *low, int *high) | 40 | void inet_get_local_port_range(int *low, int *high) |
39 | { | 41 | { |
40 | unsigned seq; | 42 | unsigned seq; |
41 | do { | 43 | do { |
42 | seq = read_seqbegin(&sysctl_port_range_lock); | 44 | seq = read_seqbegin(&sysctl_local_ports.lock); |
43 | 45 | ||
44 | *low = sysctl_local_port_range[0]; | 46 | *low = sysctl_local_ports.range[0]; |
45 | *high = sysctl_local_port_range[1]; | 47 | *high = sysctl_local_ports.range[1]; |
46 | } while (read_seqretry(&sysctl_port_range_lock, seq)); | 48 | } while (read_seqretry(&sysctl_local_ports.lock, seq)); |
47 | } | 49 | } |
48 | EXPORT_SYMBOL(inet_get_local_port_range); | 50 | EXPORT_SYMBOL(inet_get_local_port_range); |
49 | 51 | ||
diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c index e0689fd7b798..276d047fb85a 100644 --- a/net/ipv4/sysctl_net_ipv4.c +++ b/net/ipv4/sysctl_net_ipv4.c | |||
@@ -26,16 +26,13 @@ static int tcp_retr1_max = 255; | |||
26 | static int ip_local_port_range_min[] = { 1, 1 }; | 26 | static int ip_local_port_range_min[] = { 1, 1 }; |
27 | static int ip_local_port_range_max[] = { 65535, 65535 }; | 27 | static int ip_local_port_range_max[] = { 65535, 65535 }; |
28 | 28 | ||
29 | extern seqlock_t sysctl_port_range_lock; | ||
30 | extern int sysctl_local_port_range[2]; | ||
31 | |||
32 | /* Update system visible IP port range */ | 29 | /* Update system visible IP port range */ |
33 | static void set_local_port_range(int range[2]) | 30 | static void set_local_port_range(int range[2]) |
34 | { | 31 | { |
35 | write_seqlock(&sysctl_port_range_lock); | 32 | write_seqlock(&sysctl_local_ports.lock); |
36 | sysctl_local_port_range[0] = range[0]; | 33 | sysctl_local_ports.range[0] = range[0]; |
37 | sysctl_local_port_range[1] = range[1]; | 34 | sysctl_local_ports.range[1] = range[1]; |
38 | write_sequnlock(&sysctl_port_range_lock); | 35 | write_sequnlock(&sysctl_local_ports.lock); |
39 | } | 36 | } |
40 | 37 | ||
41 | /* Validate changes from /proc interface. */ | 38 | /* Validate changes from /proc interface. */ |
@@ -44,8 +41,7 @@ static int ipv4_local_port_range(ctl_table *table, int write, struct file *filp, | |||
44 | size_t *lenp, loff_t *ppos) | 41 | size_t *lenp, loff_t *ppos) |
45 | { | 42 | { |
46 | int ret; | 43 | int ret; |
47 | int range[2] = { sysctl_local_port_range[0], | 44 | int range[2]; |
48 | sysctl_local_port_range[1] }; | ||
49 | ctl_table tmp = { | 45 | ctl_table tmp = { |
50 | .data = &range, | 46 | .data = &range, |
51 | .maxlen = sizeof(range), | 47 | .maxlen = sizeof(range), |
@@ -54,6 +50,7 @@ static int ipv4_local_port_range(ctl_table *table, int write, struct file *filp, | |||
54 | .extra2 = &ip_local_port_range_max, | 50 | .extra2 = &ip_local_port_range_max, |
55 | }; | 51 | }; |
56 | 52 | ||
53 | inet_get_local_port_range(range, range + 1); | ||
57 | ret = proc_dointvec_minmax(&tmp, write, filp, buffer, lenp, ppos); | 54 | ret = proc_dointvec_minmax(&tmp, write, filp, buffer, lenp, ppos); |
58 | 55 | ||
59 | if (write && ret == 0) { | 56 | if (write && ret == 0) { |
@@ -73,8 +70,7 @@ static int ipv4_sysctl_local_port_range(ctl_table *table, int __user *name, | |||
73 | void __user *newval, size_t newlen) | 70 | void __user *newval, size_t newlen) |
74 | { | 71 | { |
75 | int ret; | 72 | int ret; |
76 | int range[2] = { sysctl_local_port_range[0], | 73 | int range[2]; |
77 | sysctl_local_port_range[1] }; | ||
78 | ctl_table tmp = { | 74 | ctl_table tmp = { |
79 | .data = &range, | 75 | .data = &range, |
80 | .maxlen = sizeof(range), | 76 | .maxlen = sizeof(range), |
@@ -83,6 +79,7 @@ static int ipv4_sysctl_local_port_range(ctl_table *table, int __user *name, | |||
83 | .extra2 = &ip_local_port_range_max, | 79 | .extra2 = &ip_local_port_range_max, |
84 | }; | 80 | }; |
85 | 81 | ||
82 | inet_get_local_port_range(range, range + 1); | ||
86 | ret = sysctl_intvec(&tmp, name, nlen, oldval, oldlenp, newval, newlen); | 83 | ret = sysctl_intvec(&tmp, name, nlen, oldval, oldlenp, newval, newlen); |
87 | if (ret == 0 && newval && newlen) { | 84 | if (ret == 0 && newval && newlen) { |
88 | if (range[1] < range[0]) | 85 | if (range[1] < range[0]) |
@@ -396,8 +393,8 @@ static struct ctl_table ipv4_table[] = { | |||
396 | { | 393 | { |
397 | .ctl_name = NET_IPV4_LOCAL_PORT_RANGE, | 394 | .ctl_name = NET_IPV4_LOCAL_PORT_RANGE, |
398 | .procname = "ip_local_port_range", | 395 | .procname = "ip_local_port_range", |
399 | .data = &sysctl_local_port_range, | 396 | .data = &sysctl_local_ports.range, |
400 | .maxlen = sizeof(sysctl_local_port_range), | 397 | .maxlen = sizeof(sysctl_local_ports.range), |
401 | .mode = 0644, | 398 | .mode = 0644, |
402 | .proc_handler = &ipv4_local_port_range, | 399 | .proc_handler = &ipv4_local_port_range, |
403 | .strategy = &ipv4_sysctl_local_port_range, | 400 | .strategy = &ipv4_sysctl_local_port_range, |