From nobody Mon Feb 9 14:32:30 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 74AE248AE2A; Wed, 21 Jan 2026 13:21:06 +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=1769001669; cv=none; b=FNSChJlhRKMtNzwX5GFcgE9f8o+8DCMdtZw/0VJSjgx2/qF4OL0lKO0h9wo9aBbCJxILN4a1lSMVfwqXnl4sbveLCvb03pD/H8l0lZX/QkAChmn3o5LUtf1Xu0XY56yS6VkqTHdFoaidGXPKaovTk6V/VQXXLNYkbm3NT3aDHP0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769001669; c=relaxed/simple; bh=I2r7cP/avxEfAooDdEHJNIdmgbvA2I/gO0PSjLhEXfo=; h=Date:To:From:Cc:Subject:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=p9UDS4IOkXt8ZbA3sMTmCRf/5Wta+5l8uN/Gm91PT4SSWH7Qj0KlwF6HoeHnceOQl6184ksOUlwrshmSndz3M4s44N4aYQW4VYWMuiCYFoR40sxNxb0oH16Fu0fwqh/zfagwyU7nAeUzMEnXIKVe1WPg7SKpNd61Yw4ZM7s9+kk= 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=UbBXYkbb; 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="UbBXYkbb" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1g4.org; s=protonmail2; t=1769001657; x=1769260857; bh=97EnEXfdGOZnSlFj4TNmyaX9AtuuT1NFsPcfG7rTSxY=; 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=UbBXYkbboJzNarrfVp6R3LKDJwLmv8hvF8CWfD0eLP+QUGzEQ58Rve23UEOgSSOIZ FB5itLZOXvS7646dVxmH9rii4L8LBZCWnG+R1dCsJ07ZaMIknoFLE5nwQhrykXherK aIOrOVulBO4IOcsL9y5IY7hX7e7ZDf3M/u+vn3rTgf6hoc1vB65YyUaYQxcT5Pjnew LGWtCv4MsC/zS32RJDEPukUrbJxiol23cArWK0/vDs+exmX5ILWxj3KP0r77RFPF5e 2A1WqUYfJZqs2TJM6l3AvHjGffRWwOtHDlXsXNifYltc2pPtLeJmk1mrxITzD+HHUo KevGEMVc8k6YQ== Date: Wed, 21 Jan 2026 13:20:54 +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 5/7] net/sched: act_gate: cancel timer outside tcf_lock Message-ID: <20260121131954.2710459-6-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: 17c3bed5517b3aeac02460dbb1810ac1584a97e5 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" Move hrtimer_cancel() out from under tcf_lock, cancel only on clockid chang= es, and always restart using the newly computed start time. For schedule replacement, bypass the prior expiry clamp so basetime moves forward without firing the new schedule early. Other schedulers explicitly cancel hrtimers on reconfig/teardown, e.g. sch_taprio advance_timer (commit 44d4775ca51805), sch_dualpi2 pi2_timer (commit 320d031ad6e4d6), and qdisc_watchdog_cancel() (commit 2fbd3da3877ad8= ). Fixes: a51c328df310 ("net: qos: introduce a gate control flow action") Signed-off-by: Paul Moses Cc: stable@vger.kernel.org --- net/sched/act_gate.c | 52 ++++++++++++++++++++------------------------ 1 file changed, 24 insertions(+), 28 deletions(-) diff --git a/net/sched/act_gate.c b/net/sched/act_gate.c index da4802bbaf4ca..48ff378bb051a 100644 --- a/net/sched/act_gate.c +++ b/net/sched/act_gate.c @@ -55,15 +55,17 @@ static void gate_get_start_time(struct tcf_gate *gact, *start =3D ktime_add_ns(base, (n + 1) * cycle); } =20 -static void gate_start_timer(struct tcf_gate *gact, ktime_t start) +static void gate_start_timer(struct tcf_gate *gact, ktime_t start, bool re= place) { ktime_t expires; =20 - expires =3D hrtimer_get_expires(&gact->hitimer); - if (expires =3D=3D 0) - expires =3D KTIME_MAX; + if (!replace) { + expires =3D hrtimer_get_expires(&gact->hitimer); + if (expires =3D=3D 0) + expires =3D KTIME_MAX; =20 - start =3D min_t(ktime_t, start, expires); + start =3D min_t(ktime_t, start, expires); + } =20 hrtimer_start(&gact->hitimer, start, HRTIMER_MODE_ABS_SOFT); } @@ -307,24 +309,9 @@ static int parse_gate_list(struct nlattr *list_attr, return err; } =20 -static void gate_setup_timer(struct tcf_gate *gact, u64 basetime, - enum tk_offsets tko, s32 clockid, - bool do_init) +static void gate_setup_timer(struct tcf_gate *gact, + enum tk_offsets tko, s32 clockid) { - struct tcf_gate_params *p; - - if (!do_init) { - p =3D rcu_dereference_protected(gact->param, - lockdep_is_held(&gact->tcf_lock)); - if (basetime =3D=3D p->tcfg_basetime && - tko =3D=3D gact->tk_offset && - clockid =3D=3D p->tcfg_clockid) - return; - - spin_unlock_bh(&gact->tcf_lock); - hrtimer_cancel(&gact->hitimer); - spin_lock_bh(&gact->tcf_lock); - } gact->tk_offset =3D tko; hrtimer_setup(&gact->hitimer, gate_timer_func, clockid, HRTIMER_MODE_ABS_= SOFT); } @@ -527,8 +514,19 @@ static int tcf_gate_init(struct net *net, struct nlatt= r *nla, goto release_mem; =20 spin_lock_bh(&gact->tcf_lock); - gate_setup_timer(gact, basetime, tk_offset, clockid, - ret =3D=3D ACT_P_CREATED); + + if (ret =3D=3D ACT_P_CREATED) { + gate_setup_timer(gact, tk_offset, clockid); + } else { + old_p =3D rcu_dereference_protected(gact->param, + lockdep_is_held(&gact->tcf_lock)); + if (!old_p || clockid !=3D old_p->tcfg_clockid) { + spin_unlock_bh(&gact->tcf_lock); + hrtimer_cancel(&gact->hitimer); + spin_lock_bh(&gact->tcf_lock); + gate_setup_timer(gact, tk_offset, clockid); + } + } gate_get_start_time(gact, p, &start); =20 old_p =3D rcu_replace_pointer(gact->param, p, @@ -542,7 +540,7 @@ static int tcf_gate_init(struct net *net, struct nlattr= *nla, =20 goto_ch =3D tcf_action_set_ctrlact(*a, parm->action, goto_ch); =20 - gate_start_timer(gact, start); + gate_start_timer(gact, start, ret !=3D ACT_P_CREATED); =20 spin_unlock_bh(&gact->tcf_lock); =20 @@ -562,9 +560,7 @@ static int tcf_gate_init(struct net *net, struct nlattr= *nla, * without taking tcf_lock. */ if (ret =3D=3D ACT_P_CREATED) - gate_setup_timer(gact, 0, - gact->tk_offset, 0, - true); + gate_setup_timer(gact, gact->tk_offset, 0); tcf_idr_release(*a, bind); return err; } --=20 2.52.GIT