]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob
21733b6afa57767452a0d59e7a8c1eb5e9cc27ac
[thirdparty/kernel/stable-queue.git] /
1 From e5db29806b99ce2b2640d2e4d4fcb983cea115c5 Mon Sep 17 00:00:00 2001
2 From: "Darrick J. Wong" <darrick.wong@oracle.com>
3 Date: Fri, 27 Feb 2015 10:44:38 -0800
4 Subject: dm io: deal with wandering queue limits when handling REQ_DISCARD and REQ_WRITE_SAME
5
6 From: "Darrick J. Wong" <darrick.wong@oracle.com>
7
8 commit e5db29806b99ce2b2640d2e4d4fcb983cea115c5 upstream.
9
10 Since it's possible for the discard and write same queue limits to
11 change while the upper level command is being sliced and diced, fix up
12 both of them (a) to reject IO if the special command is unsupported at
13 the start of the function and (b) read the limits once and let the
14 commands error out on their own if the status happens to change.
15
16 Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
17 Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
18 Signed-off-by: Mike Snitzer <snitzer@redhat.com>
19 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
20
21 ---
22 drivers/md/dm-io.c | 15 +++++++++++----
23 1 file changed, 11 insertions(+), 4 deletions(-)
24
25 --- a/drivers/md/dm-io.c
26 +++ b/drivers/md/dm-io.c
27 @@ -291,9 +291,16 @@ static void do_region(int rw, unsigned r
28 struct request_queue *q = bdev_get_queue(where->bdev);
29 unsigned short logical_block_size = queue_logical_block_size(q);
30 sector_t num_sectors;
31 + unsigned int uninitialized_var(special_cmd_max_sectors);
32
33 - /* Reject unsupported discard requests */
34 - if ((rw & REQ_DISCARD) && !blk_queue_discard(q)) {
35 + /*
36 + * Reject unsupported discard and write same requests.
37 + */
38 + if (rw & REQ_DISCARD)
39 + special_cmd_max_sectors = q->limits.max_discard_sectors;
40 + else if (rw & REQ_WRITE_SAME)
41 + special_cmd_max_sectors = q->limits.max_write_same_sectors;
42 + if ((rw & (REQ_DISCARD | REQ_WRITE_SAME)) && special_cmd_max_sectors == 0) {
43 dec_count(io, region, -EOPNOTSUPP);
44 return;
45 }
46 @@ -319,7 +326,7 @@ static void do_region(int rw, unsigned r
47 store_io_and_region_in_bio(bio, io, region);
48
49 if (rw & REQ_DISCARD) {
50 - num_sectors = min_t(sector_t, q->limits.max_discard_sectors, remaining);
51 + num_sectors = min_t(sector_t, special_cmd_max_sectors, remaining);
52 bio->bi_iter.bi_size = num_sectors << SECTOR_SHIFT;
53 remaining -= num_sectors;
54 } else if (rw & REQ_WRITE_SAME) {
55 @@ -328,7 +335,7 @@ static void do_region(int rw, unsigned r
56 */
57 dp->get_page(dp, &page, &len, &offset);
58 bio_add_page(bio, page, logical_block_size, offset);
59 - num_sectors = min_t(sector_t, q->limits.max_write_same_sectors, remaining);
60 + num_sectors = min_t(sector_t, special_cmd_max_sectors, remaining);
61 bio->bi_iter.bi_size = num_sectors << SECTOR_SHIFT;
62
63 offset = 0;