Later, the low layer (scsi) can decide when to turn back the mem of req by blk_reclaim_request() Signed-off-by: Liu Ping Fan <pingfank@xxxxxxxxxxxxxxxxxx> --- block/blk-core.c | 52 +++++++++++++++++++++++++++++++++----------------- include/linux/blkdev.h | 6 ++++-- 2 files changed, 39 insertions(+), 19 deletions(-) diff --git a/block/blk-core.c b/block/blk-core.c index beaca2e..7e8a8ae 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -2495,7 +2495,7 @@ EXPORT_SYMBOL_GPL(blk_unprep_request); /* * queue lock must be held */ -static void blk_finish_request(struct request *req, int error, int *drop_ref) +static void __blk_finish_request(struct request *req, int error, int *drop_ref) { bool ref; @@ -2517,7 +2517,10 @@ static void blk_finish_request(struct request *req, int error, int *drop_ref) blk_unprep_request(req); blk_account_io_done(req); +} +void blk_reclaim_request(struct request *req, int error) +{ if (req->end_io) req->end_io(req, error); else { @@ -2528,6 +2531,12 @@ static void blk_finish_request(struct request *req, int error, int *drop_ref) } } +static void blk_finish_request(struct request *req, int error, int *drop_ref) +{ + __blk_finish_request(req, error, drop_ref); + blk_reclaim_request(req, error); +} + /** * blk_end_bidi_request - Complete a bidi request * @rq: the request to complete @@ -2555,7 +2564,11 @@ static bool blk_end_bidi_request(struct request *rq, int error, return true; spin_lock_irqsave(q->queue_lock, flags); - blk_finish_request(rq, error, drop_ref); + /* low level wants to manage ref, so not to reclaim rq */ + if (drop_ref) + __blk_finish_request(rq, error, drop_ref); + else + blk_finish_request(rq, error, drop_ref); spin_unlock_irqrestore(q->queue_lock, flags); return false; @@ -2608,25 +2621,15 @@ bool blk_end_request(struct request *rq, int error, unsigned int nr_bytes) EXPORT_SYMBOL(blk_end_request); /** - * blk_end_request_ref - Helper function for drivers to complete the request. - * @rq: the request being processed - * @error: %0 for success, < %0 for error - * @nr_bytes: number of bytes to complete - * - * Description: - * Ends I/O on a number of bytes attached to @rq. - * If @rq has leftover, sets it up for the next range of segments. - * - * Return: - * %false - we are done with this request - * %true - still buffers pending for this request + * blk_end_request_noreclaim - same as blk_end_request, but not reclaim rq **/ -bool blk_end_request_ref(struct request *rq, int error, unsigned int nr_bytes, - int *drop_ref) +bool blk_end_request_noreclaim(struct request *rq, int error, + unsigned int nr_bytes, int *drop_ref) { + BUG_ON(!drop_ref); return blk_end_bidi_request(rq, error, nr_bytes, 0, drop_ref); } -EXPORT_SYMBOL(blk_end_request_ref); +EXPORT_SYMBOL(blk_end_request_noreclaim); /** * blk_end_request_all - Helper function for drives to finish the request. @@ -2650,6 +2653,21 @@ void blk_end_request_all(struct request *rq, int error) } EXPORT_SYMBOL(blk_end_request_all); +void blk_end_request_all_noreclaim(struct request *rq, int error) +{ + bool pending; + unsigned int bidi_bytes = 0; + int ref; + + if (unlikely(blk_bidi_rq(rq))) + bidi_bytes = blk_rq_bytes(rq->next_rq); + + pending = blk_end_bidi_request(rq, error, blk_rq_bytes(rq), bidi_bytes, + &ref); + BUG_ON(pending); +} +EXPORT_SYMBOL(blk_end_request_all_noreclaim); + /** * blk_end_request_cur - Helper function to finish the current request chunk. * @rq: the request to finish the current chunk for diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 7a2e79f..70c65d2 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -772,6 +772,7 @@ extern void generic_make_request(struct bio *bio); extern void blk_rq_init(struct request_queue *q, struct request *rq); extern void blk_put_request(struct request *); extern void __blk_put_request(struct request_queue *, struct request *); +extern void blk_reclaim_request(struct request *req, int error); 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); @@ -934,11 +935,12 @@ extern struct request *blk_fetch_request(struct request_queue *q); */ extern bool blk_update_request(struct request *rq, int error, unsigned int nr_bytes); -extern bool blk_end_request_ref(struct request *rq, int error, - unsigned int nr_bytes, int *drop_ref); extern bool blk_end_request(struct request *rq, int error, unsigned int nr_bytes); +extern bool blk_end_request_noreclaim(struct request *rq, int error, + unsigned int nr_bytes, int *drop_ref); extern void blk_end_request_all(struct request *rq, int error); +extern void blk_end_request_all_noreclaim(struct request *rq, int error); extern bool blk_end_request_cur(struct request *rq, int error); extern bool blk_end_request_err(struct request *rq, int error); extern bool __blk_end_request(struct request *rq, int error, -- 1.8.1.4 -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html