summaryrefslogtreecommitdiff
path: root/drivers/nvme
diff options
context:
space:
mode:
authorJames Smart <jsmart2021@gmail.com>2017-09-20 00:01:50 +0300
committerJens Axboe <axboe@kernel.dk>2017-09-25 21:42:11 +0300
commitfddc9923c6d41de9fe7b1f323a3cece53e046c88 (patch)
tree2eb7c2776d6779e8f98e66144a0a3040bbf43187 /drivers/nvme
parent6b71f9e1e849f82abb4a8d54ce7f4b1c71f19ac4 (diff)
downloadlinux-fddc9923c6d41de9fe7b1f323a3cece53e046c88.tar.xz
nvme-fcloop: fix port deletes and callbacks
Now that there are potentially long delays between when a remoteport or targetport delete calls is made and when the callback occurs (dev_loss_tmo timeout), no longer block in the delete routines and move the final nport puts to the callbacks. Moved the fcloop_nport_get/put/free routines to avoid forward declarations. Ensure port_info structs used in registrations are nulled in case fields are not set (ex: devloss_tmo values). Signed-off-by: James Smart <james.smart@broadcom.com> Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Jens Axboe <axboe@kernel.dk>
Diffstat (limited to 'drivers/nvme')
-rw-r--r--drivers/nvme/target/fcloop.c102
1 files changed, 38 insertions, 64 deletions
diff --git a/drivers/nvme/target/fcloop.c b/drivers/nvme/target/fcloop.c
index 1fd1afbb8b2a..7b75d9de55ab 100644
--- a/drivers/nvme/target/fcloop.c
+++ b/drivers/nvme/target/fcloop.c
@@ -224,8 +224,6 @@ struct fcloop_nport {
struct fcloop_lport *lport;
struct list_head nport_list;
struct kref ref;
- struct completion rport_unreg_done;
- struct completion tport_unreg_done;
u64 node_name;
u64 port_name;
u32 port_role;
@@ -631,6 +629,32 @@ fcloop_fcp_abort(struct nvme_fc_local_port *localport,
}
static void
+fcloop_nport_free(struct kref *ref)
+{
+ struct fcloop_nport *nport =
+ container_of(ref, struct fcloop_nport, ref);
+ unsigned long flags;
+
+ spin_lock_irqsave(&fcloop_lock, flags);
+ list_del(&nport->nport_list);
+ spin_unlock_irqrestore(&fcloop_lock, flags);
+
+ kfree(nport);
+}
+
+static void
+fcloop_nport_put(struct fcloop_nport *nport)
+{
+ kref_put(&nport->ref, fcloop_nport_free);
+}
+
+static int
+fcloop_nport_get(struct fcloop_nport *nport)
+{
+ return kref_get_unless_zero(&nport->ref);
+}
+
+static void
fcloop_localport_delete(struct nvme_fc_local_port *localport)
{
struct fcloop_lport *lport = localport->private;
@@ -644,8 +668,7 @@ fcloop_remoteport_delete(struct nvme_fc_remote_port *remoteport)
{
struct fcloop_rport *rport = remoteport->private;
- /* release any threads waiting for the unreg to complete */
- complete(&rport->nport->rport_unreg_done);
+ fcloop_nport_put(rport->nport);
}
static void
@@ -653,8 +676,7 @@ fcloop_targetport_delete(struct nvmet_fc_target_port *targetport)
{
struct fcloop_tport *tport = targetport->private;
- /* release any threads waiting for the unreg to complete */
- complete(&tport->nport->tport_unreg_done);
+ fcloop_nport_put(tport->nport);
}
#define FCLOOP_HW_QUEUES 4
@@ -722,6 +744,7 @@ fcloop_create_local_port(struct device *dev, struct device_attribute *attr,
goto out_free_opts;
}
+ memset(&pinfo, 0, sizeof(pinfo));
pinfo.node_name = opts->wwnn;
pinfo.port_name = opts->wwpn;
pinfo.port_role = opts->roles;
@@ -804,32 +827,6 @@ fcloop_delete_local_port(struct device *dev, struct device_attribute *attr,
return ret ? ret : count;
}
-static void
-fcloop_nport_free(struct kref *ref)
-{
- struct fcloop_nport *nport =
- container_of(ref, struct fcloop_nport, ref);
- unsigned long flags;
-
- spin_lock_irqsave(&fcloop_lock, flags);
- list_del(&nport->nport_list);
- spin_unlock_irqrestore(&fcloop_lock, flags);
-
- kfree(nport);
-}
-
-static void
-fcloop_nport_put(struct fcloop_nport *nport)
-{
- kref_put(&nport->ref, fcloop_nport_free);
-}
-
-static int
-fcloop_nport_get(struct fcloop_nport *nport)
-{
- return kref_get_unless_zero(&nport->ref);
-}
-
static struct fcloop_nport *
fcloop_alloc_nport(const char *buf, size_t count, bool remoteport)
{
@@ -938,6 +935,7 @@ fcloop_create_remote_port(struct device *dev, struct device_attribute *attr,
if (!nport)
return -EIO;
+ memset(&pinfo, 0, sizeof(pinfo));
pinfo.node_name = nport->node_name;
pinfo.port_name = nport->port_name;
pinfo.port_role = nport->port_role;
@@ -979,24 +977,12 @@ __unlink_remote_port(struct fcloop_nport *nport)
}
static int
-__wait_remoteport_unreg(struct fcloop_nport *nport, struct fcloop_rport *rport)
+__remoteport_unreg(struct fcloop_nport *nport, struct fcloop_rport *rport)
{
- int ret;
-
if (!rport)
return -EALREADY;
- init_completion(&nport->rport_unreg_done);
-
- ret = nvme_fc_unregister_remoteport(rport->remoteport);
- if (ret)
- return ret;
-
- wait_for_completion(&nport->rport_unreg_done);
-
- fcloop_nport_put(nport);
-
- return ret;
+ return nvme_fc_unregister_remoteport(rport->remoteport);
}
static ssize_t
@@ -1029,7 +1015,7 @@ fcloop_delete_remote_port(struct device *dev, struct device_attribute *attr,
if (!nport)
return -ENOENT;
- ret = __wait_remoteport_unreg(nport, rport);
+ ret = __remoteport_unreg(nport, rport);
return ret ? ret : count;
}
@@ -1086,24 +1072,12 @@ __unlink_target_port(struct fcloop_nport *nport)
}
static int
-__wait_targetport_unreg(struct fcloop_nport *nport, struct fcloop_tport *tport)
+__targetport_unreg(struct fcloop_nport *nport, struct fcloop_tport *tport)
{
- int ret;
-
if (!tport)
return -EALREADY;
- init_completion(&nport->tport_unreg_done);
-
- ret = nvmet_fc_unregister_targetport(tport->targetport);
- if (ret)
- return ret;
-
- wait_for_completion(&nport->tport_unreg_done);
-
- fcloop_nport_put(nport);
-
- return ret;
+ return nvmet_fc_unregister_targetport(tport->targetport);
}
static ssize_t
@@ -1136,7 +1110,7 @@ fcloop_delete_target_port(struct device *dev, struct device_attribute *attr,
if (!nport)
return -ENOENT;
- ret = __wait_targetport_unreg(nport, tport);
+ ret = __targetport_unreg(nport, tport);
return ret ? ret : count;
}
@@ -1223,11 +1197,11 @@ static void __exit fcloop_exit(void)
spin_unlock_irqrestore(&fcloop_lock, flags);
- ret = __wait_targetport_unreg(nport, tport);
+ ret = __targetport_unreg(nport, tport);
if (ret)
pr_warn("%s: Failed deleting target port\n", __func__);
- ret = __wait_remoteport_unreg(nport, rport);
+ ret = __remoteport_unreg(nport, rport);
if (ret)
pr_warn("%s: Failed deleting remote port\n", __func__);