netfilter: {ip,ip6,arp}_tables: dont block bottom half more than necessary
authorEric Dumazet <eric.dumazet@gmail.com>
Mon, 2 Aug 2010 14:49:01 +0000 (16:49 +0200)
committerPatrick McHardy <kaber@trash.net>
Mon, 2 Aug 2010 14:49:01 +0000 (16:49 +0200)
We currently disable BH for the whole duration of get_counters()

On machines with a lot of cpus and large tables, this might be too long.

We can disable preemption during the whole function, and disable BH only
while fetching counters for the current cpu.

Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
Signed-off-by: Patrick McHardy <kaber@trash.net>
net/ipv4/netfilter/arp_tables.c
net/ipv4/netfilter/ip_tables.c
net/ipv6/netfilter/ip6_tables.c

index c868dd53e432ea79da5f99512059c23fbb3fc103..6bccba31d13208d03f042002f5808c3396c1f37f 100644 (file)
@@ -710,7 +710,7 @@ static void get_counters(const struct xt_table_info *t,
        struct arpt_entry *iter;
        unsigned int cpu;
        unsigned int i;
-       unsigned int curcpu;
+       unsigned int curcpu = get_cpu();
 
        /* Instead of clearing (by a previous call to memset())
         * the counters and using adds, we set the counters
@@ -720,14 +720,16 @@ static void get_counters(const struct xt_table_info *t,
         * if new softirq were to run and call ipt_do_table
         */
        local_bh_disable();
-       curcpu = smp_processor_id();
-
        i = 0;
        xt_entry_foreach(iter, t->entries[curcpu], t->size) {
                SET_COUNTER(counters[i], iter->counters.bcnt,
                            iter->counters.pcnt);
                ++i;
        }
+       local_bh_enable();
+       /* Processing counters from other cpus, we can let bottom half enabled,
+        * (preemption is disabled)
+        */
 
        for_each_possible_cpu(cpu) {
                if (cpu == curcpu)
@@ -741,7 +743,7 @@ static void get_counters(const struct xt_table_info *t,
                }
                xt_info_wrunlock(cpu);
        }
-       local_bh_enable();
+       put_cpu();
 }
 
 static struct xt_counters *alloc_counters(const struct xt_table *table)
index 3c584a6765b07b49d755b83eb2dfce436c08b101..c439721b165a6369acd1bd2ea1d64d4b0580b1bb 100644 (file)
@@ -884,7 +884,7 @@ get_counters(const struct xt_table_info *t,
        struct ipt_entry *iter;
        unsigned int cpu;
        unsigned int i;
-       unsigned int curcpu;
+       unsigned int curcpu = get_cpu();
 
        /* Instead of clearing (by a previous call to memset())
         * the counters and using adds, we set the counters
@@ -894,14 +894,16 @@ get_counters(const struct xt_table_info *t,
         * if new softirq were to run and call ipt_do_table
         */
        local_bh_disable();
-       curcpu = smp_processor_id();
-
        i = 0;
        xt_entry_foreach(iter, t->entries[curcpu], t->size) {
                SET_COUNTER(counters[i], iter->counters.bcnt,
                            iter->counters.pcnt);
                ++i;
        }
+       local_bh_enable();
+       /* Processing counters from other cpus, we can let bottom half enabled,
+        * (preemption is disabled)
+        */
 
        for_each_possible_cpu(cpu) {
                if (cpu == curcpu)
@@ -915,7 +917,7 @@ get_counters(const struct xt_table_info *t,
                }
                xt_info_wrunlock(cpu);
        }
-       local_bh_enable();
+       put_cpu();
 }
 
 static struct xt_counters *alloc_counters(const struct xt_table *table)
index 33113c1ea02f787d595c96ba81a036c7850419b3..5359ef4daac5230e4c691c2100d8016dcb69e102 100644 (file)
@@ -897,7 +897,7 @@ get_counters(const struct xt_table_info *t,
        struct ip6t_entry *iter;
        unsigned int cpu;
        unsigned int i;
-       unsigned int curcpu;
+       unsigned int curcpu = get_cpu();
 
        /* Instead of clearing (by a previous call to memset())
         * the counters and using adds, we set the counters
@@ -907,14 +907,16 @@ get_counters(const struct xt_table_info *t,
         * if new softirq were to run and call ipt_do_table
         */
        local_bh_disable();
-       curcpu = smp_processor_id();
-
        i = 0;
        xt_entry_foreach(iter, t->entries[curcpu], t->size) {
                SET_COUNTER(counters[i], iter->counters.bcnt,
                            iter->counters.pcnt);
                ++i;
        }
+       local_bh_enable();
+       /* Processing counters from other cpus, we can let bottom half enabled,
+        * (preemption is disabled)
+        */
 
        for_each_possible_cpu(cpu) {
                if (cpu == curcpu)
@@ -928,7 +930,7 @@ get_counters(const struct xt_table_info *t,
                }
                xt_info_wrunlock(cpu);
        }
-       local_bh_enable();
+       put_cpu();
 }
 
 static struct xt_counters *alloc_counters(const struct xt_table *table)