From fabf9fcedad7385f15ef48b2c4b8d31d8b2a37f7 Mon Sep 17 00:00:00 2001 From: Vladislav Bolkhovitin Date: Fri, 27 Jul 2012 01:14:55 +0000 Subject: [PATCH] Avoid that removing the scst_local kernel module triggers a deadlock when one of its LUNs is a CD-ROM device. sr_block_release() invokes scst_local_release_adapter() indirectly with sr_mutex held. So if scst_local_release_adapter() blocks until the scst_local session has been freed a deadlock may be triggered if another CD-ROM device has to be closed in order to free that session. Fix this by changing scst_local_release_adapter() such that it does not wait until the session unregistration has finished. Call stacks obtained with echo w > /proc/sysrq-trigger: SysRq : Show Blocked State task PC stack pid father scst_mgmtd D ffffffff812f979d 0 5552 2 0x00000000 ffff88003c335b30 0000000000000046 ffffffff812f979d 0000000000000002 ffff8800171d47a0 ffff88003c335fd8 ffff88003c335fd8 ffff88003c335fd8 ffff88003d1b0000 ffff8800171d47a0 ffff88003c335b60 ffff88003c334000 Call Trace: [] ? sr_block_release+0x2d/0x60 [] ? sr_block_release+0x2d/0x60 [] schedule+0x29/0x70 [] schedule_preempt_disabled+0x27/0x40 [] mutex_lock_nested+0x187/0x390 [] ? sr_block_release+0x2d/0x60 [] sr_block_release+0x2d/0x60 [] __blkdev_put+0x19c/0x1d0 [] blkdev_put+0x5d/0x180 [] blkdev_close+0x28/0x30 [] fput+0x103/0x280 [] filp_close+0x69/0x90 [] vdisk_detach_tgt+0x134/0x150 [scst_vdisk] [] scst_free_tgt_dev+0xdf/0x220 [scst] [] ? scst_free_session_callback+0x7f/0x170 [scst] [] scst_sess_free_tgt_devs+0x7b/0x110 [scst] [] scst_free_session+0x5e/0x2a0 [scst] [] scst_free_session_callback+0x9e/0x170 [scst] [] scst_global_mgmt_thread+0x2e5/0x580 [scst] [] ? __init_waitqueue_head+0x60/0x60 [] ? scst_register_session_non_gpl+0x20/0x20 [scst] [] kthread+0xb7/0xc0 [] kernel_thread_helper+0x4/0x10 [] ? retint_restore_args+0x13/0x13 [] ? __init_kthread_worker+0x70/0x70 [] ? gs_change+0x13/0x13 iscsi-scstd D ffffffffa02b1b1f 0 5567 1 0x00000004 ffff88003c2f59a8 0000000000000046 ffffffffa02b1b1f 0000000000000002 ffff8800173b23d0 ffff88003c2f5fd8 ffff88003c2f5fd8 ffff88003c2f5fd8 ffff88003d198000 ffff8800173b23d0 ffff88003c2f59d8 ffff88003c2f4000 Call Trace: [] ? scst_unregister_target+0x8f/0x450 [scst] [] ? scst_unregister_target+0x8f/0x450 [scst] [] schedule+0x29/0x70 [] schedule_preempt_disabled+0x27/0x40 [] mutex_lock_nested+0x187/0x390 [] ? scst_unregister_target+0x8f/0x450 [scst] [] ? __iscsi_del_attr+0xea/0x190 [iscsi_scst] [] scst_unregister_target+0x8f/0x450 [scst] [] ? __iscsi_del_attr+0xea/0x190 [iscsi_scst] [] target_destroy+0x5f/0xc0 [iscsi_scst] [] target_del_all+0xf2/0x2d0 [iscsi_scst] [] release+0x4a/0xe0 [iscsi_scst] [] fput+0x103/0x280 [] filp_close+0x69/0x90 [] put_files_struct+0x103/0x1c0 [] ? put_files_struct+0x48/0x1c0 [] exit_files+0x52/0x60 [] do_exit+0x180/0x8e0 [] ? get_signal_to_deliver+0xe7/0x6e0 [] do_group_exit+0x51/0xc0 [] get_signal_to_deliver+0x21f/0x6e0 [] do_signal+0x3c/0x580 [] do_notify_resume+0x65/0xa0 [] ? trace_hardirqs_on_thunk+0x3a/0x3f [] int_signal+0x12/0x17 rmmod D ffffffffa02b1b70 0 5714 5681 0x00000000 ffff88000b497d48 0000000000000046 ffffffffa02b1b70 0000000000000002 ffff88003920a3d0 ffff88000b497fd8 ffff88000b497fd8 ffff88000b497fd8 ffff88003d17a3d0 ffff88003920a3d0 ffff88000b497d78 ffff88000b496000 Call Trace: [] ? scst_unregister_target+0xe0/0x450 [scst] [] ? scst_unregister_target+0xe0/0x450 [scst] [] schedule+0x29/0x70 [] schedule_preempt_disabled+0x27/0x40 [] mutex_lock_nested+0x187/0x390 [] ? scst_unregister_target+0xe0/0x450 [scst] [] scst_unregister_target+0xe0/0x450 [scst] [] ? scst_local_exit+0x6b/0x21a [scst_local] [] ? put_device+0x17/0x20 [] ? device_unregister+0x2a/0x60 [] __scst_local_remove_target+0xa8/0x130 [scst_local] [] scst_local_exit+0x84/0x21a [scst_local] [] sys_delete_module+0x1a6/0x2b0 [] ? trace_hardirqs_on_thunk+0x3a/0x3f [] system_call_fastpath+0x16/0x1b ata_id D ffff88003920c7a0 0 5715 5195 0x00000000 ffff880015e97818 0000000000000046 0000000000000000 0000000000000046 ffff88003920c7a0 ffff880015e97fd8 ffff880015e97fd8 ffff880015e97fd8 ffff880021788000 ffff88003920c7a0 ffff880015e977f8 7fffffffffffffff Call Trace: [] schedule+0x29/0x70 [] schedule_timeout+0x315/0x390 [] ? wait_for_common+0x43/0x170 [] ? wait_for_common+0x43/0x170 [] wait_for_common+0x122/0x170 [] ? try_to_wake_up+0x2f0/0x2f0 [] wait_for_completion+0x1d/0x20 [] scst_unregister_session+0x1a3/0x320 [scst] [] scst_local_release_adapter+0xa0/0x140 [scst_local] [] device_release+0x27/0xa0 [] kobject_release+0x8b/0x1d0 [] kobject_put+0x2c/0x60 [] put_device+0x17/0x20 [] scsi_host_dev_release+0xc0/0xe0 [] device_release+0x27/0xa0 [] kobject_release+0x8b/0x1d0 [] kobject_put+0x2c/0x60 [] put_device+0x17/0x20 [] scsi_target_dev_release+0x22/0x30 [] device_release+0x27/0xa0 [] kobject_release+0x8b/0x1d0 [] kobject_put+0x2c/0x60 [] put_device+0x17/0x20 [] scsi_device_dev_release_usercontext+0x118/0x130 [] ? scsi_device_cls_release+0x20/0x20 [] execute_in_process_context+0x86/0xa0 [] scsi_device_dev_release+0x1c/0x20 [] device_release+0x27/0xa0 [] kobject_release+0x8b/0x1d0 [] kobject_put+0x2c/0x60 [] put_device+0x17/0x20 [] scsi_device_put+0x44/0x60 [] scsi_cd_put+0x4d/0x70 [] sr_block_release+0x41/0x60 [] __blkdev_put+0x19c/0x1d0 [] blkdev_put+0x5d/0x180 [] blkdev_close+0x28/0x30 [] fput+0x103/0x280 [] ? __schedule+0x3c3/0x820 [] filp_close+0x69/0x90 [] sys_close+0xa0/0x100 [] system_call_fastpath+0x16/0x1b Signed-off-by: Bart Van Assche Cc: Richard Sharpe git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@4425 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- scst_local/scst_local.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/scst_local/scst_local.c b/scst_local/scst_local.c index b04c3ed58..ac74e13d7 100644 --- a/scst_local/scst_local.c +++ b/scst_local/scst_local.c @@ -1572,6 +1572,14 @@ static struct device scst_local_root = { static struct device *scst_local_root; #endif +static void scst_local_free_sess(struct scst_session *scst_sess) +{ + struct scst_local_sess *sess = scst_sess_get_tgt_priv(scst_sess); + + kfree(sess); + return; +} + static void scst_local_release_adapter(struct device *dev) { struct scst_local_sess *sess; @@ -1597,9 +1605,7 @@ static void scst_local_release_adapter(struct device *dev) cancel_work_sync(&sess->aen_work); #endif - scst_unregister_session(sess->scst_sess, true, NULL); - - kfree(sess); + scst_unregister_session(sess->scst_sess, false, scst_local_free_sess); out: TRACE_EXIT();