diff options
Diffstat (limited to 'drivers/target/target_core_tpg.c')
-rw-r--r-- | drivers/target/target_core_tpg.c | 73 |
1 files changed, 66 insertions, 7 deletions
diff --git a/drivers/target/target_core_tpg.c b/drivers/target/target_core_tpg.c index 736847c933e5..c0e429e5ef31 100644 --- a/drivers/target/target_core_tpg.c +++ b/drivers/target/target_core_tpg.c @@ -31,6 +31,7 @@ #include "target_core_ua.h" extern struct se_device *g_lun0_dev; +static DEFINE_XARRAY_ALLOC(tpg_xa); /* __core_tpg_get_initiator_node_acl(): * @@ -328,7 +329,7 @@ static void target_shutdown_sessions(struct se_node_acl *acl) restart: spin_lock_irqsave(&acl->nacl_sess_lock, flags); list_for_each_entry(sess, &acl->acl_sess_list, sess_acl_list) { - if (atomic_read(&sess->stopped)) + if (sess->cmd_cnt && atomic_read(&sess->cmd_cnt->stopped)) continue; list_del_init(&sess->sess_acl_list); @@ -439,6 +440,68 @@ static void core_tpg_lun_ref_release(struct percpu_ref *ref) complete(&lun->lun_shutdown_comp); } +static int target_tpg_register_rtpi(struct se_portal_group *se_tpg) +{ + u32 val; + int ret; + + if (se_tpg->rtpi_manual) { + ret = xa_insert(&tpg_xa, se_tpg->tpg_rtpi, se_tpg, GFP_KERNEL); + if (ret) { + pr_info("%s_TPG[%hu] - Can not set RTPI %#x, it is already busy", + se_tpg->se_tpg_tfo->fabric_name, + se_tpg->se_tpg_tfo->tpg_get_tag(se_tpg), + se_tpg->tpg_rtpi); + return -EINVAL; + } + } else { + ret = xa_alloc(&tpg_xa, &val, se_tpg, + XA_LIMIT(1, USHRT_MAX), GFP_KERNEL); + if (!ret) + se_tpg->tpg_rtpi = val; + } + + return ret; +} + +static void target_tpg_deregister_rtpi(struct se_portal_group *se_tpg) +{ + if (se_tpg->tpg_rtpi && se_tpg->enabled) + xa_erase(&tpg_xa, se_tpg->tpg_rtpi); +} + +int target_tpg_enable(struct se_portal_group *se_tpg) +{ + int ret; + + ret = target_tpg_register_rtpi(se_tpg); + if (ret) + return ret; + + ret = se_tpg->se_tpg_tfo->fabric_enable_tpg(se_tpg, true); + if (ret) { + target_tpg_deregister_rtpi(se_tpg); + return ret; + } + + se_tpg->enabled = true; + + return 0; +} + +int target_tpg_disable(struct se_portal_group *se_tpg) +{ + int ret; + + target_tpg_deregister_rtpi(se_tpg); + + ret = se_tpg->se_tpg_tfo->fabric_enable_tpg(se_tpg, false); + if (!ret) + se_tpg->enabled = false; + + return ret; +} + /* Does not change se_wwn->priv. */ int core_tpg_register( struct se_wwn *se_wwn, @@ -535,6 +598,8 @@ int core_tpg_deregister(struct se_portal_group *se_tpg) kfree_rcu(se_tpg->tpg_virt_lun0, rcu_head); } + target_tpg_deregister_rtpi(se_tpg); + return 0; } EXPORT_SYMBOL(core_tpg_deregister); @@ -578,10 +643,6 @@ int core_tpg_add_lun( if (ret < 0) goto out; - ret = core_alloc_rtpi(lun, dev); - if (ret) - goto out_kill_ref; - if (!(dev->transport_flags & TRANSPORT_FLAG_PASSTHROUGH_ALUA) && !(dev->se_hba->hba_flags & HBA_FLAGS_INTERNAL_USE)) target_attach_tg_pt_gp(lun, dev->t10_alua.default_tg_pt_gp); @@ -605,8 +666,6 @@ int core_tpg_add_lun( return 0; -out_kill_ref: - percpu_ref_exit(&lun->lun_ref); out: return ret; } |