scsi scan bug when peripheral qualifier of 3 is returned
It looks like in previous kernels scsi_scan_target would pass scsi_sequential_lun_scan BLIST_SPARSELUN.
} else if (res == SCSI_SCAN_TARGET_PRESENT) {
/*
* There's a target here, but lun 0 is offline so we
* can't use the report_lun scan. Fall back to a
* sequential lun scan with a bflags of SPARSELUN and
* a default scsi level of SCSI_2
*/
scsi_sequential_lun_scan(starget, BLIST_SPARSELUN,
And in the current kernel we pass it bflags.
/*
* The REPORT LUN did not scan the target,
* do a sequential scan.
*/
scsi_sequential_lun_scan(starget, bflags,
But for SCSI_SCAN_TARGET_PRESENT bflags is not set. Is the correct fix to move where bflagsp gets set in scsi_probe_and_add_lun so that it gets set for the SCSI_SCAN_TARGET_PRESENT case, or should __scsi_scan_target be passing scsi_sequential_lun_scan and possibly scsi_report_lun_scan some default bflags values?
Quoted 5 lines · Mike Christie
But for
SCSI_SCAN_TARGET_PRESENTbflags is not set. Is the correct fix to move where bflagsp gets set inscsi_probe_and_add_lunso that it gets set for theSCSI_SCAN_TARGET_PRESENTcase, or should__scsi_scan_targetbe passingscsi_sequential_lun_scanand possiblyscsi_report_lun_scansome default bflags values?
It looks OK to me as-is, since bflags is also passed to and set in scsi_probe_lun(), right?
-- Patrick Mansfield
Quoted 9 lines · Patrick Mansfield
Quoted 1 line · Mike Christie
But for
SCSI_SCAN_TARGET_PRESENTbflags is not set. Is the correct fix to move where bflagsp gets set inscsi_probe_and_add_lunso that it gets set for theSCSI_SCAN_TARGET_PRESENTcase, or should__scsi_scan_targetbe passingscsi_sequential_lun_scanand possiblyscsi_report_lun_scansome default bflags values?It looks OK to me as-is, since bflags is also passed to and set in
scsi_probe_lun(), right?
A blagfs variable gets set but it is not the same one passed into scsi_probe_and_add_lun.
static int scsi_probe_and_add_lun(struct scsi_target *starget,
uint lun, int *bflagsp,
{
struct scsi_device *sdev;
unsigned char *result;
int bflags,scsi_probe_and_add_lun gets a *bflagsp passed to it as a function arg, but then also decalres a bflags variable itself. It then passes scsi_probe_lun() the bflags it declared and does this
res = scsi_add_lun(sdev, result, &bflags);
if (res == SCSI_SCAN_LUN_PRESENT) {
if (bflags & BLIST_KEY) {
sdev->lockable = 0;
scsi_unlock_floptical(sdev, result);
}
if (bflagsp)
*bflagsp = bflags;
}so *bflagsp pointer only gets set if SCSI_SCAN_LUN_PRESENT was returned by scsi_add_lun. For SCSI_SCAN_TARGET_PRESENT we do not even get to scsi_add_lun, so for this case *bflagsp never gets set and __scsi_scan_target gets zero. Previously, __scsi_scan_target would just pass scsi_sequential_lun_scan the sparse blist flag, but now it passes zero.
Quoted 11 lines · Mike Christie
Quoted 10 lines · Patrick Mansfield
Quoted 5 lines · Mike Christie
But for
SCSI_SCAN_TARGET_PRESENTbflags is not set. Is the correct fix to move where bflagsp gets set inscsi_probe_and_add_lunso that it gets set for theSCSI_SCAN_TARGET_PRESENTcase, or should__scsi_scan_targetbe passingscsi_sequential_lun_scanand possiblyscsi_report_lun_scansome default bflags values?
Quoted 6 lines
Quoted 3 lines
It looks OK to me as-is, since bflags is also passed to and set in
scsi_probe_lun(), right?A blagfs variable gets set but it is not the same one passed into
scsi_probe_and_add_lun.
Oh ... good catch there.
Quoted 24 lines
static int scsi_probe_and_add_lun(struct
scsi_target*starget,
uint lun, int *bflagsp,{ struct scsi_device *sdev; unsigned char *result; int bflags,
scsi_probe_and_add_lungets a *bflagsp passed to it as a function arg, but then also decalres a bflags variable itself. It then passesscsi_probe_lun()the bflags it declared and does thisres = scsi_add_lun(sdev, result, &bflags); if (res == SCSI_SCAN_LUN_PRESENT) { if (bflags & BLIST_KEY) { sdev->lockable = 0; scsi_unlock_floptical(sdev, result); } if (bflagsp) *bflagsp = bflags; }
Quoted 5 lines
so *bflagsp pointer only gets set if
SCSI_SCAN_LUN_PRESENTwas returned byscsi_add_lun. ForSCSI_SCAN_TARGET_PRESENTwe do not even get toscsi_add_lun, so for this case *bflagsp never gets set and__scsi_scan_targetgets zero. Previously,__scsi_scan_targetwould just passscsi_sequential_lun_scanthe sparse blist flag, but now it passes zero.
So yes we should always set *bflagsp. i.e.:
drivers/scsi/scsi_scan.c renamed from drivers/scsi/orig-scsi_scan.c +2 -2
@@ -891,13 +891,13 @@ static int scsi_probe_and_add_lun(struct } res =scsi_add_lun (sdev, result, &bflags); +if (bflagsp) + *bflagsp = bflags;if (res ==SCSI_SCAN_LUN_PRESENT ) {if (bflags &BLIST_KEY ) { sdev->lockable =0 ;scsi_unlock_floptical (sdev, result); } -if (bflagsp) - *bflagsp = bflags; } out_free_result:
Also ... it looks like we should just pass bflags not &bflags to scsi_add_lun(), since scsi_add_lun() does not modifies bflags.
-- Patrick Mansfield
drivers/scsi/scsi_scan.c static int scsi_probe_and_add_lun(struct · line 895
Quoted 10 lines · Patrick Mansfield
So yes we should always set *bflagsp. i.e.:
drivers/scsi/scsi_scan.c renamed from drivers/scsi/orig-scsi_scan.c +2
-0@@ -891,13 +891,13 @@ static int scsi_probe_and_add_lun(struct } res =scsi_add_lun (sdev, result, &bflags); +if (bflagsp) + *bflagsp = bflags;
For SCSI_SCAN_TARGET_PRESENT, we never get this far. We bail out a couple of lines above in the check for PQ=3. Also, for some boxes like Clarions we have this in devinfo:
{"DGC", "RAID", NULL, BLIST_SPARSELUN}, /* Dell PV 650F,
storage on LUN 0 */
{"DGC", "DISK", NULL, BLIST_SPARSELUN},But LUN0 shows up as DGC/LUNZ. When we used to hardcode BLIST_SPARSELUN as a argument to scsi_sequential_lun_scan, we could find a least 8 devices but now we hit this in scsi_sequential_lun_scan:
/*
* If not sparse lun and no device attached at LUN 0 do not scan
* any further.
*/
if (!sparse_lun && (lun0_res != SCSI_SCAN_LUN_PRESENT))
return;Does IBM's fastt/DS or other boxes have this problem too? For Clarions do I just have to add a DGC/LUNZ entry to the devinfo list?
Quoted 10 lines · Mike Christie
Quoted 9 lines · Patrick Mansfield
So yes we should always set *bflagsp. i.e.:
---
linux-2.6.15/drivers/scsi/orig-scsi_scan.c2006-01-02
21:52:12.000000000 -0800
+++linux-2.6.15/drivers/scsi/scsi_scan.c2006-01-04
10:58:36.000000000 -0800(quoted diff) +0
-0@@ -891,13 +891,13 @@ static int scsi_probe_and_add_lun(struct }
Quoted 7 lines
Review static int scsi_probe_and_add_lun(struct · line 895
Quoted 3 lines
(quoted diff) +2
-0res = scsi_add_lun(sdev, result, &bflags); + if (bflagsp) + *bflagsp = bflags;For
SCSI_SCAN_TARGET_PRESENT, we never get this far. We bail out a couple of lines above in the check for PQ=3. Also, for some boxes like
OK :-/
Then like this?
drivers/scsi/scsi_scan.c renamed from drivers/scsi/orig-scsi_scan.c +2 -2
@@ -868,6 +868,8 @@ static int scsi_probe_and_add_lun(structif (scsi_probe_lun (sdev, result, result_len, &bflags)) goto out_free_result; +if (bflagsp) + *bflagsp = bflags;/* * result contains valid SCSI INQUIRY data.
@@ -896,8 +898,6 @@ static int scsi_probe_and_add_lun(struct sdev->lockable =0 ;scsi_unlock_floptical (sdev, result); } -if (bflagsp) - *bflagsp = bflags; } out_free_result:
Quoted 19 lines
Clarions we have this in devinfo:
{"DGC", "RAID", NULL, BLIST_SPARSELUN}, /* Dell PV 650F, storage on LUN 0 */ {"DGC", "DISK", NULL, BLIST_SPARSELUN},But LUN0 shows up as DGC/LUNZ. When we used to hardcode
BLIST_SPARSELUNas a argument toscsi_sequential_lun_scan, we could find a least 8 devices but now we hit this inscsi_sequential_lun_scan:/* * If not sparse lun and no device attached at LUN 0 do not scan * any further. */ if (!sparse_lun && (lun0_res != SCSI_SCAN_LUN_PRESENT)) return;
Quoted 1 line
Does IBM's fastt/DS or other boxes have this problem too?
For fastt, DS and other newer storage, we (likely) always use REPORT LUN and so would never hit that code.
Quoted 2 lines
For Clarions
do I just have to add a DGC/LUNZ entry to the devinfo list?
If they do not support REPORT LUN, yes (AFAIR/CT, my brain is slow ...).
Also, on some storage boxes, you can conditionaly set the scsi level too. You could try changing that and/or also add a blist BLIST_REPORTLUN2 for them to devinfo, or just use the sg report lun to test it.
Don't forget you can dynamically add devinfo values via modparam and /proc/scsi.
-- Patrick Mansfield
Quoted 1 line · Patrick Mansfield
Then like this?
Yep, this works for our setup. Thanks.
Quoted 22 lines
drivers/scsi/scsi_scan.c renamed from drivers/scsi/orig-scsi_scan.c +2
-2@@ -868,6 +868,8 @@ static int scsi_probe_and_add_lun(structif (scsi_probe_lun (sdev, result, result_len, &bflags)) goto out_free_result; +if (bflagsp) + *bflagsp = bflags;/* * result contains valid SCSI INQUIRY data. @@ -896,8 +898,6 @@ static int scsi_probe_and_add_lun(struct sdev->lockable =0 ;scsi_unlock_floptical (sdev, result); } -if (bflagsp) - *bflagsp = bflags; } out_free_result:
.....
Quoted 4 lines
Don't forget you can dynamically add devinfo values via modparam and
/proc/scsi.
I did not know this. I was looking for a writable proc file for some reason. Thanks.