diff options
-rw-r--r-- | block/blk-core.c | 25 | ||||
-rw-r--r-- | block/blk-settings.c | 17 | ||||
-rw-r--r-- | drivers/scsi/scsi_lib.c | 2 | ||||
-rw-r--r-- | include/linux/blkdev.h | 4 |
4 files changed, 47 insertions, 1 deletions
diff --git a/block/blk-core.c b/block/blk-core.c index 3c3789492c10..5ab3ac22930c 100644 --- a/block/blk-core.c +++ b/block/blk-core.c | |||
@@ -608,6 +608,7 @@ blk_init_allocated_queue_node(struct request_queue *q, request_fn_proc *rfn, | |||
608 | 608 | ||
609 | q->request_fn = rfn; | 609 | q->request_fn = rfn; |
610 | q->prep_rq_fn = NULL; | 610 | q->prep_rq_fn = NULL; |
611 | q->unprep_rq_fn = NULL; | ||
611 | q->unplug_fn = generic_unplug_device; | 612 | q->unplug_fn = generic_unplug_device; |
612 | q->queue_flags = QUEUE_FLAG_DEFAULT; | 613 | q->queue_flags = QUEUE_FLAG_DEFAULT; |
613 | q->queue_lock = lock; | 614 | q->queue_lock = lock; |
@@ -2133,6 +2134,26 @@ static bool blk_update_bidi_request(struct request *rq, int error, | |||
2133 | return false; | 2134 | return false; |
2134 | } | 2135 | } |
2135 | 2136 | ||
2137 | /** | ||
2138 | * blk_unprep_request - unprepare a request | ||
2139 | * @req: the request | ||
2140 | * | ||
2141 | * This function makes a request ready for complete resubmission (or | ||
2142 | * completion). It happens only after all error handling is complete, | ||
2143 | * so represents the appropriate moment to deallocate any resources | ||
2144 | * that were allocated to the request in the prep_rq_fn. The queue | ||
2145 | * lock is held when calling this. | ||
2146 | */ | ||
2147 | void blk_unprep_request(struct request *req) | ||
2148 | { | ||
2149 | struct request_queue *q = req->q; | ||
2150 | |||
2151 | req->cmd_flags &= ~REQ_DONTPREP; | ||
2152 | if (q->unprep_rq_fn) | ||
2153 | q->unprep_rq_fn(q, req); | ||
2154 | } | ||
2155 | EXPORT_SYMBOL_GPL(blk_unprep_request); | ||
2156 | |||
2136 | /* | 2157 | /* |
2137 | * queue lock must be held | 2158 | * queue lock must be held |
2138 | */ | 2159 | */ |
@@ -2148,6 +2169,10 @@ static void blk_finish_request(struct request *req, int error) | |||
2148 | 2169 | ||
2149 | blk_delete_timer(req); | 2170 | blk_delete_timer(req); |
2150 | 2171 | ||
2172 | if (req->cmd_flags & REQ_DONTPREP) | ||
2173 | blk_unprep_request(req); | ||
2174 | |||
2175 | |||
2151 | blk_account_io_done(req); | 2176 | blk_account_io_done(req); |
2152 | 2177 | ||
2153 | if (req->end_io) | 2178 | if (req->end_io) |
diff --git a/block/blk-settings.c b/block/blk-settings.c index f5ed5a1187ba..a234f4bf1d6f 100644 --- a/block/blk-settings.c +++ b/block/blk-settings.c | |||
@@ -37,6 +37,23 @@ void blk_queue_prep_rq(struct request_queue *q, prep_rq_fn *pfn) | |||
37 | EXPORT_SYMBOL(blk_queue_prep_rq); | 37 | EXPORT_SYMBOL(blk_queue_prep_rq); |
38 | 38 | ||
39 | /** | 39 | /** |
40 | * blk_queue_unprep_rq - set an unprepare_request function for queue | ||
41 | * @q: queue | ||
42 | * @ufn: unprepare_request function | ||
43 | * | ||
44 | * It's possible for a queue to register an unprepare_request callback | ||
45 | * which is invoked before the request is finally completed. The goal | ||
46 | * of the function is to deallocate any data that was allocated in the | ||
47 | * prepare_request callback. | ||
48 | * | ||
49 | */ | ||
50 | void blk_queue_unprep_rq(struct request_queue *q, unprep_rq_fn *ufn) | ||
51 | { | ||
52 | q->unprep_rq_fn = ufn; | ||
53 | } | ||
54 | EXPORT_SYMBOL(blk_queue_unprep_rq); | ||
55 | |||
56 | /** | ||
40 | * blk_queue_merge_bvec - set a merge_bvec function for queue | 57 | * blk_queue_merge_bvec - set a merge_bvec function for queue |
41 | * @q: queue | 58 | * @q: queue |
42 | * @mbfn: merge_bvec_fn | 59 | * @mbfn: merge_bvec_fn |
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 5f1160841b0e..ee836193f531 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c | |||
@@ -85,7 +85,7 @@ static void scsi_unprep_request(struct request *req) | |||
85 | { | 85 | { |
86 | struct scsi_cmnd *cmd = req->special; | 86 | struct scsi_cmnd *cmd = req->special; |
87 | 87 | ||
88 | req->cmd_flags &= ~REQ_DONTPREP; | 88 | blk_unprep_request(req); |
89 | req->special = NULL; | 89 | req->special = NULL; |
90 | 90 | ||
91 | scsi_put_command(cmd); | 91 | scsi_put_command(cmd); |
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 204fbe22354d..6bba04c7ec48 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h | |||
@@ -200,6 +200,7 @@ struct request_pm_state | |||
200 | typedef void (request_fn_proc) (struct request_queue *q); | 200 | typedef void (request_fn_proc) (struct request_queue *q); |
201 | typedef int (make_request_fn) (struct request_queue *q, struct bio *bio); | 201 | typedef int (make_request_fn) (struct request_queue *q, struct bio *bio); |
202 | typedef int (prep_rq_fn) (struct request_queue *, struct request *); | 202 | typedef int (prep_rq_fn) (struct request_queue *, struct request *); |
203 | typedef void (unprep_rq_fn) (struct request_queue *, struct request *); | ||
203 | typedef void (unplug_fn) (struct request_queue *); | 204 | typedef void (unplug_fn) (struct request_queue *); |
204 | 205 | ||
205 | struct bio_vec; | 206 | struct bio_vec; |
@@ -282,6 +283,7 @@ struct request_queue | |||
282 | request_fn_proc *request_fn; | 283 | request_fn_proc *request_fn; |
283 | make_request_fn *make_request_fn; | 284 | make_request_fn *make_request_fn; |
284 | prep_rq_fn *prep_rq_fn; | 285 | prep_rq_fn *prep_rq_fn; |
286 | unprep_rq_fn *unprep_rq_fn; | ||
285 | unplug_fn *unplug_fn; | 287 | unplug_fn *unplug_fn; |
286 | merge_bvec_fn *merge_bvec_fn; | 288 | merge_bvec_fn *merge_bvec_fn; |
287 | prepare_flush_fn *prepare_flush_fn; | 289 | prepare_flush_fn *prepare_flush_fn; |
@@ -841,6 +843,7 @@ extern void blk_complete_request(struct request *); | |||
841 | extern void __blk_complete_request(struct request *); | 843 | extern void __blk_complete_request(struct request *); |
842 | extern void blk_abort_request(struct request *); | 844 | extern void blk_abort_request(struct request *); |
843 | extern void blk_abort_queue(struct request_queue *); | 845 | extern void blk_abort_queue(struct request_queue *); |
846 | extern void blk_unprep_request(struct request *); | ||
844 | 847 | ||
845 | /* | 848 | /* |
846 | * Access functions for manipulating queue properties | 849 | * Access functions for manipulating queue properties |
@@ -885,6 +888,7 @@ extern int blk_queue_dma_drain(struct request_queue *q, | |||
885 | extern void blk_queue_lld_busy(struct request_queue *q, lld_busy_fn *fn); | 888 | extern void blk_queue_lld_busy(struct request_queue *q, lld_busy_fn *fn); |
886 | extern void blk_queue_segment_boundary(struct request_queue *, unsigned long); | 889 | extern void blk_queue_segment_boundary(struct request_queue *, unsigned long); |
887 | extern void blk_queue_prep_rq(struct request_queue *, prep_rq_fn *pfn); | 890 | extern void blk_queue_prep_rq(struct request_queue *, prep_rq_fn *pfn); |
891 | extern void blk_queue_unprep_rq(struct request_queue *, unprep_rq_fn *ufn); | ||
888 | extern void blk_queue_merge_bvec(struct request_queue *, merge_bvec_fn *); | 892 | extern void blk_queue_merge_bvec(struct request_queue *, merge_bvec_fn *); |
889 | extern void blk_queue_dma_alignment(struct request_queue *, int); | 893 | extern void blk_queue_dma_alignment(struct request_queue *, int); |
890 | extern void blk_queue_update_dma_alignment(struct request_queue *, int); | 894 | extern void blk_queue_update_dma_alignment(struct request_queue *, int); |