summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorken <ken@FreeBSD.org>2017-05-10 15:20:38 +0000
committerken <ken@FreeBSD.org>2017-05-10 15:20:38 +0000
commit9ca7a8eab244f079cc0da2a0eef47165d4bece82 (patch)
tree7a80fa1d48c34444b540146083506986ddf2b9ed
parente18a1f1bdc4c218ec482daf2fe86d8f571234336 (diff)
downloadFreeBSD-src-9ca7a8eab244f079cc0da2a0eef47165d4bece82.zip
FreeBSD-src-9ca7a8eab244f079cc0da2a0eef47165d4bece82.tar.gz
MFC r317775:
Fix error recovery behavior in the pass(4) driver. After FreeBSD SVN revision 236814, the pass(4) driver changed from only doing error recovery when the CAM_PASS_ERR_RECOVER flag was set on a CCB to sometimes doing error recovery if the passed in retry count was non-zero. Error recovery would happen if two conditions were met: 1. The error recovery action was simply a retry. (Which is most cases.) 2. The retry_count is non-zero. (Which happened a lot because of cut-and-pasted code.) This explains a bug I noticed in with camcontrol: # camcontrol tur da34 -v Unit is ready # camcontrol reset da34 Reset of 1:172:0 was successful At this point, there should be a Unit Attention: # camcontrol tur da34 -v Unit is ready No Unit Attention. Try it again: # camcontrol reset da34 Reset of 1:172:0 was successful Now set the retry_count to 0 for the TUR: # camcontrol tur da34 -v -C 0 Unit is not ready (pass42:mps1:0:172:0): TEST UNIT READY. CDB: 00 00 00 00 00 00 (pass42:mps1:0:172:0): CAM status: SCSI Status Error (pass42:mps1:0:172:0): SCSI status: Check Condition (pass42:mps1:0:172:0): SCSI sense: UNIT ATTENTION asc:29,2 (SCSI bus reset occurred) (pass42:mps1:0:172:0): Field Replaceable Unit: 2 There is the unit attention. camcontrol(8) has a default retry_count of 1, in case someone sets the -E flag without setting -C. The CAM_PASS_ERR_RECOVER behavior was only broken with the CAMIOCOMMAND ioctl, which is the synchronous pass(4) API. It has worked as intended (error recovery is only done when the flag is set) in the asynchronous API (CAMIOQUEUE ioctl). sys/cam/scsi/scsi_pass.c: In passsendccb(), when calling cam_periph_runccb(), only specify the error routine when CAM_PASS_ERR_RECOVER is set. share/man/man4/pass.4: Document that CAM_PASS_ERR_RECOVER is needed to enable error recovery. Reported by: Terry Kennedy <TERRY@glaver.org> PR: kern/218572 Sponsored by: Spectra Logic
-rw-r--r--share/man/man4/pass.412
-rw-r--r--sys/cam/scsi/scsi_pass.c6
2 files changed, 14 insertions, 4 deletions
diff --git a/share/man/man4/pass.4 b/share/man/man4/pass.4
index 3a2e1e7..e09b08e 100644
--- a/share/man/man4/pass.4
+++ b/share/man/man4/pass.4
@@ -27,7 +27,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd March 17, 2015
+.Dd May 3, 2017
.Dt PASS 4
.Os
.Sh NAME
@@ -85,6 +85,11 @@ Some examples of xpt-only CCBs are XPT_SCAN_BUS,
XPT_DEV_MATCH, XPT_RESET_BUS, XPT_SCAN_LUN, XPT_ENG_INQ, and XPT_ENG_EXEC.
These CCB types have various attributes that make it illogical or
impossible to service them through the passthrough interface.
+.Pp
+If the user would like the kernel to do error recovery, the
+.Dv CAM_PASS_ERR_RECOVER
+flag must be set on the CCB, and the retry_count field set to the number
+of retries.
.It CAMGETPASSTHRU union ccb *
This ioctl takes an XPT_GDEVLIST CCB, and returns the passthrough device
corresponding to the device in question.
@@ -160,6 +165,11 @@ available for userland use with the
and
.Dv CAMIOGET
ioctls and will be preserved across calls.
+.Pp
+If the user would like the kernel to do error recovery, the
+.Dv CAM_PASS_ERR_RECOVER
+flag must be set on the CCB, and the retry_count field set to the number
+of retries.
.It CAMIOGET union ccb *
Retrieve completed CAM CCBs queued via the
.Dv CAMIOQUEUE
diff --git a/sys/cam/scsi/scsi_pass.c b/sys/cam/scsi/scsi_pass.c
index 68412b4..f70347c 100644
--- a/sys/cam/scsi/scsi_pass.c
+++ b/sys/cam/scsi/scsi_pass.c
@@ -2213,9 +2213,9 @@ passsendccb(struct cam_periph *periph, union ccb *ccb, union ccb *inccb)
* that request. Otherwise, it's up to the user to perform any
* error recovery.
*/
- cam_periph_runccb(ccb, passerror, /* cam_flags */ CAM_RETRY_SELTO,
- /* sense_flags */ ((ccb->ccb_h.flags & CAM_PASS_ERR_RECOVER) ?
- SF_RETRY_UA : SF_NO_RECOVERY) | SF_NO_PRINT,
+ cam_periph_runccb(ccb, (ccb->ccb_h.flags & CAM_PASS_ERR_RECOVER) ?
+ passerror : NULL, /* cam_flags */ CAM_RETRY_SELTO,
+ /* sense_flags */ SF_RETRY_UA | SF_NO_PRINT,
softc->device_stats);
cam_periph_unmapmem(ccb, &mapinfo);
OpenPOWER on IntegriCloud