diff options
Diffstat (limited to 'usr/src/uts/common/os/log_sysevent.c')
-rw-r--r-- | usr/src/uts/common/os/log_sysevent.c | 59 |
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); |