diff options
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/md/dm-io.c | 23 | ||||
| -rw-r--r-- | drivers/md/dm-kcopyd.c | 18 | ||||
| -rw-r--r-- | drivers/md/dm-thin.c | 2 |
3 files changed, 33 insertions, 10 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. |
diff --git a/drivers/md/dm-kcopyd.c b/drivers/md/dm-kcopyd.c index bed444c93d8d..68c02673263b 100644 --- a/drivers/md/dm-kcopyd.c +++ b/drivers/md/dm-kcopyd.c | |||
| @@ -349,7 +349,7 @@ static void complete_io(unsigned long error, void *context) | |||
| 349 | struct dm_kcopyd_client *kc = job->kc; | 349 | struct dm_kcopyd_client *kc = job->kc; |
| 350 | 350 | ||
| 351 | if (error) { | 351 | if (error) { |
| 352 | if (job->rw == WRITE) | 352 | if (job->rw & WRITE) |
| 353 | job->write_err |= error; | 353 | job->write_err |= error; |
| 354 | else | 354 | else |
| 355 | job->read_err = 1; | 355 | job->read_err = 1; |
| @@ -361,7 +361,7 @@ static void complete_io(unsigned long error, void *context) | |||
| 361 | } | 361 | } |
| 362 | } | 362 | } |
| 363 | 363 | ||
| 364 | if (job->rw == WRITE) | 364 | if (job->rw & WRITE) |
| 365 | push(&kc->complete_jobs, job); | 365 | push(&kc->complete_jobs, job); |
| 366 | 366 | ||
| 367 | else { | 367 | else { |
| @@ -432,7 +432,7 @@ static int process_jobs(struct list_head *jobs, struct dm_kcopyd_client *kc, | |||
| 432 | 432 | ||
| 433 | if (r < 0) { | 433 | if (r < 0) { |
| 434 | /* error this rogue job */ | 434 | /* error this rogue job */ |
| 435 | if (job->rw == WRITE) | 435 | if (job->rw & WRITE) |
| 436 | job->write_err = (unsigned long) -1L; | 436 | job->write_err = (unsigned long) -1L; |
| 437 | else | 437 | else |
| 438 | job->read_err = 1; | 438 | job->read_err = 1; |
| @@ -585,6 +585,7 @@ int dm_kcopyd_copy(struct dm_kcopyd_client *kc, struct dm_io_region *from, | |||
| 585 | unsigned int flags, dm_kcopyd_notify_fn fn, void *context) | 585 | unsigned int flags, dm_kcopyd_notify_fn fn, void *context) |
| 586 | { | 586 | { |
| 587 | struct kcopyd_job *job; | 587 | struct kcopyd_job *job; |
| 588 | int i; | ||
| 588 | 589 | ||
| 589 | /* | 590 | /* |
| 590 | * Allocate an array of jobs consisting of one master job | 591 | * Allocate an array of jobs consisting of one master job |
| @@ -611,7 +612,16 @@ int dm_kcopyd_copy(struct dm_kcopyd_client *kc, struct dm_io_region *from, | |||
| 611 | memset(&job->source, 0, sizeof job->source); | 612 | memset(&job->source, 0, sizeof job->source); |
| 612 | job->source.count = job->dests[0].count; | 613 | job->source.count = job->dests[0].count; |
| 613 | job->pages = &zero_page_list; | 614 | job->pages = &zero_page_list; |
| 614 | job->rw = WRITE; | 615 | |
| 616 | /* | ||
| 617 | * Use WRITE SAME to optimize zeroing if all dests support it. | ||
| 618 | */ | ||
| 619 | job->rw = WRITE | REQ_WRITE_SAME; | ||
| 620 | for (i = 0; i < job->num_dests; i++) | ||
| 621 | if (!bdev_write_same(job->dests[i].bdev)) { | ||
| 622 | job->rw = WRITE; | ||
| 623 | break; | ||
| 624 | } | ||
| 615 | } | 625 | } |
| 616 | 626 | ||
| 617 | job->fn = fn; | 627 | job->fn = fn; |
diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c index fba378f234a5..4b940745ba9e 100644 --- a/drivers/md/dm-thin.c +++ b/drivers/md/dm-thin.c | |||
| @@ -2779,7 +2779,7 @@ static void thin_io_hints(struct dm_target *ti, struct queue_limits *limits) | |||
| 2779 | 2779 | ||
| 2780 | static struct target_type thin_target = { | 2780 | static struct target_type thin_target = { |
| 2781 | .name = "thin", | 2781 | .name = "thin", |
| 2782 | .version = {1, 5, 0}, | 2782 | .version = {1, 6, 0}, |
| 2783 | .module = THIS_MODULE, | 2783 | .module = THIS_MODULE, |
| 2784 | .ctr = thin_ctr, | 2784 | .ctr = thin_ctr, |
| 2785 | .dtr = thin_dtr, | 2785 | .dtr = thin_dtr, |
