nvmet-fc: simplify nvmet_fc_alloc_hostport

Once a host is already created, avoid allocate additional hostports that
will be thrown away. add an helper function to handle host search.

Reviewed-by: Himanshu Madhani <himanshu.madhani@oracle.com>
Signed-off-by: James Smart <jsmart2021@gmail.com>
Signed-off-by: Amit Engel <amit.engel@dell.com>
Reviewed-by: Chaitanya Kulkarni <chaitanya.kulkarni@wdc.com>
Signed-off-by: Christoph Hellwig <hch@lst.de>
This commit is contained in:
Amit Engel 2021-03-22 21:57:17 +02:00 committed by Christoph Hellwig
parent bdaf132791
commit 0d8ddeea11

View file

@ -1020,61 +1020,76 @@ nvmet_fc_free_hostport(struct nvmet_fc_hostport *hostport)
nvmet_fc_hostport_put(hostport);
}
static struct nvmet_fc_hostport *
nvmet_fc_match_hostport(struct nvmet_fc_tgtport *tgtport, void *hosthandle)
{
struct nvmet_fc_hostport *host;
lockdep_assert_held(&tgtport->lock);
list_for_each_entry(host, &tgtport->host_list, host_list) {
if (host->hosthandle == hosthandle && !host->invalid) {
if (nvmet_fc_hostport_get(host))
return (host);
}
}
return NULL;
}
static struct nvmet_fc_hostport *
nvmet_fc_alloc_hostport(struct nvmet_fc_tgtport *tgtport, void *hosthandle)
{
struct nvmet_fc_hostport *newhost, *host, *match = NULL;
struct nvmet_fc_hostport *newhost, *match = NULL;
unsigned long flags;
/* if LLDD not implemented, leave as NULL */
if (!hosthandle)
return NULL;
/* take reference for what will be the newly allocated hostport */
/*
* take reference for what will be the newly allocated hostport if
* we end up using a new allocation
*/
if (!nvmet_fc_tgtport_get(tgtport))
return ERR_PTR(-EINVAL);
newhost = kzalloc(sizeof(*newhost), GFP_KERNEL);
if (!newhost) {
spin_lock_irqsave(&tgtport->lock, flags);
list_for_each_entry(host, &tgtport->host_list, host_list) {
if (host->hosthandle == hosthandle && !host->invalid) {
if (nvmet_fc_hostport_get(host)) {
match = host;
break;
}
}
}
spin_unlock_irqrestore(&tgtport->lock, flags);
/* no allocation - release reference */
nvmet_fc_tgtport_put(tgtport);
return (match) ? match : ERR_PTR(-ENOMEM);
}
newhost->tgtport = tgtport;
newhost->hosthandle = hosthandle;
INIT_LIST_HEAD(&newhost->host_list);
kref_init(&newhost->ref);
spin_lock_irqsave(&tgtport->lock, flags);
list_for_each_entry(host, &tgtport->host_list, host_list) {
if (host->hosthandle == hosthandle && !host->invalid) {
if (nvmet_fc_hostport_get(host)) {
match = host;
break;
}
}
}
if (match) {
kfree(newhost);
newhost = NULL;
/* releasing allocation - release reference */
nvmet_fc_tgtport_put(tgtport);
} else
list_add_tail(&newhost->host_list, &tgtport->host_list);
match = nvmet_fc_match_hostport(tgtport, hosthandle);
spin_unlock_irqrestore(&tgtport->lock, flags);
return (match) ? match : newhost;
if (match) {
/* no new allocation - release reference */
nvmet_fc_tgtport_put(tgtport);
return match;
}
newhost = kzalloc(sizeof(*newhost), GFP_KERNEL);
if (!newhost) {
/* no new allocation - release reference */
nvmet_fc_tgtport_put(tgtport);
return ERR_PTR(-ENOMEM);
}
spin_lock_irqsave(&tgtport->lock, flags);
match = nvmet_fc_match_hostport(tgtport, hosthandle);
if (match) {
/* new allocation not needed */
kfree(newhost);
newhost = match;
/* no new allocation - release reference */
nvmet_fc_tgtport_put(tgtport);
} else {
newhost->tgtport = tgtport;
newhost->hosthandle = hosthandle;
INIT_LIST_HEAD(&newhost->host_list);
kref_init(&newhost->ref);
list_add_tail(&newhost->host_list, &tgtport->host_list);
}
spin_unlock_irqrestore(&tgtport->lock, flags);
return newhost;
}
static void