6891680 Never get a callback on MP_RegisterForObjectPropertyChanges MPAPI functions for SAN events
authorJiri Svoboda <Jiri.Svoboda@Sun.COM>
Wed, 07 Apr 2010 13:30:39 +0200
changeset 12087 0e8c10460a8b
parent 12086 d9562b318e63
child 12088 9a04c0e98238
6891680 Never get a callback on MP_RegisterForObjectPropertyChanges MPAPI functions for SAN events
usr/src/lib/mpapi/libmpscsi_vhci/common/mp_utils.c
usr/src/uts/common/io/scsi/adapters/scsi_vhci/mpapi_impl.c
usr/src/uts/common/sys/scsi/adapters/mpapi_impl.h
--- a/usr/src/lib/mpapi/libmpscsi_vhci/common/mp_utils.c	Tue Apr 06 23:31:14 2010 -0700
+++ b/usr/src/lib/mpapi/libmpscsi_vhci/common/mp_utils.c	Wed Apr 07 13:30:39 2010 +0200
@@ -19,8 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
  */
 
 #include "mp_utils.h"
@@ -69,77 +68,77 @@
 
 		case MP_DRVR_INVALID_ID:
 			log(LOG_INFO, "getStatus4ErrorCode()",
-				" received mp_errno=MP_DRVR_INVALID_ID"
-				" from driver call.");
+			    " received mp_errno=MP_DRVR_INVALID_ID"
+			    " from driver call.");
 			log(LOG_INFO, "getStatus4ErrorCode()",
-				" returning MP_STATUS_OBJECT_NOT_FOUND"
-				" to caller.");
+			    " returning MP_STATUS_OBJECT_NOT_FOUND"
+			    " to caller.");
 			mpStatus = MP_STATUS_OBJECT_NOT_FOUND;
 			break;
 
 
 		case MP_DRVR_ID_OBSOLETE:
 			log(LOG_INFO, "getStatus4ErrorCode()",
-				" received mp_errno=MP_DRVR_ID_OBSOLETE"
-				" from driver call.");
+			    " received mp_errno=MP_DRVR_ID_OBSOLETE"
+			    " from driver call.");
 			log(LOG_INFO, "getStatus4ErrorCode()",
-				" returning MP_STATUS_OBJECT_NOT_FOUND"
-				" to caller.");
+			    " returning MP_STATUS_OBJECT_NOT_FOUND"
+			    " to caller.");
 			mpStatus = MP_STATUS_OBJECT_NOT_FOUND;
 			break;
 
 
 		case MP_DRVR_ACCESS_SYMMETRIC:
 			log(LOG_INFO, "getStatus4ErrorCode()",
-				" received mp_errno=MP_DRVR_ACCESS_SYMMETRIC"
-				" from driver call.");
+			    " received mp_errno=MP_DRVR_ACCESS_SYMMETRIC"
+			    " from driver call.");
 			log(LOG_INFO, "getStatus4ErrorCode()",
-				" returning MP_STATUS_INVALID_PARAMETER"
-				" to caller.");
+			    " returning MP_STATUS_INVALID_PARAMETER"
+			    " to caller.");
 			mpStatus = MP_STATUS_INVALID_PARAMETER;
 			break;
 
 
 		case MP_DRVR_PATH_UNAVAILABLE:
 			log(LOG_INFO, "getStatus4ErrorCode()",
-				" received mp_errno=MP_DRVR_PATH_UNAVAILABLE"
-				" from driver call.");
+			    " received mp_errno=MP_DRVR_PATH_UNAVAILABLE"
+			    " from driver call.");
 			log(LOG_INFO, "getStatus4ErrorCode()",
-				" returning MP_STATUS_PATH_NONOPERATIONAL"
-				" to caller.");
+			    " returning MP_STATUS_PATH_NONOPERATIONAL"
+			    " to caller.");
 			mpStatus = MP_STATUS_PATH_NONOPERATIONAL;
 			break;
 
 
 		case MP_DRVR_IDS_NOT_ASSOCIATED:
 			log(LOG_INFO, "getStatus4ErrorCode()",
-				" received mp_errno=MP_DRVR_IDS_NOT_ASSOCIATED"
-				" from driver call.");
+			    " received mp_errno=MP_DRVR_IDS_NOT_ASSOCIATED"
+			    " from driver call.");
 			log(LOG_INFO, "getStatus4ErrorCode()",
-				" returning MP_STATUS_INVALID_PARAMETER"
-				" to caller.");
+			    " returning MP_STATUS_INVALID_PARAMETER"
+			    " to caller.");
 			mpStatus = MP_STATUS_INVALID_PARAMETER;
 			break;
 
 
 		case MP_DRVR_ILLEGAL_ACCESS_STATE_REQUEST:
 			log(LOG_INFO, "getStatus4ErrorCode()",
-				" received mp_errno="
-				"MP_DRVR_ILLEGAL_ACCESS_STATE_REQUEST"
-				" from driver call.");
+			    " received mp_errno="
+			    "MP_DRVR_ILLEGAL_ACCESS_STATE_REQUEST"
+			    " from driver call.");
 			log(LOG_INFO, "getStatus4ErrorCode()",
-				" returning MP_STATUS_INVALID_PARAMETER"
-				" to caller.");
+			    " returning MP_STATUS_INVALID_PARAMETER"
+			    " to caller.");
 			mpStatus = MP_STATUS_ACCESS_STATE_INVALID;
 			break;
 
 
 		default:
 			log(LOG_INFO, "getStatus4ErrorCode()",
-				" - received (unsupported) mp_errno=%d from"
-				" driver call.", driverError);
+			    " - received (unsupported) mp_errno=%d from"
+			    " driver call.", driverError);
 			log(LOG_INFO, "getStatus4ErrorCode()",
-				" - returning MP_STATUS_FAILED to caller.");
+			    " - returning MP_STATUS_FAILED to caller.");
 			mpStatus = MP_STATUS_FAILED;
 	}
 
@@ -231,7 +230,13 @@
 		log(LOG_INFO, "notifyClient()", ": [%s]",
 		    subClassName);
 
-		if (strncmp(subClassName, ESC_SUN_MP_LU_CHANGE, 255) == 0) {
+		if (strncmp(subClassName, ESC_SUN_MP_PLUGIN_CHANGE, 255)
+		    == 0) {
+
+			index = MP_OBJECT_TYPE_PLUGIN;
+
+		} else if (strncmp(subClassName, ESC_SUN_MP_LU_CHANGE, 255)
+		    == 0) {
 
 			index = MP_OBJECT_TYPE_MULTIPATH_LU;
 
@@ -241,7 +246,7 @@
 			index = MP_OBJECT_TYPE_PATH_LU;
 
 		} else if (strncmp(subClassName, ESC_SUN_MP_INIT_PORT_CHANGE,
-					255) == 0) {
+		    255) == 0) {
 
 			index = MP_OBJECT_TYPE_INITIATOR_PORT;
 
@@ -251,18 +256,18 @@
 			index = MP_OBJECT_TYPE_TARGET_PORT_GROUP;
 
 		} else if (strncmp(subClassName, ESC_SUN_MP_TARGET_PORT_CHANGE,
-					255) == 0) {
+		    255) == 0) {
 
 			index = MP_OBJECT_TYPE_TARGET_PORT;
 
 		} else if (strncmp(subClassName, ESC_SUN_MP_DEV_PROD_CHANGE,
-					255) == 0) {
+		    255) == 0) {
 
 			index = MP_OBJECT_TYPE_DEVICE_PRODUCT;
 		}
 
 	} else if ((strstr(subClassName, "add")) ||
-			(strstr(subClassName, "initiator_register"))) {
+	    (strstr(subClassName, "initiator_register"))) {
 
 		eventType = VISA_CHANGE;
 		becomingVisible = MP_TRUE;
@@ -272,7 +277,7 @@
 		log(LOG_INFO, "notifyClient()", ": [%s]",
 		    subClassName);
 
-		if (strncmp(subClassName, ESC_DEVFS_DEVI_ADD, 255) == 0) {
+		if (strncmp(subClassName, ESC_SUN_MP_LU_ADD, 255) == 0) {
 
 			index = MP_OBJECT_TYPE_MULTIPATH_LU;
 
@@ -282,17 +287,17 @@
 			index = MP_OBJECT_TYPE_PATH_LU;
 
 		} else if (strncmp(subClassName, ESC_DDI_INITIATOR_REGISTER,
-					244) == 0) {
+		    244) == 0) {
 
 			index = MP_OBJECT_TYPE_INITIATOR_PORT;
 
 		} else if (strncmp(subClassName, ESC_SUN_MP_TPG_ADD,
-					255) == 0) {
+		    255) == 0) {
 
 			index = MP_OBJECT_TYPE_TARGET_PORT_GROUP;
 
 		} else if (strncmp(subClassName, ESC_SUN_MP_TARGET_PORT_ADD,
-					255) == 0) {
+		    255) == 0) {
 
 			index = MP_OBJECT_TYPE_TARGET_PORT;
 
@@ -304,7 +309,7 @@
 
 
 	} else if ((strstr(subClassName, "remove")) ||
-			(strstr(subClassName, "initiator_unregister"))) {
+	    (strstr(subClassName, "initiator_unregister"))) {
 
 		eventType = VISA_CHANGE;
 		becomingVisible = MP_FALSE;
@@ -314,7 +319,7 @@
 		log(LOG_INFO, "notifyClient()", ": [%s]",
 		    subClassName);
 
-		if (strncmp(subClassName, ESC_DEVFS_DEVI_REMOVE, 255) == 0) {
+		if (strncmp(subClassName, ESC_SUN_MP_LU_REMOVE, 255) == 0) {
 
 			index = MP_OBJECT_TYPE_MULTIPATH_LU;
 
@@ -324,7 +329,7 @@
 			index = MP_OBJECT_TYPE_PATH_LU;
 
 		} else if (strncmp(subClassName, ESC_DDI_INITIATOR_UNREGISTER,
-					255) == 0) {
+		    255) == 0) {
 
 			index = MP_OBJECT_TYPE_INITIATOR_PORT;
 
@@ -334,12 +339,12 @@
 			index = MP_OBJECT_TYPE_TARGET_PORT_GROUP;
 
 		} else if (strncmp(subClassName, ESC_SUN_MP_TARGET_PORT_REMOVE,
-					255) == 0) {
+		    255) == 0) {
 
 			index = MP_OBJECT_TYPE_TARGET_PORT;
 
 		} else if (strncmp(subClassName, ESC_SUN_MP_DEV_PROD_REMOVE,
-					255) == 0) {
+		    255) == 0) {
 
 			index = MP_OBJECT_TYPE_DEVICE_PRODUCT;
 		}
@@ -382,43 +387,35 @@
 			log(LOG_INFO, "notifyClient()",
 			    "- no property change callback to notify");
 
-			    (void) pthread_mutex_unlock(&g_prop_mutex);
+			(void) pthread_mutex_unlock(&g_prop_mutex);
 
-			    return;
-		    }
+			return;
+		}
 
-		    (void) pthread_mutex_unlock(&g_prop_mutex);
+		(void) pthread_mutex_unlock(&g_prop_mutex);
 	}
 
 	(void) sysevent_get_attr_list(ev, &attr_list);
 	if (NULL != attr_list) {
 
 		if ((VISA_CHANGE == eventType) &&
-		    (MP_OBJECT_TYPE_MULTIPATH_LU == index)) {
-
-			(void) nvlist_lookup_int32_array(attr_list,
-			    DEVFS_INSTANCE, &instance, &nelem);
+		    (MP_OBJECT_TYPE_PLUGIN == index)) {
 
-			log(LOG_INFO, "notifyClient()",
-			    "- event has [%d] elements",
-			    nelem);
-
-			if (NULL != instance) {
+			val = (uint64_t *)malloc(sizeof (uint64_t));
+			valAllocated = 1;
 
-				val = (uint64_t *)malloc(sizeof (uint64_t));
-
-				valAllocated = 1;
-
-				*val = *instance;
-				nelem = 1;
-
-			} else {
-
-				nelem = 0;
-			}
+			/*
+			 * We have no well-defined way to determine our OSN.
+			 * Currently the common library uses 0 as OSN for every
+			 * plugin, so just use 0. If the OSN assigned by the
+			 * common library changed, this code would have to be
+			 * updated.
+			 */
+			*val = 0;
+			nelem = 1;
 
 		} else if ((VISA_CHANGE == eventType) &&
-			(MP_OBJECT_TYPE_INITIATOR_PORT == index)) {
+		    (MP_OBJECT_TYPE_INITIATOR_PORT == index)) {
 
 			(void) nvlist_lookup_int32_array(attr_list,
 			    DDI_INSTANCE, &instance, &nelem);
@@ -453,7 +450,7 @@
 		} else {
 
 			(void) nvlist_lookup_uint64_array(attr_list, OIDLIST,
-					    &val, &nelem);
+			    &val, &nelem);
 
 			log(LOG_INFO, "notifyClient()",
 			    "- event has [%d] elements",
@@ -500,18 +497,17 @@
 			for (i = 0; i < oidList->oidCount; i++) {
 
 				log(LOG_INFO, "notifyClient()",
-					"oidList->oids[%d].objectType"
-					"           = %d",
-					i, oidList->oids[i].objectType);
+				    "oidList->oids[%d].objectType"
+				    "           = %d",
+				    i, oidList->oids[i].objectType);
 				log(LOG_INFO, "notifyClient()",
-					"oidList->oids[%d].ownerId"
-					"              = %d",
-					i, oidList->oids[i].ownerId);
+				    "oidList->oids[%d].ownerId"
+				    "              = %d",
+				    i, oidList->oids[i].ownerId);
 				log(LOG_INFO, "notifyClient()",
-					"oidList->oids[%d].objectSequenceNumber"
-					" = %llx",
-					i,
-					oidList->oids[i].objectSequenceNumber);
+				    "oidList->oids[%d].objectSequenceNumber"
+				    " = %llx",
+				    i, oidList->oids[i].objectSequenceNumber);
 			}
 
 			if (eventType == PROP_CHANGE) {
@@ -519,10 +515,10 @@
 				(void) pthread_mutex_lock(&g_prop_mutex);
 
 				pCallerData = g_Property_Callback_List[index].
-					pCallerData;
+				    pCallerData;
 
 				(g_Property_Callback_List[index].pClientFn)
-				(oidList, pCallerData);
+				    (oidList, pCallerData);
 
 				(void) pthread_mutex_unlock(&g_prop_mutex);
 
@@ -531,10 +527,10 @@
 				(void) pthread_mutex_lock(&g_visa_mutex);
 
 				pCallerData = g_Visibility_Callback_List[index].
-					pCallerData;
+				    pCallerData;
 
 				(g_Visibility_Callback_List[index].pClientFn)
-				(becomingVisible, oidList, pCallerData);
+				    (becomingVisible, oidList, pCallerData);
 
 				(void) pthread_mutex_unlock(&g_visa_mutex);
 
@@ -570,11 +566,16 @@
 }
 
 /* Registers the plugin to the sysevent framework */
-MP_STATUS init_sysevents() {
+MP_STATUS
+init_sysevents(void) {
 
 	const char *subclass_list[] = {
 
+		ESC_SUN_MP_PLUGIN_CHANGE,
+
 		ESC_SUN_MP_LU_CHANGE,
+		ESC_SUN_MP_LU_ADD,
+		ESC_SUN_MP_LU_REMOVE,
 
 		ESC_SUN_MP_PATH_CHANGE,
 		ESC_SUN_MP_PATH_ADD,
@@ -596,13 +597,6 @@
 
 	};
 
-	const char *lu_subclass_list[] = {
-
-		ESC_DEVFS_DEVI_ADD,
-		ESC_DEVFS_DEVI_REMOVE
-
-	};
-
 	const char *init_port_subclass_list[] = {
 
 		ESC_DDI_INITIATOR_REGISTER,
@@ -626,7 +620,8 @@
 	}
 
 	if (sysevent_subscribe_event(g_SysEventHandle, EC_SUN_MP,
-					subclass_list, 14) != 0) {
+	    subclass_list, sizeof (subclass_list) / sizeof (subclass_list[0]))
+	    != 0) {
 
 
 		log(LOG_INFO, "init_sysevents()",
@@ -639,22 +634,9 @@
 		return (MP_STATUS_FAILED);
 	}
 
-	if (sysevent_subscribe_event(g_SysEventHandle, EC_DEVFS,
-					lu_subclass_list, 2) != 0) {
-
-
-		log(LOG_INFO, "init_sysevents()",
-		    "- sysevent_subscribe_event() failed for lu_subclass_list");
-
-		log(LOG_INFO, "init_sysevents()", "- error exit");
-
-		sysevent_unbind_handle(g_SysEventHandle);
-
-		return (MP_STATUS_FAILED);
-	}
-
 	if (sysevent_subscribe_event(g_SysEventHandle, EC_DDI,
-					init_port_subclass_list, 2) != 0) {
+	    init_port_subclass_list, sizeof (init_port_subclass_list) /
+	    sizeof (init_port_subclass_list[0])) != 0) {
 
 
 		log(LOG_INFO, "init_sysevents()",
--- a/usr/src/uts/common/io/scsi/adapters/scsi_vhci/mpapi_impl.c	Tue Apr 06 23:31:14 2010 -0700
+++ b/usr/src/uts/common/io/scsi/adapters/scsi_vhci/mpapi_impl.c	Wed Apr 07 13:30:39 2010 +0200
@@ -19,8 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
  */
 
 /*
@@ -135,6 +134,9 @@
 static int vhci_mpapi_copyout_iocdata(void *, void *, int);
 static int vhci_mpapi_chk_last_path(mdi_pathinfo_t *);
 static int vhci_mpapi_sync_lu_oid_list(struct scsi_vhci *);
+static void vhci_mpapi_set_lu_valid(struct scsi_vhci *, mpapi_item_t *, int);
+static void vhci_mpapi_set_tpg_as_prop(struct scsi_vhci *, mpapi_item_t *,
+    uint32_t);
 static mpapi_item_list_t *vhci_mpapi_get_tpg_for_lun(struct scsi_vhci *,
     char *, void *, void *);
 static int vhci_mpapi_check_tp_in_tpg(mpapi_tpg_data_t *tpgdata, void *tp);
@@ -1731,6 +1733,7 @@
 	int			rval = 0;
 	mpapi_item_list_t	*ilist;
 	mpapi_lu_data_t		*lud;
+	uint64_t		raw_oid;
 
 	mutex_enter(&vhci->vhci_mutex);
 	vhci->vhci_conf_flags |= VHCI_CONF_FLAGS_AUTO_FAILBACK;
@@ -1744,6 +1747,14 @@
 		ilist = ilist->next;
 	}
 
+	/*
+	 * We don't really know the plugin OSN so just set 0, it will be ignored
+	 * by libmpscsi_vhci.
+	 */
+	raw_oid = 0;
+	vhci_mpapi_log_sysevent(vhci->vhci_dip, &raw_oid,
+	    ESC_SUN_MP_PLUGIN_CHANGE);
+
 	return (rval);
 }
 
@@ -1755,6 +1766,7 @@
 	int			rval = 0;
 	mpapi_item_list_t	*ilist;
 	mpapi_lu_data_t		*lud;
+	uint64_t		raw_oid;
 
 	mutex_enter(&vhci->vhci_mutex);
 	vhci->vhci_conf_flags &= ~VHCI_CONF_FLAGS_AUTO_FAILBACK;
@@ -1768,6 +1780,14 @@
 		ilist = ilist->next;
 	}
 
+	/*
+	 * We don't really know the plugin OSN so just set 0, it will be ignored
+	 * by libmpscsi_vhci.
+	 */
+	raw_oid = 0;
+	vhci_mpapi_log_sysevent(vhci->vhci_dip, &raw_oid,
+	    ESC_SUN_MP_PLUGIN_CHANGE);
+
 	return (rval);
 }
 
@@ -2743,7 +2763,6 @@
 
 			lu = kmem_zalloc(sizeof (mpapi_lu_data_t), KM_SLEEP);
 			lu->resp = res;
-			lu->valid = 1;
 			lu->prop.id = (uint64_t)item->oid.raw_oid;
 			/*
 			 * XXX: luGroupID is currently unsupported
@@ -2794,9 +2813,7 @@
 			lu->path_list = vhci_mpapi_create_list_head();
 			lu->tpg_list = vhci_mpapi_create_list_head();
 			item->idata = (void *)lu;
-			vhci_mpapi_log_sysevent(vhci->vhci_dip,
-			    &(item->oid.raw_oid), ESC_SUN_MP_LU_CHANGE);
-
+			vhci_mpapi_set_lu_valid(vhci, item, 1);
 		}
 		break;
 
@@ -2928,7 +2945,7 @@
 		 * SAME LUN came online!! So, update the resp in main list.
 		 */
 		ld = lu_list->item->idata;
-		ld->valid = 1;
+		vhci_mpapi_set_lu_valid(vhci, lu_list->item, 1);
 		ld->resp = vlun;
 	}
 
@@ -3544,7 +3561,7 @@
 		 * SAME LUN came online!! So, update the resp in main list.
 		 */
 		ld = lu_list->item->idata;
-		ld->valid = 1;
+		vhci_mpapi_set_lu_valid(vhci, lu_list->item, 1);
 		ld->resp = vlun;
 	}
 
@@ -3941,6 +3958,65 @@
 }
 
 /*
+ * Set new value for the valid field of an MP LU.
+ *
+ * This should be called to set new value for the valid field instead of
+ * accessing it directly. If the value has changed, the appropriate
+ * sysevent is generated.
+ *
+ * An exception is when the LU is created an the valid field is set for
+ * the first time. In this case we do not want to generate an event
+ * so the field should be set directly instead of calling this function.
+ *
+ * Rationale for introducing ESC_SUN_MP_LU_{ADD|REMOVE}: When the last
+ * path to a MPLU goes offline, the client node is offlined (not removed).
+ * When a path to the MPLU goes back online, the client node is onlined.
+ * There is no existing sysevent that whould announce this.
+ * EC_DEVFS / ESC_DEVFS_DEVI_{ADD|REMOVE} do not work, because the
+ * client node is just offlined/onlined, not removed/re-added.
+ * EC_DEV_{ADD|REMOVE} / ESC_DISK only works for block devices, not
+ * for other LUs (such as tape). Therefore special event subclasses
+ * for addition/removal of a MPLU are needed.
+ */
+static void vhci_mpapi_set_lu_valid(struct scsi_vhci *vhci,
+    mpapi_item_t *lu_item, int valid)
+{
+	mpapi_lu_data_t *lu_data;
+
+	lu_data = (mpapi_lu_data_t *)lu_item->idata;
+	if (valid == lu_data->valid)
+		return;
+	lu_data->valid = valid;
+
+	vhci_mpapi_log_sysevent(vhci->vhci_dip, &(lu_item->oid.raw_oid),
+	    valid ? ESC_SUN_MP_LU_ADD : ESC_SUN_MP_LU_REMOVE);
+}
+
+/*
+ * Set new value for TPG accessState property.
+ *
+ * This should be called to set the new value instead of changing the field
+ * directly. If the value has changed, the appropriate sysevent is generated.
+ *
+ * An exception is when the TPG is created and the accessState field is set
+ * for the first time. In this case we do not want to generate an event
+ * so the field should be set directly instead of calling this function.
+ */
+static void vhci_mpapi_set_tpg_as_prop(struct scsi_vhci *vhci,
+    mpapi_item_t *tpg_item, uint32_t new_state)
+{
+	mpapi_tpg_data_t *tpg_data;
+
+	tpg_data = (mpapi_tpg_data_t *)tpg_item->idata;
+	if (new_state == tpg_data->prop.accessState)
+		return;
+	tpg_data->prop.accessState = new_state;
+
+	vhci_mpapi_log_sysevent(vhci->vhci_dip, &(tpg_item->oid.raw_oid),
+	    ESC_SUN_MP_TPG_CHANGE);
+}
+
+/*
  * Routine to sync Initiator Port List with what MDI maintains. This means
  * MP API knows about Initiator Ports which don't have a pip.
  */
@@ -4030,7 +4106,8 @@
 	scsi_vhci_priv_t	*svp;
 	mpapi_item_list_t	*ilist, *lu_list;
 	mpapi_path_data_t	*pp;
-	mpapi_lu_data_t		*ld;
+	int			old_state;
+	int			old_in_okay, new_in_okay;
 
 	vhci = ddi_get_soft_state(vhci_softstate, ddi_get_instance(vdip));
 
@@ -4039,8 +4116,27 @@
 	if (ilist != NULL) {
 		mutex_enter(&ilist->item->item_mutex);
 		pp = ilist->item->idata;
+		old_state = pp->prop.pathState;
 		pp->prop.pathState = state;
 		pp->valid = 1;
+
+		/*
+		 * MP API does not distiguish between ACTIVE and PASSIVE
+		 * and thus libmpscsi_vhci renders both as MP_PATH_STATE_OKAY.
+		 * Therefore if we are transitioning between ACTIVE and PASSIVE
+		 * we do not want to generate an event.
+		 */
+
+		old_in_okay = (old_state == MP_DRVR_PATH_STATE_ACTIVE ||
+		    old_state == MP_DRVR_PATH_STATE_PASSIVE);
+		new_in_okay = (state == MP_DRVR_PATH_STATE_ACTIVE ||
+		    state == MP_DRVR_PATH_STATE_PASSIVE);
+
+		if (state != old_state && !(old_in_okay && new_in_okay)) {
+			vhci_mpapi_log_sysevent(vdip,
+			    &(ilist->item->oid.raw_oid),
+			    ESC_SUN_MP_PATH_CHANGE);
+		}
 	} else {
 		VHCI_DEBUG(1, (CE_WARN, NULL, "vhci_mpapi_set_path_state: "
 		    "pip(%p) not found", (void *)pip));
@@ -4089,8 +4185,8 @@
 			lu_list = vhci_get_mpapi_item(vhci, NULL,
 			    MP_OBJECT_TYPE_MULTIPATH_LU, (void *)svl);
 			if (lu_list != NULL) {
-				ld = lu_list->item->idata;
-				ld->valid = 0;
+				vhci_mpapi_set_lu_valid(vhci, lu_list->item, 0);
+
 				VHCI_DEBUG(6, (CE_NOTE, NULL,
 				    "vhci_mpapi_set_path_state: "
 				    " Invalidated LU(%s)", svl->svl_lun_wwn));
@@ -4206,7 +4302,6 @@
 		return (-1);
 	}
 	lu_data->resp = vlun;
-	lu_data->valid = 1;
 
 	/*
 	 * For each "pclass of PATH" and "pclass of TPG" match of this LU,
@@ -4241,16 +4336,19 @@
 				    tpg_data->prop.tpgId,
 				    tpg_data->pclass));
 				if (MDI_PI_IS_ONLINE(path_data->resp)) {
-					tpg_data->prop.accessState =
-					    MP_DRVR_ACCESS_STATE_ACTIVE;
+					vhci_mpapi_set_tpg_as_prop(vhci,
+					    tpg_list->item,
+					    MP_DRVR_ACCESS_STATE_ACTIVE);
 					break;
 				} else if (MDI_PI_IS_STANDBY(path_data->resp)) {
-					tpg_data->prop.accessState =
-					    MP_DRVR_ACCESS_STATE_STANDBY;
+					vhci_mpapi_set_tpg_as_prop(vhci,
+					    tpg_list->item,
+					    MP_DRVR_ACCESS_STATE_STANDBY);
 					break;
 				} else {
-					tpg_data->prop.accessState =
-					    MP_DRVR_ACCESS_STATE_UNAVAILABLE;
+					vhci_mpapi_set_tpg_as_prop(vhci,
+					    tpg_list->item,
+					    MP_DRVR_ACCESS_STATE_UNAVAILABLE);
 				}
 			}
 			path_list = path_list->next;
@@ -4258,6 +4356,9 @@
 		tpg_list = tpg_list->next;
 	}
 
+	if (vhci_mpapi_chk_last_path((mdi_pathinfo_t *)path_data->resp) != -1)
+		vhci_mpapi_set_lu_valid(vhci, lu_list->item, 1);
+
 	return (rval);
 }
 
--- a/usr/src/uts/common/sys/scsi/adapters/mpapi_impl.h	Tue Apr 06 23:31:14 2010 -0700
+++ b/usr/src/uts/common/sys/scsi/adapters/mpapi_impl.h	Wed Apr 07 13:30:39 2010 +0200
@@ -19,8 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
  */
 
 #ifndef _SYS_SCSI_ADAPTERS_MPAPI_IMPL_H
@@ -439,7 +438,11 @@
  */
 #define	EC_SUN_MP			"EC_sun_mp"
 
+#define	ESC_SUN_MP_PLUGIN_CHANGE	"ESC_sun_mp_plugin_change"
+
 #define	ESC_SUN_MP_LU_CHANGE		"ESC_sun_mp_lu_change"
+#define	ESC_SUN_MP_LU_ADD		"ESC_sun_mp_lu_add"
+#define	ESC_SUN_MP_LU_REMOVE		"ESC_sun_mp_lu_remove"
 
 #define	ESC_SUN_MP_PATH_CHANGE		"ESC_sun_mp_path_change"
 #define	ESC_SUN_MP_PATH_ADD		"ESC_sun_mp_path_add"