linux-scsi.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Douglas Gilbert <dgilbert@interlog.com>
To: Hannes Reinecke <hare@suse.de>, linux-scsi@vger.kernel.org
Cc: martin.petersen@oracle.com, tomas.winkler@intel.com, emilne@redhat.com
Subject: Re: [PATCH 08/12] scsi_debug: rework resp_report_luns
Date: Wed, 27 Apr 2016 00:08:41 -0400	[thread overview]
Message-ID: <57203B49.7040706@interlog.com> (raw)
In-Reply-To: <571F0A20.5040205@suse.de>

On 2016-04-26 02:26 AM, Hannes Reinecke wrote:
> On 04/25/2016 06:16 PM, Douglas Gilbert wrote:
>> Based on "[PATH V2] scsi_debug: rework resp_report_luns" patch
>> sent by Tomas Winkler on Thursday, 26 Feb 2015. His notes:
>>    1. Remove duplicated boundary checks which simplify the fill-in
>>       loop
>>    2. Use more of scsi generic API
>> Replace fixed length response array a with heap allocation
>> allowing up to 16383 LUNs per target.
>>
>> Signed-off-by: Douglas Gilbert <dgilbert@interlog.com>
>> ---
>>   drivers/scsi/scsi_debug.c | 138 ++++++++++++++++++++++++++++++----------------
>>   1 file changed, 91 insertions(+), 47 deletions(-)
>>
>> diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
>> index cf44ab0..eac62b8 100644
>> --- a/drivers/scsi/scsi_debug.c
>> +++ b/drivers/scsi/scsi_debug.c
>> @@ -3205,63 +3205,99 @@ static int resp_get_lba_status(struct scsi_cmnd *scp,
>>   	return fill_from_dev_buffer(scp, arr, SDEBUG_GET_LBA_STATUS_LEN);
>>   }
>>
>> -#define SDEBUG_RLUN_ARR_SZ 256
>> -
>> -static int resp_report_luns(struct scsi_cmnd * scp,
>> -			    struct sdebug_dev_info * devip)
>> +/* Even though each pseudo target has a REPORT LUNS "well known logical unit"
>> + * (W-LUN), the normal Linux scanning logic does not associate it with a
>> + * device (e.g. /dev/sg7). The following magic will make that association:
>> + *   "cd /sys/class/scsi_host/host<n> ; echo '- - 49409' > scan"
>> + * where <n> is a host number. If there are multiple targets in a host then
>> + * the above will associate a W-LUN to each target. To only get a W-LUN
>> + * for target 2, then use "echo '- 2 49409' > scan" . */
>> +static int resp_report_luns(struct scsi_cmnd *scp,
>> +			    struct sdebug_dev_info *devip)
>>   {
>> +	unsigned char *cmd = scp->cmnd;
>>   	unsigned int alloc_len;
>> -	int lun_cnt, i, upper, num, n, want_wlun, shortish;
>> +	unsigned char select_report;
>>   	u64 lun;
>> -	unsigned char *cmd = scp->cmnd;
>> -	int select_report = (int)cmd[2];
>> -	struct scsi_lun *one_lun;
>> -	unsigned char arr[SDEBUG_RLUN_ARR_SZ];
>> -	unsigned char * max_addr;
>> +	struct scsi_lun *lun_p;
>> +	u8 *arr;
>> +	unsigned int lun_cnt;	/* normal LUN count (max: 16383) */
>> +	unsigned int wlun_cnt;	/* report luns W-LUN count */
>> +	unsigned int tlun_cnt;	/* total LUN count */
>> +	unsigned int rlen;	/* response length (in bytes) less header */
>> +	int i, res;
>>
>>   	clear_luns_changed_on_target(devip);
>> -	alloc_len = cmd[9] + (cmd[8] << 8) + (cmd[7] << 16) + (cmd[6] << 24);
>> -	shortish = (alloc_len < 4);
>> -	if (shortish || (select_report > 2)) {
>> -		mk_sense_invalid_fld(scp, SDEB_IN_CDB, shortish ? 6 : 2, -1);
>> +
>> +	select_report = cmd[2];
>> +	alloc_len = get_unaligned_be32(cmd + 6);
>> +
>> +	if (alloc_len < 4) {
>> +		pr_err("alloc len too small %d\n", alloc_len);
>> +		mk_sense_invalid_fld(scp, SDEB_IN_CDB, 6, -1);
>>   		return check_condition_result;
>>   	}
>> -	/* can produce response with up to 16k luns (lun 0 to lun 16383) */
>> -	memset(arr, 0, SDEBUG_RLUN_ARR_SZ);
>> +
>> +	if (select_report > 0x02) {
>> +		pr_err("select report invalid %d\n", select_report);
>> +		mk_sense_invalid_fld(scp, SDEB_IN_CDB, 2, -1);
>> +		return check_condition_result;
>> +	}
>> +
>>   	lun_cnt = sdebug_max_luns;
>> -	if (1 == select_report)
>> +	wlun_cnt = 0;
>> +
>> +	/* report only w_lun */
>> +	if (select_report == 0x01)
>>   		lun_cnt = 0;
>> -	else if (sdebug_no_lun_0 && (lun_cnt > 0))
>> +
>> +	if (sdebug_no_lun_0 && (lun_cnt > 0))
>>   		--lun_cnt;
>> -	want_wlun = (select_report > 0) ? 1 : 0;
>> -	num = lun_cnt + want_wlun;
>> -	arr[2] = ((sizeof(struct scsi_lun) * num) >> 8) & 0xff;
>> -	arr[3] = (sizeof(struct scsi_lun) * num) & 0xff;
>> -	n = min((int)((SDEBUG_RLUN_ARR_SZ - 8) /
>> -			    sizeof(struct scsi_lun)), num);
>> -	if (n < num) {
>> -		want_wlun = 0;
>> -		lun_cnt = n;
>> -	}
>> -	one_lun = (struct scsi_lun *) &arr[8];
>> -	max_addr = arr + SDEBUG_RLUN_ARR_SZ;
>> -	for (i = 0, lun = (sdebug_no_lun_0 ? 1 : 0);
>> -             ((i < lun_cnt) && ((unsigned char *)(one_lun + i) < max_addr));
>> -	     i++, lun++) {
>> -		upper = (lun >> 8) & 0x3f;
>> -		if (upper)
>> -			one_lun[i].scsi_lun[0] =
>> -			    (upper | (SAM2_LUN_ADDRESS_METHOD << 6));
>> -		one_lun[i].scsi_lun[1] = lun & 0xff;
>> -	}
>> -	if (want_wlun) {
>> -		one_lun[i].scsi_lun[0] = (SCSI_W_LUN_REPORT_LUNS >> 8) & 0xff;
>> -		one_lun[i].scsi_lun[1] = SCSI_W_LUN_REPORT_LUNS & 0xff;
>> -		i++;
>> -	}
>> -	alloc_len = (unsigned char *)(one_lun + i) - arr;
>> -	return fill_from_dev_buffer(scp, arr,
>> -				    min((int)alloc_len, SDEBUG_RLUN_ARR_SZ));
>> +
>> +	/* report w_lun */
>> +	if (select_report == 0x01 || select_report == 0x02)
>> +		wlun_cnt = 1;
>> +
>> +	tlun_cnt = lun_cnt + wlun_cnt;
>> +	/* can produce response with up to 16k luns (lun 0 to lun 16383) */
>> +	arr = kzalloc((tlun_cnt * sizeof(lun_p->scsi_lun)) + 8, GFP_ATOMIC);
>> +	if (!arr) {
>> +		pr_warn("No space for report luns response\n");
>> +		mk_sense_buffer(scp, ILLEGAL_REQUEST, INSUFF_RES_ASC,
>> +				INSUFF_RES_ASCQ);
>> +		return check_condition_result;
>> +	}
>> +	pr_debug("select_report %d luns = %d wluns = %d no_lun0 %d\n",
>> +		 select_report, lun_cnt, wlun_cnt, sdebug_no_lun_0);
>> +
>> +	lun = 0LL;
>> +	/* luns start at offset 8 after the byte length */
>> +	lun_p = (struct scsi_lun *)&arr[8];
>> +
>> +	/* skip lun 0 */
>> +	if (sdebug_no_lun_0)
>> +		lun++;
>> +	/*
>> +	 * Address method (we use Peripherial = 00b)
>> +	 * 10b - Logical unit
>> +	 * 00b - Peripherial device - Use this one
>> +	 * 01b - Logical device
>> +	 * 11b - reserved
>> +	 */
>> +	for (i = 0; i < lun_cnt; i++)
>> +		int_to_scsilun(lun++, lun_p++);
>> +
>> +	/* report SCSI_W_LUN_REPORT_LUN */
>> +	if (wlun_cnt)
>> +		int_to_scsilun(SCSI_W_LUN_REPORT_LUNS, lun_p++);
>> +
>> +	rlen = tlun_cnt * sizeof(struct scsi_lun);
>> +
>> +	put_unaligned_be32(rlen, &arr[0]);
>> +
>> +	res = fill_from_dev_buffer(scp, arr, rlen + 8);
>> +	kfree(arr);
>> +	return res;
>>   }
>>
>>   static int resp_xdwriteread(struct scsi_cmnd *scp, unsigned long long lba,
>> @@ -4299,6 +4335,10 @@ static ssize_t max_luns_store(struct device_driver *ddp, const char *buf,
>>   	bool changed;
>>
>>   	if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) {
>> +		if (n > 16383) {
>> +			pr_warn("max_luns can be no more than 16383\n");
>> +			return -EINVAL;
>> +		}
>>   		changed = (sdebug_max_luns != n);
>>   		sdebug_max_luns = n;
>>   		sdebug_max_tgts_luns();
>> @@ -4643,6 +4683,10 @@ static int __init scsi_debug_init(void)
>>   		pr_err("invalid physblk_exp %u\n", sdebug_physblk_exp);
>>   		return -EINVAL;
>>   	}
>> +	if (sdebug_max_luns > 16383) {
>> +		pr_warn("max_luns can be no more than 16383, use default\n");
>> +		sdebug_max_luns = DEF_MAX_LUNS;
>> +	}
>>
>>   	if (sdebug_lowest_aligned > 0x3fff) {
>>   		pr_err("lowest_aligned too big: %u\n", sdebug_lowest_aligned);
>>
> Hmm.
>
> Have you actually checked this?

Yes I did and it worked!! It took 13 minutes on my laptop with
'max_luns=16383' and after that I could access various LUs across
that range. You can try it yourself :-)

> Thing is, only LUNs 0-255 are numbered sequentially; any higher LUNs
> has to use one of the various encoding schemes, at which point the
> sequentiality (sp?) breaks down.

I checked sam6r01.pdf clause 4.7.5 and you are correct. So the
comment inherited from Tomas's patch about 16k luns is wrong.

> So to be correct you probably should be using a loop from 0-255 to
> generate the low-order LUNs, and another loop from 255 - lun_cnt to
> construct the higher-order LUNs from the address method + lun number.

So should I scale max_luns back to no more than 256 (which should
produce LUNs 0...255 (or if no_lun_0=1 produce LUNs 1...255)), or
switch to flat space addressing (address_method=1) at LUN 256
through 16383?

The driver already has the capability of building an arbitrary
number of targets (num_tgts) and hosts (add_host: it says a max
of 127 but that is not enforced). The previous limit on LUNs
(per target, per host) was 31.

Doug Gilbert



  reply	other threads:[~2016-04-27  4:08 UTC|newest]

Thread overview: 41+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-04-25 16:16 [PATCH 00/12] scsi_debug: multiple queue support and cleanup Douglas Gilbert
2016-04-25 16:16 ` [PATCH 01/12] scsi_debug: cleanup naming and bit crunching Douglas Gilbert
2016-04-26  6:14   ` Hannes Reinecke
2016-04-26 18:13   ` Bart Van Assche
2016-04-26 18:27     ` James Bottomley
2016-04-27  5:25     ` Douglas Gilbert
2016-04-25 16:16 ` [PATCH 02/12] scsi_debug: ignore host lock option Douglas Gilbert
2016-04-26  6:15   ` Hannes Reinecke
2016-04-25 16:16 ` [PATCH 03/12] scsi_debug: replace jiffy timers with hr timers Douglas Gilbert
2016-04-26  6:17   ` Hannes Reinecke
2016-04-26 18:38   ` Bart Van Assche
2016-04-25 16:16 ` [PATCH 04/12] scsi_debug: make jiffy delay name clearer Douglas Gilbert
2016-04-26  6:17   ` Hannes Reinecke
2016-04-25 16:16 ` [PATCH 05/12] scsi_debug: replace tasklet with work queue Douglas Gilbert
2016-04-26  6:20   ` Hannes Reinecke
2016-04-25 16:16 ` [PATCH 06/12] scsi_debug: re-order file scope declarations Douglas Gilbert
2016-04-26  6:21   ` Hannes Reinecke
2016-04-26 20:55   ` Bart Van Assche
2016-04-25 16:16 ` [PATCH 07/12] scsi_debug: use likely hints on fast path Douglas Gilbert
2016-04-26  6:22   ` Hannes Reinecke
2016-04-26 22:14   ` Bart Van Assche
2016-04-27  5:25     ` Douglas Gilbert
2016-04-27  5:33       ` Bart Van Assche
2016-04-27 14:29       ` Bart Van Assche
2016-04-25 16:16 ` [PATCH 08/12] scsi_debug: rework resp_report_luns Douglas Gilbert
2016-04-26  6:26   ` Hannes Reinecke
2016-04-27  4:08     ` Douglas Gilbert [this message]
2016-04-27  5:58       ` Hannes Reinecke
2016-04-26  7:33   ` Winkler, Tomas
2016-04-27 23:09   ` Bart Van Assche
2016-04-25 16:16 ` [PATCH 09/12] scsi_debug: add multiple queue support Douglas Gilbert
2016-04-26  6:29   ` Hannes Reinecke
2016-04-26 22:19   ` Bart Van Assche
2016-04-25 16:16 ` [PATCH 10/12] scsi_debug: vpd and mode page work Douglas Gilbert
2016-04-26  6:29   ` Hannes Reinecke
2016-04-25 16:16 ` [PATCH 11/12] scsi_debug: uuid for lu name Douglas Gilbert
2016-04-26  6:30   ` Hannes Reinecke
2016-04-25 16:16 ` [PATCH 12/12] scsi_debug: use locally assigned naa Douglas Gilbert
2016-04-26  6:31   ` Hannes Reinecke
2016-04-29 23:53 ` [PATCH 00/12] scsi_debug: multiple queue support and cleanup Martin K. Petersen
2016-04-30  2:06   ` Douglas Gilbert

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=57203B49.7040706@interlog.com \
    --to=dgilbert@interlog.com \
    --cc=emilne@redhat.com \
    --cc=hare@suse.de \
    --cc=linux-scsi@vger.kernel.org \
    --cc=martin.petersen@oracle.com \
    --cc=tomas.winkler@intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).