diff options
Diffstat (limited to 'net/xfrm')
-rw-r--r-- | net/xfrm/xfrm_policy.c | 28 |
1 files changed, 18 insertions, 10 deletions
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index aabc7f28e9c0..700cdd7564e4 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c | |||
@@ -329,7 +329,6 @@ struct xfrm_policy_hash { | |||
329 | 329 | ||
330 | static struct hlist_head xfrm_policy_inexact[XFRM_POLICY_MAX*2]; | 330 | static struct hlist_head xfrm_policy_inexact[XFRM_POLICY_MAX*2]; |
331 | static struct xfrm_policy_hash xfrm_policy_bydst[XFRM_POLICY_MAX*2] __read_mostly; | 331 | static struct xfrm_policy_hash xfrm_policy_bydst[XFRM_POLICY_MAX*2] __read_mostly; |
332 | static struct hlist_head *xfrm_policy_byidx __read_mostly; | ||
333 | static unsigned int xfrm_idx_hmask __read_mostly; | 332 | static unsigned int xfrm_idx_hmask __read_mostly; |
334 | static unsigned int xfrm_policy_hashmax __read_mostly = 1 * 1024 * 1024; | 333 | static unsigned int xfrm_policy_hashmax __read_mostly = 1 * 1024 * 1024; |
335 | 334 | ||
@@ -438,7 +437,7 @@ static void xfrm_byidx_resize(int total) | |||
438 | unsigned int hmask = xfrm_idx_hmask; | 437 | unsigned int hmask = xfrm_idx_hmask; |
439 | unsigned int nhashmask = xfrm_new_hash_mask(hmask); | 438 | unsigned int nhashmask = xfrm_new_hash_mask(hmask); |
440 | unsigned int nsize = (nhashmask + 1) * sizeof(struct hlist_head); | 439 | unsigned int nsize = (nhashmask + 1) * sizeof(struct hlist_head); |
441 | struct hlist_head *oidx = xfrm_policy_byidx; | 440 | struct hlist_head *oidx = init_net.xfrm.policy_byidx; |
442 | struct hlist_head *nidx = xfrm_hash_alloc(nsize); | 441 | struct hlist_head *nidx = xfrm_hash_alloc(nsize); |
443 | int i; | 442 | int i; |
444 | 443 | ||
@@ -450,7 +449,7 @@ static void xfrm_byidx_resize(int total) | |||
450 | for (i = hmask; i >= 0; i--) | 449 | for (i = hmask; i >= 0; i--) |
451 | xfrm_idx_hash_transfer(oidx + i, nidx, nhashmask); | 450 | xfrm_idx_hash_transfer(oidx + i, nidx, nhashmask); |
452 | 451 | ||
453 | xfrm_policy_byidx = nidx; | 452 | init_net.xfrm.policy_byidx = nidx; |
454 | xfrm_idx_hmask = nhashmask; | 453 | xfrm_idx_hmask = nhashmask; |
455 | 454 | ||
456 | write_unlock_bh(&xfrm_policy_lock); | 455 | write_unlock_bh(&xfrm_policy_lock); |
@@ -536,7 +535,7 @@ static u32 xfrm_gen_index(int dir) | |||
536 | idx_generator += 8; | 535 | idx_generator += 8; |
537 | if (idx == 0) | 536 | if (idx == 0) |
538 | idx = 8; | 537 | idx = 8; |
539 | list = xfrm_policy_byidx + idx_hash(idx); | 538 | list = init_net.xfrm.policy_byidx + idx_hash(idx); |
540 | found = 0; | 539 | found = 0; |
541 | hlist_for_each_entry(p, entry, list, byidx) { | 540 | hlist_for_each_entry(p, entry, list, byidx) { |
542 | if (p->index == idx) { | 541 | if (p->index == idx) { |
@@ -609,7 +608,7 @@ int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl) | |||
609 | xfrm_policy_count[dir]--; | 608 | xfrm_policy_count[dir]--; |
610 | } | 609 | } |
611 | policy->index = delpol ? delpol->index : xfrm_gen_index(dir); | 610 | policy->index = delpol ? delpol->index : xfrm_gen_index(dir); |
612 | hlist_add_head(&policy->byidx, xfrm_policy_byidx+idx_hash(policy->index)); | 611 | hlist_add_head(&policy->byidx, init_net.xfrm.policy_byidx+idx_hash(policy->index)); |
613 | policy->curlft.add_time = get_seconds(); | 612 | policy->curlft.add_time = get_seconds(); |
614 | policy->curlft.use_time = 0; | 613 | policy->curlft.use_time = 0; |
615 | if (!mod_timer(&policy->timer, jiffies + HZ)) | 614 | if (!mod_timer(&policy->timer, jiffies + HZ)) |
@@ -711,7 +710,7 @@ struct xfrm_policy *xfrm_policy_byid(u8 type, int dir, u32 id, int delete, | |||
711 | 710 | ||
712 | *err = 0; | 711 | *err = 0; |
713 | write_lock_bh(&xfrm_policy_lock); | 712 | write_lock_bh(&xfrm_policy_lock); |
714 | chain = xfrm_policy_byidx + idx_hash(id); | 713 | chain = init_net.xfrm.policy_byidx + idx_hash(id); |
715 | ret = NULL; | 714 | ret = NULL; |
716 | hlist_for_each_entry(pol, entry, chain, byidx) { | 715 | hlist_for_each_entry(pol, entry, chain, byidx) { |
717 | if (pol->type == type && pol->index == id) { | 716 | if (pol->type == type && pol->index == id) { |
@@ -1087,7 +1086,7 @@ static void __xfrm_policy_link(struct xfrm_policy *pol, int dir) | |||
1087 | 1086 | ||
1088 | list_add(&pol->walk.all, &init_net.xfrm.policy_all); | 1087 | list_add(&pol->walk.all, &init_net.xfrm.policy_all); |
1089 | hlist_add_head(&pol->bydst, chain); | 1088 | hlist_add_head(&pol->bydst, chain); |
1090 | hlist_add_head(&pol->byidx, xfrm_policy_byidx+idx_hash(pol->index)); | 1089 | hlist_add_head(&pol->byidx, init_net.xfrm.policy_byidx+idx_hash(pol->index)); |
1091 | xfrm_policy_count[dir]++; | 1090 | xfrm_policy_count[dir]++; |
1092 | xfrm_pol_hold(pol); | 1091 | xfrm_pol_hold(pol); |
1093 | 1092 | ||
@@ -2408,10 +2407,10 @@ static int __net_init xfrm_policy_init(struct net *net) | |||
2408 | hmask = 8 - 1; | 2407 | hmask = 8 - 1; |
2409 | sz = (hmask+1) * sizeof(struct hlist_head); | 2408 | sz = (hmask+1) * sizeof(struct hlist_head); |
2410 | 2409 | ||
2411 | xfrm_policy_byidx = xfrm_hash_alloc(sz); | 2410 | net->xfrm.policy_byidx = xfrm_hash_alloc(sz); |
2411 | if (!net->xfrm.policy_byidx) | ||
2412 | goto out_byidx; | ||
2412 | xfrm_idx_hmask = hmask; | 2413 | xfrm_idx_hmask = hmask; |
2413 | if (!xfrm_policy_byidx) | ||
2414 | panic("XFRM: failed to allocate byidx hash\n"); | ||
2415 | 2414 | ||
2416 | for (dir = 0; dir < XFRM_POLICY_MAX * 2; dir++) { | 2415 | for (dir = 0; dir < XFRM_POLICY_MAX * 2; dir++) { |
2417 | struct xfrm_policy_hash *htab; | 2416 | struct xfrm_policy_hash *htab; |
@@ -2429,11 +2428,20 @@ static int __net_init xfrm_policy_init(struct net *net) | |||
2429 | if (net_eq(net, &init_net)) | 2428 | if (net_eq(net, &init_net)) |
2430 | register_netdevice_notifier(&xfrm_dev_notifier); | 2429 | register_netdevice_notifier(&xfrm_dev_notifier); |
2431 | return 0; | 2430 | return 0; |
2431 | |||
2432 | out_byidx: | ||
2433 | return -ENOMEM; | ||
2432 | } | 2434 | } |
2433 | 2435 | ||
2434 | static void xfrm_policy_fini(struct net *net) | 2436 | static void xfrm_policy_fini(struct net *net) |
2435 | { | 2437 | { |
2438 | unsigned int sz; | ||
2439 | |||
2436 | WARN_ON(!list_empty(&net->xfrm.policy_all)); | 2440 | WARN_ON(!list_empty(&net->xfrm.policy_all)); |
2441 | |||
2442 | sz = (xfrm_idx_hmask + 1) * sizeof(struct hlist_head); | ||
2443 | WARN_ON(!hlist_empty(net->xfrm.policy_byidx)); | ||
2444 | xfrm_hash_free(net->xfrm.policy_byidx, sz); | ||
2437 | } | 2445 | } |
2438 | 2446 | ||
2439 | static int __net_init xfrm_net_init(struct net *net) | 2447 | static int __net_init xfrm_net_init(struct net *net) |