bounce: Refactor __blk_queue_bounce to not use bi_io_vec
A bunch of what __blk_queue_bounce() was doing was problematic for the immutable bvec work; this cleans that up and the code is quite a bit smaller, too. The __bio_for_each_segment() in copy_to_high_bio_irq() was changed because that one's looping over the original bio, not the bounce bio - a later patch renames __bio_for_each_segment() -> bio_for_each_segment_all(), and documents that bio_for_each_segment_all() is only for code that owns the bio. Signed-off-by: Kent Overstreet <koverstreet@google.com> CC: Jens Axboe <axboe@kernel.dk>
This commit is contained in:
parent
d3b45c2a05
commit
6bc454d150
1 changed files with 19 additions and 54 deletions
73
mm/bounce.c
73
mm/bounce.c
|
@ -101,7 +101,7 @@ static void copy_to_high_bio_irq(struct bio *to, struct bio *from)
|
||||||
struct bio_vec *tovec, *fromvec;
|
struct bio_vec *tovec, *fromvec;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
__bio_for_each_segment(tovec, to, i, 0) {
|
bio_for_each_segment(tovec, to, i) {
|
||||||
fromvec = from->bi_io_vec + i;
|
fromvec = from->bi_io_vec + i;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -218,78 +218,43 @@ static int must_snapshot_stable_pages(struct request_queue *q, struct bio *bio)
|
||||||
static void __blk_queue_bounce(struct request_queue *q, struct bio **bio_orig,
|
static void __blk_queue_bounce(struct request_queue *q, struct bio **bio_orig,
|
||||||
mempool_t *pool, int force)
|
mempool_t *pool, int force)
|
||||||
{
|
{
|
||||||
struct page *page;
|
struct bio *bio;
|
||||||
struct bio *bio = NULL;
|
int rw = bio_data_dir(*bio_orig);
|
||||||
int i, rw = bio_data_dir(*bio_orig);
|
|
||||||
struct bio_vec *to, *from;
|
struct bio_vec *to, *from;
|
||||||
|
unsigned i;
|
||||||
|
|
||||||
bio_for_each_segment(from, *bio_orig, i) {
|
bio_for_each_segment(from, *bio_orig, i)
|
||||||
page = from->bv_page;
|
if (page_to_pfn(from->bv_page) > queue_bounce_pfn(q))
|
||||||
|
goto bounce;
|
||||||
|
|
||||||
|
return;
|
||||||
|
bounce:
|
||||||
|
bio = bio_clone_bioset(*bio_orig, GFP_NOIO, fs_bio_set);
|
||||||
|
|
||||||
|
bio_for_each_segment(to, bio, i) {
|
||||||
|
struct page *page = to->bv_page;
|
||||||
|
|
||||||
/*
|
|
||||||
* is destination page below bounce pfn?
|
|
||||||
*/
|
|
||||||
if (page_to_pfn(page) <= queue_bounce_pfn(q) && !force)
|
if (page_to_pfn(page) <= queue_bounce_pfn(q) && !force)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/*
|
|
||||||
* irk, bounce it
|
|
||||||
*/
|
|
||||||
if (!bio) {
|
|
||||||
unsigned int cnt = (*bio_orig)->bi_vcnt;
|
|
||||||
|
|
||||||
bio = bio_alloc(GFP_NOIO, cnt);
|
|
||||||
memset(bio->bi_io_vec, 0, cnt * sizeof(struct bio_vec));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
to = bio->bi_io_vec + i;
|
|
||||||
|
|
||||||
to->bv_page = mempool_alloc(pool, q->bounce_gfp);
|
|
||||||
to->bv_len = from->bv_len;
|
|
||||||
to->bv_offset = from->bv_offset;
|
|
||||||
inc_zone_page_state(to->bv_page, NR_BOUNCE);
|
inc_zone_page_state(to->bv_page, NR_BOUNCE);
|
||||||
|
to->bv_page = mempool_alloc(pool, q->bounce_gfp);
|
||||||
|
|
||||||
if (rw == WRITE) {
|
if (rw == WRITE) {
|
||||||
char *vto, *vfrom;
|
char *vto, *vfrom;
|
||||||
|
|
||||||
flush_dcache_page(from->bv_page);
|
flush_dcache_page(page);
|
||||||
|
|
||||||
vto = page_address(to->bv_page) + to->bv_offset;
|
vto = page_address(to->bv_page) + to->bv_offset;
|
||||||
vfrom = kmap(from->bv_page) + from->bv_offset;
|
vfrom = kmap_atomic(page) + to->bv_offset;
|
||||||
memcpy(vto, vfrom, to->bv_len);
|
memcpy(vto, vfrom, to->bv_len);
|
||||||
kunmap(from->bv_page);
|
kunmap_atomic(vfrom);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* no pages bounced
|
|
||||||
*/
|
|
||||||
if (!bio)
|
|
||||||
return;
|
|
||||||
|
|
||||||
trace_block_bio_bounce(q, *bio_orig);
|
trace_block_bio_bounce(q, *bio_orig);
|
||||||
|
|
||||||
/*
|
|
||||||
* at least one page was bounced, fill in possible non-highmem
|
|
||||||
* pages
|
|
||||||
*/
|
|
||||||
__bio_for_each_segment(from, *bio_orig, i, 0) {
|
|
||||||
to = bio_iovec_idx(bio, i);
|
|
||||||
if (!to->bv_page) {
|
|
||||||
to->bv_page = from->bv_page;
|
|
||||||
to->bv_len = from->bv_len;
|
|
||||||
to->bv_offset = from->bv_offset;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bio->bi_bdev = (*bio_orig)->bi_bdev;
|
|
||||||
bio->bi_flags |= (1 << BIO_BOUNCED);
|
bio->bi_flags |= (1 << BIO_BOUNCED);
|
||||||
bio->bi_sector = (*bio_orig)->bi_sector;
|
|
||||||
bio->bi_rw = (*bio_orig)->bi_rw;
|
|
||||||
|
|
||||||
bio->bi_vcnt = (*bio_orig)->bi_vcnt;
|
|
||||||
bio->bi_idx = (*bio_orig)->bi_idx;
|
|
||||||
bio->bi_size = (*bio_orig)->bi_size;
|
|
||||||
|
|
||||||
if (pool == page_pool) {
|
if (pool == page_pool) {
|
||||||
bio->bi_end_io = bounce_end_io_write;
|
bio->bi_end_io = bounce_end_io_write;
|
||||||
|
|
Loading…
Add table
Reference in a new issue