xfrm: policy: split list insertion into a helper

... so we can reuse this later without code duplication when we add
policy to a second inexact list.

Signed-off-by: Florian Westphal <fw@strlen.de>
Acked-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
This commit is contained in:
Florian Westphal 2018-11-07 23:00:33 +01:00 committed by Steffen Klassert
parent ceb159e30a
commit a927d6af53

View File

@ -740,18 +740,12 @@ static bool xfrm_policy_mark_match(struct xfrm_policy *policy,
return false; return false;
} }
int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl) static struct xfrm_policy *xfrm_policy_insert_list(struct hlist_head *chain,
struct xfrm_policy *policy,
bool excl)
{ {
struct net *net = xp_net(policy); struct xfrm_policy *pol, *newpos = NULL, *delpol = NULL;
struct xfrm_policy *pol;
struct xfrm_policy *delpol;
struct hlist_head *chain;
struct hlist_node *newpos;
spin_lock_bh(&net->xfrm.xfrm_policy_lock);
chain = policy_hash_bysel(net, &policy->selector, policy->family, dir);
delpol = NULL;
newpos = NULL;
hlist_for_each_entry(pol, chain, bydst) { hlist_for_each_entry(pol, chain, bydst) {
if (pol->type == policy->type && if (pol->type == policy->type &&
pol->if_id == policy->if_id && pol->if_id == policy->if_id &&
@ -759,24 +753,41 @@ int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl)
xfrm_policy_mark_match(policy, pol) && xfrm_policy_mark_match(policy, pol) &&
xfrm_sec_ctx_match(pol->security, policy->security) && xfrm_sec_ctx_match(pol->security, policy->security) &&
!WARN_ON(delpol)) { !WARN_ON(delpol)) {
if (excl) { if (excl)
spin_unlock_bh(&net->xfrm.xfrm_policy_lock); return ERR_PTR(-EEXIST);
return -EEXIST;
}
delpol = pol; delpol = pol;
if (policy->priority > pol->priority) if (policy->priority > pol->priority)
continue; continue;
} else if (policy->priority >= pol->priority) { } else if (policy->priority >= pol->priority) {
newpos = &pol->bydst; newpos = pol;
continue; continue;
} }
if (delpol) if (delpol)
break; break;
} }
if (newpos) if (newpos)
hlist_add_behind_rcu(&policy->bydst, newpos); hlist_add_behind_rcu(&policy->bydst, &newpos->bydst);
else else
hlist_add_head_rcu(&policy->bydst, chain); hlist_add_head_rcu(&policy->bydst, chain);
return delpol;
}
int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl)
{
struct net *net = xp_net(policy);
struct xfrm_policy *delpol;
struct hlist_head *chain;
spin_lock_bh(&net->xfrm.xfrm_policy_lock);
chain = policy_hash_bysel(net, &policy->selector, policy->family, dir);
delpol = xfrm_policy_insert_list(chain, policy, excl);
if (IS_ERR(delpol)) {
spin_unlock_bh(&net->xfrm.xfrm_policy_lock);
return PTR_ERR(delpol);
}
__xfrm_policy_link(policy, dir); __xfrm_policy_link(policy, dir);
/* After previous checking, family can either be AF_INET or AF_INET6 */ /* After previous checking, family can either be AF_INET or AF_INET6 */