block: introduce bio_copy_data_partial
Turns out we can use bio_copy_data in raid1's write behind, and we can make alloc_behind_pages() more clean/efficient, but we need to partial version of bio_copy_data(). Signed-off-by: Ming Lei <tom.leiming@gmail.com> Reviewed-by: Jens Axboe <axboe@fb.com> Signed-off-by: Shaohua Li <shli@fb.com>
This commit is contained in:
parent
60928a91b0
commit
6f8802852f
2 changed files with 49 additions and 13 deletions
60
block/bio.c
60
block/bio.c
|
@ -1025,19 +1025,8 @@ int bio_alloc_pages(struct bio *bio, gfp_t gfp_mask)
|
|||
}
|
||||
EXPORT_SYMBOL(bio_alloc_pages);
|
||||
|
||||
/**
|
||||
* bio_copy_data - copy contents of data buffers from one chain of bios to
|
||||
* another
|
||||
* @src: source bio list
|
||||
* @dst: destination bio list
|
||||
*
|
||||
* If @src and @dst are single bios, bi_next must be NULL - otherwise, treats
|
||||
* @src and @dst as linked lists of bios.
|
||||
*
|
||||
* Stops when it reaches the end of either @src or @dst - that is, copies
|
||||
* min(src->bi_size, dst->bi_size) bytes (or the equivalent for lists of bios).
|
||||
*/
|
||||
void bio_copy_data(struct bio *dst, struct bio *src)
|
||||
static void __bio_copy_data(struct bio *dst, struct bio *src,
|
||||
int offset, int size)
|
||||
{
|
||||
struct bvec_iter src_iter, dst_iter;
|
||||
struct bio_vec src_bv, dst_bv;
|
||||
|
@ -1047,6 +1036,12 @@ void bio_copy_data(struct bio *dst, struct bio *src)
|
|||
src_iter = src->bi_iter;
|
||||
dst_iter = dst->bi_iter;
|
||||
|
||||
/* for supporting partial copy */
|
||||
if (offset || size != src->bi_iter.bi_size) {
|
||||
bio_advance_iter(src, &src_iter, offset);
|
||||
src_iter.bi_size = size;
|
||||
}
|
||||
|
||||
while (1) {
|
||||
if (!src_iter.bi_size) {
|
||||
src = src->bi_next;
|
||||
|
@ -1083,8 +1078,47 @@ void bio_copy_data(struct bio *dst, struct bio *src)
|
|||
bio_advance_iter(dst, &dst_iter, bytes);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* bio_copy_data - copy contents of data buffers from one chain of bios to
|
||||
* another
|
||||
* @src: source bio list
|
||||
* @dst: destination bio list
|
||||
*
|
||||
* If @src and @dst are single bios, bi_next must be NULL - otherwise, treats
|
||||
* @src and @dst as linked lists of bios.
|
||||
*
|
||||
* Stops when it reaches the end of either @src or @dst - that is, copies
|
||||
* min(src->bi_size, dst->bi_size) bytes (or the equivalent for lists of bios).
|
||||
*/
|
||||
void bio_copy_data(struct bio *dst, struct bio *src)
|
||||
{
|
||||
__bio_copy_data(dst, src, 0, src->bi_iter.bi_size);
|
||||
}
|
||||
EXPORT_SYMBOL(bio_copy_data);
|
||||
|
||||
/**
|
||||
* bio_copy_data_partial - copy partial contents of data buffers from one
|
||||
* chain of bios to another
|
||||
* @dst: destination bio list
|
||||
* @src: source bio list
|
||||
* @offset: starting copy from the offset
|
||||
* @size: how many bytes to copy
|
||||
*
|
||||
* If @src and @dst are single bios, bi_next must be NULL - otherwise, treats
|
||||
* @src and @dst as linked lists of bios.
|
||||
*
|
||||
* Stops when it reaches the end of either @src or @dst - that is, copies
|
||||
* min(src->bi_size, dst->bi_size) bytes (or the equivalent for lists of bios).
|
||||
*/
|
||||
void bio_copy_data_partial(struct bio *dst, struct bio *src,
|
||||
int offset, int size)
|
||||
{
|
||||
__bio_copy_data(dst, src, offset, size);
|
||||
|
||||
}
|
||||
EXPORT_SYMBOL(bio_copy_data_partial);
|
||||
|
||||
struct bio_map_data {
|
||||
int is_our_pages;
|
||||
struct iov_iter iter;
|
||||
|
|
|
@ -468,6 +468,8 @@ static inline void bio_flush_dcache_pages(struct bio *bi)
|
|||
#endif
|
||||
|
||||
extern void bio_copy_data(struct bio *dst, struct bio *src);
|
||||
extern void bio_copy_data_partial(struct bio *dst, struct bio *src,
|
||||
int offset, int size);
|
||||
extern int bio_alloc_pages(struct bio *bio, gfp_t gfp);
|
||||
extern void bio_free_pages(struct bio *bio);
|
||||
|
||||
|
|
Loading…
Reference in a new issue