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

Commit 01dcbce3 authored by Gilad Broner's avatar Gilad Broner
Browse files

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: default avatarGilad Broner <gbroner@codeaurora.org>
parent fc31d920
Loading
Loading
Loading
Loading
+14 −1
Original line number Original line Diff line number Diff line
@@ -1214,9 +1214,21 @@ EXPORT_SYMBOL(blk_make_request);
 *    Drivers often keep queueing requests until the hardware cannot accept
 *    Drivers often keep queueing requests until the hardware cannot accept
 *    more, when that condition happens we need to put the request back
 *    more, when that condition happens we need to put the request back
 *    on the queue. Must be called with queue lock held.
 *    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_delete_timer(rq);
	blk_clear_rq_complete(rq);
	blk_clear_rq_complete(rq);
	trace_block_rq_requeue(q, 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;
		q->dispatched_urgent = false;
	}
	}
	elv_requeue_request(q, rq);
	elv_requeue_request(q, rq);
	return true;
}
}
EXPORT_SYMBOL(blk_requeue_request);
EXPORT_SYMBOL(blk_requeue_request);


+5 −0
Original line number Original line Diff line number Diff line
@@ -58,6 +58,11 @@ static inline void blk_clear_rq_complete(struct request *rq)
	clear_bit(REQ_ATOM_COMPLETE, &rq->atomic_flags);
	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
 * Internal elevator interface
 */
 */
+1 −1
Original line number Original line Diff line number Diff line
@@ -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_get_request(struct request_queue *, int, gfp_t);
extern struct request *blk_make_request(struct request_queue *, struct bio *,
extern struct request *blk_make_request(struct request_queue *, struct bio *,
					gfp_t);
					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 int blk_reinsert_request(struct request_queue *q, struct request *rq);
extern bool blk_reinsert_req_sup(struct request_queue *q);
extern bool blk_reinsert_req_sup(struct request_queue *q);
extern void blk_add_request_payload(struct request *rq, struct page *page,
extern void blk_add_request_payload(struct request *rq, struct page *page,