From nobody Mon Feb 9 10:28:22 2026 Received: from mail-06.mail-europe.com (mail-06.mail-europe.com [85.9.210.45]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 0B3E533F364 for ; Wed, 21 Jan 2026 13:21:01 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=85.9.210.45 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769001663; cv=none; b=spX52SDuJF9whwZx5UpIorQOGxf+UC2cLV97wGkyOnoeBmCP9HDoPz5NMJyNzkawO/b4BbXfJEv7slCwyGuZ3uIo2CDzeDltHjJPoT7gyyTw2C+ZhTXOBK//oV3IfIBiwtw5fpVB9BptMQBt4eTm8pR5767KlRUIf74ngpnZQAg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769001663; c=relaxed/simple; bh=EDqnzZEN7orb7ZGQ+93aCuksK9MrkNnuG8+bzoNPJ5o=; h=Date:To:From:Cc:Subject:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=tKtwRTEFxw8VCclRKleRBbUNKxwXu+VaeQqtXzYw9SA2RYGJvabK29Oinh8tc+xeTPcCf10rfZfgZy+1Q7Dl2H1Bi/E4V1XpYT3etb89N9XGVxGN3IUBOHwbQy9g2rz+2RWzCc7bZvbjpcsLOTOZv9qCYItcjZzOcNPFP9IS/YY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=1g4.org; spf=pass smtp.mailfrom=1g4.org; dkim=pass (2048-bit key) header.d=1g4.org header.i=@1g4.org header.b=geHUA2+m; arc=none smtp.client-ip=85.9.210.45 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=1g4.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=1g4.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=1g4.org header.i=@1g4.org header.b="geHUA2+m" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1g4.org; s=protonmail2; t=1769001652; x=1769260852; bh=VQqC9st29svSgAOcWUIUXHbbKJPCeUzGVN5vug9MHKc=; h=Date:To:From:Cc:Subject:Message-ID:In-Reply-To:References: Feedback-ID:From:To:Cc:Date:Subject:Reply-To:Feedback-ID: Message-ID:BIMI-Selector; b=geHUA2+mJ7+w2S9X2AljL2vbIdOsi103NQ3lUAu3CazCR1vnOh1IAuzaThHzK0Ayz pUh+QSYbcWUxEthLL7pjmCgOSf4uCiQX95bWU2m25k5EOIp4GIdMQY4Be7GZW9tFUj E/Id206d+iqm7wySHK1PyxmeMkDS76F9zXCwg2CH+vOMM9uekda4u8QFT+FBxeY7hY GDcOst/SPMEuKUO/OwOZsssTXGIS3byntLhV05c88IDLMPISxR8DJFtCmy8Ix5R07O uDeQmgp5pTaZE8uImP4RJIIx2LxN3XZ+lOS1OmHAiyLWDotGgijsKH39MiKTyT0sxe hEb5uo7fH5sgA== Date: Wed, 21 Jan 2026 13:20:50 +0000 To: netdev@vger.kernel.org From: Paul Moses Cc: Jamal Hadi Salim , Cong Wang , Jiri Pirko , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman , linux-kernel@vger.kernel.org, Paul Moses , stable@vger.kernel.org Subject: [PATCH net v3 4/7] net/sched: act_gate: read schedule via RCU Message-ID: <20260121131954.2710459-5-p@1g4.org> In-Reply-To: <20260121131954.2710459-1-p@1g4.org> References: <20260121131954.2710459-1-p@1g4.org> Feedback-ID: 8253658:user:proton X-Pm-Message-ID: 35e9f1a5787104e5795d193ad305baffc241ac0c Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Switch dump/accessor reads to RCU read-side sections. This matches other actions that read params under rcu_read_lock(), e.g. act_tunnel_key dump (commit e97ae742972f6c), act_ctinfo dump (commit 799c94178cf9c9), and act_skbedit dump (commit 1f376373bd225c). Dump reads tcf_action via READ_ONCE, following the lockless action reads us= ed in act_sample (commit 5c5670fae43027) and act_gact. Timer logic stays under tcf_lock and uses rcu_dereference_protected(), keep= ing RCU readers cheap while preserving lock-serialized timer updates. Fixes: a51c328df310 ("net: qos: introduce a gate control flow action") Signed-off-by: Paul Moses Cc: stable@vger.kernel.org --- include/net/tc_act/tc_gate.h | 38 +++++++++++++++++++++++------------- net/sched/act_gate.c | 32 +++++++++++++++--------------- 2 files changed, 40 insertions(+), 30 deletions(-) diff --git a/include/net/tc_act/tc_gate.h b/include/net/tc_act/tc_gate.h index 05968b3822392..9587d9e9fa38f 100644 --- a/include/net/tc_act/tc_gate.h +++ b/include/net/tc_act/tc_gate.h @@ -57,9 +57,10 @@ static inline s32 tcf_gate_prio(const struct tc_action *= a) s32 tcfg_prio; struct tcf_gate_params *p; =20 - p =3D rcu_dereference_protected(to_gate(a)->param, - lockdep_rtnl_is_held()); + rcu_read_lock(); + p =3D rcu_dereference(to_gate(a)->param); tcfg_prio =3D p->tcfg_priority; + rcu_read_unlock(); =20 return tcfg_prio; } @@ -69,9 +70,10 @@ static inline u64 tcf_gate_basetime(const struct tc_acti= on *a) u64 tcfg_basetime; struct tcf_gate_params *p; =20 - p =3D rcu_dereference_protected(to_gate(a)->param, - lockdep_rtnl_is_held()); + rcu_read_lock(); + p =3D rcu_dereference(to_gate(a)->param); tcfg_basetime =3D p->tcfg_basetime; + rcu_read_unlock(); =20 return tcfg_basetime; } @@ -81,9 +83,10 @@ static inline u64 tcf_gate_cycletime(const struct tc_act= ion *a) u64 tcfg_cycletime; struct tcf_gate_params *p; =20 - p =3D rcu_dereference_protected(to_gate(a)->param, - lockdep_rtnl_is_held()); + rcu_read_lock(); + p =3D rcu_dereference(to_gate(a)->param); tcfg_cycletime =3D p->tcfg_cycletime; + rcu_read_unlock(); =20 return tcfg_cycletime; } @@ -93,9 +96,10 @@ static inline u64 tcf_gate_cycletimeext(const struct tc_= action *a) u64 tcfg_cycletimeext; struct tcf_gate_params *p; =20 - p =3D rcu_dereference_protected(to_gate(a)->param, - lockdep_rtnl_is_held()); + rcu_read_lock(); + p =3D rcu_dereference(to_gate(a)->param); tcfg_cycletimeext =3D p->tcfg_cycletime_ext; + rcu_read_unlock(); =20 return tcfg_cycletimeext; } @@ -105,9 +109,10 @@ static inline u32 tcf_gate_num_entries(const struct tc= _action *a) u32 num_entries; struct tcf_gate_params *p; =20 - p =3D rcu_dereference_protected(to_gate(a)->param, - lockdep_rtnl_is_held()); + rcu_read_lock(); + p =3D rcu_dereference(to_gate(a)->param); num_entries =3D p->num_entries; + rcu_read_unlock(); =20 return num_entries; } @@ -121,19 +126,23 @@ static inline struct action_gate_entry u32 num_entries; int i =3D 0; =20 - p =3D rcu_dereference_protected(to_gate(a)->param, - lockdep_rtnl_is_held()); + rcu_read_lock(); + p =3D rcu_dereference(to_gate(a)->param); num_entries =3D p->num_entries; =20 list_for_each_entry(entry, &p->entries, list) i++; =20 - if (i !=3D num_entries) + if (i !=3D num_entries) { + rcu_read_unlock(); return NULL; + } =20 oe =3D kcalloc(num_entries, sizeof(*oe), GFP_ATOMIC); - if (!oe) + if (!oe) { + rcu_read_unlock(); return NULL; + } =20 i =3D 0; list_for_each_entry(entry, &p->entries, list) { @@ -143,6 +152,7 @@ static inline struct action_gate_entry oe[i].maxoctets =3D entry->maxoctets; i++; } + rcu_read_unlock(); =20 return oe; } diff --git a/net/sched/act_gate.c b/net/sched/act_gate.c index 016708c10a8e0..da4802bbaf4ca 100644 --- a/net/sched/act_gate.c +++ b/net/sched/act_gate.c @@ -624,66 +624,66 @@ static int tcf_gate_dump(struct sk_buff *skb, struct = tc_action *a, { unsigned char *b =3D skb_tail_pointer(skb); struct tcf_gate *gact =3D to_gate(a); - struct tc_gate opt =3D { }; struct tcfg_gate_entry *entry; struct tcf_gate_params *p; struct nlattr *entry_list; + struct tc_gate opt =3D { }; struct tcf_t t; =20 opt.index =3D gact->tcf_index; opt.refcnt =3D refcount_read(&gact->tcf_refcnt) - ref; opt.bindcnt =3D atomic_read(&gact->tcf_bindcnt) - bind; =20 - spin_lock_bh(&gact->tcf_lock); - opt.action =3D gact->tcf_action; - - p =3D rcu_dereference_protected(gact->param, - lockdep_is_held(&gact->tcf_lock)); + opt.action =3D READ_ONCE(gact->tcf_action); =20 if (nla_put(skb, TCA_GATE_PARMS, sizeof(opt), &opt)) goto nla_put_failure; =20 + rcu_read_lock(); + p =3D rcu_dereference(gact->param); + if (nla_put_u64_64bit(skb, TCA_GATE_BASE_TIME, p->tcfg_basetime, TCA_GATE_PAD)) - goto nla_put_failure; + goto nla_put_failure_rcu; =20 if (nla_put_u64_64bit(skb, TCA_GATE_CYCLE_TIME, p->tcfg_cycletime, TCA_GATE_PAD)) - goto nla_put_failure; + goto nla_put_failure_rcu; =20 if (nla_put_u64_64bit(skb, TCA_GATE_CYCLE_TIME_EXT, p->tcfg_cycletime_ext, TCA_GATE_PAD)) - goto nla_put_failure; + goto nla_put_failure_rcu; =20 if (nla_put_s32(skb, TCA_GATE_CLOCKID, p->tcfg_clockid)) - goto nla_put_failure; + goto nla_put_failure_rcu; =20 if (nla_put_u32(skb, TCA_GATE_FLAGS, p->tcfg_flags)) - goto nla_put_failure; + goto nla_put_failure_rcu; =20 if (nla_put_s32(skb, TCA_GATE_PRIORITY, p->tcfg_priority)) - goto nla_put_failure; + goto nla_put_failure_rcu; =20 entry_list =3D nla_nest_start_noflag(skb, TCA_GATE_ENTRY_LIST); if (!entry_list) - goto nla_put_failure; + goto nla_put_failure_rcu; =20 list_for_each_entry(entry, &p->entries, list) { if (dumping_entry(skb, entry) < 0) - goto nla_put_failure; + goto nla_put_failure_rcu; } =20 nla_nest_end(skb, entry_list); + rcu_read_unlock(); =20 tcf_tm_dump(&t, &gact->tcf_tm); if (nla_put_64bit(skb, TCA_GATE_TM, sizeof(t), &t, TCA_GATE_PAD)) goto nla_put_failure; - spin_unlock_bh(&gact->tcf_lock); =20 return skb->len; =20 +nla_put_failure_rcu: + rcu_read_unlock(); nla_put_failure: - spin_unlock_bh(&gact->tcf_lock); nlmsg_trim(skb, b); return -1; } --=20 2.52.GIT