* [PATCH net-next v2 0/1] ppp: Replace per-CPU recursion counter with lock-owner field
@ 2025-07-10 16:24 Sebastian Andrzej Siewior
2025-07-10 16:24 ` [PATCH net-next v2 1/1] " Sebastian Andrzej Siewior
0 siblings, 1 reply; 5+ messages in thread
From: Sebastian Andrzej Siewior @ 2025-07-10 16:24 UTC (permalink / raw)
To: netdev, linux-rt-devel, linux-ppp
Cc: David S. Miller, Andrew Lunn, Clark Williams, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Simon Horman, Steven Rostedt,
Thomas Gleixner, Sebastian Andrzej Siewior
This is another approach to avoid relying on local_bh_disable() for
locking of per-CPU in ppp.
I redid it with the per-CPU lock and local_lock_nested_bh() as discussed
in v1. The xmit_recursion counter has been removed since it served the
same purpose as the owner field. Both were updated and checked.
The xmit_recursion looks like a counter in ppp_channel_push() but at
this point, the counter should always be 0 so it always serves as a
boolean. Therefore I removed it.
I do admit that this looks easier to review. On the other hand v1 had a
negative diffstat :)
v1…v2 https://lore.kernel.org/all/20250627105013.Qtv54bEk@linutronix.de/
- Instead of rewriting the sequence and adding two owner fields to
the two variables that may recurse it now adds a per-CPU variable
for locking and keeping mostly the old code flow.
Sebastian Andrzej Siewior (1):
ppp: Replace per-CPU recursion counter with lock-owner field
drivers/net/ppp/ppp_generic.c | 38 ++++++++++++++++++++++++++---------
1 file changed, 29 insertions(+), 9 deletions(-)
--
2.50.0
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH net-next v2 1/1] ppp: Replace per-CPU recursion counter with lock-owner field
2025-07-10 16:24 [PATCH net-next v2 0/1] ppp: Replace per-CPU recursion counter with lock-owner field Sebastian Andrzej Siewior
@ 2025-07-10 16:24 ` Sebastian Andrzej Siewior
2025-07-14 16:10 ` Guillaume Nault
0 siblings, 1 reply; 5+ messages in thread
From: Sebastian Andrzej Siewior @ 2025-07-10 16:24 UTC (permalink / raw)
To: netdev, linux-rt-devel, linux-ppp
Cc: David S. Miller, Andrew Lunn, Clark Williams, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Simon Horman, Steven Rostedt,
Thomas Gleixner, Sebastian Andrzej Siewior
The per-CPU variable ppp::xmit_recursion is protecting against recursion
due to wrong configuration of the ppp channels. The per-CPU variable
relies on disabled BH for its locking. Without per-CPU locking in
local_bh_disable() on PREEMPT_RT this data structure requires explicit
locking.
The ppp::xmit_recursion is used as a per-CPU boolean. The counter is
checked early in the send routing and the transmit path is only entered
if the counter is zero. Then the counter is incremented to avoid
recursion. It used to detect recursion on channel::downl and
ppp::wlock.
Create a struct ppp_xmit_recursion and move the counter into it.
Add local_lock_t to the struct and use local_lock_nested_bh() for
locking. Due to possible nesting, the lock cannot be acquired
unconditionally but it requires an owner field to identify recursion
before attempting to acquire the lock.
The counter is incremented and checked only after the lock is acquired.
Since it functions as a boolean rather than a count, and its role is now
superseded by the owner field, it can be safely removed.
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
---
drivers/net/ppp/ppp_generic.c | 38 ++++++++++++++++++++++++++---------
1 file changed, 29 insertions(+), 9 deletions(-)
diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c
index def84e87e05b2..0edc916e0a411 100644
--- a/drivers/net/ppp/ppp_generic.c
+++ b/drivers/net/ppp/ppp_generic.c
@@ -119,6 +119,11 @@ struct ppp_link_stats {
u64 tx_bytes;
};
+struct ppp_xmit_recursion {
+ struct task_struct *owner;
+ local_lock_t bh_lock;
+};
+
/*
* Data structure describing one ppp unit.
* A ppp unit corresponds to a ppp network interface device
@@ -132,7 +137,7 @@ struct ppp {
int n_channels; /* how many channels are attached 54 */
spinlock_t rlock; /* lock for receive side 58 */
spinlock_t wlock; /* lock for transmit side 5c */
- int __percpu *xmit_recursion; /* xmit recursion detect */
+ struct ppp_xmit_recursion __percpu *xmit_recursion; /* xmit recursion detect */
int mru; /* max receive unit 60 */
unsigned int flags; /* control bits 64 */
unsigned int xstate; /* transmit state bits 68 */
@@ -1262,13 +1267,18 @@ static int ppp_dev_configure(struct net *src_net, struct net_device *dev,
spin_lock_init(&ppp->rlock);
spin_lock_init(&ppp->wlock);
- ppp->xmit_recursion = alloc_percpu(int);
+ ppp->xmit_recursion = alloc_percpu(struct ppp_xmit_recursion);
if (!ppp->xmit_recursion) {
err = -ENOMEM;
goto err1;
}
- for_each_possible_cpu(cpu)
- (*per_cpu_ptr(ppp->xmit_recursion, cpu)) = 0;
+ for_each_possible_cpu(cpu) {
+ struct ppp_xmit_recursion *xmit_recursion;
+
+ xmit_recursion = per_cpu_ptr(ppp->xmit_recursion, cpu);
+ xmit_recursion->owner = NULL;
+ local_lock_init(&xmit_recursion->bh_lock);
+ }
#ifdef CONFIG_PPP_MULTILINK
ppp->minseq = -1;
@@ -1683,15 +1693,20 @@ static void __ppp_xmit_process(struct ppp *ppp, struct sk_buff *skb)
static void ppp_xmit_process(struct ppp *ppp, struct sk_buff *skb)
{
+ struct ppp_xmit_recursion *xmit_recursion;
+
local_bh_disable();
- if (unlikely(*this_cpu_ptr(ppp->xmit_recursion)))
+ xmit_recursion = this_cpu_ptr(ppp->xmit_recursion);
+ if (xmit_recursion->owner == current)
goto err;
+ local_lock_nested_bh(&ppp->xmit_recursion->bh_lock);
+ xmit_recursion->owner = current;
- (*this_cpu_ptr(ppp->xmit_recursion))++;
__ppp_xmit_process(ppp, skb);
- (*this_cpu_ptr(ppp->xmit_recursion))--;
+ xmit_recursion->owner = NULL;
+ local_unlock_nested_bh(&ppp->xmit_recursion->bh_lock);
local_bh_enable();
return;
@@ -2193,11 +2208,16 @@ static void __ppp_channel_push(struct channel *pch)
static void ppp_channel_push(struct channel *pch)
{
+ struct ppp_xmit_recursion *xmit_recursion;
+
read_lock_bh(&pch->upl);
if (pch->ppp) {
- (*this_cpu_ptr(pch->ppp->xmit_recursion))++;
+ xmit_recursion = this_cpu_ptr(pch->ppp->xmit_recursion);
+ local_lock_nested_bh(&pch->ppp->xmit_recursion->bh_lock);
+ xmit_recursion->owner = current;
__ppp_channel_push(pch);
- (*this_cpu_ptr(pch->ppp->xmit_recursion))--;
+ xmit_recursion->owner = NULL;
+ local_unlock_nested_bh(&pch->ppp->xmit_recursion->bh_lock);
} else {
__ppp_channel_push(pch);
}
--
2.50.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH net-next v2 1/1] ppp: Replace per-CPU recursion counter with lock-owner field
2025-07-10 16:24 ` [PATCH net-next v2 1/1] " Sebastian Andrzej Siewior
@ 2025-07-14 16:10 ` Guillaume Nault
2025-07-14 20:01 ` Sebastian Andrzej Siewior
0 siblings, 1 reply; 5+ messages in thread
From: Guillaume Nault @ 2025-07-14 16:10 UTC (permalink / raw)
To: Sebastian Andrzej Siewior
Cc: netdev, linux-rt-devel, linux-ppp, David S. Miller, Andrew Lunn,
Clark Williams, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Simon Horman, Steven Rostedt, Thomas Gleixner
On Thu, Jul 10, 2025 at 06:24:03PM +0200, Sebastian Andrzej Siewior wrote:
> The per-CPU variable ppp::xmit_recursion is protecting against recursion
> due to wrong configuration of the ppp channels. The per-CPU variable
I'd rather say that it's the ppp unit that is badly configured: it's
the ppp unit that can creates the loop (as it creates a networking
interface).
> relies on disabled BH for its locking. Without per-CPU locking in
> local_bh_disable() on PREEMPT_RT this data structure requires explicit
> locking.
>
> The ppp::xmit_recursion is used as a per-CPU boolean. The counter is
> checked early in the send routing and the transmit path is only entered
> if the counter is zero. Then the counter is incremented to avoid
> recursion. It used to detect recursion on channel::downl and
> ppp::wlock.
>
> Create a struct ppp_xmit_recursion and move the counter into it.
> Add local_lock_t to the struct and use local_lock_nested_bh() for
> locking. Due to possible nesting, the lock cannot be acquired
> unconditionally but it requires an owner field to identify recursion
> before attempting to acquire the lock.
>
> The counter is incremented and checked only after the lock is acquired.
> Since it functions as a boolean rather than a count, and its role is now
> superseded by the owner field, it can be safely removed.
>
> Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
> ---
> drivers/net/ppp/ppp_generic.c | 38 ++++++++++++++++++++++++++---------
> 1 file changed, 29 insertions(+), 9 deletions(-)
>
> diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c
> index def84e87e05b2..0edc916e0a411 100644
> --- a/drivers/net/ppp/ppp_generic.c
> +++ b/drivers/net/ppp/ppp_generic.c
> @@ -119,6 +119,11 @@ struct ppp_link_stats {
> u64 tx_bytes;
> };
>
> +struct ppp_xmit_recursion {
> + struct task_struct *owner;
> + local_lock_t bh_lock;
> +};
> +
This hunk conflicts with latest changes in net-next.
Apart from the two minor comments above, the patch looks good to me.
Thanks!
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH net-next v2 1/1] ppp: Replace per-CPU recursion counter with lock-owner field
2025-07-14 16:10 ` Guillaume Nault
@ 2025-07-14 20:01 ` Sebastian Andrzej Siewior
2025-07-15 17:33 ` Guillaume Nault
0 siblings, 1 reply; 5+ messages in thread
From: Sebastian Andrzej Siewior @ 2025-07-14 20:01 UTC (permalink / raw)
To: Guillaume Nault
Cc: netdev, linux-rt-devel, linux-ppp, David S. Miller, Andrew Lunn,
Clark Williams, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Simon Horman, Steven Rostedt, Thomas Gleixner
On 2025-07-14 18:10:47 [+0200], Guillaume Nault wrote:
> On Thu, Jul 10, 2025 at 06:24:03PM +0200, Sebastian Andrzej Siewior wrote:
> > The per-CPU variable ppp::xmit_recursion is protecting against recursion
> > due to wrong configuration of the ppp channels. The per-CPU variable
>
> I'd rather say that it's the ppp unit that is badly configured: it's
> the ppp unit that can creates the loop (as it creates a networking
> interface).
I can reword this.
> > index def84e87e05b2..0edc916e0a411 100644
> > --- a/drivers/net/ppp/ppp_generic.c
> > +++ b/drivers/net/ppp/ppp_generic.c
> > @@ -119,6 +119,11 @@ struct ppp_link_stats {
> > u64 tx_bytes;
> > };
> >
> > +struct ppp_xmit_recursion {
> > + struct task_struct *owner;
> > + local_lock_t bh_lock;
> > +};
> > +
>
> This hunk conflicts with latest changes in net-next.
Thank you.
> Apart from the two minor comments above, the patch looks good to me.
> Thanks!
Okay. As of the people involved while this detection was added and
polished, do you have an opinion on v1?
https://lore.kernel.org/all/20250627105013.Qtv54bEk@linutronix.de/
Sebastian
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH net-next v2 1/1] ppp: Replace per-CPU recursion counter with lock-owner field
2025-07-14 20:01 ` Sebastian Andrzej Siewior
@ 2025-07-15 17:33 ` Guillaume Nault
0 siblings, 0 replies; 5+ messages in thread
From: Guillaume Nault @ 2025-07-15 17:33 UTC (permalink / raw)
To: Sebastian Andrzej Siewior
Cc: netdev, linux-rt-devel, linux-ppp, David S. Miller, Andrew Lunn,
Clark Williams, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Simon Horman, Steven Rostedt, Thomas Gleixner
On Mon, Jul 14, 2025 at 10:01:39PM +0200, Sebastian Andrzej Siewior wrote:
> On 2025-07-14 18:10:47 [+0200], Guillaume Nault wrote:
> > On Thu, Jul 10, 2025 at 06:24:03PM +0200, Sebastian Andrzej Siewior wrote:
> > > The per-CPU variable ppp::xmit_recursion is protecting against recursion
> > > due to wrong configuration of the ppp channels. The per-CPU variable
> >
> > I'd rather say that it's the ppp unit that is badly configured: it's
> > the ppp unit that can creates the loop (as it creates a networking
> > interface).
>
> I can reword this.
>
> > > index def84e87e05b2..0edc916e0a411 100644
> > > --- a/drivers/net/ppp/ppp_generic.c
> > > +++ b/drivers/net/ppp/ppp_generic.c
> > > @@ -119,6 +119,11 @@ struct ppp_link_stats {
> > > u64 tx_bytes;
> > > };
> > >
> > > +struct ppp_xmit_recursion {
> > > + struct task_struct *owner;
> > > + local_lock_t bh_lock;
> > > +};
> > > +
> >
> > This hunk conflicts with latest changes in net-next.
>
> Thank you.
>
> > Apart from the two minor comments above, the patch looks good to me.
> > Thanks!
>
> Okay. As of the people involved while this detection was added and
> polished, do you have an opinion on v1?
> https://lore.kernel.org/all/20250627105013.Qtv54bEk@linutronix.de/
I like the idea of having an owner for each of the locks involved in
the recursion. That looks cleaner than the current approach of selecting
strategic places where to handle the possible recursion.
However, as a reviewer, I agree with Paolo that the diff is difficult
to reason about. Reviewing the v1 patch actually requires reviewing the
complete PPP channel and PPP unit transmit paths, with all their funny
features and lock interactions.
So I'd prefer that we merge your v2 (or v3). Then, if you really want
to push for the v1 approach, maybe consider proposing it as a follow up
during the next development cycle. Note that if you do so, I'd like
that you also write a selftest that could reliably trigger the
recursion when sending a packet through the channel and when sending
one through the unit.
In the end, I'm honestly not sure if the small cleanup benefice of the
lock owners approach is worth it, considering the general difficulty of
maintaining the kernel PPP implementation (brittle code, questionable
architecture, almost no reviewer).
> Sebastian
>
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2025-07-15 17:33 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-07-10 16:24 [PATCH net-next v2 0/1] ppp: Replace per-CPU recursion counter with lock-owner field Sebastian Andrzej Siewior
2025-07-10 16:24 ` [PATCH net-next v2 1/1] " Sebastian Andrzej Siewior
2025-07-14 16:10 ` Guillaume Nault
2025-07-14 20:01 ` Sebastian Andrzej Siewior
2025-07-15 17:33 ` Guillaume Nault
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).