• Max Kellermann's avatar
    [media] dvb_frontend: eliminate blocking wait in dvb_unregister_frontend() · fe35637b
    Max Kellermann authored
    The wait_event() call in dvb_unregister_frontend() waits synchronously
    for other tasks to free a file descriptor, but it does that while
    holding several mutexes.  That alone is a bad idea, but if one user
    process happens to keep a (defunct) file descriptor open indefinitely,
    the kernel will correctly detect a hung task:
    
        INFO: task kworker/0:1:314 blocked for more than 30 seconds.
              Not tainted 4.7.0-rc1-hosting+ #50
        "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
        kworker/0:1     D ffff88003daf7a50     0   314      2 0x00000000
        Workqueue: usb_hub_wq hub_event
         ffff88003daf7a50 0000000000000296 ffff88003daf7a30 ffff88003fc13f98
         ffff88003dadce00 ffff88003daf8000 ffff88003e3fc010 ffff88003d48d4f8
         ffff88003e3b5030 ffff88003e3f8898 ffff88003daf7a68 ffffffff810cf860
        Call Trace:
         [<ffffffff810cf860>] schedule+0x30/0x80
         [<ffffffff812f88d3>] dvb_unregister_frontend+0x93/0xc0
         [<ffffffff8107a000>] ? __wake_up_common+0x80/0x80
         [<ffffffff813019c7>] dvb_usb_adapter_frontend_exit+0x37/0x70
         [<ffffffff81300614>] dvb_usb_exit+0x34/0xb0
         [<ffffffff81300d4a>] dvb_usb_device_exit+0x3a/0x50
         [<ffffffff81302dc2>] pctv452e_usb_disconnect+0x52/0x60
         [<ffffffff81295a07>] usb_unbind_interface+0x67/0x1e0
         [<ffffffff810609f3>] ? __blocking_notifier_call_chain+0x53/0x70
         [<ffffffff8127ba67>] __device_release_driver+0x77/0x110
         [<ffffffff8127c2d3>] device_release_driver+0x23/0x30
         [<ffffffff8127ab5d>] bus_remove_device+0x10d/0x150
         [<ffffffff8127879b>] device_del+0x13b/0x260
         [<ffffffff81299dea>] ? usb_remove_ep_devs+0x1a/0x30
         [<ffffffff8129468e>] usb_disable_device+0x9e/0x1e0
         [<ffffffff8128bb09>] usb_disconnect+0x89/0x260
         [<ffffffff8128db8d>] hub_event+0x30d/0xfc0
         [<ffffffff81059475>] process_one_work+0x1c5/0x4a0
         [<ffffffff8105940c>] ? process_one_work+0x15c/0x4a0
         [<ffffffff81059799>] worker_thread+0x49/0x480
         [<ffffffff81059750>] ? process_one_work+0x4a0/0x4a0
         [<ffffffff81059750>] ? process_one_work+0x4a0/0x4a0
         [<ffffffff8105f65e>] kthread+0xee/0x110
         [<ffffffff810400bf>] ret_from_fork+0x1f/0x40
         [<ffffffff8105f570>] ? __kthread_unpark+0x70/0x70
        5 locks held by kworker/0:1/314:
         #0:  ("usb_hub_wq"){......}, at: [<ffffffff8105940c>] process_one_work+0x15c/0x4a0
         #1:  ((&hub->events)){......}, at: [<ffffffff8105940c>] process_one_work+0x15c/0x4a0
         #2:  (&dev->mutex){......}, at: [<ffffffff8128d8cb>] hub_event+0x4b/0xfc0
         #3:  (&dev->mutex){......}, at: [<ffffffff8128bad2>] usb_disconnect+0x52/0x260
         #4:  (&dev->mutex){......}, at: [<ffffffff8127c2cb>] device_release_driver+0x1b/0x30
    
    This patch removes the blocking wait, and postpones the kfree() call
    until all file handles have been closed by using struct kref.
    Signed-off-by: default avatarMax Kellermann <max@duempel.org>
    Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@s-opensource.com>
    fe35637b
dvb_frontend.c 74.8 KB