summaryrefslogtreecommitdiff
path: root/drivers/nvme/target/fcloop.c
diff options
context:
space:
mode:
authorJames Smart <jsmart2021@gmail.com>2017-11-29 16:47:30 -0800
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2018-04-12 12:32:16 +0200
commitf0504bf54b4dd068e6a8c4c3b3de4a50a4f7da79 (patch)
tree7db84f66666e935febb1f9f9027bce2fdb99f415 /drivers/nvme/target/fcloop.c
parent39ede1fd200f0f43bc87e12bf6cced45de610232 (diff)
nvme_fcloop: fix abort race condition
[ Upstream commit 278e096063f1914fccfc77a617be9fc8dbb31b0e ] A test case revealed a race condition of an i/o completing on a thread parallel to the delete_association generating the aborts for the outstanding ios on the controller. The i/o completion was freeing the target fcloop context, thus the abort task referenced the just-freed memory. Correct by clearing the target/initiator cross pointers in the io completion and abort tasks before calling the callbacks. On aborts that detect already finished io's, ensure the complete context is called. Signed-off-by: James Smart <james.smart@broadcom.com> Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Sasha Levin <alexander.levin@microsoft.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/nvme/target/fcloop.c')
-rw-r--r--drivers/nvme/target/fcloop.c12
1 files changed, 7 insertions, 5 deletions
diff --git a/drivers/nvme/target/fcloop.c b/drivers/nvme/target/fcloop.c
index 5b51653ba9fe..c0080f6ab2f5 100644
--- a/drivers/nvme/target/fcloop.c
+++ b/drivers/nvme/target/fcloop.c
@@ -374,6 +374,7 @@ fcloop_tgt_fcprqst_done_work(struct work_struct *work)
spin_lock(&tfcp_req->reqlock);
fcpreq = tfcp_req->fcpreq;
+ tfcp_req->fcpreq = NULL;
spin_unlock(&tfcp_req->reqlock);
if (tport->remoteport && fcpreq) {
@@ -615,11 +616,7 @@ fcloop_fcp_abort(struct nvme_fc_local_port *localport,
if (!tfcp_req)
/* abort has already been called */
- return;
-
- if (rport->targetport)
- nvmet_fc_rcv_fcp_abort(rport->targetport,
- &tfcp_req->tgt_fcp_req);
+ goto finish;
/* break initiator/target relationship for io */
spin_lock(&tfcp_req->reqlock);
@@ -627,6 +624,11 @@ fcloop_fcp_abort(struct nvme_fc_local_port *localport,
tfcp_req->fcpreq = NULL;
spin_unlock(&tfcp_req->reqlock);
+ if (rport->targetport)
+ nvmet_fc_rcv_fcp_abort(rport->targetport,
+ &tfcp_req->tgt_fcp_req);
+
+finish:
/* post the aborted io completion */
fcpreq->status = -ECANCELED;
schedule_work(&inireq->iniwork);