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

Commit d5fdcd23 authored by Ming Lei's avatar Ming Lei Committed by Greg Kroah-Hartman
Browse files

nvme-fcloop: fix "inconsistent {IN-HARDIRQ-W} -> {HARDIRQ-ON-W} usage"



[ Upstream commit 4f86a6ff6fbd891232dda3ca97fd1b9630b59809 ]

fcloop_fcp_op() could be called from flush request's ->end_io(flush_end_io) in
which the spinlock of fq->mq_flush_lock is grabbed with irq saved/disabled.

So fcloop_fcp_op() can't call spin_unlock_irq(&tfcp_req->reqlock) simply
which enables irq unconditionally.

Fixes the warning by switching to spin_lock_irqsave()/spin_unlock_irqrestore()

Fixes: c38dbbfa ("nvme-fcloop: fix inconsistent lock state warnings")
Reported-by: default avatarYi Zhang <yi.zhang@redhat.com>
Signed-off-by: default avatarMing Lei <ming.lei@redhat.com>
Reviewed-by: default avatarEwan D. Milne <emilne@redhat.com>
Tested-by: default avatarYi Zhang <yi.zhang@redhat.com>
Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
Signed-off-by: default avatarSasha Levin <sashal@kernel.org>
parent b1e6b3fd
Loading
Loading
Loading
Loading
+27 −21
Original line number Diff line number Diff line
@@ -431,10 +431,11 @@ fcloop_fcp_recv_work(struct work_struct *work)
	struct fcloop_fcpreq *tfcp_req =
		container_of(work, struct fcloop_fcpreq, fcp_rcv_work);
	struct nvmefc_fcp_req *fcpreq = tfcp_req->fcpreq;
	unsigned long flags;
	int ret = 0;
	bool aborted = false;

	spin_lock_irq(&tfcp_req->reqlock);
	spin_lock_irqsave(&tfcp_req->reqlock, flags);
	switch (tfcp_req->inistate) {
	case INI_IO_START:
		tfcp_req->inistate = INI_IO_ACTIVE;
@@ -443,11 +444,11 @@ fcloop_fcp_recv_work(struct work_struct *work)
		aborted = true;
		break;
	default:
		spin_unlock_irq(&tfcp_req->reqlock);
		spin_unlock_irqrestore(&tfcp_req->reqlock, flags);
		WARN_ON(1);
		return;
	}
	spin_unlock_irq(&tfcp_req->reqlock);
	spin_unlock_irqrestore(&tfcp_req->reqlock, flags);

	if (unlikely(aborted))
		ret = -ECANCELED;
@@ -468,8 +469,9 @@ fcloop_fcp_abort_recv_work(struct work_struct *work)
		container_of(work, struct fcloop_fcpreq, abort_rcv_work);
	struct nvmefc_fcp_req *fcpreq;
	bool completed = false;
	unsigned long flags;

	spin_lock_irq(&tfcp_req->reqlock);
	spin_lock_irqsave(&tfcp_req->reqlock, flags);
	fcpreq = tfcp_req->fcpreq;
	switch (tfcp_req->inistate) {
	case INI_IO_ABORTED:
@@ -478,11 +480,11 @@ fcloop_fcp_abort_recv_work(struct work_struct *work)
		completed = true;
		break;
	default:
		spin_unlock_irq(&tfcp_req->reqlock);
		spin_unlock_irqrestore(&tfcp_req->reqlock, flags);
		WARN_ON(1);
		return;
	}
	spin_unlock_irq(&tfcp_req->reqlock);
	spin_unlock_irqrestore(&tfcp_req->reqlock, flags);

	if (unlikely(completed)) {
		/* remove reference taken in original abort downcall */
@@ -494,9 +496,9 @@ fcloop_fcp_abort_recv_work(struct work_struct *work)
		nvmet_fc_rcv_fcp_abort(tfcp_req->tport->targetport,
					&tfcp_req->tgt_fcp_req);

	spin_lock_irq(&tfcp_req->reqlock);
	spin_lock_irqsave(&tfcp_req->reqlock, flags);
	tfcp_req->fcpreq = NULL;
	spin_unlock_irq(&tfcp_req->reqlock);
	spin_unlock_irqrestore(&tfcp_req->reqlock, flags);

	fcloop_call_host_done(fcpreq, tfcp_req, -ECANCELED);
	/* call_host_done releases reference for abort downcall */
@@ -512,11 +514,12 @@ fcloop_tgt_fcprqst_done_work(struct work_struct *work)
	struct fcloop_fcpreq *tfcp_req =
		container_of(work, struct fcloop_fcpreq, tio_done_work);
	struct nvmefc_fcp_req *fcpreq;
	unsigned long flags;

	spin_lock_irq(&tfcp_req->reqlock);
	spin_lock_irqsave(&tfcp_req->reqlock, flags);
	fcpreq = tfcp_req->fcpreq;
	tfcp_req->inistate = INI_IO_COMPLETED;
	spin_unlock_irq(&tfcp_req->reqlock);
	spin_unlock_irqrestore(&tfcp_req->reqlock, flags);

	fcloop_call_host_done(fcpreq, tfcp_req, tfcp_req->status);
}
@@ -620,13 +623,14 @@ fcloop_fcp_op(struct nvmet_fc_target_port *tgtport,
	u32 rsplen = 0, xfrlen = 0;
	int fcp_err = 0, active, aborted;
	u8 op = tgt_fcpreq->op;
	unsigned long flags;

	spin_lock_irq(&tfcp_req->reqlock);
	spin_lock_irqsave(&tfcp_req->reqlock, flags);
	fcpreq = tfcp_req->fcpreq;
	active = tfcp_req->active;
	aborted = tfcp_req->aborted;
	tfcp_req->active = true;
	spin_unlock_irq(&tfcp_req->reqlock);
	spin_unlock_irqrestore(&tfcp_req->reqlock, flags);

	if (unlikely(active))
		/* illegal - call while i/o active */
@@ -634,9 +638,9 @@ fcloop_fcp_op(struct nvmet_fc_target_port *tgtport,

	if (unlikely(aborted)) {
		/* target transport has aborted i/o prior */
		spin_lock_irq(&tfcp_req->reqlock);
		spin_lock_irqsave(&tfcp_req->reqlock, flags);
		tfcp_req->active = false;
		spin_unlock_irq(&tfcp_req->reqlock);
		spin_unlock_irqrestore(&tfcp_req->reqlock, flags);
		tgt_fcpreq->transferred_length = 0;
		tgt_fcpreq->fcp_error = -ECANCELED;
		tgt_fcpreq->done(tgt_fcpreq);
@@ -693,9 +697,9 @@ fcloop_fcp_op(struct nvmet_fc_target_port *tgtport,
		break;
	}

	spin_lock_irq(&tfcp_req->reqlock);
	spin_lock_irqsave(&tfcp_req->reqlock, flags);
	tfcp_req->active = false;
	spin_unlock_irq(&tfcp_req->reqlock);
	spin_unlock_irqrestore(&tfcp_req->reqlock, flags);

	tgt_fcpreq->transferred_length = xfrlen;
	tgt_fcpreq->fcp_error = fcp_err;
@@ -709,15 +713,16 @@ fcloop_tgt_fcp_abort(struct nvmet_fc_target_port *tgtport,
			struct nvmefc_tgt_fcp_req *tgt_fcpreq)
{
	struct fcloop_fcpreq *tfcp_req = tgt_fcp_req_to_fcpreq(tgt_fcpreq);
	unsigned long flags;

	/*
	 * mark aborted only in case there were 2 threads in transport
	 * (one doing io, other doing abort) and only kills ops posted
	 * after the abort request
	 */
	spin_lock_irq(&tfcp_req->reqlock);
	spin_lock_irqsave(&tfcp_req->reqlock, flags);
	tfcp_req->aborted = true;
	spin_unlock_irq(&tfcp_req->reqlock);
	spin_unlock_irqrestore(&tfcp_req->reqlock, flags);

	tfcp_req->status = NVME_SC_INTERNAL;

@@ -753,6 +758,7 @@ fcloop_fcp_abort(struct nvme_fc_local_port *localport,
	struct fcloop_ini_fcpreq *inireq = fcpreq->private;
	struct fcloop_fcpreq *tfcp_req;
	bool abortio = true;
	unsigned long flags;

	spin_lock(&inireq->inilock);
	tfcp_req = inireq->tfcp_req;
@@ -765,7 +771,7 @@ fcloop_fcp_abort(struct nvme_fc_local_port *localport,
		return;

	/* break initiator/target relationship for io */
	spin_lock_irq(&tfcp_req->reqlock);
	spin_lock_irqsave(&tfcp_req->reqlock, flags);
	switch (tfcp_req->inistate) {
	case INI_IO_START:
	case INI_IO_ACTIVE:
@@ -775,11 +781,11 @@ fcloop_fcp_abort(struct nvme_fc_local_port *localport,
		abortio = false;
		break;
	default:
		spin_unlock_irq(&tfcp_req->reqlock);
		spin_unlock_irqrestore(&tfcp_req->reqlock, flags);
		WARN_ON(1);
		return;
	}
	spin_unlock_irq(&tfcp_req->reqlock);
	spin_unlock_irqrestore(&tfcp_req->reqlock, flags);

	if (abortio)
		/* leave the reference while the work item is scheduled */