Commit 15f73f5b authored by Christoph Hellwig's avatar Christoph Hellwig Committed by Jens Axboe
Browse files

blk-mq: move failure injection out of blk_mq_complete_request



Move the call to blk_should_fake_timeout out of blk_mq_complete_request
and into the drivers, skipping call sites that are obvious error
handlers, and remove the now superflous blk_mq_force_complete_rq helper.
This ensures we don't keep injecting errors into completions that just
terminate the Linux request after the hardware has been reset or the
command has been aborted.

Reviewed-by: default avatarDaniel Wagner <dwagner@suse.de>
Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
Signed-off-by: default avatarJens Axboe <axboe@kernel.dk>
parent d391a7a3
Loading
Loading
Loading
Loading
+7 −27
Original line number Diff line number Diff line
@@ -655,16 +655,13 @@ static void __blk_mq_complete_request_remote(void *data)
}

/**
 * blk_mq_force_complete_rq() - Force complete the request, bypassing any error
 * 				injection that could drop the completion.
 * @rq: Request to be force completed
 * blk_mq_complete_request - end I/O on a request
 * @rq:		the request being processed
 *
 * Drivers should use blk_mq_complete_request() to complete requests in their
 * normal IO path. For timeout error recovery, drivers may call this forced
 * completion routine after they've reclaimed timed out requests to bypass
 * potentially subsequent fake timeouts.
 */
void blk_mq_force_complete_rq(struct request *rq)
 * Description:
 *	Complete a request by scheduling the ->complete_rq operation.
 **/
void blk_mq_complete_request(struct request *rq)
{
	struct blk_mq_ctx *ctx = rq->mq_ctx;
	struct request_queue *q = rq->q;
@@ -702,7 +699,7 @@ void blk_mq_force_complete_rq(struct request *rq)
	}
	put_cpu();
}
EXPORT_SYMBOL_GPL(blk_mq_force_complete_rq);
EXPORT_SYMBOL(blk_mq_complete_request);

static void hctx_unlock(struct blk_mq_hw_ctx *hctx, int srcu_idx)
	__releases(hctx->srcu)
@@ -724,23 +721,6 @@ static void hctx_lock(struct blk_mq_hw_ctx *hctx, int *srcu_idx)
		*srcu_idx = srcu_read_lock(hctx->srcu);
}

/**
 * blk_mq_complete_request - end I/O on a request
 * @rq:		the request being processed
 *
 * Description:
 *	Ends all I/O on a request. It does not handle partial completions.
 *	The actual completion happens out-of-order, through a IPI handler.
 **/
bool blk_mq_complete_request(struct request *rq)
{
	if (unlikely(blk_should_fake_timeout(rq->q)))
		return false;
	blk_mq_force_complete_rq(rq);
	return true;
}
EXPORT_SYMBOL(blk_mq_complete_request);

/**
 * blk_mq_start_request - Start processing a request
 * @rq: Pointer to request to be started
+2 −4
Original line number Diff line number Diff line
@@ -20,13 +20,11 @@ static int __init setup_fail_io_timeout(char *str)
}
__setup("fail_io_timeout=", setup_fail_io_timeout);

int blk_should_fake_timeout(struct request_queue *q)
bool __blk_should_fake_timeout(struct request_queue *q)
{
	if (!test_bit(QUEUE_FLAG_FAIL_IO, &q->queue_flags))
		return 0;

	return should_fail(&fail_io_timeout, 1);
}
EXPORT_SYMBOL_GPL(__blk_should_fake_timeout);

static int __init fail_io_timeout_debugfs(void)
{
+0 −9
Original line number Diff line number Diff line
@@ -223,18 +223,9 @@ ssize_t part_fail_show(struct device *dev, struct device_attribute *attr,
		char *buf);
ssize_t part_fail_store(struct device *dev, struct device_attribute *attr,
		const char *buf, size_t count);

#ifdef CONFIG_FAIL_IO_TIMEOUT
int blk_should_fake_timeout(struct request_queue *);
ssize_t part_timeout_show(struct device *, struct device_attribute *, char *);
ssize_t part_timeout_store(struct device *, struct device_attribute *,
				const char *, size_t);
#else
static inline int blk_should_fake_timeout(struct request_queue *q)
{
	return 0;
}
#endif

void __blk_queue_split(struct request_queue *q, struct bio **bio,
		unsigned int *nr_segs);
+4 −1
Original line number Diff line number Diff line
@@ -181,9 +181,12 @@ EXPORT_SYMBOL_GPL(bsg_job_get);
void bsg_job_done(struct bsg_job *job, int result,
		  unsigned int reply_payload_rcv_len)
{
	struct request *rq = blk_mq_rq_from_pdu(job);

	job->result = result;
	job->reply_payload_rcv_len = reply_payload_rcv_len;
	blk_mq_complete_request(blk_mq_rq_from_pdu(job));
	if (likely(!blk_should_fake_timeout(rq->q)))
		blk_mq_complete_request(rq);
}
EXPORT_SYMBOL_GPL(bsg_job_done);

+4 −2
Original line number Diff line number Diff line
@@ -509,6 +509,7 @@ static void lo_rw_aio_do_completion(struct loop_cmd *cmd)
		return;
	kfree(cmd->bvec);
	cmd->bvec = NULL;
	if (likely(!blk_should_fake_timeout(rq->q)))
		blk_mq_complete_request(rq);
}

@@ -2048,6 +2049,7 @@ static void loop_handle_cmd(struct loop_cmd *cmd)
			cmd->ret = ret;
		else
			cmd->ret = ret ? -EIO : 0;
		if (likely(!blk_should_fake_timeout(rq->q)))
			blk_mq_complete_request(rq);
	}
}
Loading