Merge tag 'dma-buf-for-4.2' of git://git.kernel.org/pub/scm/linux/kernel/git/sumits...
[linux-2.6-block.git] / net / ipv4 / netfilter / arp_tables.c
index a61200754f4ba29301855ae67055dd11d004780b..95c9b6eece25dfa8da28f8866dd7e55ec86b72e7 100644 (file)
@@ -256,7 +256,7 @@ unsigned int arpt_do_table(struct sk_buff *skb,
        const struct arphdr *arp;
        struct arpt_entry *e, *back;
        const char *indev, *outdev;
-       void *table_base;
+       const void *table_base;
        const struct xt_table_info *private;
        struct xt_action_param acpar;
        unsigned int addend;
@@ -275,7 +275,7 @@ unsigned int arpt_do_table(struct sk_buff *skb,
         * pointer.
         */
        smp_read_barrier_depends();
-       table_base = private->entries[smp_processor_id()];
+       table_base = private->entries;
 
        e = get_entry(table_base, private->hook_entry[hook]);
        back = get_entry(table_base, private->underflow[hook]);
@@ -289,13 +289,15 @@ unsigned int arpt_do_table(struct sk_buff *skb,
        arp = arp_hdr(skb);
        do {
                const struct xt_entry_target *t;
+               struct xt_counters *counter;
 
                if (!arp_packet_match(arp, skb->dev, indev, outdev, &e->arp)) {
                        e = arpt_next_entry(e);
                        continue;
                }
 
-               ADD_COUNTER(e->counters, arp_hdr_len(skb->dev), 1);
+               counter = xt_get_this_cpu_counter(&e->counters);
+               ADD_COUNTER(*counter, arp_hdr_len(skb->dev), 1);
 
                t = arpt_get_target_c(e);
 
@@ -521,6 +523,10 @@ find_check_entry(struct arpt_entry *e, const char *name, unsigned int size)
        if (ret)
                return ret;
 
+       e->counters.pcnt = xt_percpu_counter_alloc();
+       if (IS_ERR_VALUE(e->counters.pcnt))
+               return -ENOMEM;
+
        t = arpt_get_target(e);
        target = xt_request_find_target(NFPROTO_ARP, t->u.user.name,
                                        t->u.user.revision);
@@ -538,6 +544,8 @@ find_check_entry(struct arpt_entry *e, const char *name, unsigned int size)
 err:
        module_put(t->u.kernel.target->me);
 out:
+       xt_percpu_counter_free(e->counters.pcnt);
+
        return ret;
 }
 
@@ -614,6 +622,7 @@ static inline void cleanup_entry(struct arpt_entry *e)
        if (par.target->destroy != NULL)
                par.target->destroy(&par);
        module_put(par.target->me);
+       xt_percpu_counter_free(e->counters.pcnt);
 }
 
 /* Checks and translates the user-supplied table segment (held in
@@ -702,12 +711,6 @@ static int translate_table(struct xt_table_info *newinfo, void *entry0,
                return ret;
        }
 
-       /* And one copy for every other CPU */
-       for_each_possible_cpu(i) {
-               if (newinfo->entries[i] && newinfo->entries[i] != entry0)
-                       memcpy(newinfo->entries[i], entry0, newinfo->size);
-       }
-
        return ret;
 }
 
@@ -722,14 +725,16 @@ static void get_counters(const struct xt_table_info *t,
                seqcount_t *s = &per_cpu(xt_recseq, cpu);
 
                i = 0;
-               xt_entry_foreach(iter, t->entries[cpu], t->size) {
+               xt_entry_foreach(iter, t->entries, t->size) {
+                       struct xt_counters *tmp;
                        u64 bcnt, pcnt;
                        unsigned int start;
 
+                       tmp = xt_get_per_cpu_counter(&iter->counters, cpu);
                        do {
                                start = read_seqcount_begin(s);
-                               bcnt = iter->counters.bcnt;
-                               pcnt = iter->counters.pcnt;
+                               bcnt = tmp->bcnt;
+                               pcnt = tmp->pcnt;
                        } while (read_seqcount_retry(s, start));
 
                        ADD_COUNTER(counters[i], bcnt, pcnt);
@@ -774,7 +779,7 @@ static int copy_entries_to_user(unsigned int total_size,
        if (IS_ERR(counters))
                return PTR_ERR(counters);
 
-       loc_cpu_entry = private->entries[raw_smp_processor_id()];
+       loc_cpu_entry = private->entries;
        /* ... then copy entire thing ... */
        if (copy_to_user(userptr, loc_cpu_entry, total_size) != 0) {
                ret = -EFAULT;
@@ -863,16 +868,16 @@ static int compat_table_info(const struct xt_table_info *info,
                             struct xt_table_info *newinfo)
 {
        struct arpt_entry *iter;
-       void *loc_cpu_entry;
+       const void *loc_cpu_entry;
        int ret;
 
        if (!newinfo || !info)
                return -EINVAL;
 
-       /* we dont care about newinfo->entries[] */
+       /* we dont care about newinfo->entries */
        memcpy(newinfo, info, offsetof(struct xt_table_info, entries));
        newinfo->initial_entries = 0;
-       loc_cpu_entry = info->entries[raw_smp_processor_id()];
+       loc_cpu_entry = info->entries;
        xt_compat_init_offsets(NFPROTO_ARP, info->number);
        xt_entry_foreach(iter, loc_cpu_entry, info->size) {
                ret = compat_calc_entry(iter, info, loc_cpu_entry, newinfo);
@@ -1037,7 +1042,7 @@ static int __do_replace(struct net *net, const char *name,
        get_counters(oldinfo, counters);
 
        /* Decrease module usage counts and free resource */
-       loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()];
+       loc_cpu_old_entry = oldinfo->entries;
        xt_entry_foreach(iter, loc_cpu_old_entry, oldinfo->size)
                cleanup_entry(iter);
 
@@ -1084,8 +1089,7 @@ static int do_replace(struct net *net, const void __user *user,
        if (!newinfo)
                return -ENOMEM;
 
-       /* choose the copy that is on our node/cpu */
-       loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
+       loc_cpu_entry = newinfo->entries;
        if (copy_from_user(loc_cpu_entry, user + sizeof(tmp),
                           tmp.size) != 0) {
                ret = -EFAULT;
@@ -1115,7 +1119,7 @@ static int do_replace(struct net *net, const void __user *user,
 static int do_add_counters(struct net *net, const void __user *user,
                           unsigned int len, int compat)
 {
-       unsigned int i, curcpu;
+       unsigned int i;
        struct xt_counters_info tmp;
        struct xt_counters *paddc;
        unsigned int num_counters;
@@ -1125,7 +1129,6 @@ static int do_add_counters(struct net *net, const void __user *user,
        struct xt_table *t;
        const struct xt_table_info *private;
        int ret = 0;
-       void *loc_cpu_entry;
        struct arpt_entry *iter;
        unsigned int addend;
 #ifdef CONFIG_COMPAT
@@ -1181,12 +1184,13 @@ static int do_add_counters(struct net *net, const void __user *user,
        }
 
        i = 0;
-       /* Choose the copy that is on our node */
-       curcpu = smp_processor_id();
-       loc_cpu_entry = private->entries[curcpu];
+
        addend = xt_write_recseq_begin();
-       xt_entry_foreach(iter, loc_cpu_entry, private->size) {
-               ADD_COUNTER(iter->counters, paddc[i].bcnt, paddc[i].pcnt);
+       xt_entry_foreach(iter,  private->entries, private->size) {
+               struct xt_counters *tmp;
+
+               tmp = xt_get_this_cpu_counter(&iter->counters);
+               ADD_COUNTER(*tmp, paddc[i].bcnt, paddc[i].pcnt);
                ++i;
        }
        xt_write_recseq_end(addend);
@@ -1396,7 +1400,7 @@ static int translate_compat_table(const char *name,
                newinfo->hook_entry[i] = info->hook_entry[i];
                newinfo->underflow[i] = info->underflow[i];
        }
-       entry1 = newinfo->entries[raw_smp_processor_id()];
+       entry1 = newinfo->entries;
        pos = entry1;
        size = total_size;
        xt_entry_foreach(iter0, entry0, total_size) {
@@ -1416,9 +1420,17 @@ static int translate_compat_table(const char *name,
 
        i = 0;
        xt_entry_foreach(iter1, entry1, newinfo->size) {
+               iter1->counters.pcnt = xt_percpu_counter_alloc();
+               if (IS_ERR_VALUE(iter1->counters.pcnt)) {
+                       ret = -ENOMEM;
+                       break;
+               }
+
                ret = check_target(iter1, name);
-               if (ret != 0)
+               if (ret != 0) {
+                       xt_percpu_counter_free(iter1->counters.pcnt);
                        break;
+               }
                ++i;
                if (strcmp(arpt_get_target(iter1)->u.user.name,
                    XT_ERROR_TARGET) == 0)
@@ -1448,11 +1460,6 @@ static int translate_compat_table(const char *name,
                return ret;
        }
 
-       /* And one copy for every other CPU */
-       for_each_possible_cpu(i)
-               if (newinfo->entries[i] && newinfo->entries[i] != entry1)
-                       memcpy(newinfo->entries[i], entry1, newinfo->size);
-
        *pinfo = newinfo;
        *pentry0 = entry1;
        xt_free_table_info(info);
@@ -1511,8 +1518,7 @@ static int compat_do_replace(struct net *net, void __user *user,
        if (!newinfo)
                return -ENOMEM;
 
-       /* choose the copy that is on our node/cpu */
-       loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
+       loc_cpu_entry = newinfo->entries;
        if (copy_from_user(loc_cpu_entry, user + sizeof(tmp), tmp.size) != 0) {
                ret = -EFAULT;
                goto free_newinfo;
@@ -1609,7 +1615,6 @@ static int compat_copy_entries_to_user(unsigned int total_size,
        void __user *pos;
        unsigned int size;
        int ret = 0;
-       void *loc_cpu_entry;
        unsigned int i = 0;
        struct arpt_entry *iter;
 
@@ -1617,11 +1622,9 @@ static int compat_copy_entries_to_user(unsigned int total_size,
        if (IS_ERR(counters))
                return PTR_ERR(counters);
 
-       /* choose the copy on our node/cpu */
-       loc_cpu_entry = private->entries[raw_smp_processor_id()];
        pos = userptr;
        size = total_size;
-       xt_entry_foreach(iter, loc_cpu_entry, total_size) {
+       xt_entry_foreach(iter, private->entries, total_size) {
                ret = compat_copy_entry_to_user(iter, &pos,
                                                &size, counters, i++);
                if (ret != 0)
@@ -1790,8 +1793,7 @@ struct xt_table *arpt_register_table(struct net *net,
                goto out;
        }
 
-       /* choose the copy on our node/cpu */
-       loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
+       loc_cpu_entry = newinfo->entries;
        memcpy(loc_cpu_entry, repl->entries, repl->size);
 
        ret = translate_table(newinfo, loc_cpu_entry, repl);
@@ -1822,7 +1824,7 @@ void arpt_unregister_table(struct xt_table *table)
        private = xt_unregister_table(table);
 
        /* Decrease module usage counts and free resources */
-       loc_cpu_entry = private->entries[raw_smp_processor_id()];
+       loc_cpu_entry = private->entries;
        xt_entry_foreach(iter, loc_cpu_entry, private->size)
                cleanup_entry(iter);
        if (private->number > private->initial_entries)