diff options
| -rw-r--r-- | fs/bio.c | 41 | ||||
| -rw-r--r-- | include/linux/bio.h | 2 | ||||
| -rw-r--r-- | include/linux/blk_types.h | 2 |
3 files changed, 45 insertions, 0 deletions
| @@ -752,6 +752,47 @@ int bio_add_page(struct bio *bio, struct page *page, unsigned int len, | |||
| 752 | } | 752 | } |
| 753 | EXPORT_SYMBOL(bio_add_page); | 753 | EXPORT_SYMBOL(bio_add_page); |
| 754 | 754 | ||
| 755 | /** | ||
| 756 | * bio_advance - increment/complete a bio by some number of bytes | ||
| 757 | * @bio: bio to advance | ||
| 758 | * @bytes: number of bytes to complete | ||
| 759 | * | ||
| 760 | * This updates bi_sector, bi_size and bi_idx; if the number of bytes to | ||
| 761 | * complete doesn't align with a bvec boundary, then bv_len and bv_offset will | ||
| 762 | * be updated on the last bvec as well. | ||
| 763 | * | ||
| 764 | * @bio will then represent the remaining, uncompleted portion of the io. | ||
| 765 | */ | ||
| 766 | void bio_advance(struct bio *bio, unsigned bytes) | ||
| 767 | { | ||
| 768 | if (bio_integrity(bio)) | ||
| 769 | bio_integrity_advance(bio, bytes); | ||
| 770 | |||
| 771 | bio->bi_sector += bytes >> 9; | ||
| 772 | bio->bi_size -= bytes; | ||
| 773 | |||
| 774 | if (bio->bi_rw & BIO_NO_ADVANCE_ITER_MASK) | ||
| 775 | return; | ||
| 776 | |||
| 777 | while (bytes) { | ||
| 778 | if (unlikely(bio->bi_idx >= bio->bi_vcnt)) { | ||
| 779 | WARN_ONCE(1, "bio idx %d >= vcnt %d\n", | ||
| 780 | bio->bi_idx, bio->bi_vcnt); | ||
| 781 | break; | ||
| 782 | } | ||
| 783 | |||
| 784 | if (bytes >= bio_iovec(bio)->bv_len) { | ||
| 785 | bytes -= bio_iovec(bio)->bv_len; | ||
| 786 | bio->bi_idx++; | ||
| 787 | } else { | ||
| 788 | bio_iovec(bio)->bv_len -= bytes; | ||
| 789 | bio_iovec(bio)->bv_offset += bytes; | ||
| 790 | bytes = 0; | ||
| 791 | } | ||
| 792 | } | ||
| 793 | } | ||
| 794 | EXPORT_SYMBOL(bio_advance); | ||
| 795 | |||
| 755 | struct bio_map_data { | 796 | struct bio_map_data { |
| 756 | struct bio_vec *iovecs; | 797 | struct bio_vec *iovecs; |
| 757 | struct sg_iovec *sgvecs; | 798 | struct sg_iovec *sgvecs; |
diff --git a/include/linux/bio.h b/include/linux/bio.h index 669b1cb18fee..fcb4dba2d8ea 100644 --- a/include/linux/bio.h +++ b/include/linux/bio.h | |||
| @@ -248,6 +248,8 @@ extern void bio_endio(struct bio *, int); | |||
| 248 | struct request_queue; | 248 | struct request_queue; |
| 249 | extern int bio_phys_segments(struct request_queue *, struct bio *); | 249 | extern int bio_phys_segments(struct request_queue *, struct bio *); |
| 250 | 250 | ||
| 251 | extern void bio_advance(struct bio *, unsigned); | ||
| 252 | |||
| 251 | extern void bio_init(struct bio *); | 253 | extern void bio_init(struct bio *); |
| 252 | extern void bio_reset(struct bio *); | 254 | extern void bio_reset(struct bio *); |
| 253 | 255 | ||
diff --git a/include/linux/blk_types.h b/include/linux/blk_types.h index cdf11191e645..c178d25e588b 100644 --- a/include/linux/blk_types.h +++ b/include/linux/blk_types.h | |||
| @@ -197,6 +197,8 @@ enum rq_flag_bits { | |||
| 197 | REQ_SECURE) | 197 | REQ_SECURE) |
| 198 | #define REQ_CLONE_MASK REQ_COMMON_MASK | 198 | #define REQ_CLONE_MASK REQ_COMMON_MASK |
| 199 | 199 | ||
| 200 | #define BIO_NO_ADVANCE_ITER_MASK (REQ_DISCARD|REQ_WRITE_SAME) | ||
| 201 | |||
| 200 | /* This mask is used for both bio and request merge checking */ | 202 | /* This mask is used for both bio and request merge checking */ |
| 201 | #define REQ_NOMERGE_FLAGS \ | 203 | #define REQ_NOMERGE_FLAGS \ |
| 202 | (REQ_NOMERGE | REQ_STARTED | REQ_SOFTBARRIER | REQ_FLUSH | REQ_FUA) | 204 | (REQ_NOMERGE | REQ_STARTED | REQ_SOFTBARRIER | REQ_FLUSH | REQ_FUA) |
