This patch avoids that the following kernel crash can occur with synchronous TMF handling: general protection fault: 0000 [#1] SMP CPU: 0 PID: 6 Comm: kworker/u8:0 Not tainted 4.3.0-rc1-debug+ #1 Workqueue: tmr-fileio target_tmr_work [target_core_mod] Call Trace: [<ffffffff810a6915>] lock_acquire+0x65/0x90 [<ffffffff815e740b>] _raw_spin_lock_irqsave+0x4b/0x60 [<ffffffffa03bc7ca>] target_release_cmd_kref+0x2a/0xa0 [target_core_mod] [<ffffffffa03bd418>] target_put_sess_cmd+0x28/0x50 [target_core_mod] [<ffffffffa03bad50>] core_tmr_lun_reset+0x390/0x640 [target_core_mod] [<ffffffffa03bce50>] target_tmr_work+0x80/0xd0 [target_core_mod] [<ffffffff81070e6d>] process_one_work+0x19d/0x430 [<ffffffff8107120f>] worker_thread+0x10f/0x460 [<ffffffff810772ba>] kthread+0xea/0x100 [<ffffffff815e7a2f>] ret_from_fork+0x3f/0x70 Signed-off-by: Bart Van Assche <bart.vanassche@xxxxxxxxxxx> Cc: Christoph Hellwig <hch@xxxxxx> Cc: Hannes Reinecke <hare@xxxxxxx> Cc: Andy Grover <agrover@xxxxxxxxxx> Cc: Sagi Grimberg <sagig@xxxxxxxxxxxx> --- drivers/target/target_core_transport.c | 10 ++++++++++ include/target/target_core_base.h | 1 + 2 files changed, 11 insertions(+) diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index 7f4d3ac..e9bf495 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -239,6 +239,7 @@ struct se_session *transport_init_session(enum target_prot_op sup_prot_ops) INIT_LIST_HEAD(&se_sess->sess_cmd_list); INIT_LIST_HEAD(&se_sess->sess_wait_list); spin_lock_init(&se_sess->sess_cmd_lock); + init_waitqueue_head(&se_sess->cmd_list_wq); kref_init(&se_sess->sess_kref); se_sess->sup_prot_ops = sup_prot_ops; @@ -464,6 +465,13 @@ EXPORT_SYMBOL(transport_deregister_session_configfs); void transport_free_session(struct se_session *se_sess) { + spin_lock_irq(&se_sess->sess_cmd_lock); + while (wait_event_interruptible_lock_irq(se_sess->cmd_list_wq, + list_empty(&se_sess->sess_cmd_list), + se_sess->sess_cmd_lock) < 0) + ; + spin_unlock_irq(&se_sess->sess_cmd_lock); + if (se_sess->sess_cmd_map) { percpu_ida_destroy(&se_sess->sess_tag_pool); kvfree(se_sess->sess_cmd_map); @@ -2524,6 +2532,8 @@ static void target_release_cmd_kref(struct kref *kref) return; } list_del(&se_cmd->se_cmd_list); + if (list_empty(&se_cmd->se_cmd_list)) + wake_up(&se_sess->cmd_list_wq); spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags); se_cmd->se_tfo->release_cmd(se_cmd); diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h index 8b9c727..229c1c2 100644 --- a/include/target/target_core_base.h +++ b/include/target/target_core_base.h @@ -606,6 +606,7 @@ struct se_session { struct list_head sess_cmd_list; struct list_head sess_wait_list; spinlock_t sess_cmd_lock; + wait_queue_head_t cmd_list_wq; struct kref sess_kref; void *sess_cmd_map; struct percpu_ida sess_tag_pool; -- 2.1.4 -- To unsubscribe from this list: send the line "unsubscribe target-devel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html