Re: [PATCH v4 5/7] scsi-ml: adds queue_depth ramp up code

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

 



On Thu, Oct 22, 2009 at 03:46:33PM -0700, Vasu Dev wrote:
> Current FC HBA queue_depth ramp up code depends on last queue
> full time. The sdev already  has last_queue_full_time field to
> track last queue full time but stored value is truncated by
> last four bits.
> 
> So this patch updates last_queue_full_time without truncating
> last 4 bits to store full value and then updates its only
> current usages in scsi_track_queue_full to ignore last four bits
> to keep current usages same while also use this field
> in added ramp up code.
> 
> Adds scsi_handle_queue_ramp_up to ramp up queue_depth on
> successful completion of IO. The scsi_handle_queue_ramp_up will
> do ramp up on all luns of a target, just same as ramp down done
> on all luns on a target.
> 
> The ramp up is skipped in case the change_queue_depth is not
> supported by LLD or already reached to added max_queue_depth.
> 
> Updates added max_queue_depth on every new update to default
> queue_depth value.
> 
> The ramp up is also skipped if lapsed time since either last
> queue ramp up or down is less than LLD specified
> queue_ramp_up_period.
> 
> Adds queue_ramp_up_period to sysfs but only if change_queue_depth
> is supported since ramp up and queue_ramp_up_period is needed only
> in case change_queue_depth is supported first.
> 
> Initializes queue_ramp_up_period to 120HZ jiffies as initial
> default value, it is same as used in existing lpfc and qla2xxx.
> 
> -v2
>  Combined all ramp code into this single patch.
> 
> -v3
>  Moves max_queue_depth initialization after slave_configure is
> called from after slave_alloc calling done. Also adjusted
> max_queue_depth check to skip ramp up if current queue_depth
> is >= max_queue_depth.
> 
> -v4
>  Changes sdev->queue_ramp_up_period unit to ms when using sysfs i/f
> to store or show its value.
> 
> Signed-off-by: Vasu Dev <vasu.dev@xxxxxxxxx>

The patch looks good. I also ran a brief test on s390 again.

Acked-and-tested-by: Christof Schmitt <christof.schmitt@xxxxxxxxxx>

> ---
> 
>  drivers/scsi/scsi.c        |   10 ++++++++--
>  drivers/scsi/scsi_error.c  |   38 ++++++++++++++++++++++++++++++++++++++
>  drivers/scsi/scsi_scan.c   |    3 +++
>  drivers/scsi/scsi_sysfs.c  |   41 +++++++++++++++++++++++++++++++++++++++--
>  include/scsi/scsi_device.h |    9 ++++++---
>  5 files changed, 94 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
> index dd098ca..a60da55 100644
> --- a/drivers/scsi/scsi.c
> +++ b/drivers/scsi/scsi.c
> @@ -940,10 +940,16 @@ EXPORT_SYMBOL(scsi_adjust_queue_depth);
>   */
>  int scsi_track_queue_full(struct scsi_device *sdev, int depth)
>  {
> -	if ((jiffies >> 4) == sdev->last_queue_full_time)
> +
> +	/*
> +	 * Don't let QUEUE_FULLs on the same
> +	 * jiffies count, they could all be from
> +	 * same event.
> +	 */
> +	if ((jiffies >> 4) == (sdev->last_queue_full_time >> 4))
>  		return 0;
> 
> -	sdev->last_queue_full_time = (jiffies >> 4);
> +	sdev->last_queue_full_time = jiffies;
>  	if (sdev->last_queue_full_depth != depth) {
>  		sdev->last_queue_full_count = 1;
>  		sdev->last_queue_full_depth = depth;
> diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
> index 7b1e20f..08ed506 100644
> --- a/drivers/scsi/scsi_error.c
> +++ b/drivers/scsi/scsi_error.c
> @@ -331,6 +331,42 @@ static int scsi_check_sense(struct scsi_cmnd *scmd)
>  	}
>  }
> 
> +static void scsi_handle_queue_ramp_up(struct scsi_device *sdev)
> +{
> +	struct scsi_host_template *sht = sdev->host->hostt;
> +	struct scsi_device *tmp_sdev;
> +
> +	if (!sht->change_queue_depth ||
> +	    sdev->queue_depth >= sdev->max_queue_depth)
> +		return;
> +
> +	if (time_before(jiffies,
> +	    sdev->last_queue_ramp_up + sdev->queue_ramp_up_period))
> +		return;
> +
> +	if (time_before(jiffies,
> +	    sdev->last_queue_full_time + sdev->queue_ramp_up_period))
> +		return;
> +
> +	/*
> +	 * Walk all devices of a target and do
> +	 * ramp up on them.
> +	 */
> +	shost_for_each_device(tmp_sdev, sdev->host) {
> +		if (tmp_sdev->channel != sdev->channel ||
> +		    tmp_sdev->id != sdev->id ||
> +		    tmp_sdev->queue_depth == sdev->max_queue_depth)
> +			continue;
> +		/*
> +		 * call back into LLD to increase queue_depth by one
> +		 * with ramp up reason code.
> +		 */
> +		sht->change_queue_depth(tmp_sdev, tmp_sdev->queue_depth + 1,
> +					SCSI_QDEPTH_RAMP_UP);
> +		sdev->last_queue_ramp_up = jiffies;
> +	}
> +}
> +
>  static void scsi_handle_queue_full(struct scsi_device *sdev)
>  {
>  	struct scsi_host_template *sht = sdev->host->hostt;
> @@ -393,6 +429,7 @@ static int scsi_eh_completed_normally(struct scsi_cmnd *scmd)
>  	 */
>  	switch (status_byte(scmd->result)) {
>  	case GOOD:
> +		scsi_handle_queue_ramp_up(scmd->device);
>  	case COMMAND_TERMINATED:
>  		return SUCCESS;
>  	case CHECK_CONDITION:
> @@ -1425,6 +1462,7 @@ int scsi_decide_disposition(struct scsi_cmnd *scmd)
>  		 */
>  		return ADD_TO_MLQUEUE;
>  	case GOOD:
> +		scsi_handle_queue_ramp_up(scmd->device);
>  	case COMMAND_TERMINATED:
>  		return SUCCESS;
>  	case TASK_ABORTED:
> diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
> index cb6338f..2847a86 100644
> --- a/drivers/scsi/scsi_scan.c
> +++ b/drivers/scsi/scsi_scan.c
> @@ -251,6 +251,7 @@ static struct scsi_device *scsi_alloc_sdev(struct scsi_target *starget,
>  	sdev->model = scsi_null_device_strs;
>  	sdev->rev = scsi_null_device_strs;
>  	sdev->host = shost;
> +	sdev->queue_ramp_up_period = SCSI_DEFAULT_RAMP_UP_PERIOD;
>  	sdev->id = starget->id;
>  	sdev->lun = lun;
>  	sdev->channel = starget->channel;
> @@ -940,6 +941,8 @@ static int scsi_add_lun(struct scsi_device *sdev, unsigned char *inq_result,
>  		}
>  	}
> 
> +	sdev->max_queue_depth = sdev->queue_depth;
> +
>  	/*
>  	 * Ok, the device is now all set up, we can
>  	 * register it and tell the rest of the kernel
> diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
> index 4c59336..3a9e805 100644
> --- a/drivers/scsi/scsi_sysfs.c
> +++ b/drivers/scsi/scsi_sysfs.c
> @@ -771,6 +771,8 @@ sdev_store_queue_depth_rw(struct device *dev, struct device_attribute *attr,
>  	if (retval < 0)
>  		return retval;
> 
> +	sdev->max_queue_depth = sdev->queue_depth;
> +
>  	return count;
>  }
> 
> @@ -779,6 +781,37 @@ static struct device_attribute sdev_attr_queue_depth_rw =
>  	       sdev_store_queue_depth_rw);
> 
>  static ssize_t
> +sdev_show_queue_ramp_up_period(struct device *dev,
> +			       struct device_attribute *attr,
> +			       char *buf)
> +{
> +	struct scsi_device *sdev;
> +	sdev = to_scsi_device(dev);
> +	return snprintf(buf, 20, "%u\n",
> +			jiffies_to_msecs(sdev->queue_ramp_up_period));
> +}
> +
> +static ssize_t
> +sdev_store_queue_ramp_up_period(struct device *dev,
> +				struct device_attribute *attr,
> +				const char *buf, size_t count)
> +{
> +	struct scsi_device *sdev = to_scsi_device(dev);
> +	unsigned long period;
> +
> +	if (strict_strtoul(buf, 10, &period))
> +		return -EINVAL;
> +
> +	sdev->queue_ramp_up_period = msecs_to_jiffies(period);
> +	return period;
> +}
> +
> +static struct device_attribute sdev_attr_queue_ramp_up_period =
> +	__ATTR(queue_ramp_up_period, S_IRUGO | S_IWUSR,
> +	       sdev_show_queue_ramp_up_period,
> +	       sdev_store_queue_ramp_up_period);
> +
> +static ssize_t
>  sdev_store_queue_type_rw(struct device *dev, struct device_attribute *attr,
>  			 const char *buf, size_t count)
>  {
> @@ -870,8 +903,12 @@ int scsi_sysfs_add_sdev(struct scsi_device *sdev)
>  	get_device(&sdev->sdev_gendev);
> 
>  	/* create queue files, which may be writable, depending on the host */
> -	if (sdev->host->hostt->change_queue_depth)
> -		error = device_create_file(&sdev->sdev_gendev, &sdev_attr_queue_depth_rw);
> +	if (sdev->host->hostt->change_queue_depth) {
> +		error = device_create_file(&sdev->sdev_gendev,
> +					   &sdev_attr_queue_depth_rw);
> +		error = device_create_file(&sdev->sdev_gendev,
> +					   &sdev_attr_queue_ramp_up_period);
> +	}
>  	else
>  		error = device_create_file(&sdev->sdev_gendev, &dev_attr_queue_depth);
>  	if (error) {
> diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h
> index 9af48cb..92c4c3b 100644
> --- a/include/scsi/scsi_device.h
> +++ b/include/scsi/scsi_device.h
> @@ -81,11 +81,14 @@ struct scsi_device {
>  	struct list_head starved_entry;
>  	struct scsi_cmnd *current_cmnd;	/* currently active command */
>  	unsigned short queue_depth;	/* How deep of a queue we want */
> +	unsigned short max_queue_depth;	/* max queue depth */
>  	unsigned short last_queue_full_depth; /* These two are used by */
>  	unsigned short last_queue_full_count; /* scsi_track_queue_full() */
> -	unsigned long last_queue_full_time;/* don't let QUEUE_FULLs on the same
> -					   jiffie count on our counter, they
> -					   could all be from the same event. */
> +	unsigned long last_queue_full_time;	/* last queue full time */
> +	unsigned long queue_ramp_up_period;	/* ramp up period in jiffies */
> +#define SCSI_DEFAULT_RAMP_UP_PERIOD	(120 * HZ)
> +
> +	unsigned long last_queue_ramp_up;	/* last queue ramp up time */
> 
>  	unsigned int id, lun, channel;
> 
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
> the body of a message to majordomo@xxxxxxxxxxxxxxx
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [SCSI Target Devel]     [Linux SCSI Target Infrastructure]     [Kernel Newbies]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Linux IIO]     [Samba]     [Device Mapper]
  Powered by Linux