From: Bart Van Assche Date: Thu, 22 Oct 2015 22:57:04 +0000 (-0700) Subject: target: Invoke release_cmd() callback without holding a spinlock X-Git-Tag: v4.1.12-124.31.3~723 X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=d4f415a2de444592833a75dea6b7e2942310bc18;p=users%2Fjedix%2Flinux-maple.git target: Invoke release_cmd() callback without holding a spinlock This patch fixes the following kernel warning because it avoids that IRQs are disabled while ft_release_cmd() is invoked (fc_seq_set_resp() invokes spin_unlock_bh()): WARNING: CPU: 3 PID: 117 at kernel/softirq.c:150 __local_bh_enable_ip+0xaa/0x110() Call Trace: [] dump_stack+0x4f/0x7b [] warn_slowpath_common+0x8a/0xc0 [] warn_slowpath_null+0x1a/0x20 [] __local_bh_enable_ip+0xaa/0x110 [] _raw_spin_unlock_bh+0x39/0x40 [] fc_seq_set_resp+0xe4/0x100 [libfc] [] ft_free_cmd+0x4a/0x90 [tcm_fc] [] ft_release_cmd+0x12/0x20 [tcm_fc] [] target_release_cmd_kref+0x56/0x90 [target_core_mod] [] target_put_sess_cmd+0xc0/0x110 [target_core_mod] [] transport_release_cmd+0x41/0x70 [target_core_mod] [] transport_generic_free_cmd+0x35/0x420 [target_core_mod] Signed-off-by: Bart Van Assche Acked-by: Joern Engel Reviewed-by: Andy Grover Cc: Christoph Hellwig Cc: Hannes Reinecke Cc: Sagi Grimberg Signed-off-by: Nicholas Bellinger Orabug: 27781132 (backport upstream commit 9ff9d15eddd13ecdd41876c5e1f31ddbb127101c) Signed-off-by: Brian Maly Conflicts: drivers/target/target_core_tmr.c Signed-off-by: Shan Hai Reviewed-by: Jack Vogel Signed-off-by: Brian Maly --- diff --git a/drivers/target/target_core_tmr.c b/drivers/target/target_core_tmr.c index adb8016955c49..a2932044e4a53 100644 --- a/drivers/target/target_core_tmr.c +++ b/drivers/target/target_core_tmr.c @@ -133,6 +133,9 @@ void core_tmr_abort_task( if (tmr->ref_task_tag != ref_tag) continue; + if (!kref_get_unless_zero(&se_cmd->cmd_kref)) + continue; + printk("ABORT_TASK: Found referenced %s task_tag: %u\n", se_cmd->se_tfo->get_fabric_name(), ref_tag); @@ -141,13 +144,15 @@ void core_tmr_abort_task( printk("ABORT_TASK: ref_tag: %u already complete, skipping\n", ref_tag); spin_unlock(&se_cmd->t_state_lock); spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags); + + target_put_sess_cmd(se_cmd); + goto out; } se_cmd->transport_state |= CMD_T_ABORTED; spin_unlock(&se_cmd->t_state_lock); list_del_init(&se_cmd->se_cmd_list); - kref_get(&se_cmd->cmd_kref); spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags); cancel_work_sync(&se_cmd->work); diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index d1a022ff74c13..5f06a205753e1 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -2505,23 +2505,24 @@ out: EXPORT_SYMBOL(target_get_sess_cmd); static void target_release_cmd_kref(struct kref *kref) - __releases(&se_cmd->se_sess->sess_cmd_lock) { struct se_cmd *se_cmd = container_of(kref, struct se_cmd, cmd_kref); struct se_session *se_sess = se_cmd->se_sess; + unsigned long flags; + spin_lock_irqsave(&se_sess->sess_cmd_lock, flags); if (list_empty(&se_cmd->se_cmd_list)) { - spin_unlock(&se_sess->sess_cmd_lock); + spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags); se_cmd->se_tfo->release_cmd(se_cmd); return; } if (se_sess->sess_tearing_down && se_cmd->cmd_wait_set) { - spin_unlock(&se_sess->sess_cmd_lock); + spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags); complete(&se_cmd->cmd_wait_comp); return; } list_del(&se_cmd->se_cmd_list); - spin_unlock(&se_sess->sess_cmd_lock); + spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags); se_cmd->se_tfo->release_cmd(se_cmd); } @@ -2537,8 +2538,7 @@ int target_put_sess_cmd(struct se_cmd *se_cmd) se_cmd->se_tfo->release_cmd(se_cmd); return 1; } - return kref_put_spinlock_irqsave(&se_cmd->cmd_kref, target_release_cmd_kref, - &se_sess->sess_cmd_lock); + return kref_put(&se_cmd->cmd_kref, target_release_cmd_kref); } EXPORT_SYMBOL(target_put_sess_cmd);