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:
parent
fc31d920d9
commit
01dcbce3e5
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in New Issue