nvmet-fc: take tgtport refs for portentry

Ensure that the tgtport is not going away as long portentry has a
pointer on it.

Signed-off-by: Daniel Wagner <wagi@kernel.org>
Reviewed-by: Hannes Reinecke <hare@suse.de>
Signed-off-by: Christoph Hellwig <hch@lst.de>
This commit is contained in:
Daniel Wagner 2025-05-07 14:23:09 +02:00 committed by Christoph Hellwig
parent bbccbf791e
commit 596cba55ad

View File

@ -1257,6 +1257,7 @@ nvmet_fc_portentry_bind(struct nvmet_fc_tgtport *tgtport,
{
lockdep_assert_held(&nvmet_fc_tgtlock);
nvmet_fc_tgtport_get(tgtport);
pe->tgtport = tgtport;
tgtport->pe = pe;
@ -1276,8 +1277,10 @@ nvmet_fc_portentry_unbind(struct nvmet_fc_port_entry *pe)
unsigned long flags;
spin_lock_irqsave(&nvmet_fc_tgtlock, flags);
if (pe->tgtport)
if (pe->tgtport) {
nvmet_fc_tgtport_put(pe->tgtport);
pe->tgtport->pe = NULL;
}
list_del(&pe->pe_list);
spin_unlock_irqrestore(&nvmet_fc_tgtlock, flags);
}
@ -1295,8 +1298,10 @@ nvmet_fc_portentry_unbind_tgt(struct nvmet_fc_tgtport *tgtport)
spin_lock_irqsave(&nvmet_fc_tgtlock, flags);
pe = tgtport->pe;
if (pe)
if (pe) {
nvmet_fc_tgtport_put(pe->tgtport);
pe->tgtport = NULL;
}
tgtport->pe = NULL;
spin_unlock_irqrestore(&nvmet_fc_tgtlock, flags);
}
@ -1319,6 +1324,9 @@ nvmet_fc_portentry_rebind_tgt(struct nvmet_fc_tgtport *tgtport)
list_for_each_entry(pe, &nvmet_fc_portentry_list, pe_list) {
if (tgtport->fc_target_port.node_name == pe->node_name &&
tgtport->fc_target_port.port_name == pe->port_name) {
if (!nvmet_fc_tgtport_get(tgtport))
continue;
WARN_ON(pe->tgtport);
tgtport->pe = pe;
pe->tgtport = tgtport;
@ -2888,12 +2896,17 @@ nvmet_fc_add_port(struct nvmet_port *port)
list_for_each_entry(tgtport, &nvmet_fc_target_list, tgt_list) {
if ((tgtport->fc_target_port.node_name == traddr.nn) &&
(tgtport->fc_target_port.port_name == traddr.pn)) {
if (!nvmet_fc_tgtport_get(tgtport))
continue;
/* a FC port can only be 1 nvmet port id */
if (!tgtport->pe) {
nvmet_fc_portentry_bind(tgtport, pe, port);
ret = 0;
} else
ret = -EALREADY;
nvmet_fc_tgtport_put(tgtport);
break;
}
}
@ -2909,11 +2922,21 @@ static void
nvmet_fc_remove_port(struct nvmet_port *port)
{
struct nvmet_fc_port_entry *pe = port->priv;
struct nvmet_fc_tgtport *tgtport = NULL;
unsigned long flags;
spin_lock_irqsave(&nvmet_fc_tgtlock, flags);
if (pe->tgtport && nvmet_fc_tgtport_get(pe->tgtport))
tgtport = pe->tgtport;
spin_unlock_irqrestore(&nvmet_fc_tgtlock, flags);
nvmet_fc_portentry_unbind(pe);
/* terminate any outstanding associations */
__nvmet_fc_free_assocs(pe->tgtport);
if (tgtport) {
/* terminate any outstanding associations */
__nvmet_fc_free_assocs(tgtport);
nvmet_fc_tgtport_put(tgtport);
}
kfree(pe);
}
@ -2922,10 +2945,21 @@ static void
nvmet_fc_discovery_chg(struct nvmet_port *port)
{
struct nvmet_fc_port_entry *pe = port->priv;
struct nvmet_fc_tgtport *tgtport = pe->tgtport;
struct nvmet_fc_tgtport *tgtport = NULL;
unsigned long flags;
spin_lock_irqsave(&nvmet_fc_tgtlock, flags);
if (pe->tgtport && nvmet_fc_tgtport_get(pe->tgtport))
tgtport = pe->tgtport;
spin_unlock_irqrestore(&nvmet_fc_tgtlock, flags);
if (!tgtport)
return;
if (tgtport && tgtport->ops->discovery_event)
tgtport->ops->discovery_event(&tgtport->fc_target_port);
nvmet_fc_tgtport_put(tgtport);
}
static ssize_t