Re: [PATCH] ALUA support for scsi_debug

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

 



Hannes Reinecke wrote:
> Douglas Gilbert wrote:
>> Hannes Reinecke wrote:
>>> Douglas Gilbert wrote:
>>>> Hannes,
>>>> Here is my counter patch for you to consider.
>>>> I suspect my machine was running into stack
>>>> problems so I moved some arrays onto the heap.
>>>>
>>> Ah. Good. To tell the truth I was a bit concerned once I've
>>> discovered that all information pages are infact statically allocated
>>> ...
>>
>> I wasn't aware that statically allocated data (file or local
>> scope) would add to stack problems on a driver loaded as a
>> module. The arrays I moved to the heap were "auto" (i.e. non-static).
>>
> [ .. ]
>>
>> Over zealous error processing ....
>> I have made this mistake often enough, along with
>> many others, so hopefully some readers will take note:
>>
> I know. Been there before, too :-)
> 
>> <snip>
> [ .. ]
>> So the "if (alloc_len < 4 + (11 * 2))" block should be
>> removed. Also the "if (alloc_len < n)" block should be
>> removed and "min" should be (possibly a cleaner version of):
>>   min(min(alloc_len, n), SDEBUG_MAX_TGTPGS_ARR_SZ))
>>
> Ok, did so. And returned the proper (relative !) port number
> in the port descriptor list.
> 
> Is this more to your liking?

Hannes,
Looks goods, tests well.

Signed-off-by: Douglas Gilbert <dougg@xxxxxxxxxx>

Doug Gilbert

> ------------------------------------------------------------------------
> 
> diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
> index 9c0f358..8e71fd2 100644
> --- a/drivers/scsi/scsi_debug.c
> +++ b/drivers/scsi/scsi_debug.c
> @@ -52,7 +52,7 @@ #include "scsi_logging.h"
>  #include "scsi_debug.h"
>  
>  #define SCSI_DEBUG_VERSION "1.80"
> -static const char * scsi_debug_version_date = "20060914";
> +static const char * scsi_debug_version_date = "20061018";
>  
>  /* Additional Sense Code (ASC) used */
>  #define NO_ADDITIONAL_SENSE 0x0
> @@ -254,6 +254,8 @@ static int resp_requests(struct scsi_cmn
>  			 struct sdebug_dev_info * devip);
>  static int resp_start_stop(struct scsi_cmnd * scp,
>  			   struct sdebug_dev_info * devip);
> +static int resp_report_tgtpgs(struct scsi_cmnd * scp,
> +			      struct sdebug_dev_info * devip);
>  static int resp_readcap(struct scsi_cmnd * SCpnt,
>  			struct sdebug_dev_info * devip);
>  static int resp_readcap16(struct scsi_cmnd * SCpnt,
> @@ -287,9 +289,9 @@ static void __init sdebug_build_parts(un
>  static void __init init_all_queued(void);
>  static void stop_all_queued(void);
>  static int stop_queued_cmnd(struct scsi_cmnd * cmnd);
> -static int inquiry_evpd_83(unsigned char * arr, int target_dev_id,
> -			   int dev_id_num, const char * dev_id_str,
> -			   int dev_id_str_len);
> +static int inquiry_evpd_83(unsigned char * arr, int port_group_id,
> +			   int target_dev_id, int dev_id_num,
> +			   const char * dev_id_str, int dev_id_str_len);
>  static int inquiry_evpd_88(unsigned char * arr, int target_dev_id);
>  static int do_create_driverfs_files(void);
>  static void do_remove_driverfs_files(void);
> @@ -422,6 +424,15 @@ int scsi_debug_queuecommand(struct scsi_
>  		}
>  		errsts = resp_readcap16(SCpnt, devip);
>  		break;
> +	case MAINTENANCE_IN:
> +		if (MI_REPORT_TARGET_PGS != cmd[1]) {
> +			mk_sense_buffer(devip, ILLEGAL_REQUEST,
> +					INVALID_OPCODE, 0);
> +			errsts = check_condition_result;
> +			break;
> +		}
> +		errsts = resp_report_tgtpgs(SCpnt, devip);
> +		break;
>  	case READ_16:
>  	case READ_12:
>  	case READ_10:
> @@ -665,8 +676,9 @@ static const char * inq_vendor_id = "Lin
>  static const char * inq_product_id = "scsi_debug      ";
>  static const char * inq_product_rev = "0004";
>  
> -static int inquiry_evpd_83(unsigned char * arr, int target_dev_id,
> -			   int dev_id_num, const char * dev_id_str,
> +static int inquiry_evpd_83(unsigned char * arr, int port_group_id,
> +			   int target_dev_id, int dev_id_num,
> +			   const char * dev_id_str,
>  			   int dev_id_str_len)
>  {
>  	int num, port_a;
> @@ -720,6 +732,15 @@ static int inquiry_evpd_83(unsigned char
>  	arr[num++] = (port_a >> 16) & 0xff;
>  	arr[num++] = (port_a >> 8) & 0xff;
>  	arr[num++] = port_a & 0xff;
> +	/* NAA-5, Target port group identifier */
> +	arr[num++] = 0x61;	/* proto=sas, binary */
> +	arr[num++] = 0x95;	/* piv=1, target port group id */
> +	arr[num++] = 0x0;
> +	arr[num++] = 0x4;
> +	arr[num++] = 0;
> +	arr[num++] = 0;
> +	arr[num++] = (port_group_id >> 8) & 0xff;
> +	arr[num++] = port_group_id & 0xff;
>  	/* NAA-5, Target device identifier */
>  	arr[num++] = 0x61;	/* proto=sas, binary */
>  	arr[num++] = 0xa3;	/* piv=1, target device, naa */
> @@ -928,12 +949,12 @@ static int resp_inquiry(struct scsi_cmnd
>  			struct sdebug_dev_info * devip)
>  {
>  	unsigned char pq_pdt;
> -	unsigned char arr[SDEBUG_MAX_INQ_ARR_SZ];
> +	unsigned char * arr;
>  	unsigned char *cmd = (unsigned char *)scp->cmnd;
> -	int alloc_len, n;
> +	int alloc_len, n, ret;
>  
>  	alloc_len = (cmd[3] << 8) + cmd[4];
> -	memset(arr, 0, SDEBUG_MAX_INQ_ARR_SZ);
> +	arr = kzalloc(SDEBUG_MAX_INQ_ARR_SZ, GFP_KERNEL);
>  	if (devip->wlun)
>  		pq_pdt = 0x1e;	/* present, wlun */
>  	else if (scsi_debug_no_lun_0 && (0 == devip->lun))
> @@ -944,12 +965,15 @@ static int resp_inquiry(struct scsi_cmnd
>  	if (0x2 & cmd[1]) {  /* CMDDT bit set */
>  		mk_sense_buffer(devip, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB,
>  			       	0);
> +		kfree(arr);
>  		return check_condition_result;
>  	} else if (0x1 & cmd[1]) {  /* EVPD bit set */
> -		int lu_id_num, target_dev_id, len;
> +		int lu_id_num, port_group_id, target_dev_id, len;
>  		char lu_id_str[6];
>  		int host_no = devip->sdbg_host->shost->host_no;
>  		
> +		port_group_id = (((host_no + 1) & 0x7f) << 8) + 
> +		    (devip->channel & 0x7f);
>  		if (0 == scsi_debug_vpd_use_hostno)
>  			host_no = 0;
>  		lu_id_num = devip->wlun ? -1 : (((host_no + 1) * 2000) +
> @@ -977,8 +1001,9 @@ static int resp_inquiry(struct scsi_cmnd
>  			memcpy(&arr[4], lu_id_str, len);
>  		} else if (0x83 == cmd[2]) { /* device identification */
>  			arr[1] = cmd[2];	/*sanity */
> -			arr[3] = inquiry_evpd_83(&arr[4], target_dev_id,
> -						 lu_id_num, lu_id_str, len);
> +			arr[3] = inquiry_evpd_83(&arr[4], port_group_id,
> +						 target_dev_id, lu_id_num,
> +						 lu_id_str, len);
>  		} else if (0x84 == cmd[2]) { /* Software interface ident. */
>  			arr[1] = cmd[2];	/*sanity */
>  			arr[3] = inquiry_evpd_84(&arr[4]);
> @@ -1012,17 +1037,22 @@ static int resp_inquiry(struct scsi_cmnd
>  			/* Illegal request, invalid field in cdb */
>  			mk_sense_buffer(devip, ILLEGAL_REQUEST,
>  					INVALID_FIELD_IN_CDB, 0);
> +			kfree(arr);
>  			return check_condition_result;
>  		}
>  		len = min(((arr[2] << 8) + arr[3]) + 4, alloc_len);
> -		return fill_from_dev_buffer(scp, arr,
> +		ret = fill_from_dev_buffer(scp, arr,
>  			    min(len, SDEBUG_MAX_INQ_ARR_SZ));
> +		kfree(arr);
> +		return ret;
>  	}
>  	/* drops through here for a standard inquiry */
>  	arr[1] = DEV_REMOVEABLE(target) ? 0x80 : 0;	/* Removable disk */
>  	arr[2] = scsi_debug_scsi_level;
>  	arr[3] = 2;    /* response_data_format==2 */
>  	arr[4] = SDEBUG_LONG_INQ_SZ - 5;
> +	if (0 == scsi_debug_vpd_use_hostno)
> +		arr[5] = 0x10; /* claim: implicit TGPS */
>  	arr[6] = 0x10; /* claim: MultiP */
>  	/* arr[6] |= 0x40; ... claim: EncServ (enclosure services) */
>  	arr[7] = 0xa; /* claim: LINKED + CMDQUE */
> @@ -1039,8 +1069,10 @@ static int resp_inquiry(struct scsi_cmnd
>  		arr[n++] = 0x3; arr[n++] = 0x60; /* SSC-2 no version */
>  	}
>  	arr[n++] = 0xc; arr[n++] = 0xf;  /* SAS-1.1 rev 10 */
> -	return fill_from_dev_buffer(scp, arr,
> +	ret = fill_from_dev_buffer(scp, arr,
>  			    min(alloc_len, SDEBUG_LONG_INQ_SZ));
> +	kfree(arr);
> +	return ret;
>  }
>  
>  static int resp_requests(struct scsi_cmnd * scp,
> @@ -1171,6 +1203,87 @@ static int resp_readcap16(struct scsi_cm
>  				    min(alloc_len, SDEBUG_READCAP16_ARR_SZ));
>  }
>  
> +#define SDEBUG_MAX_TGTPGS_ARR_SZ 1412
> +
> +static int resp_report_tgtpgs(struct scsi_cmnd * scp,
> +			      struct sdebug_dev_info * devip)
> +{
> +	unsigned char *cmd = (unsigned char *)scp->cmnd;
> +	unsigned char * arr;
> +	int host_no = devip->sdbg_host->shost->host_no;
> +	int n, ret, alen, rlen;
> +	int port_group_a, port_group_b, port_a, port_b;
> +
> +	alen = ((cmd[6] << 24) + (cmd[7] << 16) + (cmd[8] << 8)
> +		+ cmd[9]);
> +
> +	arr = kzalloc(SDEBUG_MAX_TGTPGS_ARR_SZ, GFP_KERNEL);
> +	/*
> +	 * EVPD page 0x88 states we have two ports, one
> +	 * real and a fake port with no device connected.
> +	 * So we create two port groups with one port each
> +	 * and set the group with port B to unavailable.
> +	 */
> +	port_a = 0x1; /* relative port A */
> +	port_b = 0x2; /* relative port B */
> +	port_group_a = (((host_no + 1) & 0x7f) << 8) + 
> +	    (devip->channel & 0x7f);
> +	port_group_b = (((host_no + 1) & 0x7f) << 8) + 
> +	    (devip->channel & 0x7f) + 0x80;
> +
> +	/*
> +	 * The asymmetric access state is cycled according to the host_id.
> +	 */
> +	n = 4;
> +	if (0 == scsi_debug_vpd_use_hostno) {
> +	    arr[n++] = host_no % 3; /* Asymm access state */
> +	    arr[n++] = 0x0F; /* claim: all states are supported */
> +	} else {
> +	    arr[n++] = 0x0; /* Active/Optimized path */
> +	    arr[n++] = 0x01; /* claim: only support active/optimized paths */
> +	}
> +	arr[n++] = (port_group_a >> 8) & 0xff;
> +	arr[n++] = port_group_a & 0xff;
> +	arr[n++] = 0;    /* Reserved */
> +	arr[n++] = 0;    /* Status code */
> +	arr[n++] = 0;    /* Vendor unique */
> +	arr[n++] = 0x1;  /* One port per group */
> +	arr[n++] = 0;    /* Reserved */
> +	arr[n++] = 0;    /* Reserved */
> +	arr[n++] = (port_a >> 8) & 0xff;
> +	arr[n++] = port_a & 0xff;
> +	arr[n++] = 3;    /* Port unavailable */
> +	arr[n++] = 0x08; /* claim: only unavailalbe paths are supported */
> +	arr[n++] = (port_group_b >> 8) & 0xff;
> +	arr[n++] = port_group_b & 0xff;
> +	arr[n++] = 0;    /* Reserved */
> +	arr[n++] = 0;    /* Status code */
> +	arr[n++] = 0;    /* Vendor unique */
> +	arr[n++] = 0x1;  /* One port per group */
> +	arr[n++] = 0;    /* Reserved */
> +	arr[n++] = 0;    /* Reserved */
> +	arr[n++] = (port_b >> 8) & 0xff;
> +	arr[n++] = port_b & 0xff;
> +
> +	rlen = n - 4;
> +	arr[0] = (rlen >> 24) & 0xff;
> +	arr[1] = (rlen >> 16) & 0xff;
> +	arr[2] = (rlen >> 8) & 0xff;
> +	arr[3] = rlen & 0xff;
> +
> +	/*
> +	 * Return the smallest value of either
> +	 * - The allocated length
> +	 * - The constructed command length
> +	 * - The maximum array size
> +	 */
> +	rlen = min(alen,n);
> +	ret = fill_from_dev_buffer(scp, arr,
> +				   min(rlen, SDEBUG_MAX_TGTPGS_ARR_SZ));
> +	kfree(arr);
> +	return ret;
> +}
> +
>  /* <<Following mode page info copied from ST318451LW>> */
>  
>  static int resp_err_recov_pg(unsigned char * p, int pcontrol, int target)
> diff --git a/include/scsi/scsi.h b/include/scsi/scsi.h
> index 84a6d5f..8a3f0bd 100644
> --- a/include/scsi/scsi.h
> +++ b/include/scsi/scsi.h
> @@ -97,6 +97,7 @@ #define MODE_SENSE_10         0x5a
>  #define PERSISTENT_RESERVE_IN 0x5e
>  #define PERSISTENT_RESERVE_OUT 0x5f
>  #define REPORT_LUNS           0xa0
> +#define MAINTENANCE_IN        0xa3
>  #define MOVE_MEDIUM           0xa5
>  #define EXCHANGE_MEDIUM       0xa6
>  #define READ_12               0xa8
> @@ -114,6 +115,8 @@ #define VERIFY_16	      0x8f
>  #define SERVICE_ACTION_IN     0x9e
>  /* values for service action in */
>  #define	SAI_READ_CAPACITY_16  0x10
> +/* values for maintenance in */
> +#define MI_REPORT_TARGET_PGS  0x0a
>  
>  /* Values for T10/04-262r7 */
>  #define	ATA_16		      0x85	/* 16-byte pass-thru */

-
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