aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@lst.de>2016-04-18 17:06:28 -0400
committerDoug Ledford <dledford@redhat.com>2016-05-05 12:41:24 -0400
commit9c674815d346305068b27bf03b5e86b659a1b111 (patch)
treeb512f798dbdfb99a3cfb7ca971b04fc5c52a9000
parent4c8bb95921e9ac01b9dd0c3abbaf6514ce88af92 (diff)
IB/iser: Fix max_sectors calculation
iSER currently has a couple places that set max_sectors in either the host template or SCSI host, and all of them get it wrong. This patch instead uses a single assignment that (hopefully) gets it right: the max_sectors value must be derived from the number of segments in the FR or FMR structure, but actually be one lower than the page size multiplied by the number of sectors, as it has to handle the case of non-aligned I/O. Without this I get trivial to reproduce hangs when running xfstests (on XFS) over iSER to Linux targets. Signed-off-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Max Gurtovoy <maxg@mellanox.com> Acked-by: Sagi Grimberg <sagi@grimberg.me> Signed-off-by: Doug Ledford <dledford@redhat.com>
-rw-r--r--drivers/infiniband/ulp/iser/iscsi_iser.c14
1 files changed, 10 insertions, 4 deletions
diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.c b/drivers/infiniband/ulp/iser/iscsi_iser.c
index 80b6bedc172f..64b3d11dcf1e 100644
--- a/drivers/infiniband/ulp/iser/iscsi_iser.c
+++ b/drivers/infiniband/ulp/iser/iscsi_iser.c
@@ -612,6 +612,7 @@ iscsi_iser_session_create(struct iscsi_endpoint *ep,
612 struct Scsi_Host *shost; 612 struct Scsi_Host *shost;
613 struct iser_conn *iser_conn = NULL; 613 struct iser_conn *iser_conn = NULL;
614 struct ib_conn *ib_conn; 614 struct ib_conn *ib_conn;
615 u32 max_fr_sectors;
615 u16 max_cmds; 616 u16 max_cmds;
616 617
617 shost = iscsi_host_alloc(&iscsi_iser_sht, 0, 0); 618 shost = iscsi_host_alloc(&iscsi_iser_sht, 0, 0);
@@ -632,7 +633,6 @@ iscsi_iser_session_create(struct iscsi_endpoint *ep,
632 iser_conn = ep->dd_data; 633 iser_conn = ep->dd_data;
633 max_cmds = iser_conn->max_cmds; 634 max_cmds = iser_conn->max_cmds;
634 shost->sg_tablesize = iser_conn->scsi_sg_tablesize; 635 shost->sg_tablesize = iser_conn->scsi_sg_tablesize;
635 shost->max_sectors = iser_conn->scsi_max_sectors;
636 636
637 mutex_lock(&iser_conn->state_mutex); 637 mutex_lock(&iser_conn->state_mutex);
638 if (iser_conn->state != ISER_CONN_UP) { 638 if (iser_conn->state != ISER_CONN_UP) {
@@ -657,8 +657,6 @@ iscsi_iser_session_create(struct iscsi_endpoint *ep,
657 */ 657 */
658 shost->sg_tablesize = min_t(unsigned short, shost->sg_tablesize, 658 shost->sg_tablesize = min_t(unsigned short, shost->sg_tablesize,
659 ib_conn->device->ib_device->attrs.max_fast_reg_page_list_len); 659 ib_conn->device->ib_device->attrs.max_fast_reg_page_list_len);
660 shost->max_sectors = min_t(unsigned int,
661 1024, (shost->sg_tablesize * PAGE_SIZE) >> 9);
662 660
663 if (iscsi_host_add(shost, 661 if (iscsi_host_add(shost,
664 ib_conn->device->ib_device->dma_device)) { 662 ib_conn->device->ib_device->dma_device)) {
@@ -672,6 +670,15 @@ iscsi_iser_session_create(struct iscsi_endpoint *ep,
672 goto free_host; 670 goto free_host;
673 } 671 }
674 672
673 /*
674 * FRs or FMRs can only map up to a (device) page per entry, but if the
675 * first entry is misaligned we'll end up using using two entries
676 * (head and tail) for a single page worth data, so we have to drop
677 * one segment from the calculation.
678 */
679 max_fr_sectors = ((shost->sg_tablesize - 1) * PAGE_SIZE) >> 9;
680 shost->max_sectors = min(iser_max_sectors, max_fr_sectors);
681
675 if (cmds_max > max_cmds) { 682 if (cmds_max > max_cmds) {
676 iser_info("cmds_max changed from %u to %u\n", 683 iser_info("cmds_max changed from %u to %u\n",
677 cmds_max, max_cmds); 684 cmds_max, max_cmds);
@@ -989,7 +996,6 @@ static struct scsi_host_template iscsi_iser_sht = {
989 .queuecommand = iscsi_queuecommand, 996 .queuecommand = iscsi_queuecommand,
990 .change_queue_depth = scsi_change_queue_depth, 997 .change_queue_depth = scsi_change_queue_depth,
991 .sg_tablesize = ISCSI_ISER_DEF_SG_TABLESIZE, 998 .sg_tablesize = ISCSI_ISER_DEF_SG_TABLESIZE,
992 .max_sectors = ISER_DEF_MAX_SECTORS,
993 .cmd_per_lun = ISER_DEF_CMD_PER_LUN, 999 .cmd_per_lun = ISER_DEF_CMD_PER_LUN,
994 .eh_abort_handler = iscsi_eh_abort, 1000 .eh_abort_handler = iscsi_eh_abort,
995 .eh_device_reset_handler= iscsi_eh_device_reset, 1001 .eh_device_reset_handler= iscsi_eh_device_reset,