From a57c9d0cee79c16f7224cddcef10e57547b42e96 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Thu, 16 Jan 2014 15:23:45 +0000 Subject: [PATCH] fcst: Fix a potential deadlock This patch fixes the following lockdep warning: ====================================================== [ INFO: possible circular locking dependency detected ] 3.13.0-rc6-debug+ #5 Tainted: G W O ------------------------------------------------------- rmmod/8653 is trying to acquire lock: (scst_tgt_kref){+.+.+.}, at: [] scst_tgt_sysfs_put+0x10f/0x190 [scst] but task is already holding lock: (ft_lport_lock){+.+.+.}, at: [] ft_lport_del+0x1b/0x40 [fcst] which lock already depends on the new lock. the existing dependency chain (in reverse order) is: -> #1 (ft_lport_lock){+.+.+.}: [] lock_acquire+0xa4/0x1e0 [] mutex_lock_nested+0x77/0x430 [] ft_tgt_enable+0x20/0xd0 [fcst] [] scst_process_tgt_enable_store+0xe9/0x230 [scst] [] scst_tgt_enable_store_work_fn+0x1c/0x20 [scst] [] scst_process_sysfs_works+0xfc/0x1f0 [scst] [] sysfs_work_thread_fn+0x120/0x2b0 [scst] [] kthread+0xf0/0x110 [] ret_from_fork+0x7c/0xb0 -> #0 (scst_tgt_kref){+.+.+.}: [] __lock_acquire+0x17ab/0x1b10 [] lock_acquire+0xa4/0x1e0 [] scst_kobject_put_and_wait+0x99/0x260 [scst] [] scst_tgt_sysfs_put+0x10f/0x190 [scst] [] scst_unregister_target+0x15c/0x3c0 [scst] [] ft_tport_delete+0x2c/0xa0 [fcst] [] ft_lport_del+0x2c/0x40 [fcst] [] fc_lport_iterate+0x49/0x80 [libfc] [] ft_module_exit+0x36/0x832 [fcst] [] SyS_delete_module+0x152/0x1f0 [] system_call_fastpath+0x16/0x1b other info that might help us debug this: Possible unsafe locking scenario: CPU0 CPU1 ---- ---- lock(ft_lport_lock); lock(scst_tgt_kref); lock(ft_lport_lock); lock(scst_tgt_kref); *** DEADLOCK *** 2 locks held by rmmod/8653: #0: (fc_prov_mutex){+.+.+.}, at: [] fc_lport_iterate+0x22/0x80 [libfc] #1: (ft_lport_lock){+.+.+.}, at: [] ft_lport_del+0x1b/0x40 [fcst] stack backtrace: CPU: 0 PID: 8653 Comm: rmmod Tainted: G W O 3.13.0-rc6-debug+ #5 Hardware name: Bochs Bochs, BIOS Bochs 01/01/2011 ffffffff8222ce70 ffff88002efdbb70 ffffffff8155551c ffffffff8222ce70 ffff88002efdbbb0 ffffffff81552248 ffff88002efdbc00 ffff88002ed0ed88 ffff88002ed0e6d0 0000000000000002 0000000000000002 ffff88002ed0ed88 Call Trace: [] dump_stack+0x4e/0x7a [] print_circular_bug+0x200/0x20f [] __lock_acquire+0x17ab/0x1b10 [] lock_acquire+0xa4/0x1e0 [] scst_kobject_put_and_wait+0x99/0x260 [scst] [] scst_tgt_sysfs_put+0x10f/0x190 [scst] [] scst_unregister_target+0x15c/0x3c0 [scst] [] ft_tport_delete+0x2c/0xa0 [fcst] [] ft_lport_del+0x2c/0x40 [fcst] [] fc_lport_iterate+0x49/0x80 [libfc] [] ft_module_exit+0x36/0x832 [fcst] [] SyS_delete_module+0x152/0x1f0 [] system_call_fastpath+0x16/0x1b git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@5196 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- fcst/ft_sess.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/fcst/ft_sess.c b/fcst/ft_sess.c index 6d1ab65a3..3ce88bca4 100644 --- a/fcst/ft_sess.c +++ b/fcst/ft_sess.c @@ -608,19 +608,18 @@ int ft_tgt_release(struct scst_tgt *tgt) return 0; } +/* Caller must hold a reference on tgt->tgt_kobj. */ int ft_tgt_enable(struct scst_tgt *tgt, bool enable) { struct ft_tport *tport; int ret = 0; - mutex_lock(&ft_lport_lock); - if (enable) { FT_SESS_DBG("enable tgt %s\n", tgt->tgt_name); tport = scst_tgt_get_tgt_priv(tgt); if (tport == NULL) { ret = -E_TGT_PRIV_NOT_YET_SET; - goto out_unlock; + goto out; } tport->enabled = 1; tport->lport->service_params |= FCP_SPPF_TARG_FCN; @@ -629,8 +628,7 @@ int ft_tgt_enable(struct scst_tgt *tgt, bool enable) ft_tgt_release(tgt); } -out_unlock: - mutex_unlock(&ft_lport_lock); +out: return ret; }