[PATCH v6 15/18] nvme-fc: Hold inflight requests while in FENCING state

Daniel Wagner dwagner at suse.de
Tue Nov 3 02:51:28 PST 2026


On Mon, Nov 02, 2026 at 05:18:51PM -0800, Mohamed Khalfella wrote:
> -/* Complete the requests held in __nvme_fc_teardown_association() */
> +static bool
> +nvme_fc_cancel_held_request(struct request *req, void *data)
> +{
> +	struct nvme_fc_fcp_op *op = blk_mq_rq_to_pdu(req);
> +	struct nvme_ctrl *ctrl = data;
> +
> +	/*
> +	 * A single cmpxchg decides who completes this request. If the op is
> +	 * HELD, nvme_fc_fcpio_done() is done with it and we cancel it. If it
> +	 * is still COMPLETE, nvme_fc_fcpio_done() has not decided yet: move
> +	 * it to IDLE so its own cmpxchg to HELD fails and it completes the
> +	 * request itself (nvme_fc_complete_rq() sets IDLE anyway). Doing this
> +	 * as read-then-cmpxchg would let the op become HELD in between and
> +	 * leave it with no one to complete it.
> +	 */
> +	if (atomic_cmpxchg(&op->state, FCPOP_STATE_COMPLETE,
> +			   FCPOP_STATE_IDLE) == FCPOP_STATE_HELD)
> +		nvme_cancel_request(req, ctrl);
> +
> +	return true;
> +}
> +
>  static void
> -nvme_fc_flush_held_requests(struct nvme_fc_ctrl *ctrl)
> +nvme_fc_cancel_held_requests(struct nvme_ctrl *ctrl, struct blk_mq_tag_set *set)
>  {
> -	nvme_cancel_tagset(&ctrl->ctrl);
> -	nvme_cancel_admin_tagset(&ctrl->ctrl);
> +	if (set) {

Do we call flush when we don't have a set?

nitpick: use the early return pattern if needed.

> +		blk_mq_tagset_busy_iter(set, nvme_fc_cancel_held_request, ctrl);
> +		blk_mq_tagset_wait_completed_request(set);
> +	}
> +}
> +
> +/* Complete the requests nvme_fc_fcpio_done() held during the fence */
> +static void
> +nvme_fc_flush_held_requests(struct nvme_fc_ctrl *fc_ctrl)
> +{
> +	struct nvme_ctrl *ctrl = &fc_ctrl->ctrl;
> +
> +	nvme_fc_cancel_held_requests(ctrl, ctrl->tagset);
> +	nvme_fc_cancel_held_requests(ctrl, ctrl->admin_tagset);
>  
>  	/* re-enable the admin_q so anything new can fast fail */
> -	nvme_unquiesce_admin_queue(&ctrl->ctrl);
> +	nvme_unquiesce_admin_queue(ctrl);
>  
>  	/* resume the io queues so that things will fast fail */
> -	nvme_unquiesce_io_queues(&ctrl->ctrl);
> +	nvme_unquiesce_io_queues(ctrl);
>  }
>  
>  /*

Yes, I'd prefer this over the introduction of RCU in this code path.




More information about the Linux-nvme mailing list