changeset 10967:0f20d1dba80d

6886050 scsav3: scsi_hba_pkt_comp should detect double completions of same packet 6896150 st: doing intentional uscsi path selection causes unintended recovery. 6897284 scsi_vhci: Attempting path selection with an invalid path asserts. 6897299 ses: ses a non root user can do USCSICMD's
author Randall Ralphs <Randall.Ralphs@Sun.COM>
date Thu, 05 Nov 2009 15:47:57 -0700
parents 37e5dcdf36d3
children 7ccd43cefe5e
files usr/src/uts/common/io/scsi/adapters/scsi_vhci/scsi_vhci.c usr/src/uts/common/io/scsi/impl/scsi_hba.c usr/src/uts/common/io/scsi/impl/scsi_transport.c usr/src/uts/common/io/scsi/targets/ses.c usr/src/uts/common/io/scsi/targets/st.c usr/src/uts/common/sys/scsi/scsi_pkt.h
diffstat 6 files changed, 60 insertions(+), 6 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/uts/common/io/scsi/adapters/scsi_vhci/scsi_vhci.c	Thu Nov 05 14:34:36 2009 -0800
+++ b/usr/src/uts/common/io/scsi/adapters/scsi_vhci/scsi_vhci.c	Thu Nov 05 15:47:57 2009 -0700
@@ -2283,7 +2283,8 @@
 				}
 				goto bind_path;
 			}
-		} else if (rval == MDI_FAILURE) {
+		} else if ((rval == MDI_FAILURE) ||
+		    ((rval == MDI_NOPATH) && (path_instance))) {
 			if (pgr_sema_held) {
 				sema_v(&vlun->svl_pgr_sema);
 			}
--- a/usr/src/uts/common/io/scsi/impl/scsi_hba.c	Thu Nov 05 14:34:36 2009 -0800
+++ b/usr/src/uts/common/io/scsi/impl/scsi_hba.c	Thu Nov 05 15:47:57 2009 -0700
@@ -5206,6 +5206,23 @@
 	uint8_t		*sensep;
 
 	ASSERT(pkt);
+
+	/*
+	 * Catch second call on the same packet before doing anything else.
+	 */
+	if (pkt->pkt_flags & FLAG_PKT_COMP_CALLED) {
+		cmn_err(
+#ifdef DEBUG
+		    CE_PANIC,
+#else
+		    CE_WARN,
+#endif
+		    "%s duplicate scsi_hba_pkt_comp(9F) on same scsi_pkt(9S)",
+		    mod_containing_pc(caller()));
+	}
+
+	pkt->pkt_flags |= FLAG_PKT_COMP_CALLED;
+
 	if (pkt->pkt_comp == NULL)
 		return;
 
--- a/usr/src/uts/common/io/scsi/impl/scsi_transport.c	Thu Nov 05 14:34:36 2009 -0800
+++ b/usr/src/uts/common/io/scsi/impl/scsi_transport.c	Thu Nov 05 15:47:57 2009 -0700
@@ -54,10 +54,20 @@
  * we used to set the callback_done value to NULL after the callback
  * but this interfered with esp/fas drivers that also set the callback
  * to NULL to prevent callbacks during error recovery
- * to prevent confusion, create a truly unique value
+ * to prevent confusion, create a truly unique value.
+ * The scsi_callback_done() function is used to detect a packet
+ * completion being called a second time.
  */
-static int scsi_callback_done;
-#define	CALLBACK_DONE ((void (*)(struct scsi_pkt *))(&scsi_callback_done))
+/* ARGSUSED */
+void
+scsi_callback_done(struct scsi_pkt *pkt)
+{
+	cmn_err(CE_PANIC,
+	    "%s: duplicate scsi_callback_done() on same scsi_pkt(9s)",
+	    mod_containing_pc(caller()));
+}
+
+#define	CALLBACK_DONE (scsi_callback_done)
 
 static void
 scsi_flag_nointr_comp(struct scsi_pkt *pkt)
@@ -127,6 +137,9 @@
 #endif	/* DEBUG */
 	}
 
+	/* Some retryed packets come with this flag not cleared */
+	pkt->pkt_flags &= ~FLAG_PKT_COMP_CALLED;
+
 	/*
 	 * Check if we are required to do polled I/O. We can
 	 * get scsi_pkts that don't have the FLAG_NOINTR bit
--- a/usr/src/uts/common/io/scsi/targets/ses.c	Thu Nov 05 14:34:36 2009 -0800
+++ b/usr/src/uts/common/io/scsi/targets/ses.c	Thu Nov 05 15:47:57 2009 -0700
@@ -754,6 +754,10 @@
 		break;
 
 	case SESIOC_INIT:
+		if (drv_priv(cred_p) != 0) {
+			rv = EPERM;
+			break;
+		}
 		rv = (*ssc->ses_vec.init_enc)(ssc);
 		break;
 
@@ -776,6 +780,10 @@
 		break;
 
 	case SESIOC_SETENCSTAT:
+		if (drv_priv(cred_p) != 0) {
+			rv = EPERM;
+			break;
+		}
 		if (ddi_copyin((void *)arg, &t, sizeof (t), flg))
 			rv = EFAULT;
 		else
@@ -809,6 +817,10 @@
 		break;
 
 	case SESIOC_SETOBJSTAT:
+		if (drv_priv(cred_p) != 0) {
+			rv = EPERM;
+			break;
+		}
 		if (ddi_copyin((void *)arg, &x, sizeof (x), flg)) {
 			rv = EFAULT;
 			break;
@@ -826,6 +838,10 @@
 		break;
 
 	case USCSICMD:
+		if (drv_priv(cred_p) != 0) {
+			rv = EPERM;
+			break;
+		}
 		rv = ses_uscsi_cmd(ssc, (Uscmd *)arg, flg);
 		break;
 
--- a/usr/src/uts/common/io/scsi/targets/st.c	Thu Nov 05 14:34:36 2009 -0800
+++ b/usr/src/uts/common/io/scsi/targets/st.c	Thu Nov 05 15:47:57 2009 -0700
@@ -9708,7 +9708,7 @@
 	if (un->un_multipath) {
 
 		struct uscsi_cmd *ucmd = BP_UCMD(bp);
-		int pkt_valid;
+		int pkt_valid = 0;
 
 		if (ucmd) {
 			/*
@@ -9730,7 +9730,13 @@
 		 */
 		if ((pkt_valid != 0) &&
 		    (un->un_last_path_instance != pkt->pkt_path_instance)) {
-			if (un->un_state > ST_STATE_OPENING) {
+			/*
+			 * Don't recover the path change if it was done
+			 * intentionally or if the device has not completely
+			 * opened yet.
+			 */
+			if (((pkt->pkt_flags & FLAG_PKT_PATH_INSTANCE) == 0) &&
+			    (un->un_state > ST_STATE_OPENING)) {
 				ST_RECOV(ST_DEVINFO, st_label, CE_NOTE,
 				    "Failover detected, action is %s\n",
 				    errstatenames[action]);
--- a/usr/src/uts/common/sys/scsi/scsi_pkt.h	Thu Nov 05 14:34:36 2009 -0800
+++ b/usr/src/uts/common/sys/scsi/scsi_pkt.h	Thu Nov 05 15:47:57 2009 -0700
@@ -181,6 +181,7 @@
  */
 #define	FLAG_NOQUEUE		0x80000000
 #define	FLAG_PKT_PATH_INSTANCE	0x40000000	/* Tell vhci the path to use */
+#define	FLAG_PKT_COMP_CALLED	0x20000000	/* Set once pkt_comp called */
 
 /*
  * Definitions for the pkt_reason field.