diff options
Diffstat (limited to 'net/netfilter')
-rw-r--r-- | net/netfilter/nf_conntrack_core.c | 36 |
1 files changed, 26 insertions, 10 deletions
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index 6c1da212380d..9c661413b826 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c | |||
@@ -62,8 +62,8 @@ EXPORT_SYMBOL_GPL(nf_conntrack_htable_size); | |||
62 | unsigned int nf_conntrack_max __read_mostly; | 62 | unsigned int nf_conntrack_max __read_mostly; |
63 | EXPORT_SYMBOL_GPL(nf_conntrack_max); | 63 | EXPORT_SYMBOL_GPL(nf_conntrack_max); |
64 | 64 | ||
65 | struct nf_conn nf_conntrack_untracked; | 65 | DEFINE_PER_CPU(struct nf_conn, nf_conntrack_untracked); |
66 | EXPORT_SYMBOL_GPL(nf_conntrack_untracked); | 66 | EXPORT_PER_CPU_SYMBOL(nf_conntrack_untracked); |
67 | 67 | ||
68 | static int nf_conntrack_hash_rnd_initted; | 68 | static int nf_conntrack_hash_rnd_initted; |
69 | static unsigned int nf_conntrack_hash_rnd; | 69 | static unsigned int nf_conntrack_hash_rnd; |
@@ -1183,10 +1183,21 @@ static void nf_ct_release_dying_list(struct net *net) | |||
1183 | spin_unlock_bh(&nf_conntrack_lock); | 1183 | spin_unlock_bh(&nf_conntrack_lock); |
1184 | } | 1184 | } |
1185 | 1185 | ||
1186 | static int untrack_refs(void) | ||
1187 | { | ||
1188 | int cnt = 0, cpu; | ||
1189 | |||
1190 | for_each_possible_cpu(cpu) { | ||
1191 | struct nf_conn *ct = &per_cpu(nf_conntrack_untracked, cpu); | ||
1192 | |||
1193 | cnt += atomic_read(&ct->ct_general.use) - 1; | ||
1194 | } | ||
1195 | return cnt; | ||
1196 | } | ||
1197 | |||
1186 | static void nf_conntrack_cleanup_init_net(void) | 1198 | static void nf_conntrack_cleanup_init_net(void) |
1187 | { | 1199 | { |
1188 | /* wait until all references to nf_conntrack_untracked are dropped */ | 1200 | while (untrack_refs() > 0) |
1189 | while (atomic_read(&nf_conntrack_untracked.ct_general.use) > 1) | ||
1190 | schedule(); | 1201 | schedule(); |
1191 | 1202 | ||
1192 | nf_conntrack_helper_fini(); | 1203 | nf_conntrack_helper_fini(); |
@@ -1323,14 +1334,17 @@ module_param_call(hashsize, nf_conntrack_set_hashsize, param_get_uint, | |||
1323 | 1334 | ||
1324 | void nf_ct_untracked_status_or(unsigned long bits) | 1335 | void nf_ct_untracked_status_or(unsigned long bits) |
1325 | { | 1336 | { |
1326 | nf_conntrack_untracked.status |= bits; | 1337 | int cpu; |
1338 | |||
1339 | for_each_possible_cpu(cpu) | ||
1340 | per_cpu(nf_conntrack_untracked, cpu).status |= bits; | ||
1327 | } | 1341 | } |
1328 | EXPORT_SYMBOL_GPL(nf_ct_untracked_status_or); | 1342 | EXPORT_SYMBOL_GPL(nf_ct_untracked_status_or); |
1329 | 1343 | ||
1330 | static int nf_conntrack_init_init_net(void) | 1344 | static int nf_conntrack_init_init_net(void) |
1331 | { | 1345 | { |
1332 | int max_factor = 8; | 1346 | int max_factor = 8; |
1333 | int ret; | 1347 | int ret, cpu; |
1334 | 1348 | ||
1335 | /* Idea from tcp.c: use 1/16384 of memory. On i386: 32MB | 1349 | /* Idea from tcp.c: use 1/16384 of memory. On i386: 32MB |
1336 | * machine has 512 buckets. >= 1GB machines have 16384 buckets. */ | 1350 | * machine has 512 buckets. >= 1GB machines have 16384 buckets. */ |
@@ -1369,10 +1383,12 @@ static int nf_conntrack_init_init_net(void) | |||
1369 | goto err_extend; | 1383 | goto err_extend; |
1370 | #endif | 1384 | #endif |
1371 | /* Set up fake conntrack: to never be deleted, not in any hashes */ | 1385 | /* Set up fake conntrack: to never be deleted, not in any hashes */ |
1372 | #ifdef CONFIG_NET_NS | 1386 | for_each_possible_cpu(cpu) { |
1373 | nf_conntrack_untracked.ct_net = &init_net; | 1387 | struct nf_conn *ct = &per_cpu(nf_conntrack_untracked, cpu); |
1374 | #endif | 1388 | |
1375 | atomic_set(&nf_conntrack_untracked.ct_general.use, 1); | 1389 | write_pnet(&ct->ct_net, &init_net); |
1390 | atomic_set(&ct->ct_general.use, 1); | ||
1391 | } | ||
1376 | /* - and look it like as a confirmed connection */ | 1392 | /* - and look it like as a confirmed connection */ |
1377 | nf_ct_untracked_status_or(IPS_CONFIRMED | IPS_UNTRACKED); | 1393 | nf_ct_untracked_status_or(IPS_CONFIRMED | IPS_UNTRACKED); |
1378 | return 0; | 1394 | return 0; |