RELATIVE TARGET PORT IDENTIFIER can be read and configured via configfs: $ echo 0x10 > $TARGET/tpgt_N/attrib/rtpi RTPI can be changed only on disabled target ports. Signed-off-by: Roman Bolshakov <r.bolshakov@xxxxxxxxx> Signed-off-by: Dmitry Bogdanov <d.bogdanov@xxxxxxxxx> --- v2: do not allow to change RTPI on enabled target port --- drivers/target/target_core_tpg.c | 53 ++++++++++++++++++++++++++++++- include/target/target_core_base.h | 1 + 2 files changed, 53 insertions(+), 1 deletion(-) diff --git a/drivers/target/target_core_tpg.c b/drivers/target/target_core_tpg.c index 25ffc3d7a741..09b37ba005ff 100644 --- a/drivers/target/target_core_tpg.c +++ b/drivers/target/target_core_tpg.c @@ -442,8 +442,23 @@ static void core_tpg_lun_ref_release(struct percpu_ref *ref) static int core_tpg_register_rtpi(struct se_portal_group *se_tpg) { - return xa_alloc(&tpg_xa, &se_tpg->tpg_rtpi, se_tpg, + 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, &se_tpg->tpg_rtpi, se_tpg, XA_LIMIT(1, USHRT_MAX), GFP_KERNEL); + } + + return ret; } static void core_tpg_deregister_rtpi(struct se_portal_group *se_tpg) @@ -682,6 +697,42 @@ void core_tpg_remove_lun( percpu_ref_exit(&lun->lun_ref); } +static ssize_t core_tpg_rtpi_show(struct config_item *item, char *page) +{ + struct se_portal_group *se_tpg = attrib_to_tpg(item); + + return sysfs_emit(page, "%#x\n", se_tpg->tpg_rtpi); +} + +static ssize_t core_tpg_rtpi_store(struct config_item *item, + const char *page, size_t count) +{ + struct se_portal_group *se_tpg = attrib_to_tpg(item); + u16 val; + int ret; + + ret = kstrtou16(page, 0, &val); + if (ret < 0) + return ret; + if (val == 0) + return -EINVAL; + + if (se_tpg->enabled) { + pr_info("%s_TPG[%hu] - Can not change RTPI on enabled TPG", + se_tpg->se_tpg_tfo->fabric_name, + se_tpg->se_tpg_tfo->tpg_get_tag(se_tpg)); + return -EINVAL; + } + + se_tpg->tpg_rtpi = val; + se_tpg->rtpi_manual = true; + + return count; +} + +CONFIGFS_ATTR(core_tpg_, rtpi); + struct configfs_attribute *core_tpg_attrib_attrs[] = { + &core_tpg_attr_rtpi, NULL, }; diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h index 83b396457ed1..f2375280d6a4 100644 --- a/include/target/target_core_base.h +++ b/include/target/target_core_base.h @@ -901,6 +901,7 @@ struct se_portal_group { bool enabled; /* RELATIVE TARGET PORT IDENTIFIER */ u32 tpg_rtpi; + bool rtpi_manual; /* Used for PR SPEC_I_PT=1 and REGISTER_AND_MOVE */ atomic_t tpg_pr_ref_count; /* Spinlock for adding/removing ACLed Nodes */ -- 2.25.1