forked from Minki/linux
pppoatm: optimise PPP channel wakeups after sock_owned_by_user()
We don't need to schedule the wakeup tasklet on *every* unlock; only if we actually blocked the channel in the first place. Signed-off-by: David Woodhouse <David.Woodhouse@intel.com> Acked-by: Krzysztof Mazur <krzysiek@podlesie.net>
This commit is contained in:
parent
9eba25268e
commit
5b4d72080f
@ -113,7 +113,17 @@ static void pppoatm_release_cb(struct atm_vcc *atmvcc)
|
||||
{
|
||||
struct pppoatm_vcc *pvcc = atmvcc_to_pvcc(atmvcc);
|
||||
|
||||
tasklet_schedule(&pvcc->wakeup_tasklet);
|
||||
/*
|
||||
* As in pppoatm_pop(), it's safe to clear the BLOCKED bit here because
|
||||
* the wakeup *can't* race with pppoatm_send(). They both hold the PPP
|
||||
* channel's ->downl lock. And the potential race with *setting* it,
|
||||
* which leads to the double-check dance in pppoatm_may_send(), doesn't
|
||||
* exist here. In the sock_owned_by_user() case in pppoatm_send(), we
|
||||
* set the BLOCKED bit while the socket is still locked. We know that
|
||||
* ->release_cb() can't be called until that's done.
|
||||
*/
|
||||
if (test_and_clear_bit(BLOCKED, &pvcc->blocked))
|
||||
tasklet_schedule(&pvcc->wakeup_tasklet);
|
||||
if (pvcc->old_release_cb)
|
||||
pvcc->old_release_cb(atmvcc);
|
||||
}
|
||||
@ -292,8 +302,15 @@ 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)))
|
||||
if (sock_owned_by_user(sk_atm(vcc))) {
|
||||
/*
|
||||
* Needs to happen (and be flushed, hence test_and_) before we unlock
|
||||
* the socket. It needs to be seen by the time our ->release_cb gets
|
||||
* called.
|
||||
*/
|
||||
test_and_set_bit(BLOCKED, &pvcc->blocked);
|
||||
goto nospace;
|
||||
}
|
||||
if (test_bit(ATM_VF_RELEASED, &vcc->flags) ||
|
||||
test_bit(ATM_VF_CLOSE, &vcc->flags) ||
|
||||
!test_bit(ATM_VF_READY, &vcc->flags)) {
|
||||
|
Loading…
Reference in New Issue
Block a user