aboutsummaryrefslogtreecommitdiff
path: root/sys/cam
diff options
context:
space:
mode:
authorAlexander Motin <mav@FreeBSD.org>2021-08-21 13:31:41 +0000
committerAlexander Motin <mav@FreeBSD.org>2021-09-04 03:25:24 +0000
commitbf2cfa495f0d9a869da840851fa3f0feaf105e3d (patch)
treea5b6e9db7daa80bd1c3950ae290a20e4977d7472 /sys/cam
parent343da8f5e98ffac6a7c02fc5f8dd74290e267be0 (diff)
downloadsrc-bf2cfa495f0d9a869da840851fa3f0feaf105e3d.tar.gz
src-bf2cfa495f0d9a869da840851fa3f0feaf105e3d.zip
cam(4): Fix quick unplug/replug for SCSI.
If some device is plugged back in after unplug before the probe periph destroyed, it will just restart the probe process. But I've found that PROBE_INQUIRY_CKSUM flag not cleared between the iterations may cause AC_FOUND_DEVICE not reported on the second iteration, and because of AC_LOST_DEVICE reported during the first iteration, the device end up configured, but without any periphs attached. We've found that enabled serial console and 102-disk JBOD cause enough probe delays to easily trigger the issue for half of the disks. This change fixes it reliably on my tests. MFC after: 2 weeks Sponsored by: iXsystems, Inc. (cherry picked from commit 84d5b6bd68ce6496592adb8fdcd8cf0c246ed935)
Diffstat (limited to 'sys/cam')
-rw-r--r--sys/cam/scsi/scsi_xpt.c61
1 files changed, 38 insertions, 23 deletions
diff --git a/sys/cam/scsi/scsi_xpt.c b/sys/cam/scsi/scsi_xpt.c
index 24e8d420a88d..b43a5fa2d0b1 100644
--- a/sys/cam/scsi/scsi_xpt.c
+++ b/sys/cam/scsi/scsi_xpt.c
@@ -178,7 +178,6 @@ do { \
typedef enum {
PROBE_INQUIRY_CKSUM = 0x01,
- PROBE_SERIAL_CKSUM = 0x02,
PROBE_NO_ANNOUNCE = 0x04,
PROBE_EXTLUN = 0x08
} probe_flags;
@@ -776,8 +775,6 @@ again:
}
case PROBE_INQUIRY:
case PROBE_FULL_INQUIRY:
- case PROBE_INQUIRY_BASIC_DV1:
- case PROBE_INQUIRY_BASIC_DV2:
{
u_int inquiry_len;
struct scsi_inquiry_data *inq_buf;
@@ -792,19 +789,19 @@ again:
* serial number check finish, we attempt to figure out
* whether we still have the same device.
*/
- if (((periph->path->device->flags & CAM_DEV_UNCONFIGURED) == 0)
- && ((softc->flags & PROBE_INQUIRY_CKSUM) == 0)) {
+ if (periph->path->device->flags & CAM_DEV_UNCONFIGURED) {
+ softc->flags &= ~PROBE_INQUIRY_CKSUM;
+ } else if ((softc->flags & PROBE_INQUIRY_CKSUM) == 0) {
MD5Init(&softc->context);
MD5Update(&softc->context, (unsigned char *)inq_buf,
sizeof(struct scsi_inquiry_data));
- softc->flags |= PROBE_INQUIRY_CKSUM;
if (periph->path->device->serial_num_len > 0) {
MD5Update(&softc->context,
periph->path->device->serial_num,
periph->path->device->serial_num_len);
- softc->flags |= PROBE_SERIAL_CKSUM;
}
MD5Final(softc->digest, &softc->context);
+ softc->flags |= PROBE_INQUIRY_CKSUM;
}
if (softc->action == PROBE_INQUIRY)
@@ -820,22 +817,6 @@ again:
*/
inquiry_len = roundup2(inquiry_len, 2);
- if (softc->action == PROBE_INQUIRY_BASIC_DV1
- || softc->action == PROBE_INQUIRY_BASIC_DV2) {
- inq_buf = malloc(inquiry_len, M_CAMXPT, M_NOWAIT);
- }
- if (inq_buf == NULL) {
- xpt_print(periph->path, "malloc failure- skipping Basic"
- "Domain Validation\n");
- PROBE_SET_ACTION(softc, PROBE_DV_EXIT);
- scsi_test_unit_ready(csio,
- /*retries*/4,
- probedone,
- MSG_SIMPLE_Q_TAG,
- SSD_FULL_SIZE,
- /*timeout*/60000);
- break;
- }
scsi_inquiry(csio,
/*retries*/4,
probedone,
@@ -1020,6 +1001,40 @@ done:
}
goto done;
}
+ case PROBE_INQUIRY_BASIC_DV1:
+ case PROBE_INQUIRY_BASIC_DV2:
+ {
+ u_int inquiry_len;
+ struct scsi_inquiry_data *inq_buf;
+
+ inq_buf = &periph->path->device->inq_data;
+ inquiry_len = roundup2(SID_ADDITIONAL_LENGTH(inq_buf), 2);
+ inq_buf = malloc(inquiry_len, M_CAMXPT, M_NOWAIT);
+ if (inq_buf == NULL) {
+ xpt_print(periph->path, "malloc failure- skipping Basic"
+ "Domain Validation\n");
+ PROBE_SET_ACTION(softc, PROBE_DV_EXIT);
+ scsi_test_unit_ready(csio,
+ /*retries*/4,
+ probedone,
+ MSG_SIMPLE_Q_TAG,
+ SSD_FULL_SIZE,
+ /*timeout*/60000);
+ break;
+ }
+
+ scsi_inquiry(csio,
+ /*retries*/4,
+ probedone,
+ MSG_SIMPLE_Q_TAG,
+ (u_int8_t *)inq_buf,
+ inquiry_len,
+ /*evpd*/FALSE,
+ /*page_code*/0,
+ SSD_MIN_SIZE,
+ /*timeout*/60 * 1000);
+ break;
+ }
default:
panic("probestart: invalid action state 0x%x\n", softc->action);
}