mirror of
https://github.com/torvalds/linux.git
synced 2025-11-02 17:49:03 +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 net *net;
|
||||
u16 zone;
|
||||
int action;
|
||||
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 */
|
||||
tcf_action_inc_overlimit_qstats(&ca->common);
|
||||
out:
|
||||
return READ_ONCE(ca->tcf_action);
|
||||
return parms->action;
|
||||
}
|
||||
|
||||
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)
|
||||
goto release_idr;
|
||||
|
||||
nparms->action = parm->action;
|
||||
|
||||
spin_lock_bh(&ci->tcf_lock);
|
||||
goto_ch = tcf_action_set_ctrlact(*a, parm->action, goto_ch);
|
||||
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,
|
||||
int bind, int ref)
|
||||
{
|
||||
const struct tcf_connmark_info *ci = to_connmark(a);
|
||||
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 = {
|
||||
.index = ci->tcf_index,
|
||||
.refcnt = refcount_read(&ci->tcf_refcnt) - ref,
|
||||
.bindcnt = atomic_read(&ci->tcf_bindcnt) - bind,
|
||||
};
|
||||
struct tcf_connmark_parms *parms;
|
||||
struct tcf_t t;
|
||||
|
||||
spin_lock_bh(&ci->tcf_lock);
|
||||
parms = rcu_dereference_protected(ci->parms, lockdep_is_held(&ci->tcf_lock));
|
||||
rcu_read_lock();
|
||||
parms = rcu_dereference(ci->parms);
|
||||
|
||||
opt.action = ci->tcf_action;
|
||||
opt.action = parms->action;
|
||||
opt.zone = parms->zone;
|
||||
if (nla_put(skb, TCA_CONNMARK_PARMS, sizeof(opt), &opt))
|
||||
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,
|
||||
TCA_CONNMARK_PAD))
|
||||
goto nla_put_failure;
|
||||
spin_unlock_bh(&ci->tcf_lock);
|
||||
rcu_read_unlock();
|
||||
|
||||
return skb->len;
|
||||
|
||||
nla_put_failure:
|
||||
spin_unlock_bh(&ci->tcf_lock);
|
||||
rcu_read_unlock();
|
||||
nlmsg_trim(skb, b);
|
||||
return -1;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue