mirror of
https://github.com/torvalds/linux.git
synced 2025-08-16 06:31:34 +02:00
Revert "xfrm: destroy xfrm_state synchronously on net exit path"
This reverts commit f75a2804da
.
With all states (whether user or kern) removed from the hashtables
during deletion, there's no need for synchronous destruction of
states. xfrm6_tunnel states still need to have been destroyed (which
will be the case when its last user is deleted (not destroyed)) so
that xfrm6_tunnel_free_spi removes it from the per-netns hashtable
before the netns is destroyed.
This has the benefit of skipping one synchronize_rcu per state (in
__xfrm_state_destroy(sync=true)) when we exit a netns.
Signed-off-by: Sabrina Dubroca <sd@queasysnail.net>
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
This commit is contained in:
parent
b441cf3f8c
commit
2a198bbec6
5 changed files with 15 additions and 26 deletions
|
@ -915,7 +915,7 @@ static inline void xfrm_pols_put(struct xfrm_policy **pols, int npols)
|
||||||
xfrm_pol_put(pols[i]);
|
xfrm_pol_put(pols[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void __xfrm_state_destroy(struct xfrm_state *, bool);
|
void __xfrm_state_destroy(struct xfrm_state *);
|
||||||
|
|
||||||
static inline void __xfrm_state_put(struct xfrm_state *x)
|
static inline void __xfrm_state_put(struct xfrm_state *x)
|
||||||
{
|
{
|
||||||
|
@ -925,13 +925,7 @@ static inline void __xfrm_state_put(struct xfrm_state *x)
|
||||||
static inline void xfrm_state_put(struct xfrm_state *x)
|
static inline void xfrm_state_put(struct xfrm_state *x)
|
||||||
{
|
{
|
||||||
if (refcount_dec_and_test(&x->refcnt))
|
if (refcount_dec_and_test(&x->refcnt))
|
||||||
__xfrm_state_destroy(x, false);
|
__xfrm_state_destroy(x);
|
||||||
}
|
|
||||||
|
|
||||||
static inline void xfrm_state_put_sync(struct xfrm_state *x)
|
|
||||||
{
|
|
||||||
if (refcount_dec_and_test(&x->refcnt))
|
|
||||||
__xfrm_state_destroy(x, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void xfrm_state_hold(struct xfrm_state *x)
|
static inline void xfrm_state_hold(struct xfrm_state *x)
|
||||||
|
@ -1769,7 +1763,7 @@ struct xfrmk_spdinfo {
|
||||||
|
|
||||||
struct xfrm_state *xfrm_find_acq_byseq(struct net *net, u32 mark, u32 seq, u32 pcpu_num);
|
struct xfrm_state *xfrm_find_acq_byseq(struct net *net, u32 mark, u32 seq, u32 pcpu_num);
|
||||||
int xfrm_state_delete(struct xfrm_state *x);
|
int xfrm_state_delete(struct xfrm_state *x);
|
||||||
int xfrm_state_flush(struct net *net, u8 proto, bool task_valid, bool sync);
|
int xfrm_state_flush(struct net *net, u8 proto, bool task_valid);
|
||||||
int xfrm_dev_state_flush(struct net *net, struct net_device *dev, bool task_valid);
|
int xfrm_dev_state_flush(struct net *net, struct net_device *dev, bool task_valid);
|
||||||
int xfrm_dev_policy_flush(struct net *net, struct net_device *dev,
|
int xfrm_dev_policy_flush(struct net *net, struct net_device *dev,
|
||||||
bool task_valid);
|
bool task_valid);
|
||||||
|
|
|
@ -334,7 +334,7 @@ static void __net_exit xfrm6_tunnel_net_exit(struct net *net)
|
||||||
struct xfrm6_tunnel_net *xfrm6_tn = xfrm6_tunnel_pernet(net);
|
struct xfrm6_tunnel_net *xfrm6_tn = xfrm6_tunnel_pernet(net);
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
xfrm_state_flush(net, 0, false, true);
|
xfrm_state_flush(net, IPSEC_PROTO_ANY, false);
|
||||||
xfrm_flush_gc();
|
xfrm_flush_gc();
|
||||||
|
|
||||||
for (i = 0; i < XFRM6_TUNNEL_SPI_BYADDR_HSIZE; i++)
|
for (i = 0; i < XFRM6_TUNNEL_SPI_BYADDR_HSIZE; i++)
|
||||||
|
|
|
@ -1766,7 +1766,7 @@ static int pfkey_flush(struct sock *sk, struct sk_buff *skb, const struct sadb_m
|
||||||
if (proto == 0)
|
if (proto == 0)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
err = xfrm_state_flush(net, proto, true, false);
|
err = xfrm_state_flush(net, proto, true);
|
||||||
err2 = unicast_flush_resp(sk, hdr);
|
err2 = unicast_flush_resp(sk, hdr);
|
||||||
if (err || err2) {
|
if (err || err2) {
|
||||||
if (err == -ESRCH) /* empty table - go quietly */
|
if (err == -ESRCH) /* empty table - go quietly */
|
||||||
|
|
|
@ -592,7 +592,7 @@ void xfrm_state_free(struct xfrm_state *x)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(xfrm_state_free);
|
EXPORT_SYMBOL(xfrm_state_free);
|
||||||
|
|
||||||
static void ___xfrm_state_destroy(struct xfrm_state *x)
|
static void xfrm_state_gc_destroy(struct xfrm_state *x)
|
||||||
{
|
{
|
||||||
if (x->mode_cbs && x->mode_cbs->destroy_state)
|
if (x->mode_cbs && x->mode_cbs->destroy_state)
|
||||||
x->mode_cbs->destroy_state(x);
|
x->mode_cbs->destroy_state(x);
|
||||||
|
@ -631,7 +631,7 @@ static void xfrm_state_gc_task(struct work_struct *work)
|
||||||
synchronize_rcu();
|
synchronize_rcu();
|
||||||
|
|
||||||
hlist_for_each_entry_safe(x, tmp, &gc_list, gclist)
|
hlist_for_each_entry_safe(x, tmp, &gc_list, gclist)
|
||||||
___xfrm_state_destroy(x);
|
xfrm_state_gc_destroy(x);
|
||||||
}
|
}
|
||||||
|
|
||||||
static enum hrtimer_restart xfrm_timer_handler(struct hrtimer *me)
|
static enum hrtimer_restart xfrm_timer_handler(struct hrtimer *me)
|
||||||
|
@ -795,19 +795,14 @@ void xfrm_dev_state_free(struct xfrm_state *x)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void __xfrm_state_destroy(struct xfrm_state *x, bool sync)
|
void __xfrm_state_destroy(struct xfrm_state *x)
|
||||||
{
|
{
|
||||||
WARN_ON(x->km.state != XFRM_STATE_DEAD);
|
WARN_ON(x->km.state != XFRM_STATE_DEAD);
|
||||||
|
|
||||||
if (sync) {
|
|
||||||
synchronize_rcu();
|
|
||||||
___xfrm_state_destroy(x);
|
|
||||||
} else {
|
|
||||||
spin_lock_bh(&xfrm_state_gc_lock);
|
spin_lock_bh(&xfrm_state_gc_lock);
|
||||||
hlist_add_head(&x->gclist, &xfrm_state_gc_list);
|
hlist_add_head(&x->gclist, &xfrm_state_gc_list);
|
||||||
spin_unlock_bh(&xfrm_state_gc_lock);
|
spin_unlock_bh(&xfrm_state_gc_lock);
|
||||||
schedule_work(&xfrm_state_gc_work);
|
schedule_work(&xfrm_state_gc_work);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(__xfrm_state_destroy);
|
EXPORT_SYMBOL(__xfrm_state_destroy);
|
||||||
|
|
||||||
|
@ -922,7 +917,7 @@ xfrm_dev_state_flush_secctx_check(struct net *net, struct net_device *dev, bool
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int xfrm_state_flush(struct net *net, u8 proto, bool task_valid, bool sync)
|
int xfrm_state_flush(struct net *net, u8 proto, bool task_valid)
|
||||||
{
|
{
|
||||||
int i, err = 0, cnt = 0;
|
int i, err = 0, cnt = 0;
|
||||||
|
|
||||||
|
@ -3283,7 +3278,7 @@ void xfrm_state_fini(struct net *net)
|
||||||
unsigned int sz;
|
unsigned int sz;
|
||||||
|
|
||||||
flush_work(&net->xfrm.state_hash_work);
|
flush_work(&net->xfrm.state_hash_work);
|
||||||
xfrm_state_flush(net, 0, false, true);
|
xfrm_state_flush(net, IPSEC_PROTO_ANY, false);
|
||||||
flush_work(&xfrm_state_gc_work);
|
flush_work(&xfrm_state_gc_work);
|
||||||
|
|
||||||
WARN_ON(!list_empty(&net->xfrm.state_all));
|
WARN_ON(!list_empty(&net->xfrm.state_all));
|
||||||
|
|
|
@ -2635,7 +2635,7 @@ static int xfrm_flush_sa(struct sk_buff *skb, struct nlmsghdr *nlh,
|
||||||
struct xfrm_usersa_flush *p = nlmsg_data(nlh);
|
struct xfrm_usersa_flush *p = nlmsg_data(nlh);
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
err = xfrm_state_flush(net, p->proto, true, false);
|
err = xfrm_state_flush(net, p->proto, true);
|
||||||
if (err) {
|
if (err) {
|
||||||
if (err == -ESRCH) /* empty table */
|
if (err == -ESRCH) /* empty table */
|
||||||
return 0;
|
return 0;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue