Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit fddc9923 authored by James Smart's avatar James Smart Committed by Jens Axboe
Browse files

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: 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 6b71f9e1
Loading
Loading
Loading
Loading
+38 −64
Original line number Diff line number Diff line
@@ -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;
@@ -630,6 +628,32 @@ fcloop_fcp_abort(struct nvme_fc_local_port *localport,
	schedule_work(&inireq->iniwork);
}

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)
{
@@ -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__);