diff options
author | Mike Christie <mchristi@redhat.com> | 2016-06-02 21:12:37 -0400 |
---|---|---|
committer | Nicholas Bellinger <nab@linux-iscsi.org> | 2016-07-20 03:58:36 -0400 |
commit | ea263c7fada4af8ec7fe5fcfd6e7d7705a89351b (patch) | |
tree | 72beb3f878ba29726a189211cc4e6dacd9a6f339 | |
parent | 064cdd2d91c2805d788876082f31cc63506f22c3 (diff) |
target: Fix max_unmap_lba_count calc overflow
max_discard_sectors only 32bits, and some non scsi backend
devices will set this to the max 0xffffffff, so we can end up
overflowing during the max_unmap_lba_count calculation.
This fixes a regression caused by my patch:
commit 8a9ebe717a133ba7bc90b06047f43cc6b8bcb8b3
Author: Mike Christie <mchristi@redhat.com>
Date: Mon Jan 18 14:09:27 2016 -0600
target: Fix WRITE_SAME/DISCARD conversion to linux 512b sectors
which can result in extra discards being sent to due the overflow
causing max_unmap_lba_count to be smaller than what the backing
device can actually support.
Signed-off-by: Mike Christie <mchristi@redhat.com>
Reviewed-by: Bart Van Assche <bart.vanassche@sandisk.com>
Cc: stable@vger.kernel.org
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
-rw-r--r-- | drivers/target/target_core_device.c | 8 | ||||
-rw-r--r-- | drivers/target/target_core_file.c | 3 | ||||
-rw-r--r-- | drivers/target/target_core_iblock.c | 3 | ||||
-rw-r--r-- | include/target/target_core_backend.h | 2 |
4 files changed, 8 insertions, 8 deletions
diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c index a4046ca6e60d..6b423485c5d6 100644 --- a/drivers/target/target_core_device.c +++ b/drivers/target/target_core_device.c | |||
@@ -821,13 +821,15 @@ struct se_device *target_alloc_device(struct se_hba *hba, const char *name) | |||
821 | * in ATA and we need to set TPE=1 | 821 | * in ATA and we need to set TPE=1 |
822 | */ | 822 | */ |
823 | bool target_configure_unmap_from_queue(struct se_dev_attrib *attrib, | 823 | bool target_configure_unmap_from_queue(struct se_dev_attrib *attrib, |
824 | struct request_queue *q, int block_size) | 824 | struct request_queue *q) |
825 | { | 825 | { |
826 | int block_size = queue_logical_block_size(q); | ||
827 | |||
826 | if (!blk_queue_discard(q)) | 828 | if (!blk_queue_discard(q)) |
827 | return false; | 829 | return false; |
828 | 830 | ||
829 | attrib->max_unmap_lba_count = (q->limits.max_discard_sectors << 9) / | 831 | attrib->max_unmap_lba_count = |
830 | block_size; | 832 | q->limits.max_discard_sectors >> (ilog2(block_size) - 9); |
831 | /* | 833 | /* |
832 | * Currently hardcoded to 1 in Linux/SCSI code.. | 834 | * Currently hardcoded to 1 in Linux/SCSI code.. |
833 | */ | 835 | */ |
diff --git a/drivers/target/target_core_file.c b/drivers/target/target_core_file.c index 75f0f08b2a34..79291869bce6 100644 --- a/drivers/target/target_core_file.c +++ b/drivers/target/target_core_file.c | |||
@@ -161,8 +161,7 @@ static int fd_configure_device(struct se_device *dev) | |||
161 | dev_size, div_u64(dev_size, fd_dev->fd_block_size), | 161 | dev_size, div_u64(dev_size, fd_dev->fd_block_size), |
162 | fd_dev->fd_block_size); | 162 | fd_dev->fd_block_size); |
163 | 163 | ||
164 | if (target_configure_unmap_from_queue(&dev->dev_attrib, q, | 164 | if (target_configure_unmap_from_queue(&dev->dev_attrib, q)) |
165 | fd_dev->fd_block_size)) | ||
166 | pr_debug("IFILE: BLOCK Discard support available," | 165 | pr_debug("IFILE: BLOCK Discard support available," |
167 | " disabled by default\n"); | 166 | " disabled by default\n"); |
168 | /* | 167 | /* |
diff --git a/drivers/target/target_core_iblock.c b/drivers/target/target_core_iblock.c index 7c4efb4417b0..2077bc28640a 100644 --- a/drivers/target/target_core_iblock.c +++ b/drivers/target/target_core_iblock.c | |||
@@ -121,8 +121,7 @@ static int iblock_configure_device(struct se_device *dev) | |||
121 | dev->dev_attrib.hw_max_sectors = queue_max_hw_sectors(q); | 121 | dev->dev_attrib.hw_max_sectors = queue_max_hw_sectors(q); |
122 | dev->dev_attrib.hw_queue_depth = q->nr_requests; | 122 | dev->dev_attrib.hw_queue_depth = q->nr_requests; |
123 | 123 | ||
124 | if (target_configure_unmap_from_queue(&dev->dev_attrib, q, | 124 | if (target_configure_unmap_from_queue(&dev->dev_attrib, q)) |
125 | dev->dev_attrib.hw_block_size)) | ||
126 | pr_debug("IBLOCK: BLOCK Discard support available," | 125 | pr_debug("IBLOCK: BLOCK Discard support available," |
127 | " disabled by default\n"); | 126 | " disabled by default\n"); |
128 | 127 | ||
diff --git a/include/target/target_core_backend.h b/include/target/target_core_backend.h index d8ab5101fad5..f6f3bc52c1ac 100644 --- a/include/target/target_core_backend.h +++ b/include/target/target_core_backend.h | |||
@@ -95,6 +95,6 @@ sense_reason_t passthrough_parse_cdb(struct se_cmd *cmd, | |||
95 | bool target_sense_desc_format(struct se_device *dev); | 95 | bool target_sense_desc_format(struct se_device *dev); |
96 | sector_t target_to_linux_sector(struct se_device *dev, sector_t lb); | 96 | sector_t target_to_linux_sector(struct se_device *dev, sector_t lb); |
97 | bool target_configure_unmap_from_queue(struct se_dev_attrib *attrib, | 97 | bool target_configure_unmap_from_queue(struct se_dev_attrib *attrib, |
98 | struct request_queue *q, int block_size); | 98 | struct request_queue *q); |
99 | 99 | ||
100 | #endif /* TARGET_CORE_BACKEND_H */ | 100 | #endif /* TARGET_CORE_BACKEND_H */ |