summaryrefslogtreecommitdiff
path: root/usr/src/uts/common/os/log_sysevent.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/uts/common/os/log_sysevent.c')
-rw-r--r--usr/src/uts/common/os/log_sysevent.c59
1 files changed, 53 insertions, 6 deletions
diff --git a/usr/src/uts/common/os/log_sysevent.c b/usr/src/uts/common/os/log_sysevent.c
index 51cfa7f817..9739d4dbdf 100644
--- a/usr/src/uts/common/os/log_sysevent.c
+++ b/usr/src/uts/common/os/log_sysevent.c
@@ -21,6 +21,7 @@
/*
* Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright 2013 Nexenta Systems, Inc. All rights reserved.
+ * Copyright 2016 Toomas Soome <tsoome@me.com>
*/
#include <sys/types.h>
@@ -34,6 +35,7 @@
#include <sys/callb.h>
#include <sys/sysevent.h>
#include <sys/sysevent_impl.h>
+#include <sys/sysevent/dev.h>
#include <sys/modctl.h>
#include <sys/sysmacros.h>
#include <sys/disp.h>
@@ -568,7 +570,7 @@ free_packed_event(sysevent_t *ev)
*/
int
sysevent_add_attr(sysevent_attr_list_t **ev_attr_list, char *name,
- sysevent_value_t *se_value, int flag)
+ sysevent_value_t *se_value, int flag)
{
int error;
nvlist_t **nvlp = (nvlist_t **)ev_attr_list;
@@ -1092,7 +1094,7 @@ find_subclass(class_lst_t *c_list, char *subclass)
static void
insert_subclass(class_lst_t *c_list, char **subclass_names,
- int subclass_num, uint32_t sub_id)
+ int subclass_num, uint32_t sub_id)
{
int i, subclass_sz;
subclass_lst_t *sc_list;
@@ -1156,7 +1158,7 @@ remove_all_class(sysevent_channel_descriptor_t *chan, uint32_t sub_id)
static void
remove_class(sysevent_channel_descriptor_t *chan, uint32_t sub_id,
- char *class_name)
+ char *class_name)
{
class_lst_t *c_list;
subclass_lst_t *sc_list;
@@ -1179,7 +1181,7 @@ remove_class(sysevent_channel_descriptor_t *chan, uint32_t sub_id,
static int
insert_class(sysevent_channel_descriptor_t *chan, char *event_class,
- char **event_subclass_lst, int subclass_num, uint32_t sub_id)
+ char **event_subclass_lst, int subclass_num, uint32_t sub_id)
{
class_lst_t *c_list;
@@ -1206,7 +1208,7 @@ insert_class(sysevent_channel_descriptor_t *chan, char *event_class,
static int
add_registration(sysevent_channel_descriptor_t *chan, uint32_t sub_id,
- char *nvlbuf, size_t nvlsize)
+ char *nvlbuf, size_t nvlsize)
{
uint_t num_elem;
char *event_class;
@@ -1247,7 +1249,7 @@ add_registration(sysevent_channel_descriptor_t *chan, uint32_t sub_id,
*/
static int
get_registration(sysevent_channel_descriptor_t *chan, char *databuf,
- uint32_t *bufsz, uint32_t class_index)
+ uint32_t *bufsz, uint32_t class_index)
{
int num_classes = 0;
char *nvlbuf = NULL;
@@ -1733,6 +1735,49 @@ log_sysevent(sysevent_t *ev, int flag, sysevent_id_t *eid)
}
/*
+ * Publish EC_DEV_ADD and EC_DEV_REMOVE events from devfsadm to lofi.
+ * This interface is needed to pass device link names to the lofi driver,
+ * to be returned via ioctl() to the lofiadm command.
+ * The problem is, if lofiadm is executed in local zone, there is no
+ * mechanism to announce the device name from the /dev tree back to lofiadm,
+ * as sysevents are not accessible from local zone and devfsadmd is only
+ * running in global zone.
+ *
+ * Delayed/missed events are not fatal for lofi, as the device name returned
+ * to lofiadm is for information and can be re-queried with listing
+ * mappings with lofiadm command.
+ *
+ * Once we have a better method, this interface should be reworked.
+ */
+static void
+notify_lofi(sysevent_t *ev)
+{
+ static evchan_t *devfs_chan = NULL;
+ nvlist_t *nvlist;
+ int ret;
+
+ if ((strcmp(EC_DEV_ADD, sysevent_get_class_name(ev)) != 0) &&
+ (strcmp(EC_DEV_REMOVE, sysevent_get_class_name(ev)) != 0))
+ return;
+
+ /* only bind once to avoid bind/unbind storm on busy system */
+ if (devfs_chan == NULL) {
+ if ((ret = sysevent_evc_bind("devfsadm_event_channel",
+ &devfs_chan, EVCH_CREAT | EVCH_HOLD_PEND)) != 0) {
+ cmn_err(CE_CONT, "sysevent_evc_bind failed: %d\n", ret);
+ return;
+ }
+ }
+
+ (void) sysevent_get_attr_list(ev, &nvlist);
+ (void) sysevent_evc_publish(devfs_chan, sysevent_get_class_name(ev),
+ sysevent_get_subclass_name(ev), "illumos", EC_DEVFS, nvlist,
+ EVCH_SLEEP);
+
+ nvlist_free(nvlist);
+}
+
+/*
* log_usr_sysevent - user system event logger
* Private to devfsadm and accessible only via
* modctl(MODEVENTS, MODEVENTS_POST_EVENT)
@@ -1758,6 +1803,8 @@ log_usr_sysevent(sysevent_t *ev, int ev_size, sysevent_id_t *eid)
return (EFAULT);
}
+ notify_lofi(ev_copy);
+
if ((ret = queue_sysevent(ev_copy, &new_eid, SE_NOSLEEP)) != 0) {
if (ret == SE_ENOMEM || ret == SE_EQSIZE)
return (EAGAIN);