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 *); |
