]>
Commit | Line | Data |
---|---|---|
320f929d DM |
1 | From 6b7e9cde49691e04314342b7dce90c67ad567fcc Mon Sep 17 00:00:00 2001 |
2 | From: "Martin K. Petersen" <martin.petersen@oracle.com> | |
3 | Date: Thu, 12 May 2016 22:17:34 -0400 | |
4 | Subject: sd: Fix rw_max for devices that report an optimal xfer size | |
5 | ||
6 | For historic reasons, io_opt is in bytes and max_sectors in block layer | |
7 | sectors. This interface inconsistency is error prone and should be | |
8 | fixed. But for 4.4--4.7 let's make the unit difference explicit via a | |
9 | wrapper function. | |
10 | ||
11 | Fixes: d0eb20a863ba ("sd: Optimal I/O size is in bytes, not sectors") | |
12 | Cc: stable@vger.kernel.org # 4.4+ | |
13 | Reported-by: Fam Zheng <famz@redhat.com> | |
14 | Reviewed-by: Bart Van Assche <bart.vanassche@sandisk.com> | |
15 | Reviewed-by: Christoph Hellwig <hch@lst.de> | |
16 | Tested-by: Andrew Patterson <andrew.patterson@hpe.com> | |
17 | Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com> | |
18 | --- | |
19 | drivers/scsi/sd.c | 8 ++++---- | |
20 | drivers/scsi/sd.h | 5 +++++ | |
21 | 2 files changed, 9 insertions(+), 4 deletions(-) | |
22 | ||
23 | diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c | |
24 | index f459dff..60bff78 100644 | |
25 | --- a/drivers/scsi/sd.c | |
26 | +++ b/drivers/scsi/sd.c | |
27 | @@ -2867,10 +2867,10 @@ static int sd_revalidate_disk(struct gendisk *disk) | |
28 | if (sdkp->opt_xfer_blocks && | |
29 | sdkp->opt_xfer_blocks <= dev_max && | |
30 | sdkp->opt_xfer_blocks <= SD_DEF_XFER_BLOCKS && | |
31 | - sdkp->opt_xfer_blocks * sdp->sector_size >= PAGE_CACHE_SIZE) | |
32 | - rw_max = q->limits.io_opt = | |
33 | - sdkp->opt_xfer_blocks * sdp->sector_size; | |
34 | - else | |
35 | + logical_to_bytes(sdp, sdkp->opt_xfer_blocks) >= PAGE_SIZE) { | |
36 | + q->limits.io_opt = logical_to_bytes(sdp, sdkp->opt_xfer_blocks); | |
37 | + rw_max = logical_to_sectors(sdp, sdkp->opt_xfer_blocks); | |
38 | + } else | |
39 | rw_max = BLK_DEF_MAX_SECTORS; | |
40 | ||
41 | /* Combine with controller limits */ | |
42 | diff --git a/drivers/scsi/sd.h b/drivers/scsi/sd.h | |
43 | index 654630b..765a6f1 100644 | |
44 | --- a/drivers/scsi/sd.h | |
45 | +++ b/drivers/scsi/sd.h | |
46 | @@ -151,6 +151,11 @@ static inline sector_t logical_to_sectors(struct scsi_device *sdev, sector_t blo | |
47 | return blocks << (ilog2(sdev->sector_size) - 9); | |
48 | } | |
49 | ||
50 | +static inline unsigned int logical_to_bytes(struct scsi_device *sdev, sector_t blocks) | |
51 | +{ | |
52 | + return blocks * sdev->sector_size; | |
53 | +} | |
54 | + | |
55 | /* | |
56 | * A DIF-capable target device can be formatted with different | |
57 | * protection schemes. Currently 0 through 3 are defined: | |
58 | -- | |
59 | cgit v0.12 | |
60 |