@@ -527,17 +527,34 @@ struct bio *bio_alloc_bioset(gfp_t gfp_mask, unsigned int nr_iovecs,
}
EXPORT_SYMBOL(bio_alloc_bioset);
+void zero_fill_bvec(const struct bio_vec *bvec)
+{
+ struct page *page = bvec->bv_page;
+ u32 offset = bvec->bv_offset;
+ u32 left = bvec->bv_len;
+
+ while (left) {
+ u32 len = min_t(u32, left, PAGE_SIZE - offset);
+ void *kaddr;
+
+ kaddr = kmap_atomic(page);
+ memset(kaddr + offset, 0, len);
+ flush_dcache_page(page);
+ kunmap_atomic(kaddr);
+ page++;
+ left -= len;
+ offset = 0;
+ }
+}
+EXPORT_SYMBOL(zero_fill_bvec);
+
void zero_fill_bio_iter(struct bio *bio, struct bvec_iter start)
{
- unsigned long flags;
struct bio_vec bv;
struct bvec_iter iter;
__bio_for_each_segment(bv, bio, iter, start) {
- char *data = bvec_kmap_irq(&bv, &flags);
- memset(data, 0, bv.bv_len);
- flush_dcache_page(bv.bv_page);
- bvec_kunmap_irq(data, &flags);
+ zero_fill_bvec(&bv);
}
}
EXPORT_SYMBOL(zero_fill_bio_iter);
@@ -455,6 +455,7 @@ extern void bio_copy_data_iter(struct bio *dst, struct bvec_iter *dst_iter,
extern void bio_copy_data(struct bio *dst, struct bio *src);
extern void bio_list_copy_data(struct bio *dst, struct bio *src);
extern void bio_free_pages(struct bio *bio);
+void zero_fill_bvec(const struct bio_vec *bvec);
void zero_fill_bio_iter(struct bio *bio, struct bvec_iter iter);
void bio_truncate(struct bio *bio, unsigned new_size);
void guard_bio_eod(struct bio *bio);
Multiple block drivers use zero_fill_bio() to zero-initialize the data buffer used for read operations. Make sure that all pages are zeroed instead of only the first if one or more multi-page bvecs are used to describe the data buffer. Cc: Christoph Hellwig <hch@lst.de> Cc: Ming Lei <ming.lei@redhat.com> Cc: stable@vger.kernel.org Signed-off-by: Bart Van Assche <bvanassche@acm.org> --- block/bio.c | 27 ++++++++++++++++++++++----- include/linux/bio.h | 1 + 2 files changed, 23 insertions(+), 5 deletions(-)