Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 147092
b: refs/heads/master
c: b0fd271
h: refs/heads/master
v: v3
  • Loading branch information
Kiyoshi Ueda authored and Jens Axboe committed Jun 11, 2009
1 parent d109a9c commit e1b3a9f
Show file tree
Hide file tree
Showing 3 changed files with 106 additions and 1 deletion.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 5e50b9ef975219304cc91d601530994861585bfe
refs/heads/master: b0fd271d5fba0b2d00888363f3869e3f9b26caa9
100 changes: 100 additions & 0 deletions trunk/block/blk-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -2295,6 +2295,106 @@ int blk_lld_busy(struct request_queue *q)
}
EXPORT_SYMBOL_GPL(blk_lld_busy);

/**
* blk_rq_unprep_clone - Helper function to free all bios in a cloned request
* @rq: the clone request to be cleaned up
*
* Description:
* Free all bios in @rq for a cloned request.
*/
void blk_rq_unprep_clone(struct request *rq)
{
struct bio *bio;

while ((bio = rq->bio) != NULL) {
rq->bio = bio->bi_next;

bio_put(bio);
}
}
EXPORT_SYMBOL_GPL(blk_rq_unprep_clone);

/*
* Copy attributes of the original request to the clone request.
* The actual data parts (e.g. ->cmd, ->buffer, ->sense) are not copied.
*/
static void __blk_rq_prep_clone(struct request *dst, struct request *src)
{
dst->cpu = src->cpu;
dst->cmd_flags = (rq_data_dir(src) | REQ_NOMERGE);
dst->cmd_type = src->cmd_type;
dst->__sector = blk_rq_pos(src);
dst->__data_len = blk_rq_bytes(src);
dst->nr_phys_segments = src->nr_phys_segments;
dst->ioprio = src->ioprio;
dst->extra_len = src->extra_len;
}

/**
* blk_rq_prep_clone - Helper function to setup clone request
* @rq: the request to be setup
* @rq_src: original request to be cloned
* @bs: bio_set that bios for clone are allocated from
* @gfp_mask: memory allocation mask for bio
* @bio_ctr: setup function to be called for each clone bio.
* Returns %0 for success, non %0 for failure.
* @data: private data to be passed to @bio_ctr
*
* Description:
* Clones bios in @rq_src to @rq, and copies attributes of @rq_src to @rq.
* The actual data parts of @rq_src (e.g. ->cmd, ->buffer, ->sense)
* are not copied, and copying such parts is the caller's responsibility.
* Also, pages which the original bios are pointing to are not copied
* and the cloned bios just point same pages.
* So cloned bios must be completed before original bios, which means
* the caller must complete @rq before @rq_src.
*/
int blk_rq_prep_clone(struct request *rq, struct request *rq_src,
struct bio_set *bs, gfp_t gfp_mask,
int (*bio_ctr)(struct bio *, struct bio *, void *),
void *data)
{
struct bio *bio, *bio_src;

if (!bs)
bs = fs_bio_set;

blk_rq_init(NULL, rq);

__rq_for_each_bio(bio_src, rq_src) {
bio = bio_alloc_bioset(gfp_mask, bio_src->bi_max_vecs, bs);
if (!bio)
goto free_and_out;

__bio_clone(bio, bio_src);

if (bio_integrity(bio_src) &&
bio_integrity_clone(bio, bio_src, gfp_mask))
goto free_and_out;

if (bio_ctr && bio_ctr(bio, bio_src, data))
goto free_and_out;

if (rq->bio) {
rq->biotail->bi_next = bio;
rq->biotail = bio;
} else
rq->bio = rq->biotail = bio;
}

__blk_rq_prep_clone(rq, rq_src);

return 0;

free_and_out:
if (bio)
bio_free(bio, bs);
blk_rq_unprep_clone(rq);

return -ENOMEM;
}
EXPORT_SYMBOL_GPL(blk_rq_prep_clone);

int kblockd_schedule_work(struct request_queue *q, struct work_struct *work)
{
return queue_work(kblockd_workqueue, work);
Expand Down
5 changes: 5 additions & 0 deletions trunk/include/linux/blkdev.h
Original file line number Diff line number Diff line change
Expand Up @@ -765,6 +765,11 @@ extern void blk_insert_request(struct request_queue *, struct request *, int, vo
extern void blk_requeue_request(struct request_queue *, struct request *);
extern int blk_rq_check_limits(struct request_queue *q, struct request *rq);
extern int blk_lld_busy(struct request_queue *q);
extern int blk_rq_prep_clone(struct request *rq, struct request *rq_src,
struct bio_set *bs, gfp_t gfp_mask,
int (*bio_ctr)(struct bio *, struct bio *, void *),
void *data);
extern void blk_rq_unprep_clone(struct request *rq);
extern int blk_insert_cloned_request(struct request_queue *q,
struct request *rq);
extern void blk_plug_device(struct request_queue *);
Expand Down

0 comments on commit e1b3a9f

Please sign in to comment.