Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

net_sched: act_pedit: use RCU in tcf_pedit_dump()

Also storing tcf_action into struct tcf_pedit_params
makes sure there is no discrepancy in tcf_pedit_act().

Signed-off-by: Eric Dumazet <edumazet@google.com>
Link: https://patch.msgid.link/20250709090204.797558-10-edumazet@google.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Eric Dumazet and committed by
Jakub Kicinski
9d096746 5d289286

+11 -10
+1
include/net/tc_act/tc_pedit.h
··· 14 14 struct tcf_pedit_parms { 15 15 struct tc_pedit_key *tcfp_keys; 16 16 struct tcf_pedit_key_ex *tcfp_keys_ex; 17 + int action; 17 18 u32 tcfp_off_max_hint; 18 19 unsigned char tcfp_nkeys; 19 20 unsigned char tcfp_flags;
+10 -10
net/sched/act_pedit.c
··· 279 279 } 280 280 281 281 p = to_pedit(*a); 282 - 282 + nparms->action = parm->action; 283 283 spin_lock_bh(&p->tcf_lock); 284 284 goto_ch = tcf_action_set_ctrlact(*a, parm->action, goto_ch); 285 285 oparms = rcu_replace_pointer(p->parms, nparms, 1); ··· 483 483 bad: 484 484 tcf_action_inc_overlimit_qstats(&p->common); 485 485 done: 486 - return p->tcf_action; 486 + return parms->action; 487 487 } 488 488 489 489 static void tcf_pedit_stats_update(struct tc_action *a, u64 bytes, u64 packets, ··· 500 500 int bind, int ref) 501 501 { 502 502 unsigned char *b = skb_tail_pointer(skb); 503 - struct tcf_pedit *p = to_pedit(a); 504 - struct tcf_pedit_parms *parms; 503 + const struct tcf_pedit *p = to_pedit(a); 504 + const struct tcf_pedit_parms *parms; 505 505 struct tc_pedit *opt; 506 506 struct tcf_t t; 507 507 int s; 508 508 509 - spin_lock_bh(&p->tcf_lock); 510 - parms = rcu_dereference_protected(p->parms, 1); 509 + rcu_read_lock(); 510 + parms = rcu_dereference(p->parms); 511 511 s = struct_size(opt, keys, parms->tcfp_nkeys); 512 512 513 513 opt = kzalloc(s, GFP_ATOMIC); 514 514 if (unlikely(!opt)) { 515 - spin_unlock_bh(&p->tcf_lock); 515 + rcu_read_unlock(); 516 516 return -ENOBUFS; 517 517 } 518 518 opt->nkeys = parms->tcfp_nkeys; ··· 521 521 flex_array_size(opt, keys, parms->tcfp_nkeys)); 522 522 opt->index = p->tcf_index; 523 523 opt->flags = parms->tcfp_flags; 524 - opt->action = p->tcf_action; 524 + opt->action = parms->action; 525 525 opt->refcnt = refcount_read(&p->tcf_refcnt) - ref; 526 526 opt->bindcnt = atomic_read(&p->tcf_bindcnt) - bind; 527 527 ··· 540 540 tcf_tm_dump(&t, &p->tcf_tm); 541 541 if (nla_put_64bit(skb, TCA_PEDIT_TM, sizeof(t), &t, TCA_PEDIT_PAD)) 542 542 goto nla_put_failure; 543 - spin_unlock_bh(&p->tcf_lock); 543 + rcu_read_unlock(); 544 544 545 545 kfree(opt); 546 546 return skb->len; 547 547 548 548 nla_put_failure: 549 - spin_unlock_bh(&p->tcf_lock); 549 + rcu_read_unlock(); 550 550 nlmsg_trim(skb, b); 551 551 kfree(opt); 552 552 return -1;