inconsistent lock state

Arjan van de Ven arjan at fenrus.demon.nl
Sun Jul 30 19:21:44 UTC 2006


> It is filled as #200500


This looks like a USB serial deadlock:

usb_serial_generic_write() does
spin_lock(&port->lock);
without disabling interrupts

a second place it gets called is from  ppp_async_push() like this:
[<f9324478>] usb_serial_generic_write+0x79/0x23d [usbserial]
[<f9322531>] serial_write+0x8a/0x99 [usbserial]
[<f933729c>] ppp_async_push+0xa7/0x3b3 [ppp_async]
[<f93375da>] ppp_async_send+0x32/0x3d [ppp_async]
[<f932f071>] ppp_channel_push+0x3a/0x94 [ppp_generic]
[<f9330395>] ppp_write+0xd5/0xe1 [ppp_generic]
[<c0471f23>] vfs_write+0xab/0x157
[<c0472568>] sys_write+0x3b/0x60


where ppp_async_push() first takes ap->xmit_lock for _bh() safeness.

now... ppp_async_push is also called from softirq context
[<f9337224>] ppp_async_push+0x2f/0x3b3 [ppp_async]
[<f9337aea>] ppp_async_process+0x48/0x5b [ppp_async]
[<c04294b4>] tasklet_action+0x65/0xca

so what can happen is this:


cpu 0 is calling usb_serial_generic_write() from user context "raw"
      and takes the port->lock

cpu 1 is calling the 2nd trace above (sys_write) and hits the ppp_async_push()
     which takes the ap->xmit_lock
cpu 1 then goes into usb_serial_generic_write() obviously, and tries to get the port->lock,
     but this spins because cpu 0 is holding this lock

cpu 0 now hits an irq, which then triggers a softirq to happen (third trace) which
     calls ppp_async_push() which tries to take the ap->xmit_lock. Which is held by cpu 1
     and so cpu 0 goes to spin and wait

and.. we have deadlock.

Pete: Does this explanation sound reasonable and correct ?




More information about the devel mailing list