Re: FC target Errors

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Tue, 2015-07-28 at 14:24 -0700, Arun Easi wrote:
> Hi Nic,
> 
> Thanks for the response, my comments below..
> 
> On Sat, 25 Jul 2015, 2:02am -0700, Nicholas A. Bellinger wrote:
> 
> > Hello Arun, Roland & Co,
> >
> > Thanks for your feedback.  Apologies for delayed response on this bug.
> >
> > On Wed, 2015-07-08 at 13:25 -0700, Arun Easi wrote:

<SNIP>

> >> Longer term (Roland alluded to this, I think), it would be best to have
> >> stack call .queue_data_in/.write_pending with a max of "max_sg_entries" SG
> >> entries at one time and repeat until the whole data is transferred; thus
> >> achieving a possible unlimited data transfer length.
> >>
> >
> > Here's a better work-around following your earlier comments to enforce
> > target-core level se_cmd->t_data_sg fabric driver limits, currently
> > assuming 1:1 PAGE_SIZE mapping per internally allocated scatterlist
> > entry.
> >
> > The max_data_sg_nents=1200 default for tcm_qla2xxx is following Roland's
> > earlier comments.
> >
> > Please review.
> >
> > diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c
> > index ce8574b..2c934fc 100644
> > --- a/drivers/target/target_core_transport.c
> > +++ b/drivers/target/target_core_transport.c
> > @@ -2254,9 +2254,9 @@ void transport_kunmap_data_sg(struct se_cmd *cmd)
> > }
> > EXPORT_SYMBOL(transport_kunmap_data_sg);
> >
> > -int
> > +sense_reason_t
> > target_alloc_sgl(struct scatterlist **sgl, unsigned int *nents, u32 length,
> > -		 bool zero_page)
> > +		 bool zero_page, u32 max_nents)
> > {
> > 	struct scatterlist *sg;
> > 	struct page *page;
> > @@ -2265,9 +2265,16 @@ target_alloc_sgl(struct scatterlist **sgl, unsigned int *nents, u32 length,
> > 	int i = 0;
> >
> > 	nent = DIV_ROUND_UP(length, PAGE_SIZE);
> > +	if (max_nents && max_nents >= nent) {
> > +		pr_err_ratelimited("Required sg nents: %u exceeded fabric driver"
> > +				   " enforced max_nents: %u, failing command\n",
> > +				   nent, max_nents);
> > +		return TCM_SECTOR_COUNT_TOO_MANY;
> 
> How about setting a residual count of the difference and allowing IO to 
> succeed? Thus, initiators could still make forward progress without 
> worrying so much about the fabric limitation.
> 

Residual count + overflow sounds like a much better work-around for this
problem.

How about something like the following in target_cmd_size_check()
to detect residual overflow early before internal SGL allocation occurs,
and reset se_cmd->data_length + ->prot_length following the fabric
provided max_data_sg_nents..?

WDYT..?

>From 78b2faf26e6b51744294761d2e111a28391b4ad5 Mon Sep 17 00:00:00 2001
From: Nicholas Bellinger <nab@xxxxxxxxxxxxxxx>
Date: Thu, 30 Jul 2015 18:28:13 -0700
Subject: [PATCH] target: Add max_data_sg_nents I/O limit + residual overflow

This patch changes target-core to enforce optional fabric driver
provided max_data_sg_nents limit, that determines the value based
upon 1:1 mapping of PAGE_SIZE to scatterlist entry.

If a new se_cmd payload length exceeds the provided value, it will
recalculate ->data_length and ->prot_length based the limit, and
sets SCF_OVERFLOW_BIT + residual_count in the out-going response.

Reported-by: Craig Watson <craig.watson@xxxxxxxxxxxxxxxxxxx>
Cc: Craig Watson <craig.watson@xxxxxxxxxxxxxxxxxxx>
Cc: Roland Dreier <roland@xxxxxxxxxxxxxxx>
Cc: Arun Easi <arun.easi@xxxxxxxxxx>
Cc: Giridhar Malavali <giridhar.malavali@xxxxxxxxxx>
Cc: Andrew Vasquez <andrew.vasquez@xxxxxxxxxx>
Cc: Christoph Hellwig <hch@xxxxxx>
Cc: Hannes Reinecke <hare@xxxxxxx>
Cc: Martin K. Petersen <martin.petersen@xxxxxxxxxx>
Signed-off-by: Nicholas Bellinger <nab@xxxxxxxxxxxxxxx>
---
 drivers/scsi/qla2xxx/tcm_qla2xxx.c     |  5 +++++
 drivers/target/target_core_spc.c       | 13 ++++++++++---
 drivers/target/target_core_transport.c | 23 +++++++++++++++++++++++
 include/target/target_core_fabric.h    | 13 +++++++++++++
 4 files changed, 51 insertions(+), 3 deletions(-)

diff --git a/drivers/scsi/qla2xxx/tcm_qla2xxx.c b/drivers/scsi/qla2xxx/tcm_qla2xxx.c
index 9224a06..6649809 100644
--- a/drivers/scsi/qla2xxx/tcm_qla2xxx.c
+++ b/drivers/scsi/qla2xxx/tcm_qla2xxx.c
@@ -1804,6 +1804,11 @@ static const struct target_core_fabric_ops tcm_qla2xxx_ops = {
 	.module				= THIS_MODULE,
 	.name				= "qla2xxx",
 	.node_acl_size			= sizeof(struct tcm_qla2xxx_nacl),
+	/*
+	 * XXX: Limit assumes single page per scatter-gather-list entry.
+	 * Current maximum is ~4.9 MB per se_cmd->t_data_sg with PAGE_SIZE=4096
+	 */
+	.max_data_sg_nents		= 1200,
 	.get_fabric_name		= tcm_qla2xxx_get_fabric_name,
 	.tpg_get_wwn			= tcm_qla2xxx_get_fabric_wwn,
 	.tpg_get_tag			= tcm_qla2xxx_get_tag,
diff --git a/drivers/target/target_core_spc.c b/drivers/target/target_core_spc.c
index b5ba1ec..ac249e9 100644
--- a/drivers/target/target_core_spc.c
+++ b/drivers/target/target_core_spc.c
@@ -484,8 +484,8 @@ static sense_reason_t
 spc_emulate_evpd_b0(struct se_cmd *cmd, unsigned char *buf)
 {
 	struct se_device *dev = cmd->se_dev;
-	int have_tp = 0;
-	int opt, min;
+	u32 mtl = 0;
+	int have_tp = 0, opt, min;
 
 	/*
 	 * Following spc3r22 section 6.5.3 Block Limits VPD page, when
@@ -516,8 +516,15 @@ spc_emulate_evpd_b0(struct se_cmd *cmd, unsigned char *buf)
 
 	/*
 	 * Set MAXIMUM TRANSFER LENGTH
+	 *
+	 * XXX: Currently assumes single PAGE_SIZE per scatterlist for fabrics
+	 * enforcing maximum HW scatter-gather-list entry limit
 	 */
-	put_unaligned_be32(dev->dev_attrib.hw_max_sectors, &buf[8]);
+	if (cmd->se_tfo->max_data_sg_nents) {
+		mtl = (cmd->se_tfo->max_data_sg_nents * PAGE_SIZE) /
+		       dev->dev_attrib.block_size;
+	}
+	put_unaligned_be32(min_not_zero(mtl, dev->dev_attrib.hw_max_sectors), &buf[8]);
 
 	/*
 	 * Set OPTIMAL TRANSFER LENGTH
diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c
index ce8574b..7723f82 100644
--- a/drivers/target/target_core_transport.c
+++ b/drivers/target/target_core_transport.c
@@ -1118,6 +1118,29 @@ target_cmd_size_check(struct se_cmd *cmd, unsigned int size)
 			cmd->data_length = size;
 		}
 	}
+	/*
+	 * Check if fabric enforced maximum SGL entries per I/O descriptor
+	 * exceeds se_cmd->data_length.  If true, set SCF_OVERFLOW_BIT +
+	 * residual_count and reduce original cmd->data_length to maximum
+	 * length based on single PAGE_SIZE entry scatter-lists.
+	 */
+	if (cmd->se_tfo->max_data_sg_nents) {
+		u32 mtl = (cmd->se_tfo->max_data_sg_nents * PAGE_SIZE);
+
+		if (cmd->data_length > mtl) {
+			cmd->se_cmd_flags |= SCF_OVERFLOW_BIT;
+			cmd->residual_count = (mtl - cmd->data_length);
+			cmd->data_length = mtl;
+			/*
+			 * Reset sbc_check_prot() calculated protection payload
+			 * length based upon the new smaller MTL.
+			 */
+			if (cmd->prot_length) {
+				u32 sectors = (mtl / dev->dev_attrib.block_size);
+				cmd->prot_length = dev->prot_length * sectors;
+			}
+		}
+	}
 
 	return 0;
 
diff --git a/include/target/target_core_fabric.h b/include/target/target_core_fabric.h
index 18afef9..995f2e1 100644
--- a/include/target/target_core_fabric.h
+++ b/include/target/target_core_fabric.h
@@ -5,6 +5,19 @@ struct target_core_fabric_ops {
 	struct module *module;
 	const char *name;
 	size_t node_acl_size;
+	/*
+	 * Limits number of scatterlist entries per SCF_SCSI_DATA_CDB payload.
+	 * Setting this value tells target-core to enforce this limit, and
+	 * report as INQUIRY EVPD=b0 MAXIMUM TRANSFER LENGTH.
+	 *
+	 * target-core will currently reset se_cmd->data_length to this
+	 * maximum size, and set OVERFLOW residual count if length exceeds
+	 * this limit.
+	 *
+	 * XXX: Not all initiator hosts honor this block-limit EVPD
+	 * XXX: Currently assumes single PAGE_SIZE per scatterlist entry
+	 */
+	u32 max_data_sg_nents;
 	char *(*get_fabric_name)(void);
 	char *(*tpg_get_wwn)(struct se_portal_group *);
 	u16 (*tpg_get_tag)(struct se_portal_group *);
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe target-devel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Linux SCSI]     [Kernel Newbies]     [Linux SCSI Target Infrastructure]     [Share Photos]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Linux IIO]     [Device Mapper]

  Powered by Linux