10dc974a9SCathy Zhou /*
20dc974a9SCathy Zhou * CDDL HEADER START
30dc974a9SCathy Zhou *
40dc974a9SCathy Zhou * The contents of this file are subject to the terms of the
50dc974a9SCathy Zhou * Common Development and Distribution License (the "License").
60dc974a9SCathy Zhou * You may not use this file except in compliance with the License.
70dc974a9SCathy Zhou *
80dc974a9SCathy Zhou * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90dc974a9SCathy Zhou * or http://www.opensolaris.org/os/licensing.
100dc974a9SCathy Zhou * See the License for the specific language governing permissions
110dc974a9SCathy Zhou * and limitations under the License.
120dc974a9SCathy Zhou *
130dc974a9SCathy Zhou * When distributing Covered Code, include this CDDL HEADER in each
140dc974a9SCathy Zhou * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150dc974a9SCathy Zhou * If applicable, add the following below this CDDL HEADER, with the
160dc974a9SCathy Zhou * fields enclosed by brackets "[]" replaced with your own identifying
170dc974a9SCathy Zhou * information: Portions Copyright [yyyy] [name of copyright owner]
180dc974a9SCathy Zhou *
190dc974a9SCathy Zhou * CDDL HEADER END
200dc974a9SCathy Zhou */
21*0756cc70SYuri Pankov
220dc974a9SCathy Zhou /*
235093e103SCathy Zhou * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
240dc974a9SCathy Zhou * Use is subject to license terms.
25*0756cc70SYuri Pankov * Copyright 2016 Nexenta Systems, Inc.
260dc974a9SCathy Zhou */
270dc974a9SCathy Zhou
280dc974a9SCathy Zhou /*
290dc974a9SCathy Zhou * datalink syseventd module.
300dc974a9SCathy Zhou *
310dc974a9SCathy Zhou * The purpose of this module is to identify all datalink related events,
320dc974a9SCathy Zhou * and react accordingly.
330dc974a9SCathy Zhou */
340dc974a9SCathy Zhou
350dc974a9SCathy Zhou #include <errno.h>
360dc974a9SCathy Zhou #include <sys/sysevent/eventdefs.h>
370dc974a9SCathy Zhou #include <string.h>
380dc974a9SCathy Zhou #include <libnvpair.h>
390dc974a9SCathy Zhou #include <librcm.h>
400dc974a9SCathy Zhou #include <libsysevent.h>
415ad1f010SStephen Hanson #include "sysevent_signal.h"
420dc974a9SCathy Zhou
434dc92747SCheng Sean Ye extern void syseventd_err_print(char *, ...);
444dc92747SCheng Sean Ye
454dc92747SCheng Sean Ye struct event_list {
464dc92747SCheng Sean Ye nvlist_t *ev;
474dc92747SCheng Sean Ye struct event_list *next;
484dc92747SCheng Sean Ye };
494dc92747SCheng Sean Ye
500dc974a9SCathy Zhou static rcm_handle_t *rcm_hdl = NULL;
514dc92747SCheng Sean Ye static boolean_t dl_exiting;
524dc92747SCheng Sean Ye static thread_t dl_notify_tid;
534dc92747SCheng Sean Ye static mutex_t dl_mx;
544dc92747SCheng Sean Ye static cond_t dl_cv;
554dc92747SCheng Sean Ye static struct event_list *dl_events;
564dc92747SCheng Sean Ye
574dc92747SCheng Sean Ye /* ARGSUSED */
584dc92747SCheng Sean Ye static void *
datalink_notify_thread(void * arg)594dc92747SCheng Sean Ye datalink_notify_thread(void *arg)
604dc92747SCheng Sean Ye {
614dc92747SCheng Sean Ye struct event_list *tmp_events, *ep;
624dc92747SCheng Sean Ye
634dc92747SCheng Sean Ye (void) mutex_lock(&dl_mx);
644dc92747SCheng Sean Ye
654dc92747SCheng Sean Ye while (! dl_exiting || dl_events != NULL) {
664dc92747SCheng Sean Ye if (dl_events == NULL) {
674dc92747SCheng Sean Ye (void) cond_wait(&dl_cv, &dl_mx);
684dc92747SCheng Sean Ye continue;
694dc92747SCheng Sean Ye }
704dc92747SCheng Sean Ye
714dc92747SCheng Sean Ye tmp_events = dl_events;
724dc92747SCheng Sean Ye dl_events = NULL;
734dc92747SCheng Sean Ye
744dc92747SCheng Sean Ye (void) mutex_unlock(&dl_mx);
754dc92747SCheng Sean Ye
764dc92747SCheng Sean Ye while (tmp_events != NULL) {
775ad1f010SStephen Hanson struct sigaction cbuf, dfl;
785ad1f010SStephen Hanson
795ad1f010SStephen Hanson /*
805ad1f010SStephen Hanson * Ignore SIGCLD for the
815ad1f010SStephen Hanson * duration of the rcm_notify_event call.
825ad1f010SStephen Hanson */
835ad1f010SStephen Hanson (void) memset(&dfl, 0, sizeof (dfl));
845ad1f010SStephen Hanson dfl.sa_handler = SIG_IGN;
855ad1f010SStephen Hanson (void) sigaction(SIGCHLD, &dfl, &cbuf);
865ad1f010SStephen Hanson
874dc92747SCheng Sean Ye /*
884dc92747SCheng Sean Ye * Send the PHYSLINK_NEW event to network_rcm to update
894dc92747SCheng Sean Ye * the network devices cache accordingly.
904dc92747SCheng Sean Ye */
914dc92747SCheng Sean Ye if (rcm_notify_event(rcm_hdl, RCM_RESOURCE_PHYSLINK_NEW,
924dc92747SCheng Sean Ye 0, tmp_events->ev, NULL) != RCM_SUCCESS)
935ad1f010SStephen Hanson syseventd_err_print("datalink_mod: Can not "
944dc92747SCheng Sean Ye "notify event: %s\n", strerror(errno));
954dc92747SCheng Sean Ye
965ad1f010SStephen Hanson (void) sigaction(SIGCHLD, &cbuf, NULL);
974dc92747SCheng Sean Ye ep = tmp_events;
984dc92747SCheng Sean Ye tmp_events = tmp_events->next;
994dc92747SCheng Sean Ye nvlist_free(ep->ev);
1004dc92747SCheng Sean Ye free(ep);
1014dc92747SCheng Sean Ye }
1024dc92747SCheng Sean Ye
1034dc92747SCheng Sean Ye (void) mutex_lock(&dl_mx);
1044dc92747SCheng Sean Ye }
1054dc92747SCheng Sean Ye
1064dc92747SCheng Sean Ye (void) mutex_unlock(&dl_mx);
1074dc92747SCheng Sean Ye
1084dc92747SCheng Sean Ye return (NULL);
1094dc92747SCheng Sean Ye }
1100dc974a9SCathy Zhou
1110dc974a9SCathy Zhou /*ARGSUSED*/
1120dc974a9SCathy Zhou static int
datalink_deliver_event(sysevent_t * ev,int unused)1130dc974a9SCathy Zhou datalink_deliver_event(sysevent_t *ev, int unused)
1140dc974a9SCathy Zhou {
1150dc974a9SCathy Zhou const char *class = sysevent_get_class_name(ev);
1160dc974a9SCathy Zhou const char *subclass = sysevent_get_subclass_name(ev);
1170dc974a9SCathy Zhou nvlist_t *nvl;
1184dc92747SCheng Sean Ye struct event_list *newp, **elpp;
1190dc974a9SCathy Zhou
1200dc974a9SCathy Zhou if (strcmp(class, EC_DATALINK) != 0 ||
1210dc974a9SCathy Zhou strcmp(subclass, ESC_DATALINK_PHYS_ADD) != 0) {
1220dc974a9SCathy Zhou return (0);
1230dc974a9SCathy Zhou }
1240dc974a9SCathy Zhou
1250dc974a9SCathy Zhou if (sysevent_get_attr_list(ev, &nvl) != 0)
1260dc974a9SCathy Zhou return (EINVAL);
1270dc974a9SCathy Zhou
1285093e103SCathy Zhou /*
1294dc92747SCheng Sean Ye * rcm_notify_event() needs to be called asynchronously otherwise when
1304dc92747SCheng Sean Ye * sysevent queue is full, deadlock will happen.
1315093e103SCathy Zhou */
1324dc92747SCheng Sean Ye if ((newp = malloc(sizeof (struct event_list))) == NULL)
1334dc92747SCheng Sean Ye return (ENOMEM);
1344dc92747SCheng Sean Ye
1354dc92747SCheng Sean Ye newp->ev = nvl;
1364dc92747SCheng Sean Ye newp->next = NULL;
1374dc92747SCheng Sean Ye
1384dc92747SCheng Sean Ye /*
1394dc92747SCheng Sean Ye * queue up at the end of the event list and signal notify_thread to
1404dc92747SCheng Sean Ye * process it.
1414dc92747SCheng Sean Ye */
1424dc92747SCheng Sean Ye (void) mutex_lock(&dl_mx);
1434dc92747SCheng Sean Ye elpp = &dl_events;
1444dc92747SCheng Sean Ye while (*elpp != NULL)
1454dc92747SCheng Sean Ye elpp = &(*elpp)->next;
1464dc92747SCheng Sean Ye *elpp = newp;
1474dc92747SCheng Sean Ye (void) cond_signal(&dl_cv);
1484dc92747SCheng Sean Ye (void) mutex_unlock(&dl_mx);
1490dc974a9SCathy Zhou
1504dc92747SCheng Sean Ye return (0);
1510dc974a9SCathy Zhou }
1520dc974a9SCathy Zhou
1530dc974a9SCathy Zhou static struct slm_mod_ops datalink_mod_ops = {
1540dc974a9SCathy Zhou SE_MAJOR_VERSION,
1550dc974a9SCathy Zhou SE_MINOR_VERSION,
1560dc974a9SCathy Zhou SE_MAX_RETRY_LIMIT,
1570dc974a9SCathy Zhou datalink_deliver_event
1580dc974a9SCathy Zhou };
1590dc974a9SCathy Zhou
1600dc974a9SCathy Zhou struct slm_mod_ops *
slm_init()1610dc974a9SCathy Zhou slm_init()
1620dc974a9SCathy Zhou {
1634dc92747SCheng Sean Ye dl_events = NULL;
1644dc92747SCheng Sean Ye dl_exiting = B_FALSE;
1654dc92747SCheng Sean Ye
1660dc974a9SCathy Zhou if (rcm_alloc_handle(NULL, 0, NULL, &rcm_hdl) != RCM_SUCCESS)
1670dc974a9SCathy Zhou return (NULL);
1680dc974a9SCathy Zhou
169*0756cc70SYuri Pankov (void) mutex_init(&dl_mx, USYNC_THREAD, NULL);
170*0756cc70SYuri Pankov (void) cond_init(&dl_cv, USYNC_THREAD, NULL);
171*0756cc70SYuri Pankov
1724dc92747SCheng Sean Ye if (thr_create(NULL, 0, datalink_notify_thread, NULL, 0,
1734dc92747SCheng Sean Ye &dl_notify_tid) != 0) {
1744dc92747SCheng Sean Ye (void) rcm_free_handle(rcm_hdl);
175*0756cc70SYuri Pankov (void) mutex_destroy(&dl_mx);
176*0756cc70SYuri Pankov (void) cond_destroy(&dl_cv);
1774dc92747SCheng Sean Ye return (NULL);
1784dc92747SCheng Sean Ye }
1794dc92747SCheng Sean Ye
1800dc974a9SCathy Zhou return (&datalink_mod_ops);
1810dc974a9SCathy Zhou }
1820dc974a9SCathy Zhou
1830dc974a9SCathy Zhou void
slm_fini()1840dc974a9SCathy Zhou slm_fini()
1850dc974a9SCathy Zhou {
1864dc92747SCheng Sean Ye (void) mutex_lock(&dl_mx);
1874dc92747SCheng Sean Ye dl_exiting = B_TRUE;
1884dc92747SCheng Sean Ye (void) cond_signal(&dl_cv);
1894dc92747SCheng Sean Ye (void) mutex_unlock(&dl_mx);
1904dc92747SCheng Sean Ye (void) thr_join(dl_notify_tid, NULL, NULL);
1914dc92747SCheng Sean Ye
1924dc92747SCheng Sean Ye (void) mutex_destroy(&dl_mx);
1934dc92747SCheng Sean Ye (void) cond_destroy(&dl_cv);
1940dc974a9SCathy Zhou (void) rcm_free_handle(rcm_hdl);
1950dc974a9SCathy Zhou rcm_hdl = NULL;
1960dc974a9SCathy Zhou }
197