/*----------------------------------------------------------------- * IO routines that accept a list of pages. *---------------------------------------------------------------*/ static void do_region(int rw, unsigned region, struct dm_io_region *where, struct dpages *dp, struct io *io) { struct bio *bio; struct page *page; unsigned long len; unsigned offset; unsigned num_bvecs; sector_t remaining = where->count; /* * where->count may be zero if rw holds a flush and we need to * send a zero-sized flush. */ do { /* * Allocate a suitably sized-bio. */ num_bvecs = dm_sector_div_up(remaining, (PAGE_SIZE >> SECTOR_SHIFT)); num_bvecs = min_t(int, bio_get_nr_vecs(where->bdev), num_bvecs); bio = bio_alloc_bioset(GFP_NOIO, num_bvecs, io->client->bios); if (!bio) { printk(KERN_WARNING "%s : %s() failed\n", __FILE__, __func__); BUG_ON(1); } bio->bi_sector = where->sector + (where->count - remaining); bio->bi_bdev = where->bdev; bio->bi_end_io = endio; bio->bi_destructor = dm_bio_destructor; store_io_and_region_in_bio(bio, io, region); /* * Try and add as many pages as possible. */ while (remaining) { dp->get_page(dp, &page, &len, &offset); len = min(len, to_bytes(remaining)); if (!bio_add_page(bio, page, len, offset)) break; offset = 0; remaining -= to_sector(len); dp->next_page(dp); } atomic_inc(&io->count); submit_bio(rw, bio); } while (remaining); }
static void do_region(int rw, unsigned region, struct dm_io_region *where, struct dpages *dp, struct io *io) { struct bio *bio; struct page *page; unsigned long len; unsigned offset; unsigned num_bvecs; sector_t remaining = where->count; struct request_queue *q = bdev_get_queue(where->bdev); sector_t discard_sectors; do { if (rw & REQ_DISCARD) num_bvecs = 1; else num_bvecs = min_t(int, bio_get_nr_vecs(where->bdev), dm_sector_div_up(remaining, (PAGE_SIZE >> SECTOR_SHIFT))); bio = bio_alloc_bioset(GFP_NOIO, num_bvecs, io->client->bios); bio->bi_sector = where->sector + (where->count - remaining); bio->bi_bdev = where->bdev; bio->bi_end_io = endio; bio->bi_destructor = dm_bio_destructor; store_io_and_region_in_bio(bio, io, region); if (rw & REQ_DISCARD) { discard_sectors = min_t(sector_t, q->limits.max_discard_sectors, remaining); bio->bi_size = discard_sectors << SECTOR_SHIFT; remaining -= discard_sectors; } else while (remaining) { dp->get_page(dp, &page, &len, &offset); len = min(len, to_bytes(remaining)); if (!bio_add_page(bio, page, len, offset)) break; offset = 0; remaining -= to_sector(len); dp->next_page(dp); } atomic_inc(&io->count); submit_bio(rw, bio); } while (remaining); }
/*----------------------------------------------------------------- * IO routines that accept a list of pages. *---------------------------------------------------------------*/ static void do_region(int rw, unsigned region, struct dm_io_region *where, struct dpages *dp, struct io *io) { struct bio *bio; struct page *page; unsigned long len; unsigned offset; unsigned num_bvecs; sector_t remaining = where->count; struct request_queue *q = bdev_get_queue(where->bdev); unsigned short logical_block_size = queue_logical_block_size(q); sector_t num_sectors; unsigned int uninitialized_var(special_cmd_max_sectors); /* * Reject unsupported discard and write same requests. */ if (rw & REQ_DISCARD) special_cmd_max_sectors = q->limits.max_discard_sectors; else if (rw & REQ_WRITE_SAME) special_cmd_max_sectors = q->limits.max_write_same_sectors; if ((rw & (REQ_DISCARD | REQ_WRITE_SAME)) && special_cmd_max_sectors == 0) { dec_count(io, region, -EOPNOTSUPP); return; } /* * where->count may be zero if rw holds a flush and we need to * send a zero-sized flush. */ do { /* * Allocate a suitably sized-bio. */ if ((rw & REQ_DISCARD) || (rw & REQ_WRITE_SAME)) num_bvecs = 1; else num_bvecs = min_t(int, BIO_MAX_PAGES, dm_sector_div_up(remaining, (PAGE_SIZE >> SECTOR_SHIFT))); bio = bio_alloc_bioset(GFP_NOIO, num_bvecs, io->client->bios); bio->bi_iter.bi_sector = where->sector + (where->count - remaining); bio->bi_bdev = where->bdev; bio->bi_end_io = endio; store_io_and_region_in_bio(bio, io, region); if (rw & REQ_DISCARD) { num_sectors = min_t(sector_t, special_cmd_max_sectors, remaining); bio->bi_iter.bi_size = num_sectors << SECTOR_SHIFT; remaining -= num_sectors; } else if (rw & REQ_WRITE_SAME) { /* * WRITE SAME only uses a single page. */ dp->get_page(dp, &page, &len, &offset); bio_add_page(bio, page, logical_block_size, offset); num_sectors = min_t(sector_t, special_cmd_max_sectors, remaining); bio->bi_iter.bi_size = num_sectors << SECTOR_SHIFT; offset = 0; remaining -= num_sectors; dp->next_page(dp); } else while (remaining) { /* * Try and add as many pages as possible. */ dp->get_page(dp, &page, &len, &offset); len = min(len, to_bytes(remaining)); if (!bio_add_page(bio, page, len, offset)) break; offset = 0; remaining -= to_sector(len); dp->next_page(dp); } atomic_inc(&io->count); submit_bio(rw, bio); } while (remaining); }