aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md/dm-io.c
diff options
context:
space:
mode:
authorMike Snitzer <snitzer@redhat.com>2012-12-21 15:23:37 -0500
committerAlasdair G Kergon <agk@redhat.com>2012-12-21 15:23:37 -0500
commit70d6c400acc386ea910c77318688541fc32e7ce8 (patch)
tree6ab32a9b9699656c8d9147b38a776f615c1c737a /drivers/md/dm-io.c
parent4f0b70b0479101522b8645ddc1f5ee7137821db3 (diff)
dm kcopyd: add WRITE SAME support to dm_kcopyd_zero
Add WRITE SAME support to dm-io and make it accessible to dm_kcopyd_zero(). dm_kcopyd_zero() provides an asynchronous interface whereas the blkdev_issue_write_same() interface is synchronous. WRITE SAME is a SCSI command that can be leveraged for more efficient zeroing of a specified logical extent of a device which supports it. Only a single zeroed logical block is transfered to the target for each WRITE SAME and the target then writes that same block across the specified extent. The dm thin target uses this. Signed-off-by: Mike Snitzer <snitzer@redhat.com> Signed-off-by: Alasdair G Kergon <agk@redhat.com>
Diffstat (limited to 'drivers/md/dm-io.c')
-rw-r--r--drivers/md/dm-io.c23
1 files changed, 18 insertions, 5 deletions
diff --git a/drivers/md/dm-io.c b/drivers/md/dm-io.c
index 1c46f97d6664..ea49834377c8 100644
--- a/drivers/md/dm-io.c
+++ b/drivers/md/dm-io.c
@@ -287,7 +287,8 @@ static void do_region(int rw, unsigned region, struct dm_io_region *where,
287 unsigned num_bvecs; 287 unsigned num_bvecs;
288 sector_t remaining = where->count; 288 sector_t remaining = where->count;
289 struct request_queue *q = bdev_get_queue(where->bdev); 289 struct request_queue *q = bdev_get_queue(where->bdev);
290 sector_t discard_sectors; 290 unsigned short logical_block_size = queue_logical_block_size(q);
291 sector_t num_sectors;
291 292
292 /* 293 /*
293 * where->count may be zero if rw holds a flush and we need to 294 * where->count may be zero if rw holds a flush and we need to
@@ -297,7 +298,7 @@ static void do_region(int rw, unsigned region, struct dm_io_region *where,
297 /* 298 /*
298 * Allocate a suitably sized-bio. 299 * Allocate a suitably sized-bio.
299 */ 300 */
300 if (rw & REQ_DISCARD) 301 if ((rw & REQ_DISCARD) || (rw & REQ_WRITE_SAME))
301 num_bvecs = 1; 302 num_bvecs = 1;
302 else 303 else
303 num_bvecs = min_t(int, bio_get_nr_vecs(where->bdev), 304 num_bvecs = min_t(int, bio_get_nr_vecs(where->bdev),
@@ -310,9 +311,21 @@ static void do_region(int rw, unsigned region, struct dm_io_region *where,
310 store_io_and_region_in_bio(bio, io, region); 311 store_io_and_region_in_bio(bio, io, region);
311 312
312 if (rw & REQ_DISCARD) { 313 if (rw & REQ_DISCARD) {
313 discard_sectors = min_t(sector_t, q->limits.max_discard_sectors, remaining); 314 num_sectors = min_t(sector_t, q->limits.max_discard_sectors, remaining);
314 bio->bi_size = discard_sectors << SECTOR_SHIFT; 315 bio->bi_size = num_sectors << SECTOR_SHIFT;
315 remaining -= discard_sectors; 316 remaining -= num_sectors;
317 } else if (rw & REQ_WRITE_SAME) {
318 /*
319 * WRITE SAME only uses a single page.
320 */
321 dp->get_page(dp, &page, &len, &offset);
322 bio_add_page(bio, page, logical_block_size, offset);
323 num_sectors = min_t(sector_t, q->limits.max_write_same_sectors, remaining);
324 bio->bi_size = num_sectors << SECTOR_SHIFT;
325
326 offset = 0;
327 remaining -= num_sectors;
328 dp->next_page(dp);
316 } else while (remaining) { 329 } else while (remaining) {
317 /* 330 /*
318 * Try and add as many pages as possible. 331 * Try and add as many pages as possible.