diff options
| author | Steffen Klassert <steffen.klassert@secunet.com> | 2011-12-21 16:48:08 -0500 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2011-12-21 16:48:08 -0500 |
| commit | c0ed1c14a72ca9ebacd51fb94a8aca488b0d361e (patch) | |
| tree | e689f7fd62e7633b9b254f9a456b65a1150c6e23 /net/xfrm | |
| parent | 9f28a2fc0bd77511f649c0a788c7bf9a5fd04edb (diff) | |
net: Add a flow_cache_flush_deferred function
flow_cach_flush() might sleep but can be called from
atomic context via the xfrm garbage collector. So add
a flow_cache_flush_deferred() function and use this if
the xfrm garbage colector is invoked from within the
packet path.
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
Acked-by: Timo Teräs <timo.teras@iki.fi>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/xfrm')
| -rw-r--r-- | net/xfrm/xfrm_policy.c | 18 |
1 files changed, 14 insertions, 4 deletions
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index 2118d6446630..9049a5caeb25 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c | |||
| @@ -2276,8 +2276,6 @@ static void __xfrm_garbage_collect(struct net *net) | |||
| 2276 | { | 2276 | { |
| 2277 | struct dst_entry *head, *next; | 2277 | struct dst_entry *head, *next; |
| 2278 | 2278 | ||
| 2279 | flow_cache_flush(); | ||
| 2280 | |||
| 2281 | spin_lock_bh(&xfrm_policy_sk_bundle_lock); | 2279 | spin_lock_bh(&xfrm_policy_sk_bundle_lock); |
| 2282 | head = xfrm_policy_sk_bundles; | 2280 | head = xfrm_policy_sk_bundles; |
| 2283 | xfrm_policy_sk_bundles = NULL; | 2281 | xfrm_policy_sk_bundles = NULL; |
| @@ -2290,6 +2288,18 @@ static void __xfrm_garbage_collect(struct net *net) | |||
| 2290 | } | 2288 | } |
| 2291 | } | 2289 | } |
| 2292 | 2290 | ||
| 2291 | static void xfrm_garbage_collect(struct net *net) | ||
| 2292 | { | ||
| 2293 | flow_cache_flush(); | ||
| 2294 | __xfrm_garbage_collect(net); | ||
| 2295 | } | ||
| 2296 | |||
| 2297 | static void xfrm_garbage_collect_deferred(struct net *net) | ||
| 2298 | { | ||
| 2299 | flow_cache_flush_deferred(); | ||
| 2300 | __xfrm_garbage_collect(net); | ||
| 2301 | } | ||
| 2302 | |||
| 2293 | static void xfrm_init_pmtu(struct dst_entry *dst) | 2303 | static void xfrm_init_pmtu(struct dst_entry *dst) |
| 2294 | { | 2304 | { |
| 2295 | do { | 2305 | do { |
| @@ -2422,7 +2432,7 @@ int xfrm_policy_register_afinfo(struct xfrm_policy_afinfo *afinfo) | |||
| 2422 | if (likely(dst_ops->neigh_lookup == NULL)) | 2432 | if (likely(dst_ops->neigh_lookup == NULL)) |
| 2423 | dst_ops->neigh_lookup = xfrm_neigh_lookup; | 2433 | dst_ops->neigh_lookup = xfrm_neigh_lookup; |
| 2424 | if (likely(afinfo->garbage_collect == NULL)) | 2434 | if (likely(afinfo->garbage_collect == NULL)) |
| 2425 | afinfo->garbage_collect = __xfrm_garbage_collect; | 2435 | afinfo->garbage_collect = xfrm_garbage_collect_deferred; |
| 2426 | xfrm_policy_afinfo[afinfo->family] = afinfo; | 2436 | xfrm_policy_afinfo[afinfo->family] = afinfo; |
| 2427 | } | 2437 | } |
| 2428 | write_unlock_bh(&xfrm_policy_afinfo_lock); | 2438 | write_unlock_bh(&xfrm_policy_afinfo_lock); |
| @@ -2516,7 +2526,7 @@ static int xfrm_dev_event(struct notifier_block *this, unsigned long event, void | |||
| 2516 | 2526 | ||
| 2517 | switch (event) { | 2527 | switch (event) { |
| 2518 | case NETDEV_DOWN: | 2528 | case NETDEV_DOWN: |
| 2519 | __xfrm_garbage_collect(dev_net(dev)); | 2529 | xfrm_garbage_collect(dev_net(dev)); |
| 2520 | } | 2530 | } |
| 2521 | return NOTIFY_DONE; | 2531 | return NOTIFY_DONE; |
| 2522 | } | 2532 | } |
