[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20250318-nvmet-fcloop-v3-9-05fec0fc02f6@kernel.org>
Date: Tue, 18 Mar 2025 11:40:03 +0100
From: Daniel Wagner <wagi@...nel.org>
To: James Smart <james.smart@...adcom.com>, Christoph Hellwig <hch@....de>,
Sagi Grimberg <sagi@...mberg.me>, Chaitanya Kulkarni <kch@...dia.com>
Cc: Hannes Reinecke <hare@...e.de>, Keith Busch <kbusch@...nel.org>,
linux-nvme@...ts.infradead.org, linux-kernel@...r.kernel.org,
Daniel Wagner <wagi@...nel.org>
Subject: [PATCH v3 09/18] nvmet-fcloop: prevent double port deletion
The delete callback can be called either via the unregister function or
from the transport directly. Thus it is necessary ensure resources are
not freed multiple times.
Signed-off-by: Daniel Wagner <wagi@...nel.org>
---
drivers/nvme/target/fcloop.c | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
diff --git a/drivers/nvme/target/fcloop.c b/drivers/nvme/target/fcloop.c
index de23f0bc5599b6f8dd5c3713dd38c952e6fdda28..06f42da6a0335c53ae319133119d057aab12e07e 100644
--- a/drivers/nvme/target/fcloop.c
+++ b/drivers/nvme/target/fcloop.c
@@ -215,6 +215,8 @@ struct fcloop_lport_priv {
struct fcloop_lport *lport;
};
+#define PORT_DELETE 0
+
struct fcloop_rport {
struct nvme_fc_remote_port *remoteport;
struct nvmet_fc_target_port *targetport;
@@ -223,6 +225,7 @@ struct fcloop_rport {
spinlock_t lock;
struct list_head ls_list;
struct work_struct ls_work;
+ unsigned long flags;
};
struct fcloop_tport {
@@ -233,6 +236,7 @@ struct fcloop_tport {
spinlock_t lock;
struct list_head ls_list;
struct work_struct ls_work;
+ unsigned long flags;
};
struct fcloop_nport {
@@ -1062,14 +1066,20 @@ static void
fcloop_remoteport_delete(struct nvme_fc_remote_port *remoteport)
{
struct fcloop_rport *rport = remoteport->private;
+ bool delete_port = true;
unsigned long flags;
flush_work(&rport->ls_work);
spin_lock_irqsave(&fcloop_lock, flags);
+ if (test_and_set_bit(PORT_DELETE, &rport->flags))
+ delete_port = false;
rport->nport->rport = NULL;
spin_unlock_irqrestore(&fcloop_lock, flags);
+ if (!delete_port)
+ return;
+
/* nport ref put: rport */
fcloop_nport_put(rport->nport);
}
@@ -1078,14 +1088,20 @@ static void
fcloop_targetport_delete(struct nvmet_fc_target_port *targetport)
{
struct fcloop_tport *tport = targetport->private;
+ bool delete_port = true;
unsigned long flags;
flush_work(&tport->ls_work);
spin_lock_irqsave(&fcloop_lock, flags);
+ if (test_and_set_bit(PORT_DELETE, &tport->flags))
+ delete_port = false;
tport->nport->tport = NULL;
spin_unlock_irqrestore(&fcloop_lock, flags);
+ if (!delete_port)
+ return;
+
complete(&tport->nport->tport_unreg_done);
/* nport ref put: tport */
@@ -1394,6 +1410,7 @@ fcloop_create_remote_port(struct device *dev, struct device_attribute *attr,
rport->nport = nport;
rport->lport = nport->lport;
nport->rport = rport;
+ rport->flags = 0;
spin_lock_init(&rport->lock);
INIT_WORK(&rport->ls_work, fcloop_rport_lsrqst_work);
INIT_LIST_HEAD(&rport->ls_list);
@@ -1492,6 +1509,7 @@ fcloop_create_target_port(struct device *dev, struct device_attribute *attr,
tport->nport = nport;
tport->lport = nport->lport;
nport->tport = tport;
+ tport->flags = 0;
spin_lock_init(&tport->lock);
INIT_WORK(&tport->ls_work, fcloop_tport_lsrqst_work);
INIT_LIST_HEAD(&tport->ls_list);
--
2.48.1
Powered by blists - more mailing lists