xref: /onnv-gate/usr/src/lib/lvm/libmeta/common/meta_se_notify.c (revision 1623:7bac4a816ebe)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*1623Stw21770  * Common Development and Distribution License (the "License").
6*1623Stw21770  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
210Sstevel@tonic-gate 
220Sstevel@tonic-gate /*
23*1623Stw21770  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
240Sstevel@tonic-gate  * Use is subject to license terms.
250Sstevel@tonic-gate  */
260Sstevel@tonic-gate 
270Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
280Sstevel@tonic-gate 
290Sstevel@tonic-gate #include <stdlib.h>
300Sstevel@tonic-gate #include <meta.h>
310Sstevel@tonic-gate #include <libsysevent.h>
320Sstevel@tonic-gate #include <libnvpair.h>
330Sstevel@tonic-gate #include <sys/sysevent/svm.h>
340Sstevel@tonic-gate #include <sys/sysevent/eventdefs.h>
350Sstevel@tonic-gate #include <dlfcn.h>
360Sstevel@tonic-gate 
370Sstevel@tonic-gate char *
obj2devname(uint32_t tag,set_t setno,md_dev64_t dev)380Sstevel@tonic-gate obj2devname(uint32_t tag, set_t setno, md_dev64_t dev)
390Sstevel@tonic-gate {
400Sstevel@tonic-gate 	char		*setname;
41*1623Stw21770 	char		*uname;
420Sstevel@tonic-gate 	char		name[MD_MAX_CTDLEN];
430Sstevel@tonic-gate 	mdsetname_t	*sp;
440Sstevel@tonic-gate 	md_error_t	status = mdnullerror;
450Sstevel@tonic-gate 	md_set_record	*md_sr;
460Sstevel@tonic-gate 	minor_t		mnum = meta_getminor(dev);
470Sstevel@tonic-gate 	int		rtn = 0;
480Sstevel@tonic-gate 
490Sstevel@tonic-gate 	setname = NULL;
500Sstevel@tonic-gate 	if ((setno != MD_SET_BAD) &&
510Sstevel@tonic-gate 		((sp = metasetnosetname(setno, &status)) != NULL)) {
520Sstevel@tonic-gate 		setname = sp->setname;
530Sstevel@tonic-gate 	}
540Sstevel@tonic-gate 
550Sstevel@tonic-gate 	name[0] = '\0';
560Sstevel@tonic-gate 	switch (tag) {
570Sstevel@tonic-gate 	case SVM_TAG_HS:
580Sstevel@tonic-gate 	case SVM_TAG_METADEVICE:
590Sstevel@tonic-gate 	case SVM_TAG_MIRROR:
600Sstevel@tonic-gate 	case SVM_TAG_RAID5:
610Sstevel@tonic-gate 	case SVM_TAG_STRIPE:
620Sstevel@tonic-gate 	case SVM_TAG_TRANS:
63*1623Stw21770 		uname = get_mdname(sp, mnum);
64*1623Stw21770 		if (uname == NULL)
65*1623Stw21770 			return (NULL);
66*1623Stw21770 
67*1623Stw21770 		(void) strcpy(name, uname);
680Sstevel@tonic-gate 		break;
690Sstevel@tonic-gate 	case SVM_TAG_HSP:
70*1623Stw21770 		uname = get_hspname(sp, mnum);
71*1623Stw21770 		if (uname == NULL)
72*1623Stw21770 			return (NULL);
73*1623Stw21770 
74*1623Stw21770 		(void) strcpy(name, uname);
750Sstevel@tonic-gate 		break;
760Sstevel@tonic-gate 	case SVM_TAG_DRIVE:
770Sstevel@tonic-gate 		(void) sprintf(name, "drive");
780Sstevel@tonic-gate 		break;
790Sstevel@tonic-gate 	case SVM_TAG_HOST:
800Sstevel@tonic-gate 		md_sr = NULL;
810Sstevel@tonic-gate 		if (setname != NULL) {
820Sstevel@tonic-gate 			md_sr = getsetbyname(setname, &status);
830Sstevel@tonic-gate 		}
840Sstevel@tonic-gate 		if ((md_sr != NULL) && (md_sr->sr_nodes[mnum] != NULL)) {
850Sstevel@tonic-gate 			/*
860Sstevel@tonic-gate 			 * Get the host data from the node array.
870Sstevel@tonic-gate 			 */
880Sstevel@tonic-gate 			rtn = snprintf(name, sizeof (name), "%s",
890Sstevel@tonic-gate 			    md_sr->sr_nodes[mnum]);
900Sstevel@tonic-gate 		}
910Sstevel@tonic-gate 		if ((name[0] == '\0') || (rtn >= sizeof (name))) {
920Sstevel@tonic-gate 			(void) sprintf(name, "host");
930Sstevel@tonic-gate 			rtn = 0;
940Sstevel@tonic-gate 		}
950Sstevel@tonic-gate 		break;
960Sstevel@tonic-gate 	case SVM_TAG_SET:
970Sstevel@tonic-gate 		if (setname == NULL) {
980Sstevel@tonic-gate 			(void) sprintf(name, "diskset");
990Sstevel@tonic-gate 		} else {
1000Sstevel@tonic-gate 			rtn = snprintf(name, sizeof (name), "%s", setname);
1010Sstevel@tonic-gate 		}
1020Sstevel@tonic-gate 		break;
1030Sstevel@tonic-gate 	default:
1040Sstevel@tonic-gate 		if ((setname = get_devname(setno, dev)) != NULL) {
1050Sstevel@tonic-gate 			rtn = snprintf(name, sizeof (name), "%s", setname);
1060Sstevel@tonic-gate 		}
1070Sstevel@tonic-gate 		break;
1080Sstevel@tonic-gate 	}
1090Sstevel@tonic-gate 	mdclrerror(&status);
1100Sstevel@tonic-gate 
1110Sstevel@tonic-gate 	/* Check if we got any rubbish for any of the snprintf's */
1120Sstevel@tonic-gate 	if ((name[0] == '\0') || (rtn >= sizeof (name))) {
1130Sstevel@tonic-gate 		return (NULL);
1140Sstevel@tonic-gate 	}
1150Sstevel@tonic-gate 
1160Sstevel@tonic-gate 	return (strdup(name));
1170Sstevel@tonic-gate }
1180Sstevel@tonic-gate 
1190Sstevel@tonic-gate /* Sysevent subclass and mdnotify event type pairs */
1200Sstevel@tonic-gate struct node {
1210Sstevel@tonic-gate 	char	*se_ev;
1220Sstevel@tonic-gate 	evid_t	md_ev;
1230Sstevel@tonic-gate };
1240Sstevel@tonic-gate 
1250Sstevel@tonic-gate /* Table must be sorted in ascending order */
1260Sstevel@tonic-gate static struct node ev_table[] = {
1270Sstevel@tonic-gate 	{ ESC_SVM_ADD,			EV_ADD },
1280Sstevel@tonic-gate 	{ ESC_SVM_ATTACH,		EV_ATTACH },
1290Sstevel@tonic-gate 	{ ESC_SVM_ATTACHING,		EV_ATTACHING },
1300Sstevel@tonic-gate 	{ ESC_SVM_CHANGE,		EV_CHANGE },
1310Sstevel@tonic-gate 	{ ESC_SVM_CREATE,		EV_CREATE },
1320Sstevel@tonic-gate 	{ ESC_SVM_DELETE,		EV_DELETE },
1330Sstevel@tonic-gate 	{ ESC_SVM_DETACH,		EV_DETACH },
1340Sstevel@tonic-gate 	{ ESC_SVM_DETACHING,		EV_DETACHING },
1350Sstevel@tonic-gate 	{ ESC_SVM_DRIVE_ADD,		EV_DRIVE_ADD },
1360Sstevel@tonic-gate 	{ ESC_SVM_DRIVE_DELETE,		EV_DRIVE_DELETE },
1370Sstevel@tonic-gate 	{ ESC_SVM_ENABLE,		EV_ENABLE },
1380Sstevel@tonic-gate 	{ ESC_SVM_ERRED,		EV_ERRED },
1390Sstevel@tonic-gate 	{ ESC_SVM_EXCHANGE,		EV_EXCHANGE },
1400Sstevel@tonic-gate 	{ ESC_SVM_GROW,			EV_GROW },
1410Sstevel@tonic-gate 	{ ESC_SVM_HS_CHANGED,		EV_HS_CHANGED },
1420Sstevel@tonic-gate 	{ ESC_SVM_HS_FREED,		EV_HS_FREED },
1430Sstevel@tonic-gate 	{ ESC_SVM_HOST_ADD,		EV_HOST_ADD },
1440Sstevel@tonic-gate 	{ ESC_SVM_HOST_DELETE,		EV_HOST_DELETE },
1450Sstevel@tonic-gate 	{ ESC_SVM_HOTSPARED,		EV_HOTSPARED },
1460Sstevel@tonic-gate 	{ ESC_SVM_INIT_FAILED,		EV_INIT_FAILED },
1470Sstevel@tonic-gate 	{ ESC_SVM_INIT_FATAL,		EV_INIT_FATAL },
1480Sstevel@tonic-gate 	{ ESC_SVM_INIT_START,		EV_INIT_START },
1490Sstevel@tonic-gate 	{ ESC_SVM_INIT_SUCCESS,		EV_INIT_SUCCESS },
1500Sstevel@tonic-gate 	{ ESC_SVM_IOERR,		EV_IOERR },
1510Sstevel@tonic-gate 	{ ESC_SVM_LASTERRED,		EV_LASTERRED },
1520Sstevel@tonic-gate 	{ ESC_SVM_MEDIATOR_ADD,		EV_MEDIATOR_ADD },
1530Sstevel@tonic-gate 	{ ESC_SVM_MEDIATOR_DELETE,	EV_MEDIATOR_DELETE },
1540Sstevel@tonic-gate 	{ ESC_SVM_OFFLINE,		EV_OFFLINE },
1550Sstevel@tonic-gate 	{ ESC_SVM_OK,			EV_OK },
1560Sstevel@tonic-gate 	{ ESC_SVM_ONLINE,		EV_ONLINE },
1570Sstevel@tonic-gate 	{ ESC_SVM_OPEN_FAIL,		EV_OPEN_FAIL },
1580Sstevel@tonic-gate 	{ ESC_SVM_REGEN_DONE,		EV_REGEN_DONE },
1590Sstevel@tonic-gate 	{ ESC_SVM_REGEN_FAILED,		EV_REGEN_FAILED },
1600Sstevel@tonic-gate 	{ ESC_SVM_REGEN_START,		EV_REGEN_START },
1610Sstevel@tonic-gate 	{ ESC_SVM_RELEASE,		EV_RELEASE },
1620Sstevel@tonic-gate 	{ ESC_SVM_REMOVE,		EV_REMOVE },
1630Sstevel@tonic-gate 	{ ESC_SVM_RENAME_DST,		EV_RENAME_DST },
1640Sstevel@tonic-gate 	{ ESC_SVM_RENAME_SRC,		EV_RENAME_SRC },
1650Sstevel@tonic-gate 	{ ESC_SVM_REPLACE,		EV_REPLACE },
1660Sstevel@tonic-gate 	{ ESC_SVM_RESYNC_DONE,		EV_RESYNC_DONE },
1670Sstevel@tonic-gate 	{ ESC_SVM_RESYNC_FAILED,	EV_RESYNC_FAILED },
1680Sstevel@tonic-gate 	{ ESC_SVM_RESYNC_START,		EV_RESYNC_START },
1690Sstevel@tonic-gate 	{ ESC_SVM_RESYNC_SUCCESS,	EV_RESYNC_SUCCESS },
1700Sstevel@tonic-gate 	{ ESC_SVM_TAKEOVER,		EV_TAKEOVER }
1710Sstevel@tonic-gate };
1720Sstevel@tonic-gate 
1730Sstevel@tonic-gate static ev_obj_t md_tags[] = {
1740Sstevel@tonic-gate 	EVO_UNSPECIFIED,
1750Sstevel@tonic-gate 	EVO_METADEV,
1760Sstevel@tonic-gate 	EVO_MIRROR,
1770Sstevel@tonic-gate 	EVO_STRIPE,
1780Sstevel@tonic-gate 	EVO_RAID5,
1790Sstevel@tonic-gate 	EVO_TRANS,
1800Sstevel@tonic-gate 	EVO_REPLICA,
1810Sstevel@tonic-gate 	EVO_HSP,
1820Sstevel@tonic-gate 	EVO_HS,
1830Sstevel@tonic-gate 	EVO_SET,
1840Sstevel@tonic-gate 	EVO_DRIVE,
1850Sstevel@tonic-gate 	EVO_HOST,
1860Sstevel@tonic-gate 	EVO_MEDIATOR
1870Sstevel@tonic-gate };
1880Sstevel@tonic-gate 
1890Sstevel@tonic-gate static int
ev_compare(const void * node1,const void * node2)1900Sstevel@tonic-gate ev_compare(const void *node1, const void *node2)
1910Sstevel@tonic-gate {
1920Sstevel@tonic-gate 	return (strcmp((const char *)node1,
1930Sstevel@tonic-gate 	    ((const struct node *)node2)->se_ev));
1940Sstevel@tonic-gate }
1950Sstevel@tonic-gate 
1960Sstevel@tonic-gate /*
1970Sstevel@tonic-gate  * Log mdnotify event
1980Sstevel@tonic-gate  */
1990Sstevel@tonic-gate void
do_mdnotify(char * se_subclass,uint32_t tag,set_t setno,md_dev64_t devid)2000Sstevel@tonic-gate do_mdnotify(char *se_subclass, uint32_t tag, set_t setno, md_dev64_t devid)
2010Sstevel@tonic-gate {
2020Sstevel@tonic-gate 	evid_t		ev_type;
2030Sstevel@tonic-gate 	ev_obj_t	md_tag;
2040Sstevel@tonic-gate 	struct node	*node_ptr;
2050Sstevel@tonic-gate 
2060Sstevel@tonic-gate 	/* Translate sysevent into mdnotify event */
2070Sstevel@tonic-gate 	node_ptr = bsearch(se_subclass, ev_table, (sizeof (ev_table) /
2080Sstevel@tonic-gate 	    sizeof (ev_table[0])), sizeof (ev_table[0]), ev_compare);
2090Sstevel@tonic-gate 
2100Sstevel@tonic-gate 	if (node_ptr == NULL) {
2110Sstevel@tonic-gate 		ev_type = EV_EMPTY;
2120Sstevel@tonic-gate 	} else {
2130Sstevel@tonic-gate 		ev_type = node_ptr->md_ev;
2140Sstevel@tonic-gate 	}
2150Sstevel@tonic-gate 
2160Sstevel@tonic-gate 	if (tag >= (sizeof (md_tags) / sizeof (md_tags[0]))) {
2170Sstevel@tonic-gate 		md_tag = EVO_UNSPECIFIED;
2180Sstevel@tonic-gate 	} else {
2190Sstevel@tonic-gate 		md_tag = md_tags[tag];
2200Sstevel@tonic-gate 	}
2210Sstevel@tonic-gate 
2220Sstevel@tonic-gate 	NOTIFY_MD(md_tag, setno, devid, ev_type);
2230Sstevel@tonic-gate }
2240Sstevel@tonic-gate 
2250Sstevel@tonic-gate /*
2260Sstevel@tonic-gate  * External symbols from libsysevent and libnvpair which are not
2270Sstevel@tonic-gate  * available in static forms
2280Sstevel@tonic-gate  */
2290Sstevel@tonic-gate static void	*se_handle = NULL, *nv_handle = NULL;
2300Sstevel@tonic-gate static int	(*_sysevent_post_event)(char *, char *, char *, char *,
2310Sstevel@tonic-gate 		    nvlist_t *, sysevent_id_t *) = NULL;
2320Sstevel@tonic-gate static int	(*_nvlist_alloc)(nvlist_t **, uint_t, int) = NULL;
2330Sstevel@tonic-gate static void	(*_nvlist_free)(nvlist_t *) = NULL;
2340Sstevel@tonic-gate static int	(*_nvlist_add_uint32)(nvlist_t *, char *, uint32_t) = NULL;
2350Sstevel@tonic-gate static int	(*_nvlist_add_uint64)(nvlist_t *, char *, uint64_t) = NULL;
2360Sstevel@tonic-gate static int	(*_nvlist_add_string)(nvlist_t *, char *, char *) = NULL;
2370Sstevel@tonic-gate 
2380Sstevel@tonic-gate /*
2390Sstevel@tonic-gate  * Load nvpair and sysevent symbols
2400Sstevel@tonic-gate  */
2410Sstevel@tonic-gate static int
load_sev_lib()2420Sstevel@tonic-gate load_sev_lib()
2430Sstevel@tonic-gate {
2440Sstevel@tonic-gate 	/* Try to load the sysevent symbol */
2450Sstevel@tonic-gate 	if (se_handle == NULL) {
2460Sstevel@tonic-gate 		se_handle = dlopen("/usr/lib/libsysevent.so.1", RTLD_LAZY);
2470Sstevel@tonic-gate 	}
2480Sstevel@tonic-gate 	if (se_handle != NULL) {
2490Sstevel@tonic-gate 		if ((_sysevent_post_event == NULL) &&
2500Sstevel@tonic-gate 			(_sysevent_post_event = (int (*)(char *, char *, char *,
2510Sstevel@tonic-gate 			    char *, nvlist_t *, sysevent_id_t *))
2520Sstevel@tonic-gate 			    dlsym(se_handle, "sysevent_post_event")) == NULL) {
2530Sstevel@tonic-gate 			goto out;
2540Sstevel@tonic-gate 		}
2550Sstevel@tonic-gate 	} else {
2560Sstevel@tonic-gate 		return (1);
2570Sstevel@tonic-gate 	}
2580Sstevel@tonic-gate 
2590Sstevel@tonic-gate 	/* Try to load the nvpair symbols */
2600Sstevel@tonic-gate 	if (nv_handle == NULL) {
2610Sstevel@tonic-gate 		nv_handle = dlopen("/usr/lib/libnvpair.so.1", RTLD_LAZY);
2620Sstevel@tonic-gate 	}
2630Sstevel@tonic-gate 	if (nv_handle != NULL) {
2640Sstevel@tonic-gate 		if ((_nvlist_alloc == NULL) &&
2650Sstevel@tonic-gate 			(_nvlist_alloc = (int (*)(nvlist_t **, uint_t, int))
2660Sstevel@tonic-gate 			    dlsym(nv_handle, "nvlist_alloc")) == NULL) {
2670Sstevel@tonic-gate 			goto out;
2680Sstevel@tonic-gate 		}
2690Sstevel@tonic-gate 		if ((_nvlist_free == NULL) &&
2700Sstevel@tonic-gate 			(_nvlist_free = (void (*)(nvlist_t *))dlsym(nv_handle,
2710Sstevel@tonic-gate 			    "nvlist_free")) == NULL) {
2720Sstevel@tonic-gate 			goto out;
2730Sstevel@tonic-gate 		}
2740Sstevel@tonic-gate 		if ((_nvlist_add_uint32 == NULL) &&
2750Sstevel@tonic-gate 			(_nvlist_add_uint32 = (int (*)(nvlist_t *, char *,
2760Sstevel@tonic-gate 			    uint32_t))dlsym(nv_handle,
2770Sstevel@tonic-gate 			    "nvlist_add_uint32")) == NULL) {
2780Sstevel@tonic-gate 			goto out;
2790Sstevel@tonic-gate 		}
2800Sstevel@tonic-gate 		if ((_nvlist_add_uint64 == NULL) &&
2810Sstevel@tonic-gate 			(_nvlist_add_uint64 = (int (*)(nvlist_t *, char *,
2820Sstevel@tonic-gate 			    uint64_t))dlsym(nv_handle,
2830Sstevel@tonic-gate 			    "nvlist_add_uint64")) == NULL) {
2840Sstevel@tonic-gate 			goto out;
2850Sstevel@tonic-gate 		}
2860Sstevel@tonic-gate 		if ((_nvlist_add_string == NULL) &&
2870Sstevel@tonic-gate 			(_nvlist_add_string = (int (*)(nvlist_t *, char *,
2880Sstevel@tonic-gate 			    char *))dlsym(nv_handle,
2890Sstevel@tonic-gate 			    "nvlist_add_string")) == NULL) {
2900Sstevel@tonic-gate 			goto out;
2910Sstevel@tonic-gate 		}
2920Sstevel@tonic-gate 
2930Sstevel@tonic-gate 		return (0);
2940Sstevel@tonic-gate 	}
2950Sstevel@tonic-gate 
2960Sstevel@tonic-gate out:
2970Sstevel@tonic-gate 	if ((se_handle != NULL) && (dlclose(se_handle) == 0)) {
2980Sstevel@tonic-gate 		se_handle = NULL;
2990Sstevel@tonic-gate 	}
3000Sstevel@tonic-gate 
3010Sstevel@tonic-gate 	if ((nv_handle != NULL) && (dlclose(nv_handle) == 0)) {
3020Sstevel@tonic-gate 		nv_handle = NULL;
3030Sstevel@tonic-gate 	}
3040Sstevel@tonic-gate 
3050Sstevel@tonic-gate 	_sysevent_post_event = NULL;
3060Sstevel@tonic-gate 	_nvlist_alloc = NULL;
3070Sstevel@tonic-gate 	_nvlist_free = NULL;
3080Sstevel@tonic-gate 	_nvlist_add_uint32 = NULL;
3090Sstevel@tonic-gate 	_nvlist_add_uint64 = NULL;
3100Sstevel@tonic-gate 	_nvlist_add_string = NULL;
3110Sstevel@tonic-gate 
3120Sstevel@tonic-gate 	return (1);
3130Sstevel@tonic-gate }
3140Sstevel@tonic-gate 
3150Sstevel@tonic-gate /*
3160Sstevel@tonic-gate  * Log SVM sys events
3170Sstevel@tonic-gate  */
3180Sstevel@tonic-gate void
meta_svm_sysevent(char * se_class,char * se_subclass,uint32_t tag,set_t setno,md_dev64_t devid)3190Sstevel@tonic-gate meta_svm_sysevent(
3200Sstevel@tonic-gate 	char		*se_class,
3210Sstevel@tonic-gate 	char		*se_subclass,
3220Sstevel@tonic-gate 	uint32_t	tag,
3230Sstevel@tonic-gate 	set_t		setno,
3240Sstevel@tonic-gate 	md_dev64_t	devid
3250Sstevel@tonic-gate )
3260Sstevel@tonic-gate {
3270Sstevel@tonic-gate 	sysevent_id_t	eid;
3280Sstevel@tonic-gate 	nvlist_t	*attr_list;
3290Sstevel@tonic-gate 	int		err = 0;
3300Sstevel@tonic-gate 	char		*devname;
3310Sstevel@tonic-gate 
3320Sstevel@tonic-gate 	/* Raise the mdnotify event before anything else */
3330Sstevel@tonic-gate 	do_mdnotify(se_subclass, tag, setno, devid);
3340Sstevel@tonic-gate 
3350Sstevel@tonic-gate 	/* Just get out if the sysevent symbol can't be loaded */
3360Sstevel@tonic-gate 	if (load_sev_lib()) {
3370Sstevel@tonic-gate 		return;
3380Sstevel@tonic-gate 	}
3390Sstevel@tonic-gate 
3400Sstevel@tonic-gate 	err = (*_nvlist_alloc)(&attr_list, NV_UNIQUE_NAME, 0);
3410Sstevel@tonic-gate 
3420Sstevel@tonic-gate 	if (err == 0) {
3430Sstevel@tonic-gate 		/* Add the version number */
3440Sstevel@tonic-gate 		err = (*_nvlist_add_uint32)(attr_list, SVM_VERSION_NO,
3450Sstevel@tonic-gate 		    (uint32_t)SVM_VERSION);
3460Sstevel@tonic-gate 		if (err != 0) {
3470Sstevel@tonic-gate 			goto fail;
3480Sstevel@tonic-gate 		}
3490Sstevel@tonic-gate 
3500Sstevel@tonic-gate 		/* Add the tag attribute */
3510Sstevel@tonic-gate 		err = (*_nvlist_add_uint32)(attr_list, SVM_TAG, (uint32_t)tag);
3520Sstevel@tonic-gate 		if (err != 0) {
3530Sstevel@tonic-gate 			goto fail;
3540Sstevel@tonic-gate 		}
3550Sstevel@tonic-gate 
3560Sstevel@tonic-gate 		/* Add the set number attribute */
3570Sstevel@tonic-gate 		err = (*_nvlist_add_uint32)(attr_list, SVM_SET_NO,
3580Sstevel@tonic-gate 		    (uint32_t)setno);
3590Sstevel@tonic-gate 		if (err != 0) {
3600Sstevel@tonic-gate 			goto fail;
3610Sstevel@tonic-gate 		}
3620Sstevel@tonic-gate 
3630Sstevel@tonic-gate 		/* Add the device id attribute */
3640Sstevel@tonic-gate 		err = (*_nvlist_add_uint64)(attr_list, SVM_DEV_ID,
3650Sstevel@tonic-gate 		    (uint64_t)devid);
3660Sstevel@tonic-gate 		if (err != 0) {
3670Sstevel@tonic-gate 			goto fail;
3680Sstevel@tonic-gate 		}
3690Sstevel@tonic-gate 
3700Sstevel@tonic-gate 		/* Add the device name attribute */
3710Sstevel@tonic-gate 		devname = obj2devname(tag, setno, devid);
3720Sstevel@tonic-gate 		if (devname != NULL) {
3730Sstevel@tonic-gate 			err = (*_nvlist_add_string)(attr_list, SVM_DEV_NAME,
3740Sstevel@tonic-gate 			    devname);
3750Sstevel@tonic-gate 			free(devname);
3760Sstevel@tonic-gate 		} else {
3770Sstevel@tonic-gate 			err = (*_nvlist_add_string)(attr_list, SVM_DEV_NAME,
3780Sstevel@tonic-gate 			    "unspecified");
3790Sstevel@tonic-gate 		}
3800Sstevel@tonic-gate 		if (err != 0) {
3810Sstevel@tonic-gate 			goto fail;
3820Sstevel@tonic-gate 		}
3830Sstevel@tonic-gate 
3840Sstevel@tonic-gate 		/* Attempt to post event */
3850Sstevel@tonic-gate 		(void) (*_sysevent_post_event)(se_class, se_subclass,
3860Sstevel@tonic-gate 		    SUNW_VENDOR, EP_SVM, attr_list, &eid);
3870Sstevel@tonic-gate 
3880Sstevel@tonic-gate 		(*_nvlist_free)(attr_list);
3890Sstevel@tonic-gate 	}
3900Sstevel@tonic-gate 
3910Sstevel@tonic-gate 	return;
3920Sstevel@tonic-gate 
3930Sstevel@tonic-gate fail:
3940Sstevel@tonic-gate 	(*_nvlist_free)(attr_list);
3950Sstevel@tonic-gate }
396