History

netfilter: xtables: avoid percpu ruleset duplication

We store the rule blob per (possible) cpu. Unfortunately this means we can waste lot of memory on big smp machines. ipt_entry structure ('rule head') is 112 byte, so e.g. with maxcpu=64 one single rule eats close to 8k RAM. Since previous patch made counters percpu it appears there is nothing left in the rule blob that needs to be percpu. On my test system (144 possible cpus, 400k dummy rules) this change saves close to 9 Gigabyte of RAM.

Florian Westphal committed 11 years ago

Commit 482cfc31 parent 71ae0df5 files · +57 −149Browse files

Unified · Split

5 files
  1. include/linux/netfilter/x_tables.h +2 −2
  2. net/ipv4/netfilter/arp_tables.c +15 −35
  3. net/ipv4/netfilter/ip_tables.c +16 −48
  4. net/ipv6/netfilter/ip6_tables.c +16 −49
  5. net/netfilter/x_tables.c +8 −15
include/linux/netfilter/x_tables.h+2−2
@@ -224,9 +224,9 @@ struct xt_table_info { · 223 unmodified lines
224 unsigned int stacksize;224 unsigned int stacksize;
225 unsigned int __percpu *stackptr;225 unsigned int __percpu *stackptr;
226 void ***jumpstack;226 void ***jumpstack;
227 /* ipt_entry tables: one per CPU */227
228 /* Note : this field MUST be the last one, see XT_TABLE_INFO_SZ */228 /* Note : this field MUST be the last one, see XT_TABLE_INFO_SZ */
229 void *entries[1];229 void *entries;
230};230};
231 231
232#define XT_TABLE_INFO_SZ (offsetof(struct xt_table_info, entries) \232#define XT_TABLE_INFO_SZ (offsetof(struct xt_table_info, entries) \
net/ipv4/netfilter/arp_tables.c+15−35
@@ -275,7 +275,7 @@ unsigned int arpt_do_table(struct sk_buff *skb, · 274 unmodified lines
275 * pointer.275 * pointer.
276 */276 */
277 smp_read_barrier_depends();277 smp_read_barrier_depends();
278 table_base = private->entries[smp_processor_id()];278 table_base = private->entries;
279 279
280 e = get_entry(table_base, private->hook_entry[hook]);280 e = get_entry(table_base, private->hook_entry[hook]);
281 back = get_entry(table_base, private->underflow[hook]);281 back = get_entry(table_base, private->underflow[hook]);
@@ -711,12 +711,6 @@ static int translate_table(struct xt_table_info *newinfo, void *entry0, · 429 unmodified lines
711 return ret;711 return ret;
712 }712 }
713 713
714 /* And one copy for every other CPU */
715 for_each_possible_cpu(i) {
716 if (newinfo->entries[i] && newinfo->entries[i] != entry0)
717 memcpy(newinfo->entries[i], entry0, newinfo->size);
718 }
719
720 return ret;714 return ret;
721}715}
722 716
@@ -731,7 +725,7 @@ static void get_counters(const struct xt_table_info *t, · 8 unmodified lines
731 seqcount_t *s = &per_cpu(xt_recseq, cpu);725 seqcount_t *s = &per_cpu(xt_recseq, cpu);
732 726
733 i = 0;727 i = 0;
734 xt_entry_foreach(iter, t->entries[cpu], t->size) {728 xt_entry_foreach(iter, t->entries, t->size) {
735 struct xt_counters *tmp;729 struct xt_counters *tmp;
736 u64 bcnt, pcnt;730 u64 bcnt, pcnt;
737 unsigned int start;731 unsigned int start;
@@ -785,7 +779,7 @@ static int copy_entries_to_user(unsigned int total_size, · 47 unmodified lines
785 if (IS_ERR(counters))779 if (IS_ERR(counters))
786 return PTR_ERR(counters);780 return PTR_ERR(counters);
787 781
788 loc_cpu_entry = private->entries[raw_smp_processor_id()];782 loc_cpu_entry = private->entries;
789 /* ... then copy entire thing ... */783 /* ... then copy entire thing ... */
790 if (copy_to_user(userptr, loc_cpu_entry, total_size) != 0) {784 if (copy_to_user(userptr, loc_cpu_entry, total_size) != 0) {
791 ret = -EFAULT;785 ret = -EFAULT;
@@ -880,10 +874,10 @@ static int compat_table_info(const struct xt_table_info *info, · 88 unmodified lines
880 if (!newinfo || !info)874 if (!newinfo || !info)
881 return -EINVAL;875 return -EINVAL;
882 876
883 /* we dont care about newinfo->entries[] */877 /* we dont care about newinfo->entries */
884 memcpy(newinfo, info, offsetof(struct xt_table_info, entries));878 memcpy(newinfo, info, offsetof(struct xt_table_info, entries));
885 newinfo->initial_entries = 0;879 newinfo->initial_entries = 0;
886 loc_cpu_entry = info->entries[raw_smp_processor_id()];880 loc_cpu_entry = info->entries;
887 xt_compat_init_offsets(NFPROTO_ARP, info->number);881 xt_compat_init_offsets(NFPROTO_ARP, info->number);
888 xt_entry_foreach(iter, loc_cpu_entry, info->size) {882 xt_entry_foreach(iter, loc_cpu_entry, info->size) {
889 ret = compat_calc_entry(iter, info, loc_cpu_entry, newinfo);883 ret = compat_calc_entry(iter, info, loc_cpu_entry, newinfo);
@@ -1048,7 +1042,7 @@ static int __do_replace(struct net *net, const char *name, · 158 unmodified lines
1048 get_counters(oldinfo, counters);1042 get_counters(oldinfo, counters);
1049 1043
1050 /* Decrease module usage counts and free resource */1044 /* Decrease module usage counts and free resource */
1051 loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()];1045 loc_cpu_old_entry = oldinfo->entries;
1052 xt_entry_foreach(iter, loc_cpu_old_entry, oldinfo->size)1046 xt_entry_foreach(iter, loc_cpu_old_entry, oldinfo->size)
1053 cleanup_entry(iter);1047 cleanup_entry(iter);
1054 1048
@@ -1095,8 +1089,7 @@ static int do_replace(struct net *net, const void __user *user, · 40 unmodified lines
1095 if (!newinfo)1089 if (!newinfo)
1096 return -ENOMEM;1090 return -ENOMEM;
1097 1091
1098 /* choose the copy that is on our node/cpu */1092 loc_cpu_entry = newinfo->entries;
1099 loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
1100 if (copy_from_user(loc_cpu_entry, user + sizeof(tmp),1093 if (copy_from_user(loc_cpu_entry, user + sizeof(tmp),
1101 tmp.size) != 0) {1094 tmp.size) != 0) {
1102 ret = -EFAULT;1095 ret = -EFAULT;
@@ -1126,7 +1119,7 @@ static int do_replace(struct net *net, const void __user *user, · 23 unmodified lines
1126static int do_add_counters(struct net *net, const void __user *user,1119static int do_add_counters(struct net *net, const void __user *user,
1127 unsigned int len, int compat)1120 unsigned int len, int compat)
1128{1121{
1129 unsigned int i, curcpu;1122 unsigned int i;
1130 struct xt_counters_info tmp;1123 struct xt_counters_info tmp;
1131 struct xt_counters *paddc;1124 struct xt_counters *paddc;
1132 unsigned int num_counters;1125 unsigned int num_counters;
@@ -1136,7 +1129,6 @@ static int do_add_counters(struct net *net, const void __user *user, · 3 unmodified lines
1136 struct xt_table *t;1129 struct xt_table *t;
1137 const struct xt_table_info *private;1130 const struct xt_table_info *private;
1138 int ret = 0;1131 int ret = 0;
1139 void *loc_cpu_entry;
1140 struct arpt_entry *iter;1132 struct arpt_entry *iter;
1141 unsigned int addend;1133 unsigned int addend;
1142#ifdef CONFIG_COMPAT1134#ifdef CONFIG_COMPAT
@@ -1192,11 +1184,9 @@ static int do_add_counters(struct net *net, const void __user *user, · 49 unmodified lines
1192 }1184 }
1193 1185
1194 i = 0;1186 i = 0;
1195 /* Choose the copy that is on our node */1187
1196 curcpu = smp_processor_id();
1197 loc_cpu_entry = private->entries[curcpu];
1198 addend = xt_write_recseq_begin();1188 addend = xt_write_recseq_begin();
1199 xt_entry_foreach(iter, loc_cpu_entry, private->size) {1189 xt_entry_foreach(iter, private->entries, private->size) {
1200 struct xt_counters *tmp;1190 struct xt_counters *tmp;
1201 1191
1202 tmp = xt_get_this_cpu_counter(&iter->counters);1192 tmp = xt_get_this_cpu_counter(&iter->counters);
@@ -1410,7 +1400,7 @@ static int translate_compat_table(const char *name, · 207 unmodified lines
1410 newinfo->hook_entry[i] = info->hook_entry[i];1400 newinfo->hook_entry[i] = info->hook_entry[i];
1411 newinfo->underflow[i] = info->underflow[i];1401 newinfo->underflow[i] = info->underflow[i];
1412 }1402 }
1413 entry1 = newinfo->entries[raw_smp_processor_id()];1403 entry1 = newinfo->entries;
1414 pos = entry1;1404 pos = entry1;
1415 size = total_size;1405 size = total_size;
1416 xt_entry_foreach(iter0, entry0, total_size) {1406 xt_entry_foreach(iter0, entry0, total_size) {
@@ -1470,11 +1460,6 @@ static int translate_compat_table(const char *name, · 53 unmodified lines
1470 return ret;1460 return ret;
1471 }1461 }
1472 1462
1473 /* And one copy for every other CPU */
1474 for_each_possible_cpu(i)
1475 if (newinfo->entries[i] && newinfo->entries[i] != entry1)
1476 memcpy(newinfo->entries[i], entry1, newinfo->size);
1477
1478 *pinfo = newinfo;1463 *pinfo = newinfo;
1479 *pentry0 = entry1;1464 *pentry0 = entry1;
1480 xt_free_table_info(info);1465 xt_free_table_info(info);
@@ -1533,8 +1518,7 @@ static int compat_do_replace(struct net *net, void __user *user, · 52 unmodified lines
1533 if (!newinfo)1518 if (!newinfo)
1534 return -ENOMEM;1519 return -ENOMEM;
1535 1520
1536 /* choose the copy that is on our node/cpu */1521 loc_cpu_entry = newinfo->entries;
1537 loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
1538 if (copy_from_user(loc_cpu_entry, user + sizeof(tmp), tmp.size) != 0) {1522 if (copy_from_user(loc_cpu_entry, user + sizeof(tmp), tmp.size) != 0) {
1539 ret = -EFAULT;1523 ret = -EFAULT;
1540 goto free_newinfo;1524 goto free_newinfo;
@@ -1631,7 +1615,6 @@ static int compat_copy_entries_to_user(unsigned int total_size, · 90 unmodified lines
1631 void __user *pos;1615 void __user *pos;
1632 unsigned int size;1616 unsigned int size;
1633 int ret = 0;1617 int ret = 0;
1634 void *loc_cpu_entry;
1635 unsigned int i = 0;1618 unsigned int i = 0;
1636 struct arpt_entry *iter;1619 struct arpt_entry *iter;
1637 1620
@@ -1639,11 +1622,9 @@ static int compat_copy_entries_to_user(unsigned int total_size, · 1 unmodified line
1639 if (IS_ERR(counters))1622 if (IS_ERR(counters))
1640 return PTR_ERR(counters);1623 return PTR_ERR(counters);
1641 1624
1642 /* choose the copy on our node/cpu */
1643 loc_cpu_entry = private->entries[raw_smp_processor_id()];
1644 pos = userptr;1625 pos = userptr;
1645 size = total_size;1626 size = total_size;
1646 xt_entry_foreach(iter, loc_cpu_entry, total_size) {1627 xt_entry_foreach(iter, private->entries, total_size) {
1647 ret = compat_copy_entry_to_user(iter, &pos,1628 ret = compat_copy_entry_to_user(iter, &pos,
1648 &size, counters, i++);1629 &size, counters, i++);
1649 if (ret != 0)1630 if (ret != 0)
@@ -1812,8 +1793,7 @@ struct xt_table *arpt_register_table(struct net *net, · 162 unmodified lines
1812 goto out;1793 goto out;
1813 }1794 }
1814 1795
1815 /* choose the copy on our node/cpu */1796 loc_cpu_entry = newinfo->entries;
1816 loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
1817 memcpy(loc_cpu_entry, repl->entries, repl->size);1797 memcpy(loc_cpu_entry, repl->entries, repl->size);
1818 1798
1819 ret = translate_table(newinfo, loc_cpu_entry, repl);1799 ret = translate_table(newinfo, loc_cpu_entry, repl);
@@ -1844,7 +1824,7 @@ void arpt_unregister_table(struct xt_table *table) · 24 unmodified lines
1844 private = xt_unregister_table(table);1824 private = xt_unregister_table(table);
1845 1825
1846 /* Decrease module usage counts and free resources */1826 /* Decrease module usage counts and free resources */
1847 loc_cpu_entry = private->entries[raw_smp_processor_id()];1827 loc_cpu_entry = private->entries;
1848 xt_entry_foreach(iter, loc_cpu_entry, private->size)1828 xt_entry_foreach(iter, loc_cpu_entry, private->size)
1849 cleanup_entry(iter);1829 cleanup_entry(iter);
1850 if (private->number > private->initial_entries)1830 if (private->number > private->initial_entries)
net/ipv4/netfilter/ip_tables.c+16−48
@@ -254,15 +254,13 @@ static void trace_packet(const struct sk_buff *skb, · 253 unmodified lines
254 const struct xt_table_info *private,254 const struct xt_table_info *private,
255 const struct ipt_entry *e)255 const struct ipt_entry *e)
256{256{
257 const void *table_base;
258 const struct ipt_entry *root;257 const struct ipt_entry *root;
259 const char *hookname, *chainname, *comment;258 const char *hookname, *chainname, *comment;
260 const struct ipt_entry *iter;259 const struct ipt_entry *iter;
261 unsigned int rulenum = 0;260 unsigned int rulenum = 0;
262 struct net *net = dev_net(in ? in : out);261 struct net *net = dev_net(in ? in : out);
263 262
264 table_base = private->entries[smp_processor_id()];263 root = get_entry(private->entries, private->hook_entry[hook]);
265 root = get_entry(table_base, private->hook_entry[hook]);
266 264
267 hookname = chainname = hooknames[hook];265 hookname = chainname = hooknames[hook];
268 comment = comments[NF_IP_TRACE_COMMENT_RULE];266 comment = comments[NF_IP_TRACE_COMMENT_RULE];
@@ -331,7 +329,7 @@ ipt_do_table(struct sk_buff *skb, · 62 unmodified lines
331 * pointer.329 * pointer.
332 */330 */
333 smp_read_barrier_depends();331 smp_read_barrier_depends();
334 table_base = private->entries[cpu];332 table_base = private->entries;
335 jumpstack = (struct ipt_entry **)private->jumpstack[cpu];333 jumpstack = (struct ipt_entry **)private->jumpstack[cpu];
336 stackptr = per_cpu_ptr(private->stackptr, cpu);334 stackptr = per_cpu_ptr(private->stackptr, cpu);
337 origptr = *stackptr;335 origptr = *stackptr;
@@ -877,12 +875,6 @@ translate_table(struct net *net, struct xt_table_info *newinfo, void *entry0, · 539 unmodified lines
877 return ret;875 return ret;
878 }876 }
879 877
880 /* And one copy for every other CPU */
881 for_each_possible_cpu(i) {
882 if (newinfo->entries[i] && newinfo->entries[i] != entry0)
883 memcpy(newinfo->entries[i], entry0, newinfo->size);
884 }
885
886 return ret;878 return ret;
887}879}
888 880
@@ -898,7 +890,7 @@ get_counters(const struct xt_table_info *t, · 9 unmodified lines
898 seqcount_t *s = &per_cpu(xt_recseq, cpu);890 seqcount_t *s = &per_cpu(xt_recseq, cpu);
899 891
900 i = 0;892 i = 0;
901 xt_entry_foreach(iter, t->entries[cpu], t->size) {893 xt_entry_foreach(iter, t->entries, t->size) {
902 struct xt_counters *tmp;894 struct xt_counters *tmp;
903 u64 bcnt, pcnt;895 u64 bcnt, pcnt;
904 unsigned int start;896 unsigned int start;
@@ -946,17 +938,13 @@ copy_entries_to_user(unsigned int total_size, · 41 unmodified lines
946 struct xt_counters *counters;938 struct xt_counters *counters;
947 const struct xt_table_info *private = table->private;939 const struct xt_table_info *private = table->private;
948 int ret = 0;940 int ret = 0;
949 const void *loc_cpu_entry;941 void *loc_cpu_entry;
950 942
951 counters = alloc_counters(table);943 counters = alloc_counters(table);
952 if (IS_ERR(counters))944 if (IS_ERR(counters))
953 return PTR_ERR(counters);945 return PTR_ERR(counters);
954 946
955 /* choose the copy that is on our node/cpu, ...947 loc_cpu_entry = private->entries;
956 * This choice is lazy (because current thread is
957 * allowed to migrate to another cpu)
958 */
959 loc_cpu_entry = private->entries[raw_smp_processor_id()];
960 if (copy_to_user(userptr, loc_cpu_entry, total_size) != 0) {948 if (copy_to_user(userptr, loc_cpu_entry, total_size) != 0) {
961 ret = -EFAULT;949 ret = -EFAULT;
962 goto free_counters;950 goto free_counters;
@@ -1070,10 +1058,10 @@ static int compat_table_info(const struct xt_table_info *info, · 107 unmodified lines
1070 if (!newinfo || !info)1058 if (!newinfo || !info)
1071 return -EINVAL;1059 return -EINVAL;
1072 1060
1073 /* we dont care about newinfo->entries[] */1061 /* we dont care about newinfo->entries */
1074 memcpy(newinfo, info, offsetof(struct xt_table_info, entries));1062 memcpy(newinfo, info, offsetof(struct xt_table_info, entries));
1075 newinfo->initial_entries = 0;1063 newinfo->initial_entries = 0;
1076 loc_cpu_entry = info->entries[raw_smp_processor_id()];1064 loc_cpu_entry = info->entries;
1077 xt_compat_init_offsets(AF_INET, info->number);1065 xt_compat_init_offsets(AF_INET, info->number);
1078 xt_entry_foreach(iter, loc_cpu_entry, info->size) {1066 xt_entry_foreach(iter, loc_cpu_entry, info->size) {
1079 ret = compat_calc_entry(iter, info, loc_cpu_entry, newinfo);1067 ret = compat_calc_entry(iter, info, loc_cpu_entry, newinfo);
@@ -1194,7 +1182,6 @@ __do_replace(struct net *net, const char *name, unsigned int valid_hooks, · 114 unmodified lines
1194 struct xt_table *t;1182 struct xt_table *t;
1195 struct xt_table_info *oldinfo;1183 struct xt_table_info *oldinfo;
1196 struct xt_counters *counters;1184 struct xt_counters *counters;
1197 void *loc_cpu_old_entry;
1198 struct ipt_entry *iter;1185 struct ipt_entry *iter;
1199 1186
1200 ret = 0;1187 ret = 0;
@@ -1237,8 +1224,7 @@ __do_replace(struct net *net, const char *name, unsigned int valid_hooks, · 36 unmodified lines
1237 get_counters(oldinfo, counters);1224 get_counters(oldinfo, counters);
1238 1225
1239 /* Decrease module usage counts and free resource */1226 /* Decrease module usage counts and free resource */
1240 loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()];1227 xt_entry_foreach(iter, oldinfo->entries, oldinfo->size)
1241 xt_entry_foreach(iter, loc_cpu_old_entry, oldinfo->size)
1242 cleanup_entry(iter, net);1228 cleanup_entry(iter, net);
1243 1229
1244 xt_free_table_info(oldinfo);1230 xt_free_table_info(oldinfo);
@@ -1284,8 +1270,7 @@ do_replace(struct net *net, const void __user *user, unsigned int len) · 39 unmodified lines
1284 if (!newinfo)1270 if (!newinfo)
1285 return -ENOMEM;1271 return -ENOMEM;
1286 1272
1287 /* choose the copy that is on our node/cpu */1273 loc_cpu_entry = newinfo->entries;
1288 loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
1289 if (copy_from_user(loc_cpu_entry, user + sizeof(tmp),1274 if (copy_from_user(loc_cpu_entry, user + sizeof(tmp),
1290 tmp.size) != 0) {1275 tmp.size) != 0) {
1291 ret = -EFAULT;1276 ret = -EFAULT;
@@ -1316,7 +1301,7 @@ static int · 24 unmodified lines
1316do_add_counters(struct net *net, const void __user *user,1301do_add_counters(struct net *net, const void __user *user,
1317 unsigned int len, int compat)1302 unsigned int len, int compat)
1318{1303{
1319 unsigned int i, curcpu;1304 unsigned int i;
1320 struct xt_counters_info tmp;1305 struct xt_counters_info tmp;
1321 struct xt_counters *paddc;1306 struct xt_counters *paddc;
1322 unsigned int num_counters;1307 unsigned int num_counters;
@@ -1326,7 +1311,6 @@ do_add_counters(struct net *net, const void __user *user, · 3 unmodified lines
1326 struct xt_table *t;1311 struct xt_table *t;
1327 const struct xt_table_info *private;1312 const struct xt_table_info *private;
1328 int ret = 0;1313 int ret = 0;
1329 void *loc_cpu_entry;
1330 struct ipt_entry *iter;1314 struct ipt_entry *iter;
1331 unsigned int addend;1315 unsigned int addend;
1332#ifdef CONFIG_COMPAT1316#ifdef CONFIG_COMPAT
@@ -1382,11 +1366,8 @@ do_add_counters(struct net *net, const void __user *user, · 49 unmodified lines
1382 }1366 }
1383 1367
1384 i = 0;1368 i = 0;
1385 /* Choose the copy that is on our node */
1386 curcpu = smp_processor_id();
1387 loc_cpu_entry = private->entries[curcpu];
1388 addend = xt_write_recseq_begin();1369 addend = xt_write_recseq_begin();
1389 xt_entry_foreach(iter, loc_cpu_entry, private->size) {1370 xt_entry_foreach(iter, private->entries, private->size) {
1390 struct xt_counters *tmp;1371 struct xt_counters *tmp;
1391 1372
1392 tmp = xt_get_this_cpu_counter(&iter->counters);1373 tmp = xt_get_this_cpu_counter(&iter->counters);
@@ -1739,7 +1720,7 @@ translate_compat_table(struct net *net, · 346 unmodified lines
1739 newinfo->hook_entry[i] = info->hook_entry[i];1720 newinfo->hook_entry[i] = info->hook_entry[i];
1740 newinfo->underflow[i] = info->underflow[i];1721 newinfo->underflow[i] = info->underflow[i];
1741 }1722 }
1742 entry1 = newinfo->entries[raw_smp_processor_id()];1723 entry1 = newinfo->entries;
1743 pos = entry1;1724 pos = entry1;
1744 size = total_size;1725 size = total_size;
1745 xt_entry_foreach(iter0, entry0, total_size) {1726 xt_entry_foreach(iter0, entry0, total_size) {
@@ -1791,11 +1772,6 @@ translate_compat_table(struct net *net, · 45 unmodified lines
1791 return ret;1772 return ret;
1792 }1773 }
1793 1774
1794 /* And one copy for every other CPU */
1795 for_each_possible_cpu(i)
1796 if (newinfo->entries[i] && newinfo->entries[i] != entry1)
1797 memcpy(newinfo->entries[i], entry1, newinfo->size);
1798
1799 *pinfo = newinfo;1775 *pinfo = newinfo;
1800 *pentry0 = entry1;1776 *pentry0 = entry1;
1801 xt_free_table_info(info);1777 xt_free_table_info(info);
@@ -1842,8 +1818,7 @@ compat_do_replace(struct net *net, void __user *user, unsigned int len) · 40 unmodified lines
1842 if (!newinfo)1818 if (!newinfo)
1843 return -ENOMEM;1819 return -ENOMEM;
1844 1820
1845 /* choose the copy that is on our node/cpu */1821 loc_cpu_entry = newinfo->entries;
1846 loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
1847 if (copy_from_user(loc_cpu_entry, user + sizeof(tmp),1822 if (copy_from_user(loc_cpu_entry, user + sizeof(tmp),
1848 tmp.size) != 0) {1823 tmp.size) != 0) {
1849 ret = -EFAULT;1824 ret = -EFAULT;
@@ -1914,7 +1889,6 @@ compat_copy_entries_to_user(unsigned int total_size, struct xt_table *table, · 64 unmodified lines
1914 void __user *pos;1889 void __user *pos;
1915 unsigned int size;1890 unsigned int size;
1916 int ret = 0;1891 int ret = 0;
1917 const void *loc_cpu_entry;
1918 unsigned int i = 0;1892 unsigned int i = 0;
1919 struct ipt_entry *iter;1893 struct ipt_entry *iter;
1920 1894
@@ -1922,14 +1896,9 @@ compat_copy_entries_to_user(unsigned int total_size, struct xt_table *table, · 1 unmodified line
1922 if (IS_ERR(counters))1896 if (IS_ERR(counters))
1923 return PTR_ERR(counters);1897 return PTR_ERR(counters);
1924 1898
1925 /* choose the copy that is on our node/cpu, ...
1926 * This choice is lazy (because current thread is
1927 * allowed to migrate to another cpu)
1928 */
1929 loc_cpu_entry = private->entries[raw_smp_processor_id()];
1930 pos = userptr;1899 pos = userptr;
1931 size = total_size;1900 size = total_size;
1932 xt_entry_foreach(iter, loc_cpu_entry, total_size) {1901 xt_entry_foreach(iter, private->entries, total_size) {
1933 ret = compat_copy_entry_to_user(iter, &pos,1902 ret = compat_copy_entry_to_user(iter, &pos,
1934 &size, counters, i++);1903 &size, counters, i++);
1935 if (ret != 0)1904 if (ret != 0)
@@ -2104,8 +2073,7 @@ struct xt_table *ipt_register_table(struct net *net, · 168 unmodified lines
2104 goto out;2073 goto out;
2105 }2074 }
2106 2075
2107 /* choose the copy on our node/cpu, but dont care about preemption */2076 loc_cpu_entry = newinfo->entries;
2108 loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
2109 memcpy(loc_cpu_entry, repl->entries, repl->size);2077 memcpy(loc_cpu_entry, repl->entries, repl->size);
2110 2078
2111 ret = translate_table(net, newinfo, loc_cpu_entry, repl);2079 ret = translate_table(net, newinfo, loc_cpu_entry, repl);
@@ -2136,7 +2104,7 @@ void ipt_unregister_table(struct net *net, struct xt_table *table) · 24 unmodified lines
2136 private = xt_unregister_table(table);2104 private = xt_unregister_table(table);
2137 2105
2138 /* Decrease module usage counts and free resources */2106 /* Decrease module usage counts and free resources */
2139 loc_cpu_entry = private->entries[raw_smp_processor_id()];2107 loc_cpu_entry = private->entries;
2140 xt_entry_foreach(iter, loc_cpu_entry, private->size)2108 xt_entry_foreach(iter, loc_cpu_entry, private->size)
2141 cleanup_entry(iter, net);2109 cleanup_entry(iter, net);
2142 if (private->number > private->initial_entries)2110 if (private->number > private->initial_entries)
net/ipv6/netfilter/ip6_tables.c+16−49
@@ -283,15 +283,13 @@ static void trace_packet(const struct sk_buff *skb, · 282 unmodified lines
283 const struct xt_table_info *private,283 const struct xt_table_info *private,
284 const struct ip6t_entry *e)284 const struct ip6t_entry *e)
285{285{
286 const void *table_base;
287 const struct ip6t_entry *root;286 const struct ip6t_entry *root;
288 const char *hookname, *chainname, *comment;287 const char *hookname, *chainname, *comment;
289 const struct ip6t_entry *iter;288 const struct ip6t_entry *iter;
290 unsigned int rulenum = 0;289 unsigned int rulenum = 0;
291 struct net *net = dev_net(in ? in : out);290 struct net *net = dev_net(in ? in : out);
292 291
293 table_base = private->entries[smp_processor_id()];292 root = get_entry(private->entries, private->hook_entry[hook]);
294 root = get_entry(table_base, private->hook_entry[hook]);
295 293
296 hookname = chainname = hooknames[hook];294 hookname = chainname = hooknames[hook];
297 comment = comments[NF_IP6_TRACE_COMMENT_RULE];295 comment = comments[NF_IP6_TRACE_COMMENT_RULE];
@@ -357,7 +355,7 @@ ip6t_do_table(struct sk_buff *skb, · 59 unmodified lines
357 */355 */
358 smp_read_barrier_depends();356 smp_read_barrier_depends();
359 cpu = smp_processor_id();357 cpu = smp_processor_id();
360 table_base = private->entries[cpu];358 table_base = private->entries;
361 jumpstack = (struct ip6t_entry **)private->jumpstack[cpu];359 jumpstack = (struct ip6t_entry **)private->jumpstack[cpu];
362 stackptr = per_cpu_ptr(private->stackptr, cpu);360 stackptr = per_cpu_ptr(private->stackptr, cpu);
363 origptr = *stackptr;361 origptr = *stackptr;
@@ -890,12 +888,6 @@ translate_table(struct net *net, struct xt_table_info *newinfo, void *entry0, · 526 unmodified lines
890 return ret;888 return ret;
891 }889 }
892 890
893 /* And one copy for every other CPU */
894 for_each_possible_cpu(i) {
895 if (newinfo->entries[i] && newinfo->entries[i] != entry0)
896 memcpy(newinfo->entries[i], entry0, newinfo->size);
897 }
898
899 return ret;891 return ret;
900}892}
901 893
@@ -911,7 +903,7 @@ get_counters(const struct xt_table_info *t, · 9 unmodified lines
911 seqcount_t *s = &per_cpu(xt_recseq, cpu);903 seqcount_t *s = &per_cpu(xt_recseq, cpu);
912 904
913 i = 0;905 i = 0;
914 xt_entry_foreach(iter, t->entries[cpu], t->size) {906 xt_entry_foreach(iter, t->entries, t->size) {
915 struct xt_counters *tmp;907 struct xt_counters *tmp;
916 u64 bcnt, pcnt;908 u64 bcnt, pcnt;
917 unsigned int start;909 unsigned int start;
@@ -959,17 +951,13 @@ copy_entries_to_user(unsigned int total_size, · 41 unmodified lines
959 struct xt_counters *counters;951 struct xt_counters *counters;
960 const struct xt_table_info *private = table->private;952 const struct xt_table_info *private = table->private;
961 int ret = 0;953 int ret = 0;
962 const void *loc_cpu_entry;954 void *loc_cpu_entry;
963 955
964 counters = alloc_counters(table);956 counters = alloc_counters(table);
965 if (IS_ERR(counters))957 if (IS_ERR(counters))
966 return PTR_ERR(counters);958 return PTR_ERR(counters);
967 959
968 /* choose the copy that is on our node/cpu, ...960 loc_cpu_entry = private->entries;
969 * This choice is lazy (because current thread is
970 * allowed to migrate to another cpu)
971 */
972 loc_cpu_entry = private->entries[raw_smp_processor_id()];
973 if (copy_to_user(userptr, loc_cpu_entry, total_size) != 0) {961 if (copy_to_user(userptr, loc_cpu_entry, total_size) != 0) {
974 ret = -EFAULT;962 ret = -EFAULT;
975 goto free_counters;963 goto free_counters;
@@ -1083,10 +1071,10 @@ static int compat_table_info(const struct xt_table_info *info, · 107 unmodified lines
1083 if (!newinfo || !info)1071 if (!newinfo || !info)
1084 return -EINVAL;1072 return -EINVAL;
1085 1073
1086 /* we dont care about newinfo->entries[] */1074 /* we dont care about newinfo->entries */
1087 memcpy(newinfo, info, offsetof(struct xt_table_info, entries));1075 memcpy(newinfo, info, offsetof(struct xt_table_info, entries));
1088 newinfo->initial_entries = 0;1076 newinfo->initial_entries = 0;
1089 loc_cpu_entry = info->entries[raw_smp_processor_id()];1077 loc_cpu_entry = info->entries;
1090 xt_compat_init_offsets(AF_INET6, info->number);1078 xt_compat_init_offsets(AF_INET6, info->number);
1091 xt_entry_foreach(iter, loc_cpu_entry, info->size) {1079 xt_entry_foreach(iter, loc_cpu_entry, info->size) {
1092 ret = compat_calc_entry(iter, info, loc_cpu_entry, newinfo);1080 ret = compat_calc_entry(iter, info, loc_cpu_entry, newinfo);
@@ -1207,7 +1195,6 @@ __do_replace(struct net *net, const char *name, unsigned int valid_hooks, · 114 unmodified lines
1207 struct xt_table *t;1195 struct xt_table *t;
1208 struct xt_table_info *oldinfo;1196 struct xt_table_info *oldinfo;
1209 struct xt_counters *counters;1197 struct xt_counters *counters;
1210 const void *loc_cpu_old_entry;
1211 struct ip6t_entry *iter;1198 struct ip6t_entry *iter;
1212 1199
1213 ret = 0;1200 ret = 0;
@@ -1250,8 +1237,7 @@ __do_replace(struct net *net, const char *name, unsigned int valid_hooks, · 36 unmodified lines
1250 get_counters(oldinfo, counters);1237 get_counters(oldinfo, counters);
1251 1238
1252 /* Decrease module usage counts and free resource */1239 /* Decrease module usage counts and free resource */
1253 loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()];1240 xt_entry_foreach(iter, oldinfo->entries, oldinfo->size)
1254 xt_entry_foreach(iter, loc_cpu_old_entry, oldinfo->size)
1255 cleanup_entry(iter, net);1241 cleanup_entry(iter, net);
1256 1242
1257 xt_free_table_info(oldinfo);1243 xt_free_table_info(oldinfo);
@@ -1297,8 +1283,7 @@ do_replace(struct net *net, const void __user *user, unsigned int len) · 39 unmodified lines
1297 if (!newinfo)1283 if (!newinfo)
1298 return -ENOMEM;1284 return -ENOMEM;
1299 1285
1300 /* choose the copy that is on our node/cpu */1286 loc_cpu_entry = newinfo->entries;
1301 loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
1302 if (copy_from_user(loc_cpu_entry, user + sizeof(tmp),1287 if (copy_from_user(loc_cpu_entry, user + sizeof(tmp),
1303 tmp.size) != 0) {1288 tmp.size) != 0) {
1304 ret = -EFAULT;1289 ret = -EFAULT;
@@ -1329,7 +1314,7 @@ static int · 24 unmodified lines
1329do_add_counters(struct net *net, const void __user *user, unsigned int len,1314do_add_counters(struct net *net, const void __user *user, unsigned int len,
1330 int compat)1315 int compat)
1331{1316{
1332 unsigned int i, curcpu;1317 unsigned int i;
1333 struct xt_counters_info tmp;1318 struct xt_counters_info tmp;
1334 struct xt_counters *paddc;1319 struct xt_counters *paddc;
1335 unsigned int num_counters;1320 unsigned int num_counters;
@@ -1339,7 +1324,6 @@ do_add_counters(struct net *net, const void __user *user, unsigned int len, · 3 unmodified lines
1339 struct xt_table *t;1324 struct xt_table *t;
1340 const struct xt_table_info *private;1325 const struct xt_table_info *private;
1341 int ret = 0;1326 int ret = 0;
1342 const void *loc_cpu_entry;
1343 struct ip6t_entry *iter;1327 struct ip6t_entry *iter;
1344 unsigned int addend;1328 unsigned int addend;
1345#ifdef CONFIG_COMPAT1329#ifdef CONFIG_COMPAT
@@ -1395,11 +1379,8 @@ do_add_counters(struct net *net, const void __user *user, unsigned int len, · 49 unmodified lines
1395 }1379 }
1396 1380
1397 i = 0;1381 i = 0;
1398 /* Choose the copy that is on our node */
1399 curcpu = smp_processor_id();
1400 addend = xt_write_recseq_begin();1382 addend = xt_write_recseq_begin();
1401 loc_cpu_entry = private->entries[curcpu];1383 xt_entry_foreach(iter, private->entries, private->size) {
1402 xt_entry_foreach(iter, loc_cpu_entry, private->size) {
1403 struct xt_counters *tmp;1384 struct xt_counters *tmp;
1404 1385
1405 tmp = xt_get_this_cpu_counter(&iter->counters);1386 tmp = xt_get_this_cpu_counter(&iter->counters);
@@ -1407,7 +1388,6 @@ do_add_counters(struct net *net, const void __user *user, unsigned int len, · 1 unmodified line
1407 ++i;1388 ++i;
1408 }1389 }
1409 xt_write_recseq_end(addend);1390 xt_write_recseq_end(addend);
1410
1411 unlock_up_free:1391 unlock_up_free:
1412 local_bh_enable();1392 local_bh_enable();
1413 xt_table_unlock(t);1393 xt_table_unlock(t);
@@ -1750,7 +1730,7 @@ translate_compat_table(struct net *net, · 336 unmodified lines
1750 newinfo->hook_entry[i] = info->hook_entry[i];1730 newinfo->hook_entry[i] = info->hook_entry[i];
1751 newinfo->underflow[i] = info->underflow[i];1731 newinfo->underflow[i] = info->underflow[i];
1752 }1732 }
1753 entry1 = newinfo->entries[raw_smp_processor_id()];1733 entry1 = newinfo->entries;
1754 pos = entry1;1734 pos = entry1;
1755 size = total_size;1735 size = total_size;
1756 xt_entry_foreach(iter0, entry0, total_size) {1736 xt_entry_foreach(iter0, entry0, total_size) {
@@ -1802,11 +1782,6 @@ translate_compat_table(struct net *net, · 45 unmodified lines
1802 return ret;1782 return ret;
1803 }1783 }
1804 1784
1805 /* And one copy for every other CPU */
1806 for_each_possible_cpu(i)
1807 if (newinfo->entries[i] && newinfo->entries[i] != entry1)
1808 memcpy(newinfo->entries[i], entry1, newinfo->size);
1809
1810 *pinfo = newinfo;1785 *pinfo = newinfo;
1811 *pentry0 = entry1;1786 *pentry0 = entry1;
1812 xt_free_table_info(info);1787 xt_free_table_info(info);
@@ -1853,8 +1828,7 @@ compat_do_replace(struct net *net, void __user *user, unsigned int len) · 40 unmodified lines
1853 if (!newinfo)1828 if (!newinfo)
1854 return -ENOMEM;1829 return -ENOMEM;
1855 1830
1856 /* choose the copy that is on our node/cpu */1831 loc_cpu_entry = newinfo->entries;
1857 loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
1858 if (copy_from_user(loc_cpu_entry, user + sizeof(tmp),1832 if (copy_from_user(loc_cpu_entry, user + sizeof(tmp),
1859 tmp.size) != 0) {1833 tmp.size) != 0) {
1860 ret = -EFAULT;1834 ret = -EFAULT;
@@ -1925,7 +1899,6 @@ compat_copy_entries_to_user(unsigned int total_size, struct xt_table *table, · 64 unmodified lines
1925 void __user *pos;1899 void __user *pos;
1926 unsigned int size;1900 unsigned int size;
1927 int ret = 0;1901 int ret = 0;
1928 const void *loc_cpu_entry;
1929 unsigned int i = 0;1902 unsigned int i = 0;
1930 struct ip6t_entry *iter;1903 struct ip6t_entry *iter;
1931 1904
@@ -1933,14 +1906,9 @@ compat_copy_entries_to_user(unsigned int total_size, struct xt_table *table, · 1 unmodified line
1933 if (IS_ERR(counters))1906 if (IS_ERR(counters))
1934 return PTR_ERR(counters);1907 return PTR_ERR(counters);
1935 1908
1936 /* choose the copy that is on our node/cpu, ...
1937 * This choice is lazy (because current thread is
1938 * allowed to migrate to another cpu)
1939 */
1940 loc_cpu_entry = private->entries[raw_smp_processor_id()];
1941 pos = userptr;1909 pos = userptr;
1942 size = total_size;1910 size = total_size;
1943 xt_entry_foreach(iter, loc_cpu_entry, total_size) {1911 xt_entry_foreach(iter, private->entries, total_size) {
1944 ret = compat_copy_entry_to_user(iter, &pos,1912 ret = compat_copy_entry_to_user(iter, &pos,
1945 &size, counters, i++);1913 &size, counters, i++);
1946 if (ret != 0)1914 if (ret != 0)
@@ -2115,8 +2083,7 @@ struct xt_table *ip6t_register_table(struct net *net, · 168 unmodified lines
2115 goto out;2083 goto out;
2116 }2084 }
2117 2085
2118 /* choose the copy on our node/cpu, but dont care about preemption */2086 loc_cpu_entry = newinfo->entries;
2119 loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
2120 memcpy(loc_cpu_entry, repl->entries, repl->size);2087 memcpy(loc_cpu_entry, repl->entries, repl->size);
2121 2088
2122 ret = translate_table(net, newinfo, loc_cpu_entry, repl);2089 ret = translate_table(net, newinfo, loc_cpu_entry, repl);
@@ -2146,7 +2113,7 @@ void ip6t_unregister_table(struct net *net, struct xt_table *table) · 23 unmodified lines
2146 private = xt_unregister_table(table);2113 private = xt_unregister_table(table);
2147 2114
2148 /* Decrease module usage counts and free resources */2115 /* Decrease module usage counts and free resources */
2149 loc_cpu_entry = private->entries[raw_smp_processor_id()];2116 loc_cpu_entry = private->entries;
2150 xt_entry_foreach(iter, loc_cpu_entry, private->size)2117 xt_entry_foreach(iter, loc_cpu_entry, private->size)
2151 cleanup_entry(iter, net);2118 cleanup_entry(iter, net);
2152 if (private->number > private->initial_entries)2119 if (private->number > private->initial_entries)
net/netfilter/x_tables.c+8−15
@@ -659,7 +659,6 @@ EXPORT_SYMBOL_GPL(xt_compat_target_to_user); · 658 unmodified lines
659struct xt_table_info *xt_alloc_table_info(unsigned int size)659struct xt_table_info *xt_alloc_table_info(unsigned int size)
660{660{
661 struct xt_table_info *newinfo;661 struct xt_table_info *newinfo;
662 int cpu;
663 662
664 /* Pedantry: prevent them from hitting BUG() in vmalloc.c --RR */663 /* Pedantry: prevent them from hitting BUG() in vmalloc.c --RR */
665 if ((SMP_ALIGN(size) >> PAGE_SHIFT) + 2 > totalram_pages)664 if ((SMP_ALIGN(size) >> PAGE_SHIFT) + 2 > totalram_pages)
@@ -671,19 +670,14 @@ struct xt_table_info *xt_alloc_table_info(unsigned int size) · 5 unmodified lines
671 670
672 newinfo->size = size;671 newinfo->size = size;
673 672
674 for_each_possible_cpu(cpu) {673 if (size <= PAGE_SIZE)
675 if (size <= PAGE_SIZE)674 newinfo->entries = kmalloc(size, GFP_KERNEL);
676 newinfo->entries[cpu] = kmalloc_node(size,675 else
677 GFP_KERNEL,676 newinfo->entries = vmalloc(size);
678 cpu_to_node(cpu));
679 else
680 newinfo->entries[cpu] = vmalloc_node(size,
681 cpu_to_node(cpu));
682 677
683 if (newinfo->entries[cpu] == NULL) {678 if (newinfo->entries == NULL) {
684 xt_free_table_info(newinfo);679 xt_free_table_info(newinfo);
685 return NULL;680 return NULL;
686 }
687 }681 }
688 682
689 return newinfo;683 return newinfo;
@@ -694,8 +688,7 @@ void xt_free_table_info(struct xt_table_info *info) · 4 unmodified lines
694{688{
695 int cpu;689 int cpu;
696 690
697 for_each_possible_cpu(cpu)691 kvfree(info->entries);
698 kvfree(info->entries[cpu]);
699 692
700 if (info->jumpstack != NULL) {693 if (info->jumpstack != NULL) {
701 for_each_possible_cpu(cpu)694 for_each_possible_cpu(cpu)

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t