diff mbox

[v3,8/7] pppoatm: fix missing wakeup in pppoatm_send()

Message ID 1352292734.7340.35.camel@shinybook.infradead.org
State Changes Requested, archived
Delegated to: David Miller
Headers show

Commit Message

David Woodhouse Nov. 7, 2012, 12:52 p.m. UTC
Now that we can return zero from pppoatm_send() for reasons *other* than
the queue being full, that means we can't depend on a subsequent call to
pppoatm_pop() waking the queue, and we might leave it stalled
indefinitely.

Fix this by immediately scheduling the wakeup tasklet. As documented
already elsewhere, the PPP channel's ->downl lock protects against the
wakeup happening too soon and effectively being missed.

Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
----
Untested.
With this sorted, Acked-By: David Woodhouse <David.Woodhouse@intel.com<
to the other seven. Thanks.

Comments

David Miller Nov. 9, 2012, 9:30 p.m. UTC | #1
From: David Woodhouse <dwmw2@infradead.org>
Date: Wed, 07 Nov 2012 12:52:14 +0000

> Now that we can return zero from pppoatm_send() for reasons *other* than
> the queue being full, that means we can't depend on a subsequent call to
> pppoatm_pop() waking the queue, and we might leave it stalled
> indefinitely.
> 
> Fix this by immediately scheduling the wakeup tasklet. As documented
> already elsewhere, the PPP channel's ->downl lock protects against the
> wakeup happening too soon and effectively being missed.
> 
> Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
> ----
> Untested.
> With this sorted, Acked-By: David Woodhouse <David.Woodhouse@intel.com<
> to the other seven. Thanks.

I don't know what to do with this patch because I don't have any
context whatsoever.

So I'm tossing it, please resubmit it when it's meant to be
applied, and with some context.
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
David Woodhouse Nov. 10, 2012, 7:36 a.m. UTC | #2
On Fri, 2012-11-09 at 16:30 -0500, David Miller wrote:
> I don't know what to do with this patch because I don't have any
> context whatsoever.

I sent two replies to Krzysztof's series starting with [PATCH v3 0/7]  
in Message-Id: <1352240222-363-1-git-send-email-krzysiek@podlesie.net>

The first was pointing out a problem; the second was a [PATCH v3 8/7]
which fixed the problem I'd pointed out. It wasn't clear to me that more
context would be needed. In particular, [PATCH v3 8/7] was a reply to
0/7, just as the other patches ##1-7 had been.

> So I'm tossing it, please resubmit it when it's meant to be
> applied, and with some context.

That's OK. I was hoping for an ack from Chas and/or Krzysztof,
especially as I hadn't tested my patch. So hopefully there'll be a v4
series of 8 patches, including this one... and all from the same person,
which makes it slightly easier to follow :)
David Miller Nov. 10, 2012, 6:38 p.m. UTC | #3
From: David Woodhouse <dwmw2@infradead.org>
Date: Sat, 10 Nov 2012 07:36:13 +0000

> I was hoping for an ack from Chas and/or Krzysztof, especially as I
> hadn't tested my patch. So hopefully there'll be a v4 series of 8
> patches, including this one... and all from the same person, which
> makes it slightly easier to follow :)

Ok, great.
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Krzysztof Mazur Nov. 10, 2012, 8:23 p.m. UTC | #4
On Wed, Nov 07, 2012 at 12:52:14PM +0000, David Woodhouse wrote:
> 
> diff --git a/net/atm/pppoatm.c b/net/atm/pppoatm.c
> index 7507c20..56ad541 100644
> --- a/net/atm/pppoatm.c
> +++ b/net/atm/pppoatm.c
> @@ -283,11 +283,11 @@ static int pppoatm_send(struct ppp_channel *chan, struct sk_buff *skb)
>  	vcc = ATM_SKB(skb)->vcc;
>  	bh_lock_sock(sk_atm(vcc));
>  	if (sock_owned_by_user(sk_atm(vcc)))
> -		goto nospace;
> +		goto nospace_sched_wakeup;
>  	if (test_bit(ATM_VF_RELEASED, &vcc->flags)
> -			|| test_bit(ATM_VF_CLOSE, &vcc->flags)
> -			|| !test_bit(ATM_VF_READY, &vcc->flags))
> -		goto nospace;
> +	    || test_bit(ATM_VF_CLOSE, &vcc->flags)
> +	    || !test_bit(ATM_VF_READY, &vcc->flags))
> +		goto nospace_sched_wakeup;
>  
>  	switch (pvcc->encaps) {		/* LLC encapsulation needed */
>  	case e_llc:
> @@ -328,7 +328,17 @@ static int pppoatm_send(struct ppp_channel *chan, struct sk_buff *skb)
>  	    ? DROP_PACKET : 1;
>  	bh_unlock_sock(sk_atm(vcc));
>  	return ret;
> -nospace:
> + nospace_sched_wakeup:
> +	/* If we're returning zero for reasons *other* than the queue
> +	 * being full, then we need to ensure that a wakeup will
> +	 * happen and not just leave the channel stalled for ever.
> +	 * Just schedule the wakeup tasklet directly. As observed in
> +	 * pppoatm_pop(), it'll take the channel's ->downl lock which
> +	 * is also held by our caller, so it can't happen "too soon"
> +	 * and cause us to effectively miss a wakeup.
> +	 */
> +	tasklet_schedule(&pvcc->wakeup_tasklet);

With this tasklet_schedule() we implement a "spin_lock" here, but in
this case both conditions (vcc not ready and socket locked) can be true
for a long time and we can spin here for a long time. I confirmed it by
reverting patch 1 (atm: detach protocol before closing vcc) and now
I have 50% of CPU used by ksoftirqd and 50% by pppd (UP system).

Krzysiek
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
David Woodhouse Nov. 10, 2012, 9:02 p.m. UTC | #5
On Sat, 2012-11-10 at 21:23 +0100, Krzysztof Mazur wrote:
> With this tasklet_schedule() we implement a "spin_lock" here, but in
> this case both conditions (vcc not ready and socket locked) can be
> true for a long time and we can spin here for a long time. I confirmed
> it by reverting patch 1 (atm: detach protocol before closing vcc) and
> now I have 50% of CPU used by ksoftirqd and 50% by pppd (UP system).

Ah, thanks.

Can we take the lock in the tasklet, so we wait for it instead of
spinning?
David Woodhouse Nov. 11, 2012, 7:28 a.m. UTC | #6
On Sat, 2012-11-10 at 21:23 +0100, Krzysztof Mazur wrote:
> With this tasklet_schedule() we implement a "spin_lock" here, but in
> this case both conditions (vcc not ready and socket locked) can be
> true for a long time and we can spin here for a long time. 

Reading this more carefully this morning... I hadn't realised it was
these conditions, and not the sock_owned_by_user(), which had triggered.
Yes, perhaps we should just return zero in that case and find another
wakeup trigger... if indeed a wakeup is ever required in the VF_RELEASED
and VF_CLOSE case. And if we've fixed things so that !VF_READY can never
happen (have we?).... perhaps this one doesn't matter at all? It was the
sock_owned_by_user() case I was most interested in, and I was expecting
that lock would generally be held briefly enough that the tasklet would
be fine. Was that not so?
diff mbox

Patch

diff --git a/net/atm/pppoatm.c b/net/atm/pppoatm.c
index 7507c20..56ad541 100644
--- a/net/atm/pppoatm.c
+++ b/net/atm/pppoatm.c
@@ -283,11 +283,11 @@  static int pppoatm_send(struct ppp_channel *chan, struct sk_buff *skb)
 	vcc = ATM_SKB(skb)->vcc;
 	bh_lock_sock(sk_atm(vcc));
 	if (sock_owned_by_user(sk_atm(vcc)))
-		goto nospace;
+		goto nospace_sched_wakeup;
 	if (test_bit(ATM_VF_RELEASED, &vcc->flags)
-			|| test_bit(ATM_VF_CLOSE, &vcc->flags)
-			|| !test_bit(ATM_VF_READY, &vcc->flags))
-		goto nospace;
+	    || test_bit(ATM_VF_CLOSE, &vcc->flags)
+	    || !test_bit(ATM_VF_READY, &vcc->flags))
+		goto nospace_sched_wakeup;
 
 	switch (pvcc->encaps) {		/* LLC encapsulation needed */
 	case e_llc:
@@ -328,7 +328,17 @@  static int pppoatm_send(struct ppp_channel *chan, struct sk_buff *skb)
 	    ? DROP_PACKET : 1;
 	bh_unlock_sock(sk_atm(vcc));
 	return ret;
-nospace:
+ nospace_sched_wakeup:
+	/* If we're returning zero for reasons *other* than the queue
+	 * being full, then we need to ensure that a wakeup will
+	 * happen and not just leave the channel stalled for ever.
+	 * Just schedule the wakeup tasklet directly. As observed in
+	 * pppoatm_pop(), it'll take the channel's ->downl lock which
+	 * is also held by our caller, so it can't happen "too soon"
+	 * and cause us to effectively miss a wakeup.
+	 */
+	tasklet_schedule(&pvcc->wakeup_tasklet);
+ nospace:
 	bh_unlock_sock(sk_atm(vcc));
 	/*
 	 * We don't have space to send this SKB now, but we might have