Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/kaber/nf-next-2.6
[safe/jmp/linux-2.6] / net / netfilter / x_tables.c
index 5baccfa..509a956 100644 (file)
@@ -625,6 +625,20 @@ void xt_free_table_info(struct xt_table_info *info)
 }
 EXPORT_SYMBOL(xt_free_table_info);
 
+void xt_table_entry_swap_rcu(struct xt_table_info *oldinfo,
+                            struct xt_table_info *newinfo)
+{
+       unsigned int cpu;
+
+       for_each_possible_cpu(cpu) {
+               void *p = oldinfo->entries[cpu];
+               rcu_assign_pointer(oldinfo->entries[cpu], newinfo->entries[cpu]);
+               newinfo->entries[cpu] = p;
+       }
+
+}
+EXPORT_SYMBOL_GPL(xt_table_entry_swap_rcu);
+
 /* Find table by name, grabs mutex & ref.  Returns ERR_PTR() on error. */
 struct xt_table *xt_find_table_lock(struct net *net, u_int8_t af,
                                    const char *name)
@@ -671,21 +685,22 @@ xt_replace_table(struct xt_table *table,
        struct xt_table_info *oldinfo, *private;
 
        /* Do the substitution. */
-       write_lock_bh(&table->lock);
+       mutex_lock(&table->lock);
        private = table->private;
        /* Check inside lock: is the old number correct? */
        if (num_counters != private->number) {
                duprintf("num_counters != table->private->number (%u/%u)\n",
                         num_counters, private->number);
-               write_unlock_bh(&table->lock);
+               mutex_unlock(&table->lock);
                *error = -EAGAIN;
                return NULL;
        }
        oldinfo = private;
-       table->private = newinfo;
+       rcu_assign_pointer(table->private, newinfo);
        newinfo->initial_entries = oldinfo->initial_entries;
-       write_unlock_bh(&table->lock);
+       mutex_unlock(&table->lock);
 
+       synchronize_net();
        return oldinfo;
 }
 EXPORT_SYMBOL_GPL(xt_replace_table);
@@ -719,7 +734,8 @@ struct xt_table *xt_register_table(struct net *net, struct xt_table *table,
 
        /* Simplifies replace_table code. */
        table->private = bootstrap;
-       rwlock_init(&table->lock);
+       mutex_init(&table->lock);
+
        if (!xt_replace_table(table, 0, newinfo, &ret))
                goto unlock;