diff options
author | Alexander Motin <mav@FreeBSD.org> | 2021-08-21 13:31:41 +0000 |
---|---|---|
committer | Alexander Motin <mav@FreeBSD.org> | 2021-09-04 03:27:37 +0000 |
commit | 70d16ac0e889b88693d75c3541c6156355314124 (patch) | |
tree | 032ba30b8c1fe013c5b1440e893ed61015887fff | |
parent | 0eb56e7496f6d8056990d07500be015fcb09dd54 (diff) |
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)
-rw-r--r-- | sys/cam/scsi/scsi_xpt.c | 62 |
1 files changed, 38 insertions, 24 deletions
diff --git a/sys/cam/scsi/scsi_xpt.c b/sys/cam/scsi/scsi_xpt.c index 6f0c88d8fb30..9a71c6b251ce 100644 --- a/sys/cam/scsi/scsi_xpt.c +++ b/sys/cam/scsi/scsi_xpt.c @@ -180,7 +180,6 @@ do { \ typedef enum { PROBE_INQUIRY_CKSUM = 0x01, - PROBE_SERIAL_CKSUM = 0x02, PROBE_NO_ANNOUNCE = 0x04, PROBE_EXTLUN = 0x08 } probe_flags; @@ -778,8 +777,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; @@ -794,20 +791,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) @@ -823,22 +819,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, @@ -1023,6 +1003,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); } |