Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3c892a09 authored by Ming Lei's avatar Ming Lei Committed by Jens Axboe
Browse files

block: bounce: don't access bio->bi_io_vec in copy_to_high_bio_irq



Firstly this patch introduces BVEC_ITER_ALL_INIT for iterating one bio
from start to end.

As we need to support multipage bvecs, don't access bio->bi_io_vec
in copy_to_high_bio_irq(), and just use the standard iterator for that.

Signed-off-by: default avatarMing Lei <ming.lei@redhat.com>
Signed-off-by: default avatarJens Axboe <axboe@kernel.dk>
parent 7891f05c
Loading
Loading
Loading
Loading
+11 −5
Original line number Original line Diff line number Diff line
@@ -113,24 +113,30 @@ int init_emergency_isa_pool(void)
static void copy_to_high_bio_irq(struct bio *to, struct bio *from)
static void copy_to_high_bio_irq(struct bio *to, struct bio *from)
{
{
	unsigned char *vfrom;
	unsigned char *vfrom;
	struct bio_vec tovec, *fromvec = from->bi_io_vec;
	struct bio_vec tovec, fromvec;
	struct bvec_iter iter;
	struct bvec_iter iter;
	/*
	 * The bio of @from is created by bounce, so we can iterate
	 * its bvec from start to end, but the @from->bi_iter can't be
	 * trusted because it might be changed by splitting.
	 */
	struct bvec_iter from_iter = BVEC_ITER_ALL_INIT;


	bio_for_each_segment(tovec, to, iter) {
	bio_for_each_segment(tovec, to, iter) {
		if (tovec.bv_page != fromvec->bv_page) {
		fromvec = bio_iter_iovec(from, from_iter);
		if (tovec.bv_page != fromvec.bv_page) {
			/*
			/*
			 * fromvec->bv_offset and fromvec->bv_len might have
			 * fromvec->bv_offset and fromvec->bv_len might have
			 * been modified by the block layer, so use the original
			 * been modified by the block layer, so use the original
			 * copy, bounce_copy_vec already uses tovec->bv_len
			 * copy, bounce_copy_vec already uses tovec->bv_len
			 */
			 */
			vfrom = page_address(fromvec->bv_page) +
			vfrom = page_address(fromvec.bv_page) +
				tovec.bv_offset;
				tovec.bv_offset;


			bounce_copy_vec(&tovec, vfrom);
			bounce_copy_vec(&tovec, vfrom);
			flush_dcache_page(tovec.bv_page);
			flush_dcache_page(tovec.bv_page);
		}
		}

		bio_advance_iter(from, &from_iter, tovec.bv_len);
		fromvec++;
	}
	}
}
}


+9 −0
Original line number Original line Diff line number Diff line
@@ -125,4 +125,13 @@ static inline bool bvec_iter_rewind(const struct bio_vec *bv,
		((bvl = bvec_iter_bvec((bio_vec), (iter))), 1);	\
		((bvl = bvec_iter_bvec((bio_vec), (iter))), 1);	\
	     bvec_iter_advance((bio_vec), &(iter), (bvl).bv_len))
	     bvec_iter_advance((bio_vec), &(iter), (bvl).bv_len))


/* for iterating one bio from start to end */
#define BVEC_ITER_ALL_INIT (struct bvec_iter)				\
{									\
	.bi_sector	= 0,						\
	.bi_size	= UINT_MAX,					\
	.bi_idx		= 0,						\
	.bi_bvec_done	= 0,						\
}

#endif /* __LINUX_BVEC_ITER_H */
#endif /* __LINUX_BVEC_ITER_H */