Commit c5760f30 authored by James Smart's avatar James Smart Committed by Jens Axboe

nvme-fc: fix localport resume using stale values

The localport resume was not updating the lldd ops structure. If the
lldd is unloaded and reloaded, the ops pointers will differ.

Additionally, as there are device references taken by the localport,
ensure that resume only resumes if the device matches as well.
Signed-off-by: default avatarJames Smart <james.smart@broadcom.com>
Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
Signed-off-by: default avatarJens Axboe <axboe@kernel.dk>
parent 84fef62d
...@@ -268,7 +268,9 @@ nvme_fc_lport_get(struct nvme_fc_lport *lport) ...@@ -268,7 +268,9 @@ nvme_fc_lport_get(struct nvme_fc_lport *lport)
static struct nvme_fc_lport * static struct nvme_fc_lport *
nvme_fc_attach_to_unreg_lport(struct nvme_fc_port_info *pinfo) nvme_fc_attach_to_unreg_lport(struct nvme_fc_port_info *pinfo,
struct nvme_fc_port_template *ops,
struct device *dev)
{ {
struct nvme_fc_lport *lport; struct nvme_fc_lport *lport;
unsigned long flags; unsigned long flags;
...@@ -280,6 +282,11 @@ nvme_fc_attach_to_unreg_lport(struct nvme_fc_port_info *pinfo) ...@@ -280,6 +282,11 @@ nvme_fc_attach_to_unreg_lport(struct nvme_fc_port_info *pinfo)
lport->localport.port_name != pinfo->port_name) lport->localport.port_name != pinfo->port_name)
continue; continue;
if (lport->dev != dev) {
lport = ERR_PTR(-EXDEV);
goto out_done;
}
if (lport->localport.port_state != FC_OBJSTATE_DELETED) { if (lport->localport.port_state != FC_OBJSTATE_DELETED) {
lport = ERR_PTR(-EEXIST); lport = ERR_PTR(-EEXIST);
goto out_done; goto out_done;
...@@ -296,6 +303,7 @@ nvme_fc_attach_to_unreg_lport(struct nvme_fc_port_info *pinfo) ...@@ -296,6 +303,7 @@ nvme_fc_attach_to_unreg_lport(struct nvme_fc_port_info *pinfo)
/* resume the lport */ /* resume the lport */
lport->ops = ops;
lport->localport.port_role = pinfo->port_role; lport->localport.port_role = pinfo->port_role;
lport->localport.port_id = pinfo->port_id; lport->localport.port_id = pinfo->port_id;
lport->localport.port_state = FC_OBJSTATE_ONLINE; lport->localport.port_state = FC_OBJSTATE_ONLINE;
...@@ -356,7 +364,7 @@ nvme_fc_register_localport(struct nvme_fc_port_info *pinfo, ...@@ -356,7 +364,7 @@ nvme_fc_register_localport(struct nvme_fc_port_info *pinfo,
* expired, we can simply re-enable the localport. Remoteports * expired, we can simply re-enable the localport. Remoteports
* and controller reconnections should resume naturally. * and controller reconnections should resume naturally.
*/ */
newrec = nvme_fc_attach_to_unreg_lport(pinfo); newrec = nvme_fc_attach_to_unreg_lport(pinfo, template, dev);
/* found an lport, but something about its state is bad */ /* found an lport, but something about its state is bad */
if (IS_ERR(newrec)) { if (IS_ERR(newrec)) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment