diff options
author | Nicholas Bellinger <nab@linux-iscsi.org> | 2015-01-06 19:10:37 -0500 |
---|---|---|
committer | Nicholas Bellinger <nab@linux-iscsi.org> | 2015-01-09 18:21:40 -0500 |
commit | 046ba64285a4389ae5e9a7dfa253c6bff3d7c341 (patch) | |
tree | 8160b4c771df304f70cf7cfc155f6e7c152d0089 /drivers/target | |
parent | 67e51daa5029417db86f1833f1b7b2212c454fe9 (diff) |
target: Drop arbitrary maximum I/O size limit
This patch drops the arbitrary maximum I/O size limit in sbc_parse_cdb(),
which currently for fabric_max_sectors is hardcoded to 8192 (4 MB for 512
byte sector devices), and for hw_max_sectors is a backend driver dependent
value.
This limit is problematic because Linux initiators have only recently
started to honor block limits MAXIMUM TRANSFER LENGTH, and other non-Linux
based initiators (eg: MSFT Fibre Channel) can also generate I/Os larger
than 4 MB in size.
Currently when this happens, the following message will appear on the
target resulting in I/Os being returned with non recoverable status:
SCSI OP 28h with too big sectors 16384 exceeds fabric_max_sectors: 8192
Instead, drop both [fabric,hw]_max_sector checks in sbc_parse_cdb(),
and convert the existing hw_max_sectors into a purely informational
attribute used to represent the granuality that backend driver and/or
subsystem code is splitting I/Os upon.
Also, update FILEIO with an explicit FD_MAX_BYTES check in fd_execute_rw()
to deal with the one special iovec limitiation case.
v2 changes:
- Drop hw_max_sectors check in sbc_parse_cdb()
Reported-by: Lance Gropper <lance.gropper@qosserver.com>
Reported-by: Stefan Priebe <s.priebe@profihost.ag>
Cc: Christoph Hellwig <hch@lst.de>
Cc: Martin K. Petersen <martin.petersen@oracle.com>
Cc: Roland Dreier <roland@purestorage.com>
Cc: stable@vger.kernel.org # 3.4
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
Diffstat (limited to 'drivers/target')
-rw-r--r-- | drivers/target/target_core_device.c | 8 | ||||
-rw-r--r-- | drivers/target/target_core_file.c | 11 | ||||
-rw-r--r-- | drivers/target/target_core_iblock.c | 2 | ||||
-rw-r--r-- | drivers/target/target_core_sbc.c | 15 | ||||
-rw-r--r-- | drivers/target/target_core_spc.c | 5 |
5 files changed, 16 insertions, 25 deletions
diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c index 7653cfb027a2..ee4b89fb8841 100644 --- a/drivers/target/target_core_device.c +++ b/drivers/target/target_core_device.c | |||
@@ -1156,10 +1156,10 @@ int se_dev_set_optimal_sectors(struct se_device *dev, u32 optimal_sectors) | |||
1156 | dev, dev->export_count); | 1156 | dev, dev->export_count); |
1157 | return -EINVAL; | 1157 | return -EINVAL; |
1158 | } | 1158 | } |
1159 | if (optimal_sectors > dev->dev_attrib.fabric_max_sectors) { | 1159 | if (optimal_sectors > dev->dev_attrib.hw_max_sectors) { |
1160 | pr_err("dev[%p]: Passed optimal_sectors %u cannot be" | 1160 | pr_err("dev[%p]: Passed optimal_sectors %u cannot be" |
1161 | " greater than fabric_max_sectors: %u\n", dev, | 1161 | " greater than hw_max_sectors: %u\n", dev, |
1162 | optimal_sectors, dev->dev_attrib.fabric_max_sectors); | 1162 | optimal_sectors, dev->dev_attrib.hw_max_sectors); |
1163 | return -EINVAL; | 1163 | return -EINVAL; |
1164 | } | 1164 | } |
1165 | 1165 | ||
@@ -1554,7 +1554,6 @@ struct se_device *target_alloc_device(struct se_hba *hba, const char *name) | |||
1554 | DA_UNMAP_GRANULARITY_ALIGNMENT_DEFAULT; | 1554 | DA_UNMAP_GRANULARITY_ALIGNMENT_DEFAULT; |
1555 | dev->dev_attrib.max_write_same_len = DA_MAX_WRITE_SAME_LEN; | 1555 | dev->dev_attrib.max_write_same_len = DA_MAX_WRITE_SAME_LEN; |
1556 | dev->dev_attrib.fabric_max_sectors = DA_FABRIC_MAX_SECTORS; | 1556 | dev->dev_attrib.fabric_max_sectors = DA_FABRIC_MAX_SECTORS; |
1557 | dev->dev_attrib.optimal_sectors = DA_FABRIC_MAX_SECTORS; | ||
1558 | 1557 | ||
1559 | xcopy_lun = &dev->xcopy_lun; | 1558 | xcopy_lun = &dev->xcopy_lun; |
1560 | xcopy_lun->lun_se_dev = dev; | 1559 | xcopy_lun->lun_se_dev = dev; |
@@ -1595,6 +1594,7 @@ int target_configure_device(struct se_device *dev) | |||
1595 | dev->dev_attrib.hw_max_sectors = | 1594 | dev->dev_attrib.hw_max_sectors = |
1596 | se_dev_align_max_sectors(dev->dev_attrib.hw_max_sectors, | 1595 | se_dev_align_max_sectors(dev->dev_attrib.hw_max_sectors, |
1597 | dev->dev_attrib.hw_block_size); | 1596 | dev->dev_attrib.hw_block_size); |
1597 | dev->dev_attrib.optimal_sectors = dev->dev_attrib.hw_max_sectors; | ||
1598 | 1598 | ||
1599 | dev->dev_index = scsi_get_new_index(SCSI_DEVICE_INDEX); | 1599 | dev->dev_index = scsi_get_new_index(SCSI_DEVICE_INDEX); |
1600 | dev->creation_time = get_jiffies_64(); | 1600 | dev->creation_time = get_jiffies_64(); |
diff --git a/drivers/target/target_core_file.c b/drivers/target/target_core_file.c index c2aea099ea4a..b09021135c3b 100644 --- a/drivers/target/target_core_file.c +++ b/drivers/target/target_core_file.c | |||
@@ -621,7 +621,16 @@ fd_execute_rw(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents, | |||
621 | struct fd_prot fd_prot; | 621 | struct fd_prot fd_prot; |
622 | sense_reason_t rc; | 622 | sense_reason_t rc; |
623 | int ret = 0; | 623 | int ret = 0; |
624 | 624 | /* | |
625 | * We are currently limited by the number of iovecs (2048) per | ||
626 | * single vfs_[writev,readv] call. | ||
627 | */ | ||
628 | if (cmd->data_length > FD_MAX_BYTES) { | ||
629 | pr_err("FILEIO: Not able to process I/O of %u bytes due to" | ||
630 | "FD_MAX_BYTES: %u iovec count limitiation\n", | ||
631 | cmd->data_length, FD_MAX_BYTES); | ||
632 | return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; | ||
633 | } | ||
625 | /* | 634 | /* |
626 | * Call vectorized fileio functions to map struct scatterlist | 635 | * Call vectorized fileio functions to map struct scatterlist |
627 | * physical memory addresses to struct iovec virtual memory. | 636 | * physical memory addresses to struct iovec virtual memory. |
diff --git a/drivers/target/target_core_iblock.c b/drivers/target/target_core_iblock.c index 3efff94fbd97..5795cd8ab5d9 100644 --- a/drivers/target/target_core_iblock.c +++ b/drivers/target/target_core_iblock.c | |||
@@ -124,7 +124,7 @@ static int iblock_configure_device(struct se_device *dev) | |||
124 | q = bdev_get_queue(bd); | 124 | q = bdev_get_queue(bd); |
125 | 125 | ||
126 | dev->dev_attrib.hw_block_size = bdev_logical_block_size(bd); | 126 | dev->dev_attrib.hw_block_size = bdev_logical_block_size(bd); |
127 | dev->dev_attrib.hw_max_sectors = UINT_MAX; | 127 | dev->dev_attrib.hw_max_sectors = queue_max_hw_sectors(q); |
128 | dev->dev_attrib.hw_queue_depth = q->nr_requests; | 128 | dev->dev_attrib.hw_queue_depth = q->nr_requests; |
129 | 129 | ||
130 | /* | 130 | /* |
diff --git a/drivers/target/target_core_sbc.c b/drivers/target/target_core_sbc.c index 11bea1952435..cd4bed7b2757 100644 --- a/drivers/target/target_core_sbc.c +++ b/drivers/target/target_core_sbc.c | |||
@@ -953,21 +953,6 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops) | |||
953 | 953 | ||
954 | if (cmd->se_cmd_flags & SCF_SCSI_DATA_CDB) { | 954 | if (cmd->se_cmd_flags & SCF_SCSI_DATA_CDB) { |
955 | unsigned long long end_lba; | 955 | unsigned long long end_lba; |
956 | |||
957 | if (sectors > dev->dev_attrib.fabric_max_sectors) { | ||
958 | printk_ratelimited(KERN_ERR "SCSI OP %02xh with too" | ||
959 | " big sectors %u exceeds fabric_max_sectors:" | ||
960 | " %u\n", cdb[0], sectors, | ||
961 | dev->dev_attrib.fabric_max_sectors); | ||
962 | return TCM_INVALID_CDB_FIELD; | ||
963 | } | ||
964 | if (sectors > dev->dev_attrib.hw_max_sectors) { | ||
965 | printk_ratelimited(KERN_ERR "SCSI OP %02xh with too" | ||
966 | " big sectors %u exceeds backend hw_max_sectors:" | ||
967 | " %u\n", cdb[0], sectors, | ||
968 | dev->dev_attrib.hw_max_sectors); | ||
969 | return TCM_INVALID_CDB_FIELD; | ||
970 | } | ||
971 | check_lba: | 956 | check_lba: |
972 | end_lba = dev->transport->get_blocks(dev) + 1; | 957 | end_lba = dev->transport->get_blocks(dev) + 1; |
973 | if (cmd->t_task_lba + sectors > end_lba) { | 958 | if (cmd->t_task_lba + sectors > end_lba) { |
diff --git a/drivers/target/target_core_spc.c b/drivers/target/target_core_spc.c index 1307600fe726..4c71657da56a 100644 --- a/drivers/target/target_core_spc.c +++ b/drivers/target/target_core_spc.c | |||
@@ -505,7 +505,6 @@ static sense_reason_t | |||
505 | spc_emulate_evpd_b0(struct se_cmd *cmd, unsigned char *buf) | 505 | spc_emulate_evpd_b0(struct se_cmd *cmd, unsigned char *buf) |
506 | { | 506 | { |
507 | struct se_device *dev = cmd->se_dev; | 507 | struct se_device *dev = cmd->se_dev; |
508 | u32 max_sectors; | ||
509 | int have_tp = 0; | 508 | int have_tp = 0; |
510 | int opt, min; | 509 | int opt, min; |
511 | 510 | ||
@@ -539,9 +538,7 @@ spc_emulate_evpd_b0(struct se_cmd *cmd, unsigned char *buf) | |||
539 | /* | 538 | /* |
540 | * Set MAXIMUM TRANSFER LENGTH | 539 | * Set MAXIMUM TRANSFER LENGTH |
541 | */ | 540 | */ |
542 | max_sectors = min(dev->dev_attrib.fabric_max_sectors, | 541 | put_unaligned_be32(dev->dev_attrib.hw_max_sectors, &buf[8]); |
543 | dev->dev_attrib.hw_max_sectors); | ||
544 | put_unaligned_be32(max_sectors, &buf[8]); | ||
545 | 542 | ||
546 | /* | 543 | /* |
547 | * Set OPTIMAL TRANSFER LENGTH | 544 | * Set OPTIMAL TRANSFER LENGTH |