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:
 [<ffffffff812f979d>] ? sr_block_release+0x2d/0x60
 [<ffffffff812f979d>] ? sr_block_release+0x2d/0x60
 [<ffffffff814a9b19>] schedule+0x29/0x70
 [<ffffffff814a9e57>] schedule_preempt_disabled+0x27/0x40
 [<ffffffff814a79b7>] mutex_lock_nested+0x187/0x390
 [<ffffffff812f979d>] ? sr_block_release+0x2d/0x60
 [<ffffffff812f979d>] sr_block_release+0x2d/0x60
 [<ffffffff8118a1ec>] __blkdev_put+0x19c/0x1d0
 [<ffffffff8118a27d>] blkdev_put+0x5d/0x180
 [<ffffffff8118a3c8>] blkdev_close+0x28/0x30
 [<ffffffff81153633>] fput+0x103/0x280
 [<ffffffff8114fad9>] filp_close+0x69/0x90
 [<ffffffffa022ec24>] vdisk_detach_tgt+0x134/0x150 [scst_vdisk]
 [<ffffffffa02d8f2f>] scst_free_tgt_dev+0xdf/0x220 [scst]
 [<ffffffffa02d949f>] ? scst_free_session_callback+0x7f/0x170 [scst]
 [<ffffffffa02d90eb>] scst_sess_free_tgt_devs+0x7b/0x110 [scst]
 [<ffffffffa02d91de>] scst_free_session+0x5e/0x2a0 [scst]
 [<ffffffffa02d94be>] scst_free_session_callback+0x9e/0x170 [scst]
 [<ffffffffa02c6a05>] scst_global_mgmt_thread+0x2e5/0x580 [scst]
 [<ffffffff8105e850>] ? __init_waitqueue_head+0x60/0x60
 [<ffffffffa02c6720>] ? scst_register_session_non_gpl+0x20/0x20 [scst]
 [<ffffffff8105dd77>] kthread+0xb7/0xc0
 [<ffffffff814b50b4>] kernel_thread_helper+0x4/0x10
 [<ffffffff814abb30>] ? retint_restore_args+0x13/0x13
 [<ffffffff8105dcc0>] ? __init_kthread_worker+0x70/0x70
 [<ffffffff814b50b0>] ? 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:
 [<ffffffffa02b1b1f>] ? scst_unregister_target+0x8f/0x450 [scst]
 [<ffffffffa02b1b1f>] ? scst_unregister_target+0x8f/0x450 [scst]
 [<ffffffff814a9b19>] schedule+0x29/0x70
 [<ffffffff814a9e57>] schedule_preempt_disabled+0x27/0x40
 [<ffffffff814a79b7>] mutex_lock_nested+0x187/0x390
 [<ffffffffa02b1b1f>] ? scst_unregister_target+0x8f/0x450 [scst]
 [<ffffffffa025c7ba>] ? __iscsi_del_attr+0xea/0x190 [iscsi_scst]
 [<ffffffffa02b1b1f>] scst_unregister_target+0x8f/0x450 [scst]
 [<ffffffffa025c7ba>] ? __iscsi_del_attr+0xea/0x190 [iscsi_scst]
 [<ffffffffa026249f>] target_destroy+0x5f/0xc0 [iscsi_scst]
 [<ffffffffa02631f2>] target_del_all+0xf2/0x2d0 [iscsi_scst]
 [<ffffffffa025c8aa>] release+0x4a/0xe0 [iscsi_scst]
 [<ffffffff81153633>] fput+0x103/0x280
 [<ffffffff8114fad9>] filp_close+0x69/0x90
 [<ffffffff8103e533>] put_files_struct+0x103/0x1c0
 [<ffffffff8103e478>] ? put_files_struct+0x48/0x1c0
 [<ffffffff8103e6b2>] exit_files+0x52/0x60
 [<ffffffff8103eb80>] do_exit+0x180/0x8e0
 [<ffffffff8104ef87>] ? get_signal_to_deliver+0xe7/0x6e0
 [<ffffffff8103f631>] do_group_exit+0x51/0xc0
 [<ffffffff8104f0bf>] get_signal_to_deliver+0x21f/0x6e0
 [<ffffffff8100223c>] do_signal+0x3c/0x580
 [<ffffffff81002805>] do_notify_resume+0x65/0xa0
 [<ffffffff812149de>] ? trace_hardirqs_on_thunk+0x3a/0x3f
 [<ffffffff814b4122>] 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:
 [<ffffffffa02b1b70>] ? scst_unregister_target+0xe0/0x450 [scst]
 [<ffffffffa02b1b70>] ? scst_unregister_target+0xe0/0x450 [scst]
 [<ffffffff814a9b19>] schedule+0x29/0x70
 [<ffffffff814a9e57>] schedule_preempt_disabled+0x27/0x40
 [<ffffffff814a79b7>] mutex_lock_nested+0x187/0x390
 [<ffffffffa02b1b70>] ? scst_unregister_target+0xe0/0x450 [scst]
 [<ffffffffa02b1b70>] scst_unregister_target+0xe0/0x450 [scst]
 [<ffffffffa0287e51>] ? scst_local_exit+0x6b/0x21a [scst_local]
 [<ffffffff812c2d37>] ? put_device+0x17/0x20
 [<ffffffff812c3efa>] ? device_unregister+0x2a/0x60
 [<ffffffffa0285108>] __scst_local_remove_target+0xa8/0x130 [scst_local]
 [<ffffffffa0287e6a>] scst_local_exit+0x84/0x21a [scst_local]
 [<ffffffff810a40c6>] sys_delete_module+0x1a6/0x2b0
 [<ffffffff812149de>] ? trace_hardirqs_on_thunk+0x3a/0x3f
 [<ffffffff814b3de9>] 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:
 [<ffffffff814a9b19>] schedule+0x29/0x70
 [<ffffffff814a7355>] schedule_timeout+0x315/0x390
 [<ffffffff814a98e3>] ? wait_for_common+0x43/0x170
 [<ffffffff814a98e3>] ? wait_for_common+0x43/0x170
 [<ffffffff814a99c2>] wait_for_common+0x122/0x170
 [<ffffffff810705b0>] ? try_to_wake_up+0x2f0/0x2f0
 [<ffffffff814a9aed>] wait_for_completion+0x1d/0x20
 [<ffffffffa02bfad3>] scst_unregister_session+0x1a3/0x320 [scst]
 [<ffffffffa0284990>] scst_local_release_adapter+0xa0/0x140 [scst_local]
 [<ffffffff812c2f87>] device_release+0x27/0xa0
 [<ffffffff81209abb>] kobject_release+0x8b/0x1d0
 [<ffffffff8120993c>] kobject_put+0x2c/0x60
 [<ffffffff812c2d37>] put_device+0x17/0x20
 [<ffffffff812e1850>] scsi_host_dev_release+0xc0/0xe0
 [<ffffffff812c2f87>] device_release+0x27/0xa0
 [<ffffffff81209abb>] kobject_release+0x8b/0x1d0
 [<ffffffff8120993c>] kobject_put+0x2c/0x60
 [<ffffffff812c2d37>] put_device+0x17/0x20
 [<ffffffff812ea0c2>] scsi_target_dev_release+0x22/0x30
 [<ffffffff812c2f87>] device_release+0x27/0xa0
 [<ffffffff81209abb>] kobject_release+0x8b/0x1d0
 [<ffffffff8120993c>] kobject_put+0x2c/0x60
 [<ffffffff812c2d37>] put_device+0x17/0x20
 [<ffffffff812ed818>] scsi_device_dev_release_usercontext+0x118/0x130
 [<ffffffff812ed700>] ? scsi_device_cls_release+0x20/0x20
 [<ffffffff81056576>] execute_in_process_context+0x86/0xa0
 [<ffffffff812ed6dc>] scsi_device_dev_release+0x1c/0x20
 [<ffffffff812c2f87>] device_release+0x27/0xa0
 [<ffffffff81209abb>] kobject_release+0x8b/0x1d0
 [<ffffffff8120993c>] kobject_put+0x2c/0x60
 [<ffffffff812c2d37>] put_device+0x17/0x20
 [<ffffffff812df594>] scsi_device_put+0x44/0x60
 [<ffffffff812f974d>] scsi_cd_put+0x4d/0x70
 [<ffffffff812f97b1>] sr_block_release+0x41/0x60
 [<ffffffff8118a1ec>] __blkdev_put+0x19c/0x1d0
 [<ffffffff8118a27d>] blkdev_put+0x5d/0x180
 [<ffffffff8118a3c8>] blkdev_close+0x28/0x30
 [<ffffffff81153633>] fput+0x103/0x280
 [<ffffffff814a93b3>] ? __schedule+0x3c3/0x820
 [<ffffffff8114fad9>] filp_close+0x69/0x90
 [<ffffffff8114fba0>] sys_close+0xa0/0x100
 [<ffffffff814b3de9>] system_call_fastpath+0x16/0x1b

Signed-off-by: Bart Van Assche <bvanassche@acm.org>
Cc: Richard Sharpe <realrichardsharpe@gmail.com>




git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@4425 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
Vladislav Bolkhovitin
2012-07-27 01:14:55 +00:00
parent b1e0e7ef19
commit fabf9fceda

View File

@@ -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();