target: Convert se_portal_group->tpg_lun_list[] to RCU hlist
This patch converts the fixed size se_portal_group->tpg_lun_list[] to use modern RCU with hlist_head in order to support an arbitary number of se_lun ports per target endpoint. It includes dropping core_tpg_alloc_lun() from core_dev_add_lun(), and calling it directly from target_fabric_make_lun() to allocate a new se_lun. And add a new target_fabric_port_release() configfs item callback to invoke kfree_rcu() to release memory during se_lun->lun_group shutdown. Also now that se_node_acl->lun_entry_hlist is using RCU, convert existing tpg_lun_lock to struct mutex so core_tpg_add_node_to_devs() can perform RCU updater logic without releasing ->tpg_lun_mutex. Also, drop core_tpg_clear_object_luns() and it's single consumer in iscsi-target, which is duplicating TPG LUN shutdown logic and is current code results in a NOP. Finally, sbp-target and xen-scsiback fabric driver conversions are included, which are required due to the non-standard way they use ->tpg_lun_hlist. Reviewed-by: Hannes Reinecke <hare@suse.de> Cc: Christoph Hellwig <hch@lst.de> Cc: Sagi Grimberg <sagig@mellanox.com> Cc: Paul E. McKenney <paulmck@linux.vnet.ibm.com> Cc: Chris Boot <bootc@bootc.net> Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
This commit is contained in:
@@ -866,7 +866,8 @@ static int scsiback_add_translation_entry(struct vscsibk_info *info,
|
||||
struct list_head *head = &(info->v2p_entry_lists);
|
||||
unsigned long flags;
|
||||
char *lunp;
|
||||
unsigned int lun;
|
||||
unsigned int unpacked_lun;
|
||||
struct se_lun *se_lun;
|
||||
struct scsiback_tpg *tpg_entry, *tpg = NULL;
|
||||
char *error = "doesn't exist";
|
||||
|
||||
@@ -877,7 +878,7 @@ static int scsiback_add_translation_entry(struct vscsibk_info *info,
|
||||
}
|
||||
*lunp = 0;
|
||||
lunp++;
|
||||
if (kstrtouint(lunp, 10, &lun) || lun >= TRANSPORT_MAX_LUNS_PER_TPG) {
|
||||
if (kstrtouint(lunp, 10, &unpacked_lun) || unpacked_lun >= TRANSPORT_MAX_LUNS_PER_TPG) {
|
||||
pr_err("lun number not valid: %s\n", lunp);
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -886,15 +887,17 @@ static int scsiback_add_translation_entry(struct vscsibk_info *info,
|
||||
list_for_each_entry(tpg_entry, &scsiback_list, tv_tpg_list) {
|
||||
if (!strcmp(phy, tpg_entry->tport->tport_name) ||
|
||||
!strcmp(phy, tpg_entry->param_alias)) {
|
||||
spin_lock(&tpg_entry->se_tpg.tpg_lun_lock);
|
||||
if (tpg_entry->se_tpg.tpg_lun_list[lun]->lun_status ==
|
||||
TRANSPORT_LUN_STATUS_ACTIVE) {
|
||||
if (!tpg_entry->tpg_nexus)
|
||||
error = "nexus undefined";
|
||||
else
|
||||
tpg = tpg_entry;
|
||||
mutex_lock(&tpg_entry->se_tpg.tpg_lun_mutex);
|
||||
hlist_for_each_entry(se_lun, &tpg_entry->se_tpg.tpg_lun_hlist, link) {
|
||||
if (se_lun->unpacked_lun == unpacked_lun) {
|
||||
if (!tpg_entry->tpg_nexus)
|
||||
error = "nexus undefined";
|
||||
else
|
||||
tpg = tpg_entry;
|
||||
break;
|
||||
}
|
||||
}
|
||||
spin_unlock(&tpg_entry->se_tpg.tpg_lun_lock);
|
||||
mutex_unlock(&tpg_entry->se_tpg.tpg_lun_mutex);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -906,7 +909,7 @@ static int scsiback_add_translation_entry(struct vscsibk_info *info,
|
||||
mutex_unlock(&scsiback_mutex);
|
||||
|
||||
if (!tpg) {
|
||||
pr_err("%s:%d %s\n", phy, lun, error);
|
||||
pr_err("%s:%d %s\n", phy, unpacked_lun, error);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
@@ -934,7 +937,7 @@ static int scsiback_add_translation_entry(struct vscsibk_info *info,
|
||||
kref_init(&new->kref);
|
||||
new->v = *v;
|
||||
new->tpg = tpg;
|
||||
new->lun = lun;
|
||||
new->lun = unpacked_lun;
|
||||
list_add_tail(&new->l, head);
|
||||
|
||||
out:
|
||||
|
Reference in New Issue
Block a user