diff options
Diffstat (limited to 'usr/src')
-rw-r--r-- | usr/src/cmd/devfsadm/devfsadm.c | 116 | ||||
-rw-r--r-- | usr/src/cmd/devfsadm/devfsadm_impl.h | 4 | ||||
-rw-r--r-- | usr/src/uts/common/os/sunddi.c | 50 | ||||
-rw-r--r-- | usr/src/uts/common/sys/sysevent/eventdefs.h | 1 |
4 files changed, 137 insertions, 34 deletions
diff --git a/usr/src/cmd/devfsadm/devfsadm.c b/usr/src/cmd/devfsadm/devfsadm.c index 2cee988b13..4b3885e114 100644 --- a/usr/src/cmd/devfsadm/devfsadm.c +++ b/usr/src/cmd/devfsadm/devfsadm.c @@ -973,7 +973,7 @@ devi_tree_walk(struct dca_impl *dcip, int flags, char *ev_subclass) */ if (ev_subclass) build_and_enq_event(EC_DEV_ADD, ev_subclass, dcip->dci_root, - node); + node, dcip->dci_minor); if ((dcip->dci_flags & DCA_NOTIFY_RCM) && rcm_hdl) (void) notify_rcm(node, dcip->dci_minor); @@ -1567,29 +1567,25 @@ event_handler(sysevent_t *ev) &path)) != 0) goto out; - if (strcmp(subclass, ESC_DEVFS_DEVI_ADD) == 0 || - strcmp(subclass, ESC_DEVFS_DEVI_REMOVE) == 0) { - if (nvlist_lookup_string(attr_list, DEVFS_DEVI_CLASS, - &dev_ev_subclass) != 0) - dev_ev_subclass = NULL; + if (nvlist_lookup_string(attr_list, DEVFS_DEVI_CLASS, + &dev_ev_subclass) != 0) + dev_ev_subclass = NULL; - if (nvlist_lookup_string(attr_list, DEVFS_DRIVER_NAME, - &driver_name) != 0) - driver_name = NULL; + if (nvlist_lookup_string(attr_list, DEVFS_DRIVER_NAME, + &driver_name) != 0) + driver_name = NULL; - if (nvlist_lookup_int32(attr_list, DEVFS_INSTANCE, - &instance) != 0) - instance = -1; + if (nvlist_lookup_int32(attr_list, DEVFS_INSTANCE, + &instance) != 0) + instance = -1; - if (nvlist_lookup_int32(attr_list, DEVFS_BRANCH_EVENT, - &branch_event) != 0) - branch_event = 0; + if (nvlist_lookup_int32(attr_list, DEVFS_BRANCH_EVENT, + &branch_event) != 0) + branch_event = 0; - } else { - if (nvlist_lookup_string(attr_list, DEVFS_MINOR_NAME, - &minor) != 0) - minor = NULL; - } + if (nvlist_lookup_string(attr_list, DEVFS_MINOR_NAME, + &minor) != 0) + minor = NULL; lock_dev(); @@ -1597,21 +1593,24 @@ event_handler(sysevent_t *ev) add_minor_pathname(path, NULL, dev_ev_subclass); if (branch_event) { build_and_enq_event(EC_DEV_BRANCH, - ESC_DEV_BRANCH_ADD, path, DI_NODE_NIL); + ESC_DEV_BRANCH_ADD, path, DI_NODE_NIL, + NULL); } } else if (strcmp(ESC_DEVFS_MINOR_CREATE, subclass) == 0) { - add_minor_pathname(path, minor, NULL); + add_minor_pathname(path, minor, dev_ev_subclass); } else if (strcmp(ESC_DEVFS_MINOR_REMOVE, subclass) == 0) { - hot_cleanup(path, minor, NULL, NULL, -1); + hot_cleanup(path, minor, dev_ev_subclass, driver_name, + instance); } else { /* ESC_DEVFS_DEVI_REMOVE */ hot_cleanup(path, NULL, dev_ev_subclass, driver_name, instance); if (branch_event) { build_and_enq_event(EC_DEV_BRANCH, - ESC_DEV_BRANCH_REMOVE, path, DI_NODE_NIL); + ESC_DEV_BRANCH_REMOVE, path, DI_NODE_NIL, + NULL); } } @@ -1631,7 +1630,7 @@ event_handler(sysevent_t *ev) lock_dev(); build_and_enq_event(EC_DEV_BRANCH, dev_ev_subclass, path, - DI_NODE_NIL); + DI_NODE_NIL, NULL); unlock_dev(CACHE_STATE); } else err_print(UNKNOWN_EVENT, subclass); @@ -4127,7 +4126,7 @@ hot_cleanup(char *node_path, char *minor_name, char *ev_subclass, */ if (ev_subclass != NULL) nvl = build_event_attributes(EC_DEV_REMOVE, ev_subclass, - node_path, DI_NODE_NIL, driver_name, instance); + node_path, DI_NODE_NIL, driver_name, instance, minor_name); (void) strcpy(path, node_path); (void) strcat(path, ":"); @@ -7899,6 +7898,46 @@ lookup_disk_dev_name(char *node_path) } static char * +lookup_lofi_dev_name(char *node_path, char *minor) +{ + struct devlink_cb_arg cb_arg; + char *dev_name = NULL; + int i; + int len1, len2; + + cb_arg.count = 0; + cb_arg.rv = 0; + (void) di_devlink_cache_walk(devlink_cache, NULL, node_path, + DI_PRIMARY_LINK, &cb_arg, devlink_cb); + + if (cb_arg.rv == -1 || cb_arg.count == 0) + return (NULL); + + /* lookup based on a minor name ending with ",raw" */ + len1 = strlen(minor); + for (i = 0; i < cb_arg.count; i++) { + len2 = strlen(cb_arg.link_contents[i]); + if (len2 >= len1 && + strcmp(cb_arg.link_contents[i] + len2 - len1, + minor) == 0) { + dev_name = s_strdup(cb_arg.dev_names[i]); + break; + } + } + + free_dev_names(&cb_arg); + + if (dev_name == NULL) + return (NULL); + if (strlen(dev_name) == 0) { + free(dev_name); + return (NULL); + } + + return (dev_name); +} + +static char * lookup_network_dev_name(char *node_path, char *driver_name) { char *dev_name = NULL; @@ -7960,7 +7999,7 @@ lookup_printer_dev_name(char *node_path) */ static nvlist_t * build_event_attributes(char *class, char *subclass, char *node_path, - di_node_t node, char *driver_name, int instance) + di_node_t node, char *driver_name, int instance, char *minor) { nvlist_t *nvl; int err = 0; @@ -8005,6 +8044,23 @@ build_event_attributes(char *class, char *subclass, char *node_path, dev_name_lookup_err = 1; goto out; } + } else if (strcmp(subclass, ESC_LOFI) == 0) { + /* + * The raw minor node is created or removed after the block + * node. Lofi devfs events are dependent on this behavior. + * Generate the sysevent only for the raw minor node. + */ + if (strstr(minor, "raw") == NULL) { + if (nvl) { + nvlist_free(nvl); + } + return (NULL); + } + if ((dev_name = lookup_lofi_dev_name(node_path, minor)) == + NULL) { + dev_name_lookup_err = 1; + goto out; + } } if (dev_name) { @@ -8124,7 +8180,7 @@ process_syseventq() static void build_and_enq_event(char *class, char *subclass, char *node_path, - di_node_t node) + di_node_t node, char *minor) { nvlist_t *nvl; @@ -8133,10 +8189,10 @@ build_and_enq_event(char *class, char *subclass, char *node_path, if (node != DI_NODE_NIL) nvl = build_event_attributes(class, subclass, node_path, node, - di_driver_name(node), di_instance(node)); + di_driver_name(node), di_instance(node), minor); else nvl = build_event_attributes(class, subclass, node_path, node, - NULL, -1); + NULL, -1, minor); if (nvl) { enqueue_sysevent(class, subclass, nvl); diff --git a/usr/src/cmd/devfsadm/devfsadm_impl.h b/usr/src/cmd/devfsadm/devfsadm_impl.h index 20cf90891c..9c38bea1e7 100644 --- a/usr/src/cmd/devfsadm/devfsadm_impl.h +++ b/usr/src/cmd/devfsadm/devfsadm_impl.h @@ -499,9 +499,9 @@ static void (*librcm_free_handle)(rcm_handle_t *); static int (*librcm_notify_event)(rcm_handle_t *, char *, uint_t, nvlist_t *, rcm_info_t *); static nvlist_t *build_event_attributes(char *, char *, char *, - di_node_t, char *, int); + di_node_t, char *, int, char *); static void log_event(char *, char *, nvlist_t *); -static void build_and_enq_event(char *, char *, char *, di_node_t); +static void build_and_enq_event(char *, char *, char *, di_node_t, char *); static void read_logindevperm_file(void); static void set_logindev_perms(char *devlink); diff --git a/usr/src/uts/common/os/sunddi.c b/usr/src/uts/common/os/sunddi.c index e9fd930d22..7aa059f072 100644 --- a/usr/src/uts/common/os/sunddi.c +++ b/usr/src/uts/common/os/sunddi.c @@ -5514,7 +5514,7 @@ i_log_devfs_minor_create(dev_info_t *dip, char *minor_name) int se_flag; int kmem_flag; int se_err; - char *pathname; + char *pathname, *class_name; sysevent_t *ev = NULL; sysevent_id_t eid; sysevent_value_t se_val; @@ -5557,6 +5557,17 @@ i_log_devfs_minor_create(dev_info_t *dip, char *minor_name) } kmem_free(pathname, MAXPATHLEN); + /* add the device class attribute */ + if ((class_name = i_ddi_devi_class(dip)) != NULL) { + se_val.value_type = SE_DATA_TYPE_STRING; + se_val.value.sv_string = class_name; + if (sysevent_add_attr(&ev_attr_list, + DEVFS_DEVI_CLASS, &se_val, SE_SLEEP) != 0) { + sysevent_free_attr(ev_attr_list); + goto fail; + } + } + /* * allow for NULL minor names */ @@ -5604,7 +5615,7 @@ fail: static int i_log_devfs_minor_remove(dev_info_t *dip, char *minor_name) { - char *pathname; + char *pathname, *class_name; sysevent_t *ev; sysevent_id_t eid; sysevent_value_t se_val; @@ -5658,6 +5669,35 @@ i_log_devfs_minor_remove(dev_info_t *dip, char *minor_name) } } + if ((class_name = i_ddi_devi_class(dip)) != NULL) { + /* add the device class, driver name and instance attributes */ + + se_val.value_type = SE_DATA_TYPE_STRING; + se_val.value.sv_string = class_name; + if (sysevent_add_attr(&ev_attr_list, + DEVFS_DEVI_CLASS, &se_val, SE_SLEEP) != 0) { + sysevent_free_attr(ev_attr_list); + goto fail; + } + + se_val.value_type = SE_DATA_TYPE_STRING; + se_val.value.sv_string = (char *)ddi_driver_name(dip); + if (sysevent_add_attr(&ev_attr_list, + DEVFS_DRIVER_NAME, &se_val, SE_SLEEP) != 0) { + sysevent_free_attr(ev_attr_list); + goto fail; + } + + se_val.value_type = SE_DATA_TYPE_INT32; + se_val.value.sv_int32 = ddi_get_instance(dip); + if (sysevent_add_attr(&ev_attr_list, + DEVFS_INSTANCE, &se_val, SE_SLEEP) != 0) { + sysevent_free_attr(ev_attr_list); + goto fail; + } + + } + if (sysevent_attach_attributes(ev, ev_attr_list) != 0) { sysevent_free_attr(ev_attr_list); } else { @@ -5700,6 +5740,12 @@ derive_devi_class(dev_info_t *dip, char *node_type, int flag) node_type[sizeof (DDI_NT_PRINTER) - 1] == ':')) { rv = i_ddi_set_devi_class(dip, ESC_PRINTER, flag); + + } else if (strncmp(node_type, DDI_PSEUDO, + sizeof (DDI_PSEUDO) -1) == 0 && + (strncmp(ESC_LOFI, ddi_node_name(dip), + sizeof (ESC_LOFI) -1) == 0)) { + rv = i_ddi_set_devi_class(dip, ESC_LOFI, flag); } } diff --git a/usr/src/uts/common/sys/sysevent/eventdefs.h b/usr/src/uts/common/sys/sysevent/eventdefs.h index a1a81faf35..7e8eff763f 100644 --- a/usr/src/uts/common/sys/sysevent/eventdefs.h +++ b/usr/src/uts/common/sys/sysevent/eventdefs.h @@ -185,6 +185,7 @@ extern "C" { #define ESC_DISK "disk" /* disk device */ #define ESC_NETWORK "network" /* network interface */ #define ESC_PRINTER "printer" /* printer device */ +#define ESC_LOFI "lofi" /* lofi device */ /* * EC_DEV_BRANCH subclass definitions - supporting attributes (name/value pairs) |