svn commit: r199279 - in head/sys/cam: . scsi

Alexander Motin mav at FreeBSD.org
Sat Nov 14 20:13:39 UTC 2009


Author: mav
Date: Sat Nov 14 20:13:38 2009
New Revision: 199279
URL: http://svn.freebsd.org/changeset/base/199279

Log:
  MFp4:
  Fix several device freeze counting bugs.

Modified:
  head/sys/cam/cam_periph.c
  head/sys/cam/scsi/scsi_cd.c
  head/sys/cam/scsi/scsi_ch.c

Modified: head/sys/cam/cam_periph.c
==============================================================================
--- head/sys/cam/cam_periph.c	Sat Nov 14 20:06:04 2009	(r199278)
+++ head/sys/cam/cam_periph.c	Sat Nov 14 20:13:38 2009	(r199279)
@@ -981,16 +981,21 @@ camperiphdone(struct cam_periph *periph,
 {
 	union ccb      *saved_ccb;
 	cam_status	status;
-	int		frozen;
+	int		frozen = 0;
 	int		sense;
 	struct scsi_start_stop_unit *scsi_cmd;
 	u_int32_t	relsim_flags, timeout;
-	u_int32_t	qfrozen_cnt;
-	int		xpt_done_ccb;
+	int		xpt_done_ccb = FALSE;
 
-	xpt_done_ccb = FALSE;
 	status = done_ccb->ccb_h.status;
-	frozen = (status & CAM_DEV_QFRZN) != 0;
+	if (status & CAM_DEV_QFRZN) {
+		frozen = 1;
+		/*
+		 * Clear freeze flag now for case of retry,
+		 * freeze will be dropped later.
+		 */
+		done_ccb->ccb_h.status &= ~CAM_DEV_QFRZN;
+	}
 	sense  = (status & CAM_AUTOSNS_VALID) != 0;
 	status &= CAM_STATUS_MASK;
 
@@ -998,17 +1003,6 @@ camperiphdone(struct cam_periph *periph,
 	relsim_flags = 0;
 	saved_ccb = (union ccb *)done_ccb->ccb_h.saved_ccb_ptr;
 
-	/* 
-	 * Unfreeze the queue once if it is already frozen..
-	 */
-	if (frozen != 0) {
-		qfrozen_cnt = cam_release_devq(done_ccb->ccb_h.path,
-					      /*relsim_flags*/0,
-					      /*openings*/0,
-					      /*timeout*/0,
-					      /*getcount_only*/0);
-	}
-
 	switch (status) {
 	case CAM_REQ_CMP:
 	{
@@ -1185,14 +1179,33 @@ camperiphdone(struct cam_periph *periph,
 	 */
 	if (done_ccb->ccb_h.retry_count > 0)
 		done_ccb->ccb_h.retry_count--;
-
-	qfrozen_cnt = cam_release_devq(done_ccb->ccb_h.path,
-				      /*relsim_flags*/relsim_flags,
-				      /*openings*/0,
-				      /*timeout*/timeout,
-				      /*getcount_only*/0);
-	if (xpt_done_ccb == TRUE)
+	/*
+	 * Drop freeze taken due to CAM_DEV_QFREEZE flag set on recovery
+	 * request.
+	 */
+	cam_release_devq(done_ccb->ccb_h.path,
+			 /*relsim_flags*/relsim_flags,
+			 /*openings*/0,
+			 /*timeout*/timeout,
+			 /*getcount_only*/0);
+	if (xpt_done_ccb == TRUE) {
+		/*
+		 * Copy frozen flag from recovery request if it is set there
+		 * for some reason.
+		 */
+		if (frozen != 0)
+			done_ccb->ccb_h.status |= CAM_DEV_QFRZN;
 		(*done_ccb->ccb_h.cbfcnp)(periph, done_ccb);
+	} else {
+		/* Drop freeze taken, if this recovery request got error. */
+		if (frozen != 0) {
+			cam_release_devq(done_ccb->ccb_h.path,
+				 /*relsim_flags*/0,
+				 /*openings*/0,
+				 /*timeout*/0,
+				 /*getcount_only*/0);
+		}
+	}
 }
 
 /*

Modified: head/sys/cam/scsi/scsi_cd.c
==============================================================================
--- head/sys/cam/scsi/scsi_cd.c	Sat Nov 14 20:06:04 2009	(r199278)
+++ head/sys/cam/scsi/scsi_cd.c	Sat Nov 14 20:13:38 2009	(r199279)
@@ -1570,7 +1570,8 @@ cddone(struct cam_periph *periph, union 
 			bp->bio_resid = bp->bio_bcount;
 			bp->bio_error = error;
 			bp->bio_flags |= BIO_ERROR;
-			cam_release_devq(done_ccb->ccb_h.path,
+			if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0)
+				cam_release_devq(done_ccb->ccb_h.path,
 					 /*relsim_flags*/0,
 					 /*reduction*/0,
 					 /*timeout*/0,
@@ -1658,7 +1659,8 @@ cddone(struct cam_periph *periph, union 
 				struct ccb_getdev cgd;
 
 				/* Don't wedge this device's queue */
-				cam_release_devq(done_ccb->ccb_h.path,
+				if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0)
+					cam_release_devq(done_ccb->ccb_h.path,
 						 /*relsim_flags*/0,
 						 /*reduction*/0,
 						 /*timeout*/0,

Modified: head/sys/cam/scsi/scsi_ch.c
==============================================================================
--- head/sys/cam/scsi/scsi_ch.c	Sat Nov 14 20:06:04 2009	(r199278)
+++ head/sys/cam/scsi/scsi_ch.c	Sat Nov 14 20:13:38 2009	(r199279)
@@ -606,7 +606,8 @@ chdone(struct cam_periph *periph, union 
 					retry_scheduled = 0;
 
 				/* Don't wedge this device's queue */
-				cam_release_devq(done_ccb->ccb_h.path,
+				if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0)
+					cam_release_devq(done_ccb->ccb_h.path,
 						 /*relsim_flags*/0,
 						 /*reduction*/0,
 						 /*timeout*/0,


More information about the svn-src-all mailing list