diff options
-rw-r--r-- | block/blk-core.c | 100 | ||||
-rw-r--r-- | include/linux/blkdev.h | 5 |
2 files changed, 105 insertions, 0 deletions
diff --git a/block/blk-core.c b/block/blk-core.c index 03c5a64b6ccb..02a9252107ab 100644 --- a/block/blk-core.c +++ b/block/blk-core.c | |||
@@ -2295,6 +2295,106 @@ int blk_lld_busy(struct request_queue *q) | |||
2295 | } | 2295 | } |
2296 | EXPORT_SYMBOL_GPL(blk_lld_busy); | 2296 | EXPORT_SYMBOL_GPL(blk_lld_busy); |
2297 | 2297 | ||
2298 | /** | ||
2299 | * blk_rq_unprep_clone - Helper function to free all bios in a cloned request | ||
2300 | * @rq: the clone request to be cleaned up | ||
2301 | * | ||
2302 | * Description: | ||
2303 | * Free all bios in @rq for a cloned request. | ||
2304 | */ | ||
2305 | void blk_rq_unprep_clone(struct request *rq) | ||
2306 | { | ||
2307 | struct bio *bio; | ||
2308 | |||
2309 | while ((bio = rq->bio) != NULL) { | ||
2310 | rq->bio = bio->bi_next; | ||
2311 | |||
2312 | bio_put(bio); | ||
2313 | } | ||
2314 | } | ||
2315 | EXPORT_SYMBOL_GPL(blk_rq_unprep_clone); | ||
2316 | |||
2317 | /* | ||
2318 | * Copy attributes of the original request to the clone request. | ||
2319 | * The actual data parts (e.g. ->cmd, ->buffer, ->sense) are not copied. | ||
2320 | */ | ||
2321 | static void __blk_rq_prep_clone(struct request *dst, struct request *src) | ||
2322 | { | ||
2323 | dst->cpu = src->cpu; | ||
2324 | dst->cmd_flags = (rq_data_dir(src) | REQ_NOMERGE); | ||
2325 | dst->cmd_type = src->cmd_type; | ||
2326 | dst->__sector = blk_rq_pos(src); | ||
2327 | dst->__data_len = blk_rq_bytes(src); | ||
2328 | dst->nr_phys_segments = src->nr_phys_segments; | ||
2329 | dst->ioprio = src->ioprio; | ||
2330 | dst->extra_len = src->extra_len; | ||
2331 | } | ||
2332 | |||
2333 | /** | ||
2334 | * blk_rq_prep_clone - Helper function to setup clone request | ||
2335 | * @rq: the request to be setup | ||
2336 | * @rq_src: original request to be cloned | ||
2337 | * @bs: bio_set that bios for clone are allocated from | ||
2338 | * @gfp_mask: memory allocation mask for bio | ||
2339 | * @bio_ctr: setup function to be called for each clone bio. | ||
2340 | * Returns %0 for success, non %0 for failure. | ||
2341 | * @data: private data to be passed to @bio_ctr | ||
2342 | * | ||
2343 | * Description: | ||
2344 | * Clones bios in @rq_src to @rq, and copies attributes of @rq_src to @rq. | ||
2345 | * The actual data parts of @rq_src (e.g. ->cmd, ->buffer, ->sense) | ||
2346 | * are not copied, and copying such parts is the caller's responsibility. | ||
2347 | * Also, pages which the original bios are pointing to are not copied | ||
2348 | * and the cloned bios just point same pages. | ||
2349 | * So cloned bios must be completed before original bios, which means | ||
2350 | * the caller must complete @rq before @rq_src. | ||
2351 | */ | ||
2352 | int blk_rq_prep_clone(struct request *rq, struct request *rq_src, | ||
2353 | struct bio_set *bs, gfp_t gfp_mask, | ||
2354 | int (*bio_ctr)(struct bio *, struct bio *, void *), | ||
2355 | void *data) | ||
2356 | { | ||
2357 | struct bio *bio, *bio_src; | ||
2358 | |||
2359 | if (!bs) | ||
2360 | bs = fs_bio_set; | ||
2361 | |||
2362 | blk_rq_init(NULL, rq); | ||
2363 | |||
2364 | __rq_for_each_bio(bio_src, rq_src) { | ||
2365 | bio = bio_alloc_bioset(gfp_mask, bio_src->bi_max_vecs, bs); | ||
2366 | if (!bio) | ||
2367 | goto free_and_out; | ||
2368 | |||
2369 | __bio_clone(bio, bio_src); | ||
2370 | |||
2371 | if (bio_integrity(bio_src) && | ||
2372 | bio_integrity_clone(bio, bio_src, gfp_mask)) | ||
2373 | goto free_and_out; | ||
2374 | |||
2375 | if (bio_ctr && bio_ctr(bio, bio_src, data)) | ||
2376 | goto free_and_out; | ||
2377 | |||
2378 | if (rq->bio) { | ||
2379 | rq->biotail->bi_next = bio; | ||
2380 | rq->biotail = bio; | ||
2381 | } else | ||
2382 | rq->bio = rq->biotail = bio; | ||
2383 | } | ||
2384 | |||
2385 | __blk_rq_prep_clone(rq, rq_src); | ||
2386 | |||
2387 | return 0; | ||
2388 | |||
2389 | free_and_out: | ||
2390 | if (bio) | ||
2391 | bio_free(bio, bs); | ||
2392 | blk_rq_unprep_clone(rq); | ||
2393 | |||
2394 | return -ENOMEM; | ||
2395 | } | ||
2396 | EXPORT_SYMBOL_GPL(blk_rq_prep_clone); | ||
2397 | |||
2298 | int kblockd_schedule_work(struct request_queue *q, struct work_struct *work) | 2398 | int kblockd_schedule_work(struct request_queue *q, struct work_struct *work) |
2299 | { | 2399 | { |
2300 | return queue_work(kblockd_workqueue, work); | 2400 | return queue_work(kblockd_workqueue, work); |
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 5e740a135e73..ebdfde8fe556 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h | |||
@@ -765,6 +765,11 @@ extern void blk_insert_request(struct request_queue *, struct request *, int, vo | |||
765 | extern void blk_requeue_request(struct request_queue *, struct request *); | 765 | extern void blk_requeue_request(struct request_queue *, struct request *); |
766 | extern int blk_rq_check_limits(struct request_queue *q, struct request *rq); | 766 | extern int blk_rq_check_limits(struct request_queue *q, struct request *rq); |
767 | extern int blk_lld_busy(struct request_queue *q); | 767 | extern int blk_lld_busy(struct request_queue *q); |
768 | extern int blk_rq_prep_clone(struct request *rq, struct request *rq_src, | ||
769 | struct bio_set *bs, gfp_t gfp_mask, | ||
770 | int (*bio_ctr)(struct bio *, struct bio *, void *), | ||
771 | void *data); | ||
772 | extern void blk_rq_unprep_clone(struct request *rq); | ||
768 | extern int blk_insert_cloned_request(struct request_queue *q, | 773 | extern int blk_insert_cloned_request(struct request_queue *q, |
769 | struct request *rq); | 774 | struct request *rq); |
770 | extern void blk_plug_device(struct request_queue *); | 775 | extern void blk_plug_device(struct request_queue *); |