Skip to content

Commit d4f6460

Browse files
Sebastian Andrzej SiewiorPaolo Abeni
authored andcommitted
ppp: Replace per-CPU recursion counter with lock-owner field
The per-CPU variable ppp::xmit_recursion is protecting against recursion due to wrong configuration of the ppp unit. 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 <[email protected]> Link: https://patch.msgid.link/[email protected] Reviewed-by: Guillaume Nault <[email protected]> Signed-off-by: Paolo Abeni <[email protected]>
1 parent e0c7e31 commit d4f6460

File tree

1 file changed

+29
-9
lines changed

1 file changed

+29
-9
lines changed

drivers/net/ppp/ppp_generic.c

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,11 @@ struct ppp_file {
107107
#define PF_TO_PPP(pf) PF_TO_X(pf, struct ppp)
108108
#define PF_TO_CHANNEL(pf) PF_TO_X(pf, struct channel)
109109

110+
struct ppp_xmit_recursion {
111+
struct task_struct *owner;
112+
local_lock_t bh_lock;
113+
};
114+
110115
/*
111116
* Data structure describing one ppp unit.
112117
* A ppp unit corresponds to a ppp network interface device
@@ -120,7 +125,7 @@ struct ppp {
120125
int n_channels; /* how many channels are attached 54 */
121126
spinlock_t rlock; /* lock for receive side 58 */
122127
spinlock_t wlock; /* lock for transmit side 5c */
123-
int __percpu *xmit_recursion; /* xmit recursion detect */
128+
struct ppp_xmit_recursion __percpu *xmit_recursion; /* xmit recursion detect */
124129
int mru; /* max receive unit 60 */
125130
unsigned int flags; /* control bits 64 */
126131
unsigned int xstate; /* transmit state bits 68 */
@@ -1249,13 +1254,18 @@ static int ppp_dev_configure(struct net *src_net, struct net_device *dev,
12491254
spin_lock_init(&ppp->rlock);
12501255
spin_lock_init(&ppp->wlock);
12511256

1252-
ppp->xmit_recursion = alloc_percpu(int);
1257+
ppp->xmit_recursion = alloc_percpu(struct ppp_xmit_recursion);
12531258
if (!ppp->xmit_recursion) {
12541259
err = -ENOMEM;
12551260
goto err1;
12561261
}
1257-
for_each_possible_cpu(cpu)
1258-
(*per_cpu_ptr(ppp->xmit_recursion, cpu)) = 0;
1262+
for_each_possible_cpu(cpu) {
1263+
struct ppp_xmit_recursion *xmit_recursion;
1264+
1265+
xmit_recursion = per_cpu_ptr(ppp->xmit_recursion, cpu);
1266+
xmit_recursion->owner = NULL;
1267+
local_lock_init(&xmit_recursion->bh_lock);
1268+
}
12591269

12601270
#ifdef CONFIG_PPP_MULTILINK
12611271
ppp->minseq = -1;
@@ -1660,15 +1670,20 @@ static void __ppp_xmit_process(struct ppp *ppp, struct sk_buff *skb)
16601670

16611671
static void ppp_xmit_process(struct ppp *ppp, struct sk_buff *skb)
16621672
{
1673+
struct ppp_xmit_recursion *xmit_recursion;
1674+
16631675
local_bh_disable();
16641676

1665-
if (unlikely(*this_cpu_ptr(ppp->xmit_recursion)))
1677+
xmit_recursion = this_cpu_ptr(ppp->xmit_recursion);
1678+
if (xmit_recursion->owner == current)
16661679
goto err;
1680+
local_lock_nested_bh(&ppp->xmit_recursion->bh_lock);
1681+
xmit_recursion->owner = current;
16671682

1668-
(*this_cpu_ptr(ppp->xmit_recursion))++;
16691683
__ppp_xmit_process(ppp, skb);
1670-
(*this_cpu_ptr(ppp->xmit_recursion))--;
16711684

1685+
xmit_recursion->owner = NULL;
1686+
local_unlock_nested_bh(&ppp->xmit_recursion->bh_lock);
16721687
local_bh_enable();
16731688

16741689
return;
@@ -2169,11 +2184,16 @@ static void __ppp_channel_push(struct channel *pch)
21692184

21702185
static void ppp_channel_push(struct channel *pch)
21712186
{
2187+
struct ppp_xmit_recursion *xmit_recursion;
2188+
21722189
read_lock_bh(&pch->upl);
21732190
if (pch->ppp) {
2174-
(*this_cpu_ptr(pch->ppp->xmit_recursion))++;
2191+
xmit_recursion = this_cpu_ptr(pch->ppp->xmit_recursion);
2192+
local_lock_nested_bh(&pch->ppp->xmit_recursion->bh_lock);
2193+
xmit_recursion->owner = current;
21752194
__ppp_channel_push(pch);
2176-
(*this_cpu_ptr(pch->ppp->xmit_recursion))--;
2195+
xmit_recursion->owner = NULL;
2196+
local_unlock_nested_bh(&pch->ppp->xmit_recursion->bh_lock);
21772197
} else {
21782198
__ppp_channel_push(pch);
21792199
}

0 commit comments

Comments
 (0)