aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--block/blk-core.c100
-rw-r--r--include/linux/blkdev.h5
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}
2296EXPORT_SYMBOL_GPL(blk_lld_busy); 2296EXPORT_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 */
2305void 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}
2315EXPORT_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 */
2321static 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 */
2352int 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
2389free_and_out:
2390 if (bio)
2391 bio_free(bio, bs);
2392 blk_rq_unprep_clone(rq);
2393
2394 return -ENOMEM;
2395}
2396EXPORT_SYMBOL_GPL(blk_rq_prep_clone);
2397
2298int kblockd_schedule_work(struct request_queue *q, struct work_struct *work) 2398int 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
765extern void blk_requeue_request(struct request_queue *, struct request *); 765extern void blk_requeue_request(struct request_queue *, struct request *);
766extern int blk_rq_check_limits(struct request_queue *q, struct request *rq); 766extern int blk_rq_check_limits(struct request_queue *q, struct request *rq);
767extern int blk_lld_busy(struct request_queue *q); 767extern int blk_lld_busy(struct request_queue *q);
768extern 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);
772extern void blk_rq_unprep_clone(struct request *rq);
768extern int blk_insert_cloned_request(struct request_queue *q, 773extern int blk_insert_cloned_request(struct request_queue *q,
769 struct request *rq); 774 struct request *rq);
770extern void blk_plug_device(struct request_queue *); 775extern void blk_plug_device(struct request_queue *);