diff options
author | Cathy Zhou <Cathy.Zhou@Sun.COM> | 2008-08-13 14:57:47 -0700 |
---|---|---|
committer | Cathy Zhou <Cathy.Zhou@Sun.COM> | 2008-08-13 14:57:47 -0700 |
commit | 0dc974a9a2e66d676505db23524ebff105fb36a9 (patch) | |
tree | 05b6f06b156223b4807e2bc8e71bc3001ac98c93 /usr/src/cmd/devfsadm/devfsadm.c | |
parent | 8c8a8d17e0c6c68e047f0e531c3f8ce133b9aea6 (diff) | |
download | illumos-joyent-0dc974a9a2e66d676505db23524ebff105fb36a9.tar.gz |
PSARC 2008/498 datalink sysevents
6696737 ndi_devi_enter() can deadlock with stopped threads, hanging system
6729044 race between network_rcm and softmac when a physical device is attached
6729144 dlmgmtd process_db_write() leaks dlmgmt_link_t
Diffstat (limited to 'usr/src/cmd/devfsadm/devfsadm.c')
-rw-r--r-- | usr/src/cmd/devfsadm/devfsadm.c | 322 |
1 files changed, 4 insertions, 318 deletions
diff --git a/usr/src/cmd/devfsadm/devfsadm.c b/usr/src/cmd/devfsadm/devfsadm.c index d897db16c6..4fcd9e2e3d 100644 --- a/usr/src/cmd/devfsadm/devfsadm.c +++ b/usr/src/cmd/devfsadm/devfsadm.c @@ -24,8 +24,6 @@ * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" - /* * Devfsadm replaces drvconfig, audlinks, disks, tapes, ports, devlinks * as a general purpose device administrative utility. It creates @@ -229,16 +227,6 @@ static mutex_t nfp_mutex = DEFAULTMUTEX; static char *packaged_dirs[] = {"dsk", "rdsk", "term", NULL}; -/* RCM related globals */ -static void *librcm_hdl; -static rcm_handle_t *rcm_hdl = NULL; -static thread_t process_rcm_events_tid; -static struct rcm_eventq *volatile rcm_eventq_head = NULL; -static struct rcm_eventq *rcm_eventq_tail = NULL; -static mutex_t rcm_eventq_lock; -static cond_t rcm_eventq_cv; -static volatile int need_to_exit_rcm_event_thread = 0; - /* Devname globals */ static int devname_debug_msg = 1; static nvlist_t *devname_maps = NULL; @@ -416,16 +404,11 @@ main(int argc, char *argv[]) /* - * No need for rcm notifications when running - * with an alternate root. So initialize rcm only - * when devfsadm is running with root dir "/". - * Similarly, logindevperms need only be set + * logindevperms need only be set * in daemon mode and when root dir is "/". */ - if (root_dir[0] == '\0') { - (void) rcm_init(); + if (root_dir[0] == '\0') login_dev_enable = TRUE; - } daemon_update(); devfsadm_exit(0); /*NOTREACHED*/ @@ -1034,15 +1017,12 @@ devi_tree_walk(struct dca_impl *dcip, int flags, char *ev_subclass) /* * Finished creating devfs files and dev links. - * Log sysevent and notify RCM. + * Log sysevent. */ if (ev_subclass) build_and_enq_event(EC_DEV_ADD, ev_subclass, dcip->dci_root, node, dcip->dci_minor); - if ((dcip->dci_flags & DCA_NOTIFY_RCM) && rcm_hdl) - (void) notify_rcm(node, dcip->dci_minor); - /* Add new device to device allocation database */ if (system_labeled && update_devdb) { _update_devalloc_db(&devlist, 0, DA_ADD, NULL, root_dir); @@ -1769,9 +1749,7 @@ add_minor_pathname(char *node, char *minor, char *ev_subclass) } /* - * We are being invoked in response to a hotplug - * event. Also, notify RCM if nodetype indicates - * a network device has been hotplugged. + * We are being invoked in response to a hotplug event. */ dci.dci_flags = DCA_HOT_PLUG | DCA_CHECK_TYPE; @@ -1835,7 +1813,6 @@ check_minor_type(di_node_t node, di_minor_t minor, void *arg) if ((dcip->dci_flags & DCA_CHECK_TYPE) && (nt = di_minor_nodetype(minor)) && (strcmp(nt, DDI_NT_NET) == 0)) { - dcip->dci_flags |= DCA_NOTIFY_RCM; dcip->dci_flags &= ~DCA_CHECK_TYPE; } @@ -7010,20 +6987,6 @@ devfsadm_exit(int status) vprint(INFO_MID, "exit status = %d\n", status); } - if (rcm_hdl) { - if (thr_self() != process_rcm_events_tid) { - (void) mutex_lock(&rcm_eventq_lock); - need_to_exit_rcm_event_thread = 1; - (void) cond_broadcast(&rcm_eventq_cv); - (void) mutex_unlock(&rcm_eventq_lock); - - /* wait until process_rcm_events() thread exits */ - (void) thr_join(process_rcm_events_tid, NULL, NULL); - } - librcm_free_handle(rcm_hdl); - (void) dlclose(librcm_hdl); - } - exit_dev_lock(1); exit_daemon_lock(1); @@ -7787,283 +7750,6 @@ is_minor_node(char *contents, char **mn_root) } /* - * Lookup nvpair corresponding to the given name and type: - * - * The standard nvlist_lookup functions in libnvpair don't work as our - * nvlist is not allocated with NV_UNIQUE_NAME or NV_UNIQUE_NAME_TYPE. - */ -static nvpair_t * -lookup_nvpair(nvlist_t *nvl, char *name, data_type_t type) -{ - nvpair_t *nvp; - - for (nvp = nvlist_next_nvpair(nvl, NULL); nvp != NULL; - nvp = nvlist_next_nvpair(nvl, nvp)) { - if (strcmp(name, nvpair_name(nvp)) == 0 && - nvpair_type(nvp) == type) - return (nvp); - } - - return (NULL); -} - -/*ARGSUSED*/ -static void -process_rcm_events(void *arg) -{ - struct rcm_eventq *ev, *ev_next; - nvpair_t *nvp; - char *path, *driver; - int instance; - int err; - int need_to_exit; - - for (;;) { - (void) mutex_lock(&rcm_eventq_lock); - while (rcm_eventq_head == NULL && - need_to_exit_rcm_event_thread == 0) - (void) cond_wait(&rcm_eventq_cv, &rcm_eventq_lock); - - need_to_exit = need_to_exit_rcm_event_thread; - ev = rcm_eventq_head; - rcm_eventq_head = rcm_eventq_tail = NULL; - (void) mutex_unlock(&rcm_eventq_lock); - - for (; ev != NULL; ev = ev_next) { - /* - * Private notification interface to RCM: - * Do not retry the RCM notification on an error since - * we do not know whether the failure occurred in - * librcm, rcm_daemon or rcm modules or scripts. - */ - if (librcm_notify_event(rcm_hdl, - RCM_RESOURCE_NETWORK_NEW, 0, ev->nvl, NULL) - != RCM_SUCCESS) { - - err = errno; - - if (((nvp = lookup_nvpair(ev->nvl, - RCM_NV_DEVFS_PATH, DATA_TYPE_STRING)) - == NULL) || - (nvpair_value_string(nvp, &path) != 0)) - path = "unknown"; - - if (((nvp = lookup_nvpair(ev->nvl, - RCM_NV_DRIVER_NAME, DATA_TYPE_STRING)) - == NULL) || - (nvpair_value_string(nvp, &driver) != 0)) - driver = "unknown"; - if (((nvp = lookup_nvpair(ev->nvl, - RCM_NV_INSTANCE, DATA_TYPE_INT32)) - == NULL) || - (nvpair_value_int32(nvp, &instance) != 0)) - instance = -1; - - err_print(RCM_NOTIFY_FAILED, path, driver, - instance, strerror(err)); - } - - ev_next = ev->next; - nvlist_free(ev->nvl); - free(ev); - } - - if (need_to_exit) - return; - } -} - -/* - * Initialize rcm related handles and function pointers. - * Since RCM need not present in miniroot, we dlopen librcm. - */ -static int -rcm_init(void) -{ -#define LIBRCM_PATH "/lib/librcm.so" - rcm_handle_t *hdl = NULL; - int err; - - if ((librcm_hdl = dlopen(LIBRCM_PATH, RTLD_LAZY)) == NULL) { - /* - * don't log an error here, since librcm may not be present - * in miniroot. - */ - return (-1); - } - - librcm_alloc_handle = (int (*)())dlsym(librcm_hdl, "rcm_alloc_handle"); - librcm_free_handle = (void (*)())dlsym(librcm_hdl, "rcm_free_handle"); - librcm_notify_event = (int (*)())dlsym(librcm_hdl, "rcm_notify_event"); - - if (librcm_alloc_handle == NULL || librcm_notify_event == NULL || - librcm_free_handle == NULL) { - err_print(MISSING_SYMBOLS, LIBRCM_PATH); - goto out; - } - - /* Initialize the rcm handle */ - if (librcm_alloc_handle(NULL, 0, NULL, &hdl) != RCM_SUCCESS) { - err_print(RCM_ALLOC_HANDLE_ERROR); - goto out; - } - - (void) cond_init(&rcm_eventq_cv, USYNC_THREAD, 0); - (void) mutex_init(&rcm_eventq_lock, USYNC_THREAD, 0); - - /* create a thread to notify RCM of events */ - if ((err = thr_create(NULL, 0, (void *(*)(void *))process_rcm_events, - NULL, 0, &process_rcm_events_tid)) != 0) { - err_print(CANT_CREATE_THREAD, "process_rcm_events", - strerror(err)); - goto out; - } - - rcm_hdl = hdl; - return (0); - -out: - if (hdl) - librcm_free_handle(hdl); - (void) dlclose(librcm_hdl); - return (-1); -} - -/* - * Build an nvlist using the minor data. Pack it and add the packed nvlist - * as a byte array to nv_list parameter. - * Return 0 on success, errno on failure. - */ -static int -add_minor_data_to_nvl(nvlist_t *nv_list, di_minor_t minor) -{ - nvlist_t *nvl = NULL; - int32_t minor_type; - char *minor_name, *minor_node_type; - int err; - char *buf = NULL; - size_t buflen = 0; - - if ((err = nvlist_alloc(&nvl, 0, 0)) != 0) - return (err); - - minor_type = (int32_t)di_minor_type(minor); - if ((err = nvlist_add_int32(nvl, RCM_NV_MINOR_TYPE, minor_type)) != 0) - goto error; - - minor_name = di_minor_name(minor); - if ((err = nvlist_add_string(nvl, RCM_NV_MINOR_NAME, minor_name)) != 0) - goto error; - - if ((minor_node_type = di_minor_nodetype(minor)) == NULL) - minor_node_type = ""; - if ((err = nvlist_add_string(nvl, RCM_NV_MINOR_NODE_TYPE, - minor_node_type)) != 0) - goto error; - - if ((err = nvlist_pack(nvl, &buf, &buflen, NV_ENCODE_NATIVE, 0)) != 0) - goto error; - - err = nvlist_add_byte_array(nv_list, RCM_NV_MINOR_DATA, - (uchar_t *)(buf), (uint_t)(buflen)); - -error: - nvlist_free(nvl); - if (buf) - free(buf); - return (err); -} - -static void -enqueue_rcm_event(nvlist_t *nvl) -{ - struct rcm_eventq *ev; - - ev = (struct rcm_eventq *)s_zalloc(sizeof (struct rcm_eventq)); - ev->nvl = nvl; - - (void) mutex_lock(&rcm_eventq_lock); - if (rcm_eventq_head == NULL) - rcm_eventq_head = ev; - else - rcm_eventq_tail->next = ev; - rcm_eventq_tail = ev; - (void) cond_broadcast(&rcm_eventq_cv); - (void) mutex_unlock(&rcm_eventq_lock); -} - -/* - * Generate an nvlist using the information given in node and minor_name. - * If minor_name is NULL the nvlist will contain information on - * all minor nodes. Otherwise the nvlist will contain information - * only on the given minor_name. Notify RCM passing the nvlist. - * - * Return 0 upon successfully notifying RCM, errno on failure. - */ -static int -notify_rcm(di_node_t node, char *minor_name) -{ - nvlist_t *nvl = NULL; - char *path, *driver_name; - char *node_name; - int err; - int32_t instance; - di_minor_t minor; - - if ((driver_name = di_driver_name(node)) == NULL) - driver_name = ""; - - instance = (int32_t)di_instance(node); - - if ((path = di_devfs_path(node)) == NULL) { - err = errno; - goto error; - } - - if ((err = nvlist_alloc(&nvl, 0, 0)) != 0) - goto error; - - if ((err = nvlist_add_string(nvl, RCM_NV_DRIVER_NAME, driver_name)) - != 0) - goto error; - - if ((err = nvlist_add_int32(nvl, RCM_NV_INSTANCE, instance)) != 0) - goto error; - - if ((node_name = di_node_name(node)) == NULL) - node_name = ""; - if ((err = nvlist_add_string(nvl, RCM_NV_NODE_NAME, node_name)) != 0) - goto error; - - if ((err = nvlist_add_string(nvl, RCM_NV_DEVFS_PATH, path)) != 0) - goto error; - - minor = di_minor_next(node, DI_MINOR_NIL); - while (minor != DI_MINOR_NIL) { - if ((minor_name == NULL) || - (strcmp(minor_name, di_minor_name(minor)) == 0)) { - if ((err = add_minor_data_to_nvl(nvl, minor)) != 0) - goto error; - } - minor = di_minor_next(node, minor); - } - - enqueue_rcm_event(nvl); - di_devfs_path_free(path); - return (0); - -error: - err_print(RCM_NVLIST_BUILD_ERROR, ((path != NULL) ? path : "unknown"), - driver_name, instance, strerror(err)); - - if (path) - di_devfs_path_free(path); - if (nvl) - nvlist_free(nvl); - return (err); -} - -/* * Add the specified property to nvl. * Returns: * 0 successfully added |