mirror of
https://github.com/torvalds/linux.git
synced 2026-05-27 00:22:00 +02:00
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@kernel.org> Signed-off-by: Christoph Hellwig <hch@lst.de>
This commit is contained in:
parent
47a827cd79
commit
2b559a3eb5
|
|
@ -215,6 +215,9 @@ struct fcloop_lport_priv {
|
|||
struct fcloop_lport *lport;
|
||||
};
|
||||
|
||||
/* The port is already being removed, avoid double free */
|
||||
#define PORT_DELETED 0
|
||||
|
||||
struct fcloop_rport {
|
||||
struct nvme_fc_remote_port *remoteport;
|
||||
struct nvmet_fc_target_port *targetport;
|
||||
|
|
@ -223,6 +226,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 +237,7 @@ struct fcloop_tport {
|
|||
spinlock_t lock;
|
||||
struct list_head ls_list;
|
||||
struct work_struct ls_work;
|
||||
unsigned long flags;
|
||||
};
|
||||
|
||||
struct fcloop_nport {
|
||||
|
|
@ -1061,30 +1066,38 @@ static void
|
|||
fcloop_remoteport_delete(struct nvme_fc_remote_port *remoteport)
|
||||
{
|
||||
struct fcloop_rport *rport = remoteport->private;
|
||||
bool put_port = false;
|
||||
unsigned long flags;
|
||||
|
||||
flush_work(&rport->ls_work);
|
||||
|
||||
spin_lock_irqsave(&fcloop_lock, flags);
|
||||
if (!test_and_set_bit(PORT_DELETED, &rport->flags))
|
||||
put_port = true;
|
||||
rport->nport->rport = NULL;
|
||||
spin_unlock_irqrestore(&fcloop_lock, flags);
|
||||
|
||||
fcloop_nport_put(rport->nport);
|
||||
if (put_port)
|
||||
fcloop_nport_put(rport->nport);
|
||||
}
|
||||
|
||||
static void
|
||||
fcloop_targetport_delete(struct nvmet_fc_target_port *targetport)
|
||||
{
|
||||
struct fcloop_tport *tport = targetport->private;
|
||||
bool put_port = false;
|
||||
unsigned long flags;
|
||||
|
||||
flush_work(&tport->ls_work);
|
||||
|
||||
spin_lock_irqsave(&fcloop_lock, flags);
|
||||
if (!test_and_set_bit(PORT_DELETED, &tport->flags))
|
||||
put_port = true;
|
||||
tport->nport->tport = NULL;
|
||||
spin_unlock_irqrestore(&fcloop_lock, flags);
|
||||
|
||||
fcloop_nport_put(tport->nport);
|
||||
if (put_port)
|
||||
fcloop_nport_put(tport->nport);
|
||||
}
|
||||
|
||||
#define FCLOOP_HW_QUEUES 4
|
||||
|
|
@ -1427,6 +1440,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);
|
||||
|
|
@ -1524,6 +1538,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);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user