[pve-devel] [PATCH pve-kernel 2/2] backport iSCSI fix from 4.4-rc5
Thomas Lamprecht
t.lamprecht at proxmox.com
Fri Jan 8 17:05:31 CET 2016
backport ca369d51b3e1649be4a72addd6d6a168cfb3f537 from 4.4-rc5
to fix problems with connecting and writing to a iscsi device.
See forum thread 24821 for some details.
---
Makefile | 2 +
...Fix-device-imposed-transfer-length-limits.patch | 167 +++++++++++++++++++++
2 files changed, 169 insertions(+)
create mode 100644 iSCSI-block-sd-Fix-device-imposed-transfer-length-limits.patch
diff --git a/Makefile b/Makefile
index 389af54..68d27ce 100644
--- a/Makefile
+++ b/Makefile
@@ -241,6 +241,8 @@ ${KERNEL_SRC}/README ${KERNEL_CFG_ORG}: ${KERNELSRCTAR}
cd ${KERNEL_SRC}; patch -p1 <../apparmor-socket-mediation.patch
cd ${KERNEL_SRC}; patch -p1 <../CVE-2015-8709-ptrace-require-mapped-uids-gids.patch
cd ${KERNEL_SRC}; patch -p1 <../CVE-2015-7513-KVM-x86-Reload-pit-counters-for-all-channels.patch
+ # backport iSCSI fix from 4.4rc5
+ cd ${KERNEL_SRC}; patch -p1 <../iSCSI-block-sd-Fix-device-imposed-transfer-length-limits.patch
# backport aacraid update from kernel 4.4rc5
cd ${KERNEL_SRC}; patch -p1 <../0001-aacraid-fix-for-LD.patch
cd ${KERNEL_SRC}; patch -p1 <../0002-aacraid-add-power-management.patch
diff --git a/iSCSI-block-sd-Fix-device-imposed-transfer-length-limits.patch b/iSCSI-block-sd-Fix-device-imposed-transfer-length-limits.patch
new file mode 100644
index 0000000..fcd2625
--- /dev/null
+++ b/iSCSI-block-sd-Fix-device-imposed-transfer-length-limits.patch
@@ -0,0 +1,167 @@
+diff -Naur a/block/blk-settings.c b/block/blk-settings.c
+--- a/block/blk-settings.c 2015-12-01 18:36:05.000000000 +0100
++++ b/block/blk-settings.c 2015-12-18 12:02:27.076000000 +0100
+@@ -112,7 +112,7 @@
+ lim->max_integrity_segments = 0;
+ lim->seg_boundary_mask = BLK_SEG_BOUNDARY_MASK;
+ lim->max_segment_size = BLK_MAX_SEGMENT_SIZE;
+- lim->max_sectors = lim->max_hw_sectors = BLK_SAFE_MAX_SECTORS;
++ lim->max_sectors = lim->max_dev_sectors = lim->max_hw_sectors = BLK_SAFE_MAX_SECTORS;
+ lim->chunk_sectors = 0;
+ lim->max_write_same_sectors = 0;
+ lim->max_discard_sectors = 0;
+@@ -147,6 +147,7 @@
+ lim->max_hw_sectors = UINT_MAX;
+ lim->max_segment_size = UINT_MAX;
+ lim->max_sectors = UINT_MAX;
++ lim->max_dev_sectors = UINT_MAX;
+ lim->max_write_same_sectors = UINT_MAX;
+ }
+ EXPORT_SYMBOL(blk_set_stacking_limits);
+@@ -544,6 +540,7 @@
+
+ t->max_sectors = min_not_zero(t->max_sectors, b->max_sectors);
+ t->max_hw_sectors = min_not_zero(t->max_hw_sectors, b->max_hw_sectors);
++ t->max_dev_sectors = min_not_zero(t->max_dev_sectors, b->max_dev_sectors);
+ t->max_write_same_sectors = min(t->max_write_same_sectors,
+ b->max_write_same_sectors);
+ t->bounce_pfn = min_not_zero(t->bounce_pfn, b->bounce_pfn);
+diff -Naur a/block/blk-sysfs.c b/block/blk-sysfs.c
+--- a/block/blk-sysfs.c 2015-12-01 18:36:05.000000000 +0100
++++ b/block/blk-sysfs.c 2015-12-18 12:06:20.040000000 +0100
+@@ -174,6 +174,9 @@
+ if (ret < 0)
+ return ret;
+
++ max_hw_sectors_kb = min_not_zero(max_hw_sectors_kb, (unsigned long)
++ q->limits.max_dev_sectors >> 1);
++
+ if (max_sectors_kb > max_hw_sectors_kb || max_sectors_kb < page_kb)
+ return -EINVAL;
+
+diff -Naur a/drivers/scsi/sd.c b/drivers/scsi/sd.c
+--- a/drivers/scsi/sd.c 2015-12-01 18:36:07.000000000 +0100
++++ b/drivers/scsi/sd.c 2015-12-18 13:27:08.472000000 +0100
+@@ -2224,11 +2224,8 @@
+ }
+ }
+
+- if (sdkp->capacity > 0xffffffff) {
++ if (sdkp->capacity > 0xffffffff)
+ sdp->use_16_for_rw = 1;
+- sdkp->max_xfer_blocks = SD_MAX_XFER_BLOCKS;
+- } else
+- sdkp->max_xfer_blocks = SD_DEF_XFER_BLOCKS;
+
+ /* Rescale capacity to 512-byte units */
+ if (sector_size == 4096)
+@@ -2545,7 +2542,6 @@
+ {
+ unsigned int sector_sz = sdkp->device->sector_size;
+ const int vpd_len = 64;
+- u32 max_xfer_length;
+ unsigned char *buffer = kmalloc(vpd_len, GFP_KERNEL);
+
+ if (!buffer ||
+@@ -2553,14 +2549,11 @@
+ scsi_get_vpd_page(sdkp->device, 0xb0, buffer, vpd_len))
+ goto out;
+
+- max_xfer_length = get_unaligned_be32(&buffer[8]);
+- if (max_xfer_length)
+- sdkp->max_xfer_blocks = max_xfer_length;
+-
+ blk_queue_io_min(sdkp->disk->queue,
+ get_unaligned_be16(&buffer[6]) * sector_sz);
+- blk_queue_io_opt(sdkp->disk->queue,
+- get_unaligned_be32(&buffer[12]) * sector_sz);
++
++ sdkp->max_xfer_blocks = get_unaligned_be32(&buffer[8]);
++ sdkp->opt_xfer_blocks = get_unaligned_be32(&buffer[12]);
+
+ if (buffer[3] == 0x3c) {
+ unsigned int lba_count, desc_count;
+@@ -2709,6 +2702,11 @@
+ return 0;
+ }
+
++static inline u32 logical_to_sectors(struct scsi_device *sdev, u32 blocks)
++{
++ return blocks << (ilog2(sdev->sector_size) - 9);
++}
++
+ /**
+ * sd_revalidate_disk - called the first time a new disk is seen,
+ * performs disk spin up, read_capacity, etc.
+@@ -2718,8 +2716,9 @@
+ {
+ struct scsi_disk *sdkp = scsi_disk(disk);
+ struct scsi_device *sdp = sdkp->device;
++ struct request_queue *q = sdkp->disk->queue;
+ unsigned char *buffer;
+- unsigned int max_xfer;
++ unsigned int dev_max, rw_max;
+
+ SCSI_LOG_HLQUEUE(3, sd_printk(KERN_INFO, sdkp,
+ "sd_revalidate_disk\n"));
+@@ -2767,11 +2766,26 @@
+ */
+ sd_set_flush_flag(sdkp);
+
+- max_xfer = sdkp->max_xfer_blocks;
+- max_xfer <<= ilog2(sdp->sector_size) - 9;
++ /* Initial block count limit based on CDB TRANSFER LENGTH field size. */
++ dev_max = sdp->use_16_for_rw ? SD_MAX_XFER_BLOCKS : SD_DEF_XFER_BLOCKS;
++
++ /* Some devices report a maximum block count for READ/WRITE requests. */
++ dev_max = min_not_zero(dev_max, sdkp->max_xfer_blocks);
++ q->limits.max_dev_sectors = logical_to_sectors(sdp, dev_max);
++
++ /*
++ * Use the device's preferred I/O size for reads and writes
++ * unless the reported value is unreasonably large (or garbage).
++ */
++ if (sdkp->opt_xfer_blocks && sdkp->opt_xfer_blocks <= dev_max &&
++ sdkp->opt_xfer_blocks <= SD_DEF_XFER_BLOCKS)
++ rw_max = q->limits.io_opt =
++ logical_to_sectors(sdp, sdkp->opt_xfer_blocks);
++ else
++ rw_max = BLK_DEF_MAX_SECTORS;
+
+- sdkp->disk->queue->limits.max_sectors =
+- min_not_zero(queue_max_hw_sectors(sdkp->disk->queue), max_xfer);
++ /* Combine with controller limits */
++ q->limits.max_sectors = min(rw_max, queue_max_hw_sectors(q));
+
+ set_capacity(disk, sdkp->capacity);
+ sd_config_write_same(sdkp);
+diff -Naur a/drivers/scsi/sd.h b/drivers/scsi/sd.h
+--- a/drivers/scsi/sd.h 2015-12-01 18:36:07.000000000 +0100
++++ b/drivers/scsi/sd.h 2015-12-18 13:28:56.716000000 +0100
+@@ -67,6 +67,7 @@
+ atomic_t openers;
+ sector_t capacity; /* size in 512-byte sectors */
+ u32 max_xfer_blocks;
++ u32 opt_xfer_blocks;
+ u32 max_ws_blocks;
+ u32 max_unmap_blocks;
+ u32 unmap_granularity;
+diff -Naur a/include/linux/blkdev.h b/include/linux/blkdev.h
+--- a/include/linux/blkdev.h 2015-12-01 18:36:07.000000000 +0100
++++ b/include/linux/blkdev.h 2015-12-18 13:30:55.772000000 +0100
+@@ -260,6 +260,7 @@
+ unsigned long seg_boundary_mask;
+
+ unsigned int max_hw_sectors;
++ unsigned int max_dev_sectors;
+ unsigned int chunk_sectors;
+ unsigned int max_sectors;
+ unsigned int max_segment_size;
+@@ -1138,6 +1138,7 @@
+ enum blk_default_limits {
+ BLK_MAX_SEGMENTS = 128,
+ BLK_SAFE_MAX_SECTORS = 255,
++ BLK_DEF_MAX_SECTORS = 2560,
+ BLK_MAX_SEGMENT_SIZE = 65536,
+ BLK_SEG_BOUNDARY_MASK = 0xFFFFFFFFUL,
+ };
--
2.1.4
More information about the pve-devel
mailing list