summaryrefslogtreecommitdiffstats
path: root/sys/cam
diff options
context:
space:
mode:
authormav <mav@FreeBSD.org>2015-02-02 20:23:05 +0000
committermav <mav@FreeBSD.org>2015-02-02 20:23:05 +0000
commit03db0c9a45d83e232c6954379473d2f1456f9b3a (patch)
treecb599aee1bc052a2bca422a064b13c1fadfaf9c5 /sys/cam
parent54f475a481803dda7e9fcd95edd11d0c5f9a2bf1 (diff)
downloadFreeBSD-src-03db0c9a45d83e232c6954379473d2f1456f9b3a.zip
FreeBSD-src-03db0c9a45d83e232c6954379473d2f1456f9b3a.tar.gz
Retry indefinitely on SCSI BUSY status from VMware disks and CDs.
VMware returns BUSY status when storage has transient connectivity issues. It is often better to wait and let VM admin fix the problem then crash. Discussed with: ken MFC after: 1 week
Diffstat (limited to 'sys/cam')
-rw-r--r--sys/cam/cam.h3
-rw-r--r--sys/cam/cam_periph.c4
-rw-r--r--sys/cam/scsi/scsi_cd.c17
-rw-r--r--sys/cam/scsi/scsi_da.c18
4 files changed, 35 insertions, 7 deletions
diff --git a/sys/cam/cam.h b/sys/cam/cam.h
index 302504f..e08524b 100644
--- a/sys/cam/cam.h
+++ b/sys/cam/cam.h
@@ -121,7 +121,8 @@ enum {
SF_QUIET_IR = 0x04, /* Be quiet about Illegal Request reponses */
SF_PRINT_ALWAYS = 0x08, /* Always print error status. */
SF_NO_RECOVERY = 0x10, /* Don't do active error recovery. */
- SF_NO_RETRY = 0x20 /* Don't do any retries. */
+ SF_NO_RETRY = 0x20, /* Don't do any retries. */
+ SF_RETRY_BUSY = 0x40 /* Retry BUSY status. */
};
/* CAM Status field values */
diff --git a/sys/cam/cam_periph.c b/sys/cam/cam_periph.c
index 2e23996..87c1bdd 100644
--- a/sys/cam/cam_periph.c
+++ b/sys/cam/cam_periph.c
@@ -1359,8 +1359,8 @@ camperiphscsistatuserror(union ccb *ccb, union ccb **orig_ccb,
* Restart the queue after either another
* command completes or a 1 second timeout.
*/
- if (ccb->ccb_h.retry_count > 0) {
- ccb->ccb_h.retry_count--;
+ if ((sense_flags & SF_RETRY_BUSY) != 0 ||
+ (ccb->ccb_h.retry_count--) > 0) {
error = ERESTART;
*relsim_flags = RELSIM_RELEASE_AFTER_TIMEOUT
| RELSIM_RELEASE_AFTER_CMDCMPLT;
diff --git a/sys/cam/scsi/scsi_cd.c b/sys/cam/scsi/scsi_cd.c
index 47a5a43..f252b86 100644
--- a/sys/cam/scsi/scsi_cd.c
+++ b/sys/cam/scsi/scsi_cd.c
@@ -87,14 +87,16 @@ typedef enum {
CD_Q_NONE = 0x00,
CD_Q_NO_TOUCH = 0x01,
CD_Q_BCD_TRACKS = 0x02,
- CD_Q_10_BYTE_ONLY = 0x10
+ CD_Q_10_BYTE_ONLY = 0x10,
+ CD_Q_RETRY_BUSY = 0x40
} cd_quirks;
#define CD_Q_BIT_STRING \
"\020" \
"\001NO_TOUCH" \
"\002BCD_TRACKS" \
- "\00510_BYTE_ONLY"
+ "\00510_BYTE_ONLY" \
+ "\007RETRY_BUSY"
typedef enum {
CD_FLAG_INVALID = 0x0001,
@@ -189,6 +191,14 @@ static struct cd_quirk_entry cd_quirk_table[] =
{
{ T_CDROM, SIP_MEDIA_REMOVABLE, "CHINON", "CD-ROM CDS-535","*"},
/* quirks */ CD_Q_BCD_TRACKS
+ },
+ {
+ /*
+ * VMware returns BUSY status when storage has transient
+ * connectivity problems, so better wait.
+ */
+ {T_CDROM, SIP_MEDIA_REMOVABLE, "NECVMWar", "VMware IDE CDR10", "*"},
+ /*quirks*/ CD_Q_RETRY_BUSY
}
};
@@ -2581,6 +2591,9 @@ cderror(union ccb *ccb, u_int32_t cam_flags, u_int32_t sense_flags)
* don't treat UAs as errors.
*/
sense_flags |= SF_RETRY_UA;
+
+ if (softc->quirks & CD_Q_RETRY_BUSY)
+ sense_flags |= SF_RETRY_BUSY;
return (cam_periph_error(ccb, cam_flags, sense_flags,
&softc->saved_ccb));
}
diff --git a/sys/cam/scsi/scsi_da.c b/sys/cam/scsi/scsi_da.c
index a65d2dc..9b50d7a 100644
--- a/sys/cam/scsi/scsi_da.c
+++ b/sys/cam/scsi/scsi_da.c
@@ -101,7 +101,8 @@ typedef enum {
DA_Q_NO_PREVENT = 0x04,
DA_Q_4K = 0x08,
DA_Q_NO_RC16 = 0x10,
- DA_Q_NO_UNMAP = 0x20
+ DA_Q_NO_UNMAP = 0x20,
+ DA_Q_RETRY_BUSY = 0x40
} da_quirks;
#define DA_Q_BIT_STRING \
@@ -110,7 +111,9 @@ typedef enum {
"\002NO_6_BYTE" \
"\003NO_PREVENT" \
"\0044K" \
- "\005NO_RC16"
+ "\005NO_RC16" \
+ "\006NO_UNMAP" \
+ "\007RETRY_BUSY"
typedef enum {
DA_CCB_PROBE_RC = 0x01,
@@ -359,6 +362,14 @@ static struct da_quirk_entry da_quirk_table[] =
{T_DIRECT, SIP_MEDIA_FIXED, "STEC", "*", "*"},
/*quirks*/ DA_Q_NO_UNMAP
},
+ {
+ /*
+ * VMware returns BUSY status when storage has transient
+ * connectivity problems, so better wait.
+ */
+ {T_DIRECT, SIP_MEDIA_FIXED, "VMware", "Virtual disk", "*"},
+ /*quirks*/ DA_Q_RETRY_BUSY
+ },
/* USB mass storage devices supported by umass(4) */
{
/*
@@ -3630,6 +3641,9 @@ daerror(union ccb *ccb, u_int32_t cam_flags, u_int32_t sense_flags)
* don't treat UAs as errors.
*/
sense_flags |= SF_RETRY_UA;
+
+ if (softc->quirks & DA_Q_RETRY_BUSY)
+ sense_flags |= SF_RETRY_BUSY;
return(cam_periph_error(ccb, cam_flags, sense_flags,
&softc->saved_ccb));
}
OpenPOWER on IntegriCloud