ttydev_cdevsw has no d_purge

From: Konstantin Belousov <kostikbel_at_gmail.com>
Date: Wed, 1 Aug 2012 19:03:23 +0300
[Long story, the summary is in last two paragraphs]

I use several APC UPS some of which are connected by the USB<->serial
dongle.  Said USBs very much like to drop from the USB bus on a
smallest power glitch.  Today I noted that a machine dropped UPS
serial USB device, and did not reattached it.  More, attempt to show
the list of the USB devices resulted in usbconfig locking hard:

tom% sudo usbconfig list                                                      ~
load: 0.00  cmd: usbconfig 76210 [USB config SX lock] 4.63r 0.00u 0.00s 1% 1000k
^C^C
load: 0.07  cmd: usbconfig 76210 [USB config SX lock] 33.87r 0.00u 0.00s 0% 1000k

Quick inspection of the said sx revealed that the owner of the lock is
the kernel thread, with the backtrace

84 100089 usb              usbus3           mi_switch+0x184 sleepq_wait+0x42 _cv_wait+0x11e ucom_detach+0x142 uplcom_detach+0x20 device_detach+0x74 usb_detach_device+0x4a usb_unconfigure+0x34 usb_free_device+0x166 uhub_explore+0x12e usb_bus_explore+0xd2 usb_process+0x9b fork_exit+0x11f fork_trampoline+0xe

Apparently, in ucom_detach_tty(), the condition sc->sc_ttyfreed == 0
was not satisfied because apcupsd has a thread inside a tty devsw
method, which prevented the destroy_dev_sched from succeeding and the
wait hang almost forever.  More, the Giant taskqueue was stopped due
to stuck job.  Killing apcupsd, which slept interruptible, allowed
the tty destruction to proceed and freed USB config SX.  This unwedged
the USB subsystem and machine become fully functional again.

I would blame tty subsystem rather then USB subsystem.  The d_purge
method of the ttydev_cdevsw is not implemented, but it is the only
measure that can break the deadlocks like the one I described. The
d_purge shall wake up threads sleeping inside devsw methods, which was
specifically added to notify driver about device gone events.

I am sorry for not catching the backtrace for the apcupsd itself,
since it was only afterthought that apcupsd is interesting part of the
deadlock. I am sure that it was not poll() which was entered by
apcupsd, most likely it was read/write or some termios ioctl.

Received on Wed Aug 01 2012 - 14:03:28 UTC

This archive was generated by hypermail 2.4.0 : Wed May 19 2021 - 11:40:29 UTC