All of lore.kernel.org
 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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.