Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

dm io: deal with wandering queue limits when handling REQ_DISCARD and REQ_WRITE_SAME

Since it's possible for the discard and write same queue limits to
change while the upper level command is being sliced and diced, fix up
both of them (a) to reject IO if the special command is unsupported at
the start of the function and (b) read the limits once and let the
commands error out on their own if the status happens to change.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
Signed-off-by: Mike Snitzer <snitzer@redhat.com>
Cc: stable@vger.kernel.org

authored by

Darrick J. Wong and committed by
Mike Snitzer
e5db2980 09ee96b2

+11 -4
+11 -4
drivers/md/dm-io.c
··· 289 289 struct request_queue *q = bdev_get_queue(where->bdev); 290 290 unsigned short logical_block_size = queue_logical_block_size(q); 291 291 sector_t num_sectors; 292 + unsigned int uninitialized_var(special_cmd_max_sectors); 292 293 293 - /* Reject unsupported discard requests */ 294 - if ((rw & REQ_DISCARD) && !blk_queue_discard(q)) { 294 + /* 295 + * Reject unsupported discard and write same requests. 296 + */ 297 + if (rw & REQ_DISCARD) 298 + special_cmd_max_sectors = q->limits.max_discard_sectors; 299 + else if (rw & REQ_WRITE_SAME) 300 + special_cmd_max_sectors = q->limits.max_write_same_sectors; 301 + if ((rw & (REQ_DISCARD | REQ_WRITE_SAME)) && special_cmd_max_sectors == 0) { 295 302 dec_count(io, region, -EOPNOTSUPP); 296 303 return; 297 304 } ··· 324 317 store_io_and_region_in_bio(bio, io, region); 325 318 326 319 if (rw & REQ_DISCARD) { 327 - num_sectors = min_t(sector_t, q->limits.max_discard_sectors, remaining); 320 + num_sectors = min_t(sector_t, special_cmd_max_sectors, remaining); 328 321 bio->bi_iter.bi_size = num_sectors << SECTOR_SHIFT; 329 322 remaining -= num_sectors; 330 323 } else if (rw & REQ_WRITE_SAME) { ··· 333 326 */ 334 327 dp->get_page(dp, &page, &len, &offset); 335 328 bio_add_page(bio, page, logical_block_size, offset); 336 - num_sectors = min_t(sector_t, q->limits.max_write_same_sectors, remaining); 329 + num_sectors = min_t(sector_t, special_cmd_max_sectors, remaining); 337 330 bio->bi_iter.bi_size = num_sectors << SECTOR_SHIFT; 338 331 339 332 offset = 0;