From: Nicholas Bellinger <nab@xxxxxxxxxxxxxxx> Convert core_tpg_del_initiator_node_acl() to use target_put_session() kref counting, and add se_node_acl->acl_free_comp to wait for outstanding fabric session shutdown to complete in transport_deregister_session() before finishing configfs NodeACL release. Cc: Roland Dreier <roland@xxxxxxxxxxxxxxx> Cc: Christoph Hellwig <hch@xxxxxx> Cc: Andy Grover <agrover@xxxxxxxxxx> Signed-off-by: Nicholas Bellinger <nab@xxxxxxxxxxxxxxx> --- drivers/target/target_core_tpg.c | 23 ++++++++++++----------- drivers/target/target_core_transport.c | 6 ++++++ include/target/target_core_base.h | 1 + 3 files changed, 19 insertions(+), 11 deletions(-) diff --git a/drivers/target/target_core_tpg.c b/drivers/target/target_core_tpg.c index 3215340..a3ece61 100644 --- a/drivers/target/target_core_tpg.c +++ b/drivers/target/target_core_tpg.c @@ -274,6 +274,7 @@ struct se_node_acl *core_tpg_check_initiator_node_acl( INIT_LIST_HEAD(&acl->acl_list); INIT_LIST_HEAD(&acl->acl_sess_list); + init_completion(&acl->acl_free_comp); spin_lock_init(&acl->device_list_lock); spin_lock_init(&acl->nacl_sess_lock); atomic_set(&acl->acl_pr_ref_count, 0); @@ -402,6 +403,7 @@ struct se_node_acl *core_tpg_add_initiator_node_acl( INIT_LIST_HEAD(&acl->acl_list); INIT_LIST_HEAD(&acl->acl_sess_list); + init_completion(&acl->acl_free_comp); spin_lock_init(&acl->device_list_lock); spin_lock_init(&acl->nacl_sess_lock); atomic_set(&acl->acl_pr_ref_count, 0); @@ -450,7 +452,7 @@ int core_tpg_del_initiator_node_acl( { struct se_session *sess, *sess_tmp; unsigned long flags; - int dynamic_acl = 0; + int dynamic_acl = 0, rc; spin_lock_irq(&tpg->acl_node_lock); if (acl->dynamic_node_acl) { @@ -466,18 +468,17 @@ int core_tpg_del_initiator_node_acl( &tpg->tpg_sess_list, sess_list) { if (sess->se_node_acl != acl) continue; - /* - * Determine if the session needs to be closed by our context. - */ - if (!tpg->se_tpg_tfo->shutdown_session(sess)) - continue; + kref_get(&sess->sess_kref); spin_unlock_irqrestore(&tpg->session_lock, flags); - /* - * If the $FABRIC_MOD session for the Initiator Node ACL exists, - * forcefully shutdown the $FABRIC_MOD session/nexus. - */ - tpg->se_tpg_tfo->close_session(sess); + + rc = tpg->se_tpg_tfo->shutdown_session(sess); + target_put_session(sess); + if (!rc) + continue; + target_put_session(sess); + /* Wait for fabric session shutdown to complete.. */ + wait_for_completion(&acl->acl_free_comp); spin_lock_irqsave(&tpg->session_lock, flags); } diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index 751c527..ce36360 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -414,6 +414,12 @@ void transport_deregister_session(struct se_session *se_sess) pr_debug("TARGET_CORE[%s]: Deregistered fabric_sess\n", se_tpg->se_tpg_tfo->get_fabric_name()); + /* + * Awake sleeping ->acl_free_comp caller from configfs se_node_acl + * removal context + */ + if (comp_nacl) + complete(&se_nacl->acl_free_comp); } EXPORT_SYMBOL(transport_deregister_session); diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h index 6470901..9bb1c0f 100644 --- a/include/target/target_core_base.h +++ b/include/target/target_core_base.h @@ -642,6 +642,7 @@ struct se_node_acl { struct config_group *acl_default_groups[5]; struct list_head acl_list; struct list_head acl_sess_list; + struct completion acl_free_comp; }; struct se_session { -- 1.7.2.5 -- 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