aboutsummaryrefslogtreecommitdiffstats
path: root/net/netfilter
diff options
context:
space:
mode:
Diffstat (limited to 'net/netfilter')
-rw-r--r--net/netfilter/x_tables.c26
1 files changed, 21 insertions, 5 deletions
diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c
index bfbf521f6ea..bfcac92d556 100644
--- a/net/netfilter/x_tables.c
+++ b/net/netfilter/x_tables.c
@@ -625,6 +625,20 @@ void xt_free_table_info(struct xt_table_info *info)
625} 625}
626EXPORT_SYMBOL(xt_free_table_info); 626EXPORT_SYMBOL(xt_free_table_info);
627 627
628void xt_table_entry_swap_rcu(struct xt_table_info *oldinfo,
629 struct xt_table_info *newinfo)
630{
631 unsigned int cpu;
632
633 for_each_possible_cpu(cpu) {
634 void *p = oldinfo->entries[cpu];
635 rcu_assign_pointer(oldinfo->entries[cpu], newinfo->entries[cpu]);
636 newinfo->entries[cpu] = p;
637 }
638
639}
640EXPORT_SYMBOL_GPL(xt_table_entry_swap_rcu);
641
628/* Find table by name, grabs mutex & ref. Returns ERR_PTR() on error. */ 642/* Find table by name, grabs mutex & ref. Returns ERR_PTR() on error. */
629struct xt_table *xt_find_table_lock(struct net *net, u_int8_t af, 643struct xt_table *xt_find_table_lock(struct net *net, u_int8_t af,
630 const char *name) 644 const char *name)
@@ -671,21 +685,22 @@ xt_replace_table(struct xt_table *table,
671 struct xt_table_info *oldinfo, *private; 685 struct xt_table_info *oldinfo, *private;
672 686
673 /* Do the substitution. */ 687 /* Do the substitution. */
674 write_lock_bh(&table->lock); 688 mutex_lock(&table->lock);
675 private = table->private; 689 private = table->private;
676 /* Check inside lock: is the old number correct? */ 690 /* Check inside lock: is the old number correct? */
677 if (num_counters != private->number) { 691 if (num_counters != private->number) {
678 duprintf("num_counters != table->private->number (%u/%u)\n", 692 duprintf("num_counters != table->private->number (%u/%u)\n",
679 num_counters, private->number); 693 num_counters, private->number);
680 write_unlock_bh(&table->lock); 694 mutex_unlock(&table->lock);
681 *error = -EAGAIN; 695 *error = -EAGAIN;
682 return NULL; 696 return NULL;
683 } 697 }
684 oldinfo = private; 698 oldinfo = private;
685 table->private = newinfo; 699 rcu_assign_pointer(table->private, newinfo);
686 newinfo->initial_entries = oldinfo->initial_entries; 700 newinfo->initial_entries = oldinfo->initial_entries;
687 write_unlock_bh(&table->lock); 701 mutex_unlock(&table->lock);
688 702
703 synchronize_net();
689 return oldinfo; 704 return oldinfo;
690} 705}
691EXPORT_SYMBOL_GPL(xt_replace_table); 706EXPORT_SYMBOL_GPL(xt_replace_table);
@@ -719,7 +734,8 @@ struct xt_table *xt_register_table(struct net *net, struct xt_table *table,
719 734
720 /* Simplifies replace_table code. */ 735 /* Simplifies replace_table code. */
721 table->private = bootstrap; 736 table->private = bootstrap;
722 rwlock_init(&table->lock); 737 mutex_init(&table->lock);
738
723 if (!xt_replace_table(table, 0, newinfo, &ret)) 739 if (!xt_replace_table(table, 0, newinfo, &ret))
724 goto unlock; 740 goto unlock;
725 741