From 08b774f6439fa115d511a15dc9dd9313943b6301 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Wed, 9 Dec 2015 19:18:01 +0000 Subject: [PATCH] scst_main: Fix wait_event() call in scst_unregister_target() Avoid that the following kernel warning gets triggered: WARNING: CPU: 3 PID: 12967 at kernel/sched/core.c:7287 __might_sleep+0x7a/0x90() do not call blocking ops when !TASK_RUNNING; state=2 set at [] prepare_to_wait_event+0x5e/0xf0 CPU: 3 PID: 12967 Comm: scst_uid Tainted: G O 4.0.0-debug+ #1 Call Trace: [] dump_stack+0x4c/0x65 [] warn_slowpath_common+0x80/0xc0 [] warn_slowpath_fmt+0x41/0x50 [] __might_sleep+0x7a/0x90 [] mutex_lock_nested+0x2a/0x4d0 [] test_sess_list+0x1a/0x40 [scst] [] scst_unregister_target+0x26e/0x380 [scst] [] __scst_local_remove_target+0xc6/0x160 [scst_local] [] scst_local_sysfs_del_target+0xbc/0x1b0 [scst_local] [] scst_process_tgtt_mgmt_store+0x205/0x300 [scst] [] scst_tgtt_mgmt_store_work_fn+0x14/0x20 [scst] [] scst_process_sysfs_works+0xbd/0x1f0 [scst] [] sysfs_work_thread_fn+0xbd/0x310 [scst] [] kthread+0xf3/0x110 [] ret_from_fork+0x58/0x90 git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@6724 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- scst/src/scst_main.c | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/scst/src/scst_main.c b/scst/src/scst_main.c index b5b3851e9..512d0bae1 100644 --- a/scst/src/scst_main.c +++ b/scst/src/scst_main.c @@ -593,16 +593,6 @@ out_free_tgt: } EXPORT_SYMBOL(scst_register_target); -static inline int test_sess_list(struct scst_tgt *tgt) -{ - int res; - - mutex_lock(&scst_mutex); - res = list_empty(&tgt->sysfs_sess_list); - mutex_unlock(&scst_mutex); - return res; -} - /** * scst_unregister_target() - unregister target. * @@ -655,8 +645,15 @@ again: mutex_unlock(&scst_mutex); #endif + /* + * Testing tgt->sysfs_sess_list below without holding scst_mutex + * is safe because 'tgt' won't disappear until scst_free_tgt() is + * called below and because the mutex_lock(&scst_mutex) call below + * waits until scst_free_session() has finished accessing the 'tgt' + * object. + */ TRACE_DBG("%s", "Waiting for sessions shutdown"); - wait_event(tgt->unreg_waitQ, test_sess_list(tgt)); + wait_event(tgt->unreg_waitQ, list_empty(&tgt->sysfs_sess_list)); TRACE_DBG("%s", "wait_event() returned"); scst_suspend_activity(SCST_SUSPEND_TIMEOUT_UNLIMITED);