aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexey Dobriyan <adobriyan@gmail.com>2008-11-25 20:28:57 -0500
committerDavid S. Miller <davem@davemloft.net>2008-11-25 20:28:57 -0500
commit66caf628c3b634c57b14a1a104dcd57e4fab2e3b (patch)
treed5a967f7c22e55208bc536c540efb85f26b9b483
parentdc2caba7b321289e7d02e63d7216961ccecfa103 (diff)
netns xfrm: per-netns policy hash resizing work
Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/net/netns/xfrm.h1
-rw-r--r--net/xfrm/xfrm_policy.c52
2 files changed, 27 insertions, 26 deletions
diff --git a/include/net/netns/xfrm.h b/include/net/netns/xfrm.h
index d5aadf06be46..c53d17357a49 100644
--- a/include/net/netns/xfrm.h
+++ b/include/net/netns/xfrm.h
@@ -38,6 +38,7 @@ struct netns_xfrm {
38 struct hlist_head policy_inexact[XFRM_POLICY_MAX * 2]; 38 struct hlist_head policy_inexact[XFRM_POLICY_MAX * 2];
39 struct xfrm_policy_hash policy_bydst[XFRM_POLICY_MAX * 2]; 39 struct xfrm_policy_hash policy_bydst[XFRM_POLICY_MAX * 2];
40 unsigned int policy_count[XFRM_POLICY_MAX * 2]; 40 unsigned int policy_count[XFRM_POLICY_MAX * 2];
41 struct work_struct policy_hash_work;
41}; 42};
42 43
43#endif 44#endif
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index 630ec048a0d3..1d300862dc04 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -396,12 +396,12 @@ static unsigned long xfrm_new_hash_mask(unsigned int old_hmask)
396 return ((old_hmask + 1) << 1) - 1; 396 return ((old_hmask + 1) << 1) - 1;
397} 397}
398 398
399static void xfrm_bydst_resize(int dir) 399static void xfrm_bydst_resize(struct net *net, int dir)
400{ 400{
401 unsigned int hmask = init_net.xfrm.policy_bydst[dir].hmask; 401 unsigned int hmask = net->xfrm.policy_bydst[dir].hmask;
402 unsigned int nhashmask = xfrm_new_hash_mask(hmask); 402 unsigned int nhashmask = xfrm_new_hash_mask(hmask);
403 unsigned int nsize = (nhashmask + 1) * sizeof(struct hlist_head); 403 unsigned int nsize = (nhashmask + 1) * sizeof(struct hlist_head);
404 struct hlist_head *odst = init_net.xfrm.policy_bydst[dir].table; 404 struct hlist_head *odst = net->xfrm.policy_bydst[dir].table;
405 struct hlist_head *ndst = xfrm_hash_alloc(nsize); 405 struct hlist_head *ndst = xfrm_hash_alloc(nsize);
406 int i; 406 int i;
407 407
@@ -413,20 +413,20 @@ static void xfrm_bydst_resize(int dir)
413 for (i = hmask; i >= 0; i--) 413 for (i = hmask; i >= 0; i--)
414 xfrm_dst_hash_transfer(odst + i, ndst, nhashmask); 414 xfrm_dst_hash_transfer(odst + i, ndst, nhashmask);
415 415
416 init_net.xfrm.policy_bydst[dir].table = ndst; 416 net->xfrm.policy_bydst[dir].table = ndst;
417 init_net.xfrm.policy_bydst[dir].hmask = nhashmask; 417 net->xfrm.policy_bydst[dir].hmask = nhashmask;
418 418
419 write_unlock_bh(&xfrm_policy_lock); 419 write_unlock_bh(&xfrm_policy_lock);
420 420
421 xfrm_hash_free(odst, (hmask + 1) * sizeof(struct hlist_head)); 421 xfrm_hash_free(odst, (hmask + 1) * sizeof(struct hlist_head));
422} 422}
423 423
424static void xfrm_byidx_resize(int total) 424static void xfrm_byidx_resize(struct net *net, int total)
425{ 425{
426 unsigned int hmask = init_net.xfrm.policy_idx_hmask; 426 unsigned int hmask = net->xfrm.policy_idx_hmask;
427 unsigned int nhashmask = xfrm_new_hash_mask(hmask); 427 unsigned int nhashmask = xfrm_new_hash_mask(hmask);
428 unsigned int nsize = (nhashmask + 1) * sizeof(struct hlist_head); 428 unsigned int nsize = (nhashmask + 1) * sizeof(struct hlist_head);
429 struct hlist_head *oidx = init_net.xfrm.policy_byidx; 429 struct hlist_head *oidx = net->xfrm.policy_byidx;
430 struct hlist_head *nidx = xfrm_hash_alloc(nsize); 430 struct hlist_head *nidx = xfrm_hash_alloc(nsize);
431 int i; 431 int i;
432 432
@@ -438,18 +438,18 @@ static void xfrm_byidx_resize(int total)
438 for (i = hmask; i >= 0; i--) 438 for (i = hmask; i >= 0; i--)
439 xfrm_idx_hash_transfer(oidx + i, nidx, nhashmask); 439 xfrm_idx_hash_transfer(oidx + i, nidx, nhashmask);
440 440
441 init_net.xfrm.policy_byidx = nidx; 441 net->xfrm.policy_byidx = nidx;
442 init_net.xfrm.policy_idx_hmask = nhashmask; 442 net->xfrm.policy_idx_hmask = nhashmask;
443 443
444 write_unlock_bh(&xfrm_policy_lock); 444 write_unlock_bh(&xfrm_policy_lock);
445 445
446 xfrm_hash_free(oidx, (hmask + 1) * sizeof(struct hlist_head)); 446 xfrm_hash_free(oidx, (hmask + 1) * sizeof(struct hlist_head));
447} 447}
448 448
449static inline int xfrm_bydst_should_resize(int dir, int *total) 449static inline int xfrm_bydst_should_resize(struct net *net, int dir, int *total)
450{ 450{
451 unsigned int cnt = init_net.xfrm.policy_count[dir]; 451 unsigned int cnt = net->xfrm.policy_count[dir];
452 unsigned int hmask = init_net.xfrm.policy_bydst[dir].hmask; 452 unsigned int hmask = net->xfrm.policy_bydst[dir].hmask;
453 453
454 if (total) 454 if (total)
455 *total += cnt; 455 *total += cnt;
@@ -461,9 +461,9 @@ static inline int xfrm_bydst_should_resize(int dir, int *total)
461 return 0; 461 return 0;
462} 462}
463 463
464static inline int xfrm_byidx_should_resize(int total) 464static inline int xfrm_byidx_should_resize(struct net *net, int total)
465{ 465{
466 unsigned int hmask = init_net.xfrm.policy_idx_hmask; 466 unsigned int hmask = net->xfrm.policy_idx_hmask;
467 467
468 if ((hmask + 1) < xfrm_policy_hashmax && 468 if ((hmask + 1) < xfrm_policy_hashmax &&
469 total > hmask) 469 total > hmask)
@@ -488,25 +488,24 @@ void xfrm_spd_getinfo(struct xfrmk_spdinfo *si)
488EXPORT_SYMBOL(xfrm_spd_getinfo); 488EXPORT_SYMBOL(xfrm_spd_getinfo);
489 489
490static DEFINE_MUTEX(hash_resize_mutex); 490static DEFINE_MUTEX(hash_resize_mutex);
491static void xfrm_hash_resize(struct work_struct *__unused) 491static void xfrm_hash_resize(struct work_struct *work)
492{ 492{
493 struct net *net = container_of(work, struct net, xfrm.policy_hash_work);
493 int dir, total; 494 int dir, total;
494 495
495 mutex_lock(&hash_resize_mutex); 496 mutex_lock(&hash_resize_mutex);
496 497
497 total = 0; 498 total = 0;
498 for (dir = 0; dir < XFRM_POLICY_MAX * 2; dir++) { 499 for (dir = 0; dir < XFRM_POLICY_MAX * 2; dir++) {
499 if (xfrm_bydst_should_resize(dir, &total)) 500 if (xfrm_bydst_should_resize(net, dir, &total))
500 xfrm_bydst_resize(dir); 501 xfrm_bydst_resize(net, dir);
501 } 502 }
502 if (xfrm_byidx_should_resize(total)) 503 if (xfrm_byidx_should_resize(net, total))
503 xfrm_byidx_resize(total); 504 xfrm_byidx_resize(net, total);
504 505
505 mutex_unlock(&hash_resize_mutex); 506 mutex_unlock(&hash_resize_mutex);
506} 507}
507 508
508static DECLARE_WORK(xfrm_hash_work, xfrm_hash_resize);
509
510/* Generate new index... KAME seems to generate them ordered by cost 509/* Generate new index... KAME seems to generate them ordered by cost
511 * of an absolute inpredictability of ordering of rules. This will not pass. */ 510 * of an absolute inpredictability of ordering of rules. This will not pass. */
512static u32 xfrm_gen_index(int dir) 511static u32 xfrm_gen_index(int dir)
@@ -607,8 +606,8 @@ int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl)
607 606
608 if (delpol) 607 if (delpol)
609 xfrm_policy_kill(delpol); 608 xfrm_policy_kill(delpol);
610 else if (xfrm_bydst_should_resize(dir, NULL)) 609 else if (xfrm_bydst_should_resize(&init_net, dir, NULL))
611 schedule_work(&xfrm_hash_work); 610 schedule_work(&init_net.xfrm.policy_hash_work);
612 611
613 read_lock_bh(&xfrm_policy_lock); 612 read_lock_bh(&xfrm_policy_lock);
614 gc_list = NULL; 613 gc_list = NULL;
@@ -1079,8 +1078,8 @@ static void __xfrm_policy_link(struct xfrm_policy *pol, int dir)
1079 init_net.xfrm.policy_count[dir]++; 1078 init_net.xfrm.policy_count[dir]++;
1080 xfrm_pol_hold(pol); 1079 xfrm_pol_hold(pol);
1081 1080
1082 if (xfrm_bydst_should_resize(dir, NULL)) 1081 if (xfrm_bydst_should_resize(&init_net, dir, NULL))
1083 schedule_work(&xfrm_hash_work); 1082 schedule_work(&init_net.xfrm.policy_hash_work);
1084} 1083}
1085 1084
1086static struct xfrm_policy *__xfrm_policy_unlink(struct xfrm_policy *pol, 1085static struct xfrm_policy *__xfrm_policy_unlink(struct xfrm_policy *pol,
@@ -2415,6 +2414,7 @@ static int __net_init xfrm_policy_init(struct net *net)
2415 } 2414 }
2416 2415
2417 INIT_LIST_HEAD(&net->xfrm.policy_all); 2416 INIT_LIST_HEAD(&net->xfrm.policy_all);
2417 INIT_WORK(&net->xfrm.policy_hash_work, xfrm_hash_resize);
2418 if (net_eq(net, &init_net)) 2418 if (net_eq(net, &init_net))
2419 register_netdevice_notifier(&xfrm_dev_notifier); 2419 register_netdevice_notifier(&xfrm_dev_notifier);
2420 return 0; 2420 return 0;