aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorEric W. Biederman <ebiederm@xmission.com>2015-03-13 01:07:10 -0400
committerDavid S. Miller <davem@davemloft.net>2015-03-13 01:57:07 -0400
commit04f721c671656f93de888b1d176ba30b7336cca3 (patch)
tree72d8024ae51c6b3c3d82cf75bf643b54c8f9acb4 /net
parent8a4bff714fc088729abdd479acbfe934ddf16f7e (diff)
tcp_metrics: Rewrite tcp_metrics_flush_all
Rewrite tcp_metrics_flush_all so that it can cope with entries from different network namespaces on it's hash chain. This is based on the logic in tcp_metrics_nl_cmd_del for deleting a selection of entries from a tcp metrics hash chain. Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/ipv4/tcp_metrics.c21
1 files changed, 11 insertions, 10 deletions
diff --git a/net/ipv4/tcp_metrics.c b/net/ipv4/tcp_metrics.c
index 0d07e14f2ca5..baccb070427d 100644
--- a/net/ipv4/tcp_metrics.c
+++ b/net/ipv4/tcp_metrics.c
@@ -1051,18 +1051,19 @@ static void tcp_metrics_flush_all(struct net *net)
1051 unsigned int row; 1051 unsigned int row;
1052 1052
1053 for (row = 0; row < max_rows; row++, hb++) { 1053 for (row = 0; row < max_rows; row++, hb++) {
1054 struct tcp_metrics_block __rcu **pp;
1054 spin_lock_bh(&tcp_metrics_lock); 1055 spin_lock_bh(&tcp_metrics_lock);
1055 tm = deref_locked_genl(hb->chain); 1056 pp = &hb->chain;
1056 if (tm) 1057 for (tm = deref_locked_genl(*pp); tm;
1057 hb->chain = NULL; 1058 tm = deref_locked_genl(*pp)) {
1058 spin_unlock_bh(&tcp_metrics_lock); 1059 if (net_eq(tm_net(tm), net)) {
1059 while (tm) { 1060 *pp = tm->tcpm_next;
1060 struct tcp_metrics_block *next; 1061 kfree_rcu(tm, rcu_head);
1061 1062 } else {
1062 next = deref_genl(tm->tcpm_next); 1063 pp = &tm->tcpm_next;
1063 kfree_rcu(tm, rcu_head); 1064 }
1064 tm = next;
1065 } 1065 }
1066 spin_unlock_bh(&tcp_metrics_lock);
1066 } 1067 }
1067} 1068}
1068 1069