xref: /onnv-gate/usr/src/lib/lvm/libmeta/common/meta_se_notify.c (revision 1623:7bac4a816ebe)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 #include <stdlib.h>
30 #include <meta.h>
31 #include <libsysevent.h>
32 #include <libnvpair.h>
33 #include <sys/sysevent/svm.h>
34 #include <sys/sysevent/eventdefs.h>
35 #include <dlfcn.h>
36 
37 char *
obj2devname(uint32_t tag,set_t setno,md_dev64_t dev)38 obj2devname(uint32_t tag, set_t setno, md_dev64_t dev)
39 {
40 	char		*setname;
41 	char		*uname;
42 	char		name[MD_MAX_CTDLEN];
43 	mdsetname_t	*sp;
44 	md_error_t	status = mdnullerror;
45 	md_set_record	*md_sr;
46 	minor_t		mnum = meta_getminor(dev);
47 	int		rtn = 0;
48 
49 	setname = NULL;
50 	if ((setno != MD_SET_BAD) &&
51 		((sp = metasetnosetname(setno, &status)) != NULL)) {
52 		setname = sp->setname;
53 	}
54 
55 	name[0] = '\0';
56 	switch (tag) {
57 	case SVM_TAG_HS:
58 	case SVM_TAG_METADEVICE:
59 	case SVM_TAG_MIRROR:
60 	case SVM_TAG_RAID5:
61 	case SVM_TAG_STRIPE:
62 	case SVM_TAG_TRANS:
63 		uname = get_mdname(sp, mnum);
64 		if (uname == NULL)
65 			return (NULL);
66 
67 		(void) strcpy(name, uname);
68 		break;
69 	case SVM_TAG_HSP:
70 		uname = get_hspname(sp, mnum);
71 		if (uname == NULL)
72 			return (NULL);
73 
74 		(void) strcpy(name, uname);
75 		break;
76 	case SVM_TAG_DRIVE:
77 		(void) sprintf(name, "drive");
78 		break;
79 	case SVM_TAG_HOST:
80 		md_sr = NULL;
81 		if (setname != NULL) {
82 			md_sr = getsetbyname(setname, &status);
83 		}
84 		if ((md_sr != NULL) && (md_sr->sr_nodes[mnum] != NULL)) {
85 			/*
86 			 * Get the host data from the node array.
87 			 */
88 			rtn = snprintf(name, sizeof (name), "%s",
89 			    md_sr->sr_nodes[mnum]);
90 		}
91 		if ((name[0] == '\0') || (rtn >= sizeof (name))) {
92 			(void) sprintf(name, "host");
93 			rtn = 0;
94 		}
95 		break;
96 	case SVM_TAG_SET:
97 		if (setname == NULL) {
98 			(void) sprintf(name, "diskset");
99 		} else {
100 			rtn = snprintf(name, sizeof (name), "%s", setname);
101 		}
102 		break;
103 	default:
104 		if ((setname = get_devname(setno, dev)) != NULL) {
105 			rtn = snprintf(name, sizeof (name), "%s", setname);
106 		}
107 		break;
108 	}
109 	mdclrerror(&status);
110 
111 	/* Check if we got any rubbish for any of the snprintf's */
112 	if ((name[0] == '\0') || (rtn >= sizeof (name))) {
113 		return (NULL);
114 	}
115 
116 	return (strdup(name));
117 }
118 
119 /* Sysevent subclass and mdnotify event type pairs */
120 struct node {
121 	char	*se_ev;
122 	evid_t	md_ev;
123 };
124 
125 /* Table must be sorted in ascending order */
126 static struct node ev_table[] = {
127 	{ ESC_SVM_ADD,			EV_ADD },
128 	{ ESC_SVM_ATTACH,		EV_ATTACH },
129 	{ ESC_SVM_ATTACHING,		EV_ATTACHING },
130 	{ ESC_SVM_CHANGE,		EV_CHANGE },
131 	{ ESC_SVM_CREATE,		EV_CREATE },
132 	{ ESC_SVM_DELETE,		EV_DELETE },
133 	{ ESC_SVM_DETACH,		EV_DETACH },
134 	{ ESC_SVM_DETACHING,		EV_DETACHING },
135 	{ ESC_SVM_DRIVE_ADD,		EV_DRIVE_ADD },
136 	{ ESC_SVM_DRIVE_DELETE,		EV_DRIVE_DELETE },
137 	{ ESC_SVM_ENABLE,		EV_ENABLE },
138 	{ ESC_SVM_ERRED,		EV_ERRED },
139 	{ ESC_SVM_EXCHANGE,		EV_EXCHANGE },
140 	{ ESC_SVM_GROW,			EV_GROW },
141 	{ ESC_SVM_HS_CHANGED,		EV_HS_CHANGED },
142 	{ ESC_SVM_HS_FREED,		EV_HS_FREED },
143 	{ ESC_SVM_HOST_ADD,		EV_HOST_ADD },
144 	{ ESC_SVM_HOST_DELETE,		EV_HOST_DELETE },
145 	{ ESC_SVM_HOTSPARED,		EV_HOTSPARED },
146 	{ ESC_SVM_INIT_FAILED,		EV_INIT_FAILED },
147 	{ ESC_SVM_INIT_FATAL,		EV_INIT_FATAL },
148 	{ ESC_SVM_INIT_START,		EV_INIT_START },
149 	{ ESC_SVM_INIT_SUCCESS,		EV_INIT_SUCCESS },
150 	{ ESC_SVM_IOERR,		EV_IOERR },
151 	{ ESC_SVM_LASTERRED,		EV_LASTERRED },
152 	{ ESC_SVM_MEDIATOR_ADD,		EV_MEDIATOR_ADD },
153 	{ ESC_SVM_MEDIATOR_DELETE,	EV_MEDIATOR_DELETE },
154 	{ ESC_SVM_OFFLINE,		EV_OFFLINE },
155 	{ ESC_SVM_OK,			EV_OK },
156 	{ ESC_SVM_ONLINE,		EV_ONLINE },
157 	{ ESC_SVM_OPEN_FAIL,		EV_OPEN_FAIL },
158 	{ ESC_SVM_REGEN_DONE,		EV_REGEN_DONE },
159 	{ ESC_SVM_REGEN_FAILED,		EV_REGEN_FAILED },
160 	{ ESC_SVM_REGEN_START,		EV_REGEN_START },
161 	{ ESC_SVM_RELEASE,		EV_RELEASE },
162 	{ ESC_SVM_REMOVE,		EV_REMOVE },
163 	{ ESC_SVM_RENAME_DST,		EV_RENAME_DST },
164 	{ ESC_SVM_RENAME_SRC,		EV_RENAME_SRC },
165 	{ ESC_SVM_REPLACE,		EV_REPLACE },
166 	{ ESC_SVM_RESYNC_DONE,		EV_RESYNC_DONE },
167 	{ ESC_SVM_RESYNC_FAILED,	EV_RESYNC_FAILED },
168 	{ ESC_SVM_RESYNC_START,		EV_RESYNC_START },
169 	{ ESC_SVM_RESYNC_SUCCESS,	EV_RESYNC_SUCCESS },
170 	{ ESC_SVM_TAKEOVER,		EV_TAKEOVER }
171 };
172 
173 static ev_obj_t md_tags[] = {
174 	EVO_UNSPECIFIED,
175 	EVO_METADEV,
176 	EVO_MIRROR,
177 	EVO_STRIPE,
178 	EVO_RAID5,
179 	EVO_TRANS,
180 	EVO_REPLICA,
181 	EVO_HSP,
182 	EVO_HS,
183 	EVO_SET,
184 	EVO_DRIVE,
185 	EVO_HOST,
186 	EVO_MEDIATOR
187 };
188 
189 static int
ev_compare(const void * node1,const void * node2)190 ev_compare(const void *node1, const void *node2)
191 {
192 	return (strcmp((const char *)node1,
193 	    ((const struct node *)node2)->se_ev));
194 }
195 
196 /*
197  * Log mdnotify event
198  */
199 void
do_mdnotify(char * se_subclass,uint32_t tag,set_t setno,md_dev64_t devid)200 do_mdnotify(char *se_subclass, uint32_t tag, set_t setno, md_dev64_t devid)
201 {
202 	evid_t		ev_type;
203 	ev_obj_t	md_tag;
204 	struct node	*node_ptr;
205 
206 	/* Translate sysevent into mdnotify event */
207 	node_ptr = bsearch(se_subclass, ev_table, (sizeof (ev_table) /
208 	    sizeof (ev_table[0])), sizeof (ev_table[0]), ev_compare);
209 
210 	if (node_ptr == NULL) {
211 		ev_type = EV_EMPTY;
212 	} else {
213 		ev_type = node_ptr->md_ev;
214 	}
215 
216 	if (tag >= (sizeof (md_tags) / sizeof (md_tags[0]))) {
217 		md_tag = EVO_UNSPECIFIED;
218 	} else {
219 		md_tag = md_tags[tag];
220 	}
221 
222 	NOTIFY_MD(md_tag, setno, devid, ev_type);
223 }
224 
225 /*
226  * External symbols from libsysevent and libnvpair which are not
227  * available in static forms
228  */
229 static void	*se_handle = NULL, *nv_handle = NULL;
230 static int	(*_sysevent_post_event)(char *, char *, char *, char *,
231 		    nvlist_t *, sysevent_id_t *) = NULL;
232 static int	(*_nvlist_alloc)(nvlist_t **, uint_t, int) = NULL;
233 static void	(*_nvlist_free)(nvlist_t *) = NULL;
234 static int	(*_nvlist_add_uint32)(nvlist_t *, char *, uint32_t) = NULL;
235 static int	(*_nvlist_add_uint64)(nvlist_t *, char *, uint64_t) = NULL;
236 static int	(*_nvlist_add_string)(nvlist_t *, char *, char *) = NULL;
237 
238 /*
239  * Load nvpair and sysevent symbols
240  */
241 static int
load_sev_lib()242 load_sev_lib()
243 {
244 	/* Try to load the sysevent symbol */
245 	if (se_handle == NULL) {
246 		se_handle = dlopen("/usr/lib/libsysevent.so.1", RTLD_LAZY);
247 	}
248 	if (se_handle != NULL) {
249 		if ((_sysevent_post_event == NULL) &&
250 			(_sysevent_post_event = (int (*)(char *, char *, char *,
251 			    char *, nvlist_t *, sysevent_id_t *))
252 			    dlsym(se_handle, "sysevent_post_event")) == NULL) {
253 			goto out;
254 		}
255 	} else {
256 		return (1);
257 	}
258 
259 	/* Try to load the nvpair symbols */
260 	if (nv_handle == NULL) {
261 		nv_handle = dlopen("/usr/lib/libnvpair.so.1", RTLD_LAZY);
262 	}
263 	if (nv_handle != NULL) {
264 		if ((_nvlist_alloc == NULL) &&
265 			(_nvlist_alloc = (int (*)(nvlist_t **, uint_t, int))
266 			    dlsym(nv_handle, "nvlist_alloc")) == NULL) {
267 			goto out;
268 		}
269 		if ((_nvlist_free == NULL) &&
270 			(_nvlist_free = (void (*)(nvlist_t *))dlsym(nv_handle,
271 			    "nvlist_free")) == NULL) {
272 			goto out;
273 		}
274 		if ((_nvlist_add_uint32 == NULL) &&
275 			(_nvlist_add_uint32 = (int (*)(nvlist_t *, char *,
276 			    uint32_t))dlsym(nv_handle,
277 			    "nvlist_add_uint32")) == NULL) {
278 			goto out;
279 		}
280 		if ((_nvlist_add_uint64 == NULL) &&
281 			(_nvlist_add_uint64 = (int (*)(nvlist_t *, char *,
282 			    uint64_t))dlsym(nv_handle,
283 			    "nvlist_add_uint64")) == NULL) {
284 			goto out;
285 		}
286 		if ((_nvlist_add_string == NULL) &&
287 			(_nvlist_add_string = (int (*)(nvlist_t *, char *,
288 			    char *))dlsym(nv_handle,
289 			    "nvlist_add_string")) == NULL) {
290 			goto out;
291 		}
292 
293 		return (0);
294 	}
295 
296 out:
297 	if ((se_handle != NULL) && (dlclose(se_handle) == 0)) {
298 		se_handle = NULL;
299 	}
300 
301 	if ((nv_handle != NULL) && (dlclose(nv_handle) == 0)) {
302 		nv_handle = NULL;
303 	}
304 
305 	_sysevent_post_event = NULL;
306 	_nvlist_alloc = NULL;
307 	_nvlist_free = NULL;
308 	_nvlist_add_uint32 = NULL;
309 	_nvlist_add_uint64 = NULL;
310 	_nvlist_add_string = NULL;
311 
312 	return (1);
313 }
314 
315 /*
316  * Log SVM sys events
317  */
318 void
meta_svm_sysevent(char * se_class,char * se_subclass,uint32_t tag,set_t setno,md_dev64_t devid)319 meta_svm_sysevent(
320 	char		*se_class,
321 	char		*se_subclass,
322 	uint32_t	tag,
323 	set_t		setno,
324 	md_dev64_t	devid
325 )
326 {
327 	sysevent_id_t	eid;
328 	nvlist_t	*attr_list;
329 	int		err = 0;
330 	char		*devname;
331 
332 	/* Raise the mdnotify event before anything else */
333 	do_mdnotify(se_subclass, tag, setno, devid);
334 
335 	/* Just get out if the sysevent symbol can't be loaded */
336 	if (load_sev_lib()) {
337 		return;
338 	}
339 
340 	err = (*_nvlist_alloc)(&attr_list, NV_UNIQUE_NAME, 0);
341 
342 	if (err == 0) {
343 		/* Add the version number */
344 		err = (*_nvlist_add_uint32)(attr_list, SVM_VERSION_NO,
345 		    (uint32_t)SVM_VERSION);
346 		if (err != 0) {
347 			goto fail;
348 		}
349 
350 		/* Add the tag attribute */
351 		err = (*_nvlist_add_uint32)(attr_list, SVM_TAG, (uint32_t)tag);
352 		if (err != 0) {
353 			goto fail;
354 		}
355 
356 		/* Add the set number attribute */
357 		err = (*_nvlist_add_uint32)(attr_list, SVM_SET_NO,
358 		    (uint32_t)setno);
359 		if (err != 0) {
360 			goto fail;
361 		}
362 
363 		/* Add the device id attribute */
364 		err = (*_nvlist_add_uint64)(attr_list, SVM_DEV_ID,
365 		    (uint64_t)devid);
366 		if (err != 0) {
367 			goto fail;
368 		}
369 
370 		/* Add the device name attribute */
371 		devname = obj2devname(tag, setno, devid);
372 		if (devname != NULL) {
373 			err = (*_nvlist_add_string)(attr_list, SVM_DEV_NAME,
374 			    devname);
375 			free(devname);
376 		} else {
377 			err = (*_nvlist_add_string)(attr_list, SVM_DEV_NAME,
378 			    "unspecified");
379 		}
380 		if (err != 0) {
381 			goto fail;
382 		}
383 
384 		/* Attempt to post event */
385 		(void) (*_sysevent_post_event)(se_class, se_subclass,
386 		    SUNW_VENDOR, EP_SVM, attr_list, &eid);
387 
388 		(*_nvlist_free)(attr_list);
389 	}
390 
391 	return;
392 
393 fail:
394 	(*_nvlist_free)(attr_list);
395 }
396