diff options
Diffstat (limited to 'usr/src/cmd/devfsadm/devfsadm.c')
-rw-r--r-- | usr/src/cmd/devfsadm/devfsadm.c | 116 |
1 files changed, 86 insertions, 30 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); |