mirror of
https://github.com/torvalds/linux.git
synced 2025-11-03 01:59:51 +02:00
net_sched: act_connmark: use RCU in tcf_connmark_dump()
Also storing tcf_action into struct tcf_connmark_parms makes sure there is no discrepancy in tcf_connmark_act(). Signed-off-by: Eric Dumazet <edumazet@google.com> Link: https://patch.msgid.link/20250709090204.797558-3-edumazet@google.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
parent
30dbb2d0e1
commit
0d75287770
2 changed files with 11 additions and 8 deletions
|
|
@ -7,6 +7,7 @@
|
||||||
struct tcf_connmark_parms {
|
struct tcf_connmark_parms {
|
||||||
struct net *net;
|
struct net *net;
|
||||||
u16 zone;
|
u16 zone;
|
||||||
|
int action;
|
||||||
struct rcu_head rcu;
|
struct rcu_head rcu;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -88,7 +88,7 @@ TC_INDIRECT_SCOPE int tcf_connmark_act(struct sk_buff *skb,
|
||||||
/* using overlimits stats to count how many packets marked */
|
/* using overlimits stats to count how many packets marked */
|
||||||
tcf_action_inc_overlimit_qstats(&ca->common);
|
tcf_action_inc_overlimit_qstats(&ca->common);
|
||||||
out:
|
out:
|
||||||
return READ_ONCE(ca->tcf_action);
|
return parms->action;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct nla_policy connmark_policy[TCA_CONNMARK_MAX + 1] = {
|
static const struct nla_policy connmark_policy[TCA_CONNMARK_MAX + 1] = {
|
||||||
|
|
@ -167,6 +167,8 @@ static int tcf_connmark_init(struct net *net, struct nlattr *nla,
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
goto release_idr;
|
goto release_idr;
|
||||||
|
|
||||||
|
nparms->action = parm->action;
|
||||||
|
|
||||||
spin_lock_bh(&ci->tcf_lock);
|
spin_lock_bh(&ci->tcf_lock);
|
||||||
goto_ch = tcf_action_set_ctrlact(*a, parm->action, goto_ch);
|
goto_ch = tcf_action_set_ctrlact(*a, parm->action, goto_ch);
|
||||||
oparms = rcu_replace_pointer(ci->parms, nparms, lockdep_is_held(&ci->tcf_lock));
|
oparms = rcu_replace_pointer(ci->parms, nparms, lockdep_is_held(&ci->tcf_lock));
|
||||||
|
|
@ -190,20 +192,20 @@ static int tcf_connmark_init(struct net *net, struct nlattr *nla,
|
||||||
static inline int tcf_connmark_dump(struct sk_buff *skb, struct tc_action *a,
|
static inline int tcf_connmark_dump(struct sk_buff *skb, struct tc_action *a,
|
||||||
int bind, int ref)
|
int bind, int ref)
|
||||||
{
|
{
|
||||||
|
const struct tcf_connmark_info *ci = to_connmark(a);
|
||||||
unsigned char *b = skb_tail_pointer(skb);
|
unsigned char *b = skb_tail_pointer(skb);
|
||||||
struct tcf_connmark_info *ci = to_connmark(a);
|
const struct tcf_connmark_parms *parms;
|
||||||
struct tc_connmark opt = {
|
struct tc_connmark opt = {
|
||||||
.index = ci->tcf_index,
|
.index = ci->tcf_index,
|
||||||
.refcnt = refcount_read(&ci->tcf_refcnt) - ref,
|
.refcnt = refcount_read(&ci->tcf_refcnt) - ref,
|
||||||
.bindcnt = atomic_read(&ci->tcf_bindcnt) - bind,
|
.bindcnt = atomic_read(&ci->tcf_bindcnt) - bind,
|
||||||
};
|
};
|
||||||
struct tcf_connmark_parms *parms;
|
|
||||||
struct tcf_t t;
|
struct tcf_t t;
|
||||||
|
|
||||||
spin_lock_bh(&ci->tcf_lock);
|
rcu_read_lock();
|
||||||
parms = rcu_dereference_protected(ci->parms, lockdep_is_held(&ci->tcf_lock));
|
parms = rcu_dereference(ci->parms);
|
||||||
|
|
||||||
opt.action = ci->tcf_action;
|
opt.action = parms->action;
|
||||||
opt.zone = parms->zone;
|
opt.zone = parms->zone;
|
||||||
if (nla_put(skb, TCA_CONNMARK_PARMS, sizeof(opt), &opt))
|
if (nla_put(skb, TCA_CONNMARK_PARMS, sizeof(opt), &opt))
|
||||||
goto nla_put_failure;
|
goto nla_put_failure;
|
||||||
|
|
@ -212,12 +214,12 @@ static inline int tcf_connmark_dump(struct sk_buff *skb, struct tc_action *a,
|
||||||
if (nla_put_64bit(skb, TCA_CONNMARK_TM, sizeof(t), &t,
|
if (nla_put_64bit(skb, TCA_CONNMARK_TM, sizeof(t), &t,
|
||||||
TCA_CONNMARK_PAD))
|
TCA_CONNMARK_PAD))
|
||||||
goto nla_put_failure;
|
goto nla_put_failure;
|
||||||
spin_unlock_bh(&ci->tcf_lock);
|
rcu_read_unlock();
|
||||||
|
|
||||||
return skb->len;
|
return skb->len;
|
||||||
|
|
||||||
nla_put_failure:
|
nla_put_failure:
|
||||||
spin_unlock_bh(&ci->tcf_lock);
|
rcu_read_unlock();
|
||||||
nlmsg_trim(skb, b);
|
nlmsg_trim(skb, b);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue