block: do not requeue completed request

Verify request is not yet completed before requeueing it,
as requeueing a request ends its tag and sets it to -1 while
it is possible that the request has timed out and it now being
processed for error handling. Since it may be active and processed
in the low lever driver, we mustn't reset its tag.

Change-Id: Ia3e8209959fe377281f28106640a13f10501b47e
Signed-off-by: Gilad Broner <gbroner@codeaurora.org>
This commit is contained in:
Gilad Broner 2015-01-04 11:39:38 +02:00
parent fc31d920d9
commit 01dcbce3e5
3 changed files with 20 additions and 2 deletions

View File

@ -1214,9 +1214,21 @@ EXPORT_SYMBOL(blk_make_request);
* Drivers often keep queueing requests until the hardware cannot accept
* more, when that condition happens we need to put the request back
* on the queue. Must be called with queue lock held.
*
* Return: true is request was requeued, false otherwise
*/
void blk_requeue_request(struct request_queue *q, struct request *rq)
bool blk_requeue_request(struct request_queue *q, struct request *rq)
{
/*
* Request could have timed out at this point and error handling is
* now in progress so it is marked as completed. Do not allow to
* requeue a completed request as this will cause the tag to end and
* become -1. However, the request is still active and being used so tag
* being -1 is not valid.
*/
if (blk_is_req_complete(rq))
return false;
blk_delete_timer(rq);
blk_clear_rq_complete(rq);
trace_block_rq_requeue(q, rq);
@ -1237,6 +1249,7 @@ void blk_requeue_request(struct request_queue *q, struct request *rq)
q->dispatched_urgent = false;
}
elv_requeue_request(q, rq);
return true;
}
EXPORT_SYMBOL(blk_requeue_request);

View File

@ -58,6 +58,11 @@ static inline void blk_clear_rq_complete(struct request *rq)
clear_bit(REQ_ATOM_COMPLETE, &rq->atomic_flags);
}
static inline bool blk_is_req_complete(struct request *rq)
{
return test_bit(REQ_ATOM_COMPLETE, &rq->atomic_flags);
}
/*
* Internal elevator interface
*/

View File

@ -740,7 +740,7 @@ extern void __blk_put_request(struct request_queue *, struct request *);
extern struct request *blk_get_request(struct request_queue *, int, gfp_t);
extern struct request *blk_make_request(struct request_queue *, struct bio *,
gfp_t);
extern void blk_requeue_request(struct request_queue *, struct request *);
extern bool blk_requeue_request(struct request_queue *, struct request *);
extern int blk_reinsert_request(struct request_queue *q, struct request *rq);
extern bool blk_reinsert_req_sup(struct request_queue *q);
extern void blk_add_request_payload(struct request *rq, struct page *page,