diff options
author | Ingo Molnar <mingo@elte.hu> | 2012-03-12 15:44:07 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2012-03-12 15:44:11 -0400 |
commit | 35239e23c66f1614c76739b62a299c3c92d6eb68 (patch) | |
tree | 7b1e068df888ec9a00b43c1dd7517a6490da6a94 /net/ipv4 | |
parent | 3f33ab1c0c741bfab2138c14ba1918a7905a1e8b (diff) | |
parent | 87e24f4b67e68d9fd8df16e0bf9c66d1ad2a2533 (diff) |
Merge branch 'perf/urgent' into perf/core
Merge reason: We are going to queue up a dependent patch.
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'net/ipv4')
-rw-r--r-- | net/ipv4/inetpeer.c | 81 | ||||
-rw-r--r-- | net/ipv4/route.c | 12 | ||||
-rw-r--r-- | net/ipv4/tcp_input.c | 23 |
3 files changed, 97 insertions, 19 deletions
diff --git a/net/ipv4/inetpeer.c b/net/ipv4/inetpeer.c index bf4a9c4808e1..d4d61b694fab 100644 --- a/net/ipv4/inetpeer.c +++ b/net/ipv4/inetpeer.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <linux/kernel.h> | 17 | #include <linux/kernel.h> |
18 | #include <linux/mm.h> | 18 | #include <linux/mm.h> |
19 | #include <linux/net.h> | 19 | #include <linux/net.h> |
20 | #include <linux/workqueue.h> | ||
20 | #include <net/ip.h> | 21 | #include <net/ip.h> |
21 | #include <net/inetpeer.h> | 22 | #include <net/inetpeer.h> |
22 | #include <net/secure_seq.h> | 23 | #include <net/secure_seq.h> |
@@ -66,6 +67,11 @@ | |||
66 | 67 | ||
67 | static struct kmem_cache *peer_cachep __read_mostly; | 68 | static struct kmem_cache *peer_cachep __read_mostly; |
68 | 69 | ||
70 | static LIST_HEAD(gc_list); | ||
71 | static const int gc_delay = 60 * HZ; | ||
72 | static struct delayed_work gc_work; | ||
73 | static DEFINE_SPINLOCK(gc_lock); | ||
74 | |||
69 | #define node_height(x) x->avl_height | 75 | #define node_height(x) x->avl_height |
70 | 76 | ||
71 | #define peer_avl_empty ((struct inet_peer *)&peer_fake_node) | 77 | #define peer_avl_empty ((struct inet_peer *)&peer_fake_node) |
@@ -102,6 +108,50 @@ int inet_peer_threshold __read_mostly = 65536 + 128; /* start to throw entries m | |||
102 | int inet_peer_minttl __read_mostly = 120 * HZ; /* TTL under high load: 120 sec */ | 108 | int inet_peer_minttl __read_mostly = 120 * HZ; /* TTL under high load: 120 sec */ |
103 | int inet_peer_maxttl __read_mostly = 10 * 60 * HZ; /* usual time to live: 10 min */ | 109 | int inet_peer_maxttl __read_mostly = 10 * 60 * HZ; /* usual time to live: 10 min */ |
104 | 110 | ||
111 | static void inetpeer_gc_worker(struct work_struct *work) | ||
112 | { | ||
113 | struct inet_peer *p, *n; | ||
114 | LIST_HEAD(list); | ||
115 | |||
116 | spin_lock_bh(&gc_lock); | ||
117 | list_replace_init(&gc_list, &list); | ||
118 | spin_unlock_bh(&gc_lock); | ||
119 | |||
120 | if (list_empty(&list)) | ||
121 | return; | ||
122 | |||
123 | list_for_each_entry_safe(p, n, &list, gc_list) { | ||
124 | |||
125 | if(need_resched()) | ||
126 | cond_resched(); | ||
127 | |||
128 | if (p->avl_left != peer_avl_empty) { | ||
129 | list_add_tail(&p->avl_left->gc_list, &list); | ||
130 | p->avl_left = peer_avl_empty; | ||
131 | } | ||
132 | |||
133 | if (p->avl_right != peer_avl_empty) { | ||
134 | list_add_tail(&p->avl_right->gc_list, &list); | ||
135 | p->avl_right = peer_avl_empty; | ||
136 | } | ||
137 | |||
138 | n = list_entry(p->gc_list.next, struct inet_peer, gc_list); | ||
139 | |||
140 | if (!atomic_read(&p->refcnt)) { | ||
141 | list_del(&p->gc_list); | ||
142 | kmem_cache_free(peer_cachep, p); | ||
143 | } | ||
144 | } | ||
145 | |||
146 | if (list_empty(&list)) | ||
147 | return; | ||
148 | |||
149 | spin_lock_bh(&gc_lock); | ||
150 | list_splice(&list, &gc_list); | ||
151 | spin_unlock_bh(&gc_lock); | ||
152 | |||
153 | schedule_delayed_work(&gc_work, gc_delay); | ||
154 | } | ||
105 | 155 | ||
106 | /* Called from ip_output.c:ip_init */ | 156 | /* Called from ip_output.c:ip_init */ |
107 | void __init inet_initpeers(void) | 157 | void __init inet_initpeers(void) |
@@ -126,6 +176,7 @@ void __init inet_initpeers(void) | |||
126 | 0, SLAB_HWCACHE_ALIGN | SLAB_PANIC, | 176 | 0, SLAB_HWCACHE_ALIGN | SLAB_PANIC, |
127 | NULL); | 177 | NULL); |
128 | 178 | ||
179 | INIT_DELAYED_WORK_DEFERRABLE(&gc_work, inetpeer_gc_worker); | ||
129 | } | 180 | } |
130 | 181 | ||
131 | static int addr_compare(const struct inetpeer_addr *a, | 182 | static int addr_compare(const struct inetpeer_addr *a, |
@@ -447,9 +498,8 @@ relookup: | |||
447 | p->rate_last = 0; | 498 | p->rate_last = 0; |
448 | p->pmtu_expires = 0; | 499 | p->pmtu_expires = 0; |
449 | p->pmtu_orig = 0; | 500 | p->pmtu_orig = 0; |
450 | p->redirect_genid = 0; | ||
451 | memset(&p->redirect_learned, 0, sizeof(p->redirect_learned)); | 501 | memset(&p->redirect_learned, 0, sizeof(p->redirect_learned)); |
452 | 502 | INIT_LIST_HEAD(&p->gc_list); | |
453 | 503 | ||
454 | /* Link the node. */ | 504 | /* Link the node. */ |
455 | link_to_pool(p, base); | 505 | link_to_pool(p, base); |
@@ -509,3 +559,30 @@ bool inet_peer_xrlim_allow(struct inet_peer *peer, int timeout) | |||
509 | return rc; | 559 | return rc; |
510 | } | 560 | } |
511 | EXPORT_SYMBOL(inet_peer_xrlim_allow); | 561 | EXPORT_SYMBOL(inet_peer_xrlim_allow); |
562 | |||
563 | void inetpeer_invalidate_tree(int family) | ||
564 | { | ||
565 | struct inet_peer *old, *new, *prev; | ||
566 | struct inet_peer_base *base = family_to_base(family); | ||
567 | |||
568 | write_seqlock_bh(&base->lock); | ||
569 | |||
570 | old = base->root; | ||
571 | if (old == peer_avl_empty_rcu) | ||
572 | goto out; | ||
573 | |||
574 | new = peer_avl_empty_rcu; | ||
575 | |||
576 | prev = cmpxchg(&base->root, old, new); | ||
577 | if (prev == old) { | ||
578 | base->total = 0; | ||
579 | spin_lock(&gc_lock); | ||
580 | list_add_tail(&prev->gc_list, &gc_list); | ||
581 | spin_unlock(&gc_lock); | ||
582 | schedule_delayed_work(&gc_work, gc_delay); | ||
583 | } | ||
584 | |||
585 | out: | ||
586 | write_sequnlock_bh(&base->lock); | ||
587 | } | ||
588 | EXPORT_SYMBOL(inetpeer_invalidate_tree); | ||
diff --git a/net/ipv4/route.c b/net/ipv4/route.c index bcacf54e5418..019774796174 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c | |||
@@ -132,7 +132,6 @@ static int ip_rt_mtu_expires __read_mostly = 10 * 60 * HZ; | |||
132 | static int ip_rt_min_pmtu __read_mostly = 512 + 20 + 20; | 132 | static int ip_rt_min_pmtu __read_mostly = 512 + 20 + 20; |
133 | static int ip_rt_min_advmss __read_mostly = 256; | 133 | static int ip_rt_min_advmss __read_mostly = 256; |
134 | static int rt_chain_length_max __read_mostly = 20; | 134 | static int rt_chain_length_max __read_mostly = 20; |
135 | static int redirect_genid; | ||
136 | 135 | ||
137 | static struct delayed_work expires_work; | 136 | static struct delayed_work expires_work; |
138 | static unsigned long expires_ljiffies; | 137 | static unsigned long expires_ljiffies; |
@@ -937,7 +936,7 @@ static void rt_cache_invalidate(struct net *net) | |||
937 | 936 | ||
938 | get_random_bytes(&shuffle, sizeof(shuffle)); | 937 | get_random_bytes(&shuffle, sizeof(shuffle)); |
939 | atomic_add(shuffle + 1U, &net->ipv4.rt_genid); | 938 | atomic_add(shuffle + 1U, &net->ipv4.rt_genid); |
940 | redirect_genid++; | 939 | inetpeer_invalidate_tree(AF_INET); |
941 | } | 940 | } |
942 | 941 | ||
943 | /* | 942 | /* |
@@ -1485,10 +1484,8 @@ void ip_rt_redirect(__be32 old_gw, __be32 daddr, __be32 new_gw, | |||
1485 | 1484 | ||
1486 | peer = rt->peer; | 1485 | peer = rt->peer; |
1487 | if (peer) { | 1486 | if (peer) { |
1488 | if (peer->redirect_learned.a4 != new_gw || | 1487 | if (peer->redirect_learned.a4 != new_gw) { |
1489 | peer->redirect_genid != redirect_genid) { | ||
1490 | peer->redirect_learned.a4 = new_gw; | 1488 | peer->redirect_learned.a4 = new_gw; |
1491 | peer->redirect_genid = redirect_genid; | ||
1492 | atomic_inc(&__rt_peer_genid); | 1489 | atomic_inc(&__rt_peer_genid); |
1493 | } | 1490 | } |
1494 | check_peer_redir(&rt->dst, peer); | 1491 | check_peer_redir(&rt->dst, peer); |
@@ -1793,8 +1790,6 @@ static void ipv4_validate_peer(struct rtable *rt) | |||
1793 | if (peer) { | 1790 | if (peer) { |
1794 | check_peer_pmtu(&rt->dst, peer); | 1791 | check_peer_pmtu(&rt->dst, peer); |
1795 | 1792 | ||
1796 | if (peer->redirect_genid != redirect_genid) | ||
1797 | peer->redirect_learned.a4 = 0; | ||
1798 | if (peer->redirect_learned.a4 && | 1793 | if (peer->redirect_learned.a4 && |
1799 | peer->redirect_learned.a4 != rt->rt_gateway) | 1794 | peer->redirect_learned.a4 != rt->rt_gateway) |
1800 | check_peer_redir(&rt->dst, peer); | 1795 | check_peer_redir(&rt->dst, peer); |
@@ -1958,8 +1953,7 @@ static void rt_init_metrics(struct rtable *rt, const struct flowi4 *fl4, | |||
1958 | dst_init_metrics(&rt->dst, peer->metrics, false); | 1953 | dst_init_metrics(&rt->dst, peer->metrics, false); |
1959 | 1954 | ||
1960 | check_peer_pmtu(&rt->dst, peer); | 1955 | check_peer_pmtu(&rt->dst, peer); |
1961 | if (peer->redirect_genid != redirect_genid) | 1956 | |
1962 | peer->redirect_learned.a4 = 0; | ||
1963 | if (peer->redirect_learned.a4 && | 1957 | if (peer->redirect_learned.a4 && |
1964 | peer->redirect_learned.a4 != rt->rt_gateway) { | 1958 | peer->redirect_learned.a4 != rt->rt_gateway) { |
1965 | rt->rt_gateway = peer->redirect_learned.a4; | 1959 | rt->rt_gateway = peer->redirect_learned.a4; |
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 53c8ce4046b2..b5e315f13641 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c | |||
@@ -1403,8 +1403,16 @@ static int tcp_shifted_skb(struct sock *sk, struct sk_buff *skb, | |||
1403 | 1403 | ||
1404 | BUG_ON(!pcount); | 1404 | BUG_ON(!pcount); |
1405 | 1405 | ||
1406 | /* Adjust hint for FACK. Non-FACK is handled in tcp_sacktag_one(). */ | 1406 | /* Adjust counters and hints for the newly sacked sequence |
1407 | if (tcp_is_fack(tp) && (skb == tp->lost_skb_hint)) | 1407 | * range but discard the return value since prev is already |
1408 | * marked. We must tag the range first because the seq | ||
1409 | * advancement below implicitly advances | ||
1410 | * tcp_highest_sack_seq() when skb is highest_sack. | ||
1411 | */ | ||
1412 | tcp_sacktag_one(sk, state, TCP_SKB_CB(skb)->sacked, | ||
1413 | start_seq, end_seq, dup_sack, pcount); | ||
1414 | |||
1415 | if (skb == tp->lost_skb_hint) | ||
1408 | tp->lost_cnt_hint += pcount; | 1416 | tp->lost_cnt_hint += pcount; |
1409 | 1417 | ||
1410 | TCP_SKB_CB(prev)->end_seq += shifted; | 1418 | TCP_SKB_CB(prev)->end_seq += shifted; |
@@ -1430,12 +1438,6 @@ static int tcp_shifted_skb(struct sock *sk, struct sk_buff *skb, | |||
1430 | skb_shinfo(skb)->gso_type = 0; | 1438 | skb_shinfo(skb)->gso_type = 0; |
1431 | } | 1439 | } |
1432 | 1440 | ||
1433 | /* Adjust counters and hints for the newly sacked sequence range but | ||
1434 | * discard the return value since prev is already marked. | ||
1435 | */ | ||
1436 | tcp_sacktag_one(sk, state, TCP_SKB_CB(skb)->sacked, | ||
1437 | start_seq, end_seq, dup_sack, pcount); | ||
1438 | |||
1439 | /* Difference in this won't matter, both ACKed by the same cumul. ACK */ | 1441 | /* Difference in this won't matter, both ACKed by the same cumul. ACK */ |
1440 | TCP_SKB_CB(prev)->sacked |= (TCP_SKB_CB(skb)->sacked & TCPCB_EVER_RETRANS); | 1442 | TCP_SKB_CB(prev)->sacked |= (TCP_SKB_CB(skb)->sacked & TCPCB_EVER_RETRANS); |
1441 | 1443 | ||
@@ -1583,6 +1585,10 @@ static struct sk_buff *tcp_shift_skb_data(struct sock *sk, struct sk_buff *skb, | |||
1583 | } | 1585 | } |
1584 | } | 1586 | } |
1585 | 1587 | ||
1588 | /* tcp_sacktag_one() won't SACK-tag ranges below snd_una */ | ||
1589 | if (!after(TCP_SKB_CB(skb)->seq + len, tp->snd_una)) | ||
1590 | goto fallback; | ||
1591 | |||
1586 | if (!skb_shift(prev, skb, len)) | 1592 | if (!skb_shift(prev, skb, len)) |
1587 | goto fallback; | 1593 | goto fallback; |
1588 | if (!tcp_shifted_skb(sk, skb, state, pcount, len, mss, dup_sack)) | 1594 | if (!tcp_shifted_skb(sk, skb, state, pcount, len, mss, dup_sack)) |
@@ -2567,6 +2573,7 @@ static void tcp_mark_head_lost(struct sock *sk, int packets, int mark_head) | |||
2567 | 2573 | ||
2568 | if (cnt > packets) { | 2574 | if (cnt > packets) { |
2569 | if ((tcp_is_sack(tp) && !tcp_is_fack(tp)) || | 2575 | if ((tcp_is_sack(tp) && !tcp_is_fack(tp)) || |
2576 | (TCP_SKB_CB(skb)->sacked & TCPCB_SACKED_ACKED) || | ||
2570 | (oldcnt >= packets)) | 2577 | (oldcnt >= packets)) |
2571 | break; | 2578 | break; |
2572 | 2579 | ||