aboutsummaryrefslogtreecommitdiffstats
path: root/block
diff options
context:
space:
mode:
authorKiyoshi Ueda <k-ueda@ct.jp.nec.com>2009-06-11 07:10:16 -0400
committerJens Axboe <jens.axboe@oracle.com>2009-06-11 07:11:05 -0400
commitb0fd271d5fba0b2d00888363f3869e3f9b26caa9 (patch)
tree0ffd49c013476e3dc96c8bcb2ddc4c1828797be5 /block
parent5e50b9ef975219304cc91d601530994861585bfe (diff)
block: add request clone interface (v2)
This patch adds the following 2 interfaces for request-stacking drivers: - blk_rq_prep_clone(struct request *clone, struct request *orig, struct bio_set *bs, gfp_t gfp_mask, int (*bio_ctr)(struct bio *, struct bio*, void *), void *data) * Clones bios in the original request to the clone request (bio_ctr is called for each cloned bios.) * Copies attributes of the original request to the clone request. The actual data parts (e.g. ->cmd, ->buffer, ->sense) are not copied. - blk_rq_unprep_clone(struct request *clone) * Frees cloned bios from the clone request. Request stacking drivers (e.g. request-based dm) need to make a clone request for a submitted request and dispatch it to other devices. To allocate request for the clone, request stacking drivers may not be able to use blk_get_request() because the allocation may be done in an irq-disabled context. So blk_rq_prep_clone() takes a request allocated by the caller as an argument. For each clone bio in the clone request, request stacking drivers should be able to set up their own completion handler. So blk_rq_prep_clone() takes a callback function which is called for each clone bio, and a pointer for private data which is passed to the callback. NOTE: blk_rq_prep_clone() doesn't copy any actual data of the original request. Pages are shared between original bios and cloned bios. So caller must not complete the original request before the clone request. Signed-off-by: Kiyoshi Ueda <k-ueda@ct.jp.nec.com> Signed-off-by: Jun'ichi Nomura <j-nomura@ce.jp.nec.com> Cc: Boaz Harrosh <bharrosh@panasas.com> Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
Diffstat (limited to 'block')
-rw-r--r--block/blk-core.c100
1 files changed, 100 insertions, 0 deletions
diff --git a/block/blk-core.c b/block/blk-core.c
index 03c5a64b6cc..02a9252107a 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);