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 | |
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
-rw-r--r-- | usr/src/cmd/devfsadm/devfsadm.c | 322 | ||||
-rw-r--r-- | usr/src/cmd/devfsadm/devfsadm_impl.h | 15 | ||||
-rw-r--r-- | usr/src/cmd/devfsadm/message.h | 16 | ||||
-rw-r--r-- | usr/src/cmd/dlmgmtd/Makefile | 4 | ||||
-rw-r--r-- | usr/src/cmd/dlmgmtd/dlmgmt_db.c | 7 | ||||
-rw-r--r-- | usr/src/cmd/dlmgmtd/dlmgmt_door.c | 47 | ||||
-rw-r--r-- | usr/src/cmd/dlmgmtd/dlmgmt_main.c | 7 | ||||
-rw-r--r-- | usr/src/cmd/rcm_daemon/common/network_rcm.c | 293 | ||||
-rw-r--r-- | usr/src/cmd/syseventd/modules/Makefile | 5 | ||||
-rw-r--r-- | usr/src/cmd/syseventd/modules/datalink_mod/Makefile | 41 | ||||
-rw-r--r-- | usr/src/cmd/syseventd/modules/datalink_mod/datalink_mod.c | 89 | ||||
-rw-r--r-- | usr/src/lib/libdevinfo/device_info.h | 6 | ||||
-rw-r--r-- | usr/src/lib/librcm/librcm.h | 12 | ||||
-rw-r--r-- | usr/src/pkgdefs/SUNWcsu/prototype_com | 3 | ||||
-rw-r--r-- | usr/src/uts/common/io/softmac/softmac_main.c | 149 | ||||
-rw-r--r-- | usr/src/uts/common/sys/sysevent/eventdefs.h | 8 |
16 files changed, 284 insertions, 740 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 diff --git a/usr/src/cmd/devfsadm/devfsadm_impl.h b/usr/src/cmd/devfsadm/devfsadm_impl.h index 40d05e414b..4f27eb1b3a 100644 --- a/usr/src/cmd/devfsadm/devfsadm_impl.h +++ b/usr/src/cmd/devfsadm/devfsadm_impl.h @@ -25,8 +25,6 @@ #ifndef _DEVFSADM_IMPL_H #define _DEVFSADM_IMPL_H -#pragma ident "%Z%%M% %I% %E% SMI" - #ifdef __cplusplus extern "C" { #endif @@ -70,7 +68,6 @@ extern "C" { #include <thread.h> #include <message.h> #include <sys/cladm.h> -#include <librcm.h> #include <sys/sysevent/dev.h> #include <libzonecfg.h> #include <device_info.h> @@ -352,12 +349,6 @@ struct dca_impl { int dci_flags; }; -/* RCM related */ -struct rcm_eventq { - nvlist_t *nvl; - struct rcm_eventq *next; -}; - /* sysevent queue related */ typedef struct syseventq_s { struct syseventq_s *next; @@ -478,8 +469,6 @@ static void sync_handler(void *cookie, char *ap, size_t asize, static int zone_pathcheck(char *checkpath); static void process_deferred_links(struct dca_impl *dcip, int flag); static void event_handler(sysevent_t *ev); -static int rcm_init(void); -static int notify_rcm(di_node_t node, char *minor_name); static void dca_impl_init(char *root, char *minor, struct dca_impl *dcip); static void lock_dev(void); static void unlock_dev(int flag); @@ -490,10 +479,6 @@ int load_devpolicy(void); static void load_dev_acl(void); static void load_minor_perm_file(void); -static int (*librcm_alloc_handle)(char *, uint_t, void *, rcm_handle_t **); -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, char *); static void log_event(char *, char *, nvlist_t *); diff --git a/usr/src/cmd/devfsadm/message.h b/usr/src/cmd/devfsadm/message.h index 60f790293d..d3edbb6dd3 100644 --- a/usr/src/cmd/devfsadm/message.h +++ b/usr/src/cmd/devfsadm/message.h @@ -19,15 +19,13 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #ifndef _MESSAGE_H #define _MESSAGE_H -#pragma ident "%Z%%M% %I% %E% SMI" - #ifdef __cplusplus extern "C" { #endif @@ -218,18 +216,6 @@ major_number ]\n\t\t[ -n ]\n\t\t[ -r rootdir ]\n\t\t[ -v ]\n") #define INVOKED_WITH gettext("invoked with %s\n") -#define MISSING_SYMBOLS gettext("missing symbols in %s\n") - -#define RCM_ALLOC_HANDLE_ERROR gettext("Unable to allocate rcm handle\n") - -#define RCM_NOTIFY_FAILED \ - gettext("RCM notification failed: " \ - "path = %s, driver = %s, instance = %d: %s\n") - -#define RCM_NVLIST_BUILD_ERROR \ - gettext("failed to build nvlist for notifying RCM: " \ - "path = %s, driver = %s, instance = %d: %s\n") - #define INVALID_DEVLINK_SPEC gettext("Invalid devlink spec: '%s'\n") #define DRV_LOAD_REQD gettext("-n option cannot be used with -i. Ignoring\n") diff --git a/usr/src/cmd/dlmgmtd/Makefile b/usr/src/cmd/dlmgmtd/Makefile index 2e117d884e..baef35c3f8 100644 --- a/usr/src/cmd/dlmgmtd/Makefile +++ b/usr/src/cmd/dlmgmtd/Makefile @@ -22,8 +22,6 @@ # Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # -# ident "%Z%%M% %I% %E% SMI" -# PROG= dlmgmtd OBJS= dlmgmt_main.o dlmgmt_door.o dlmgmt_util.o dlmgmt_db.o @@ -42,7 +40,7 @@ $(ROOTCFGFILES) := OWNER= dladm $(ROOTCFGFILES) := GROUP= sys $(ROOTCFGDIR)/datalink.conf := FILEMODE= 644 -LDLIBS += -ldladm -ldlpi -lavl +LDLIBS += -ldladm -ldlpi -lavl -lnvpair -lsysevent .KEEP_STATE: diff --git a/usr/src/cmd/dlmgmtd/dlmgmt_db.c b/usr/src/cmd/dlmgmtd/dlmgmt_db.c index 013deaf388..e65722613b 100644 --- a/usr/src/cmd/dlmgmtd/dlmgmt_db.c +++ b/usr/src/cmd/dlmgmtd/dlmgmt_db.c @@ -24,8 +24,6 @@ * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" - #include <assert.h> #include <ctype.h> #include <errno.h> @@ -648,10 +646,13 @@ process_db_write(dlmgmt_db_req_t *req, FILE *fp, FILE *nfp) process_link_line(buf, &link_in_file)) { if (link_in_file == NULL || done) { /* - * this is a comment line, write it out. + * this is a comment line or we are done updating the + * link of the given link, write the rest of lines out. */ if (fputs(buf, nfp) == EOF) err = errno; + if (link_in_file != NULL) + link_destroy(link_in_file); continue; } diff --git a/usr/src/cmd/dlmgmtd/dlmgmt_door.c b/usr/src/cmd/dlmgmtd/dlmgmt_door.c index 50892004a9..8e1a1d9cd3 100644 --- a/usr/src/cmd/dlmgmtd/dlmgmt_door.c +++ b/usr/src/cmd/dlmgmtd/dlmgmt_door.c @@ -24,8 +24,6 @@ * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" - /* * Main door handler functions used by dlmgmtd to process the different door * call requests. Door call requests can come from the user-land applications, @@ -38,7 +36,11 @@ #include <priv_utils.h> #include <stdlib.h> #include <strings.h> +#include <syslog.h> +#include <sys/sysevent/eventdefs.h> +#include <libsysevent.h> #include <libdlmgmt.h> +#include <librcm.h> #include "dlmgmt_impl.h" typedef void dlmgmt_door_handler_t(void *, void *); @@ -67,6 +69,35 @@ dlmgmt_getlink_by_dev(char *devname) return (NULL); } +/* + * Post the EC_DATALINK sysevent for the given linkid. This sysevent will + * be consumed by the datalink sysevent module. + */ +static void +dlmgmt_post_sysevent(const char *subclass, datalink_id_t linkid) +{ + nvlist_t *nvl = NULL; + sysevent_id_t eid; + int err; + + if (((err = nvlist_alloc(&nvl, NV_UNIQUE_NAME_TYPE, 0)) != 0) || + ((err = nvlist_add_uint64(nvl, RCM_NV_LINKID, linkid)) != 0)) { + goto done; + } + + if (sysevent_post_event(EC_DATALINK, (char *)subclass, SUNW_VENDOR, + (char *)progname, nvl, &eid) == -1) { + err = errno; + } + +done: + if (err != 0) { + dlmgmt_log(LOG_WARNING, "dlmgmt_post_sysevent(%d) failed: %s", + linkid, strerror(err)); + } + nvlist_free(nvl); +} + static void dlmgmt_upcall_create(void *argp, void *retp) { @@ -165,8 +196,18 @@ done: if (err == 0) retvalp->lr_linkid = linkp->ll_linkid; - retvalp->lr_err = err; dlmgmt_table_unlock(); + + if (err == 0) { + /* + * Post the ESC_DATALINK_PHYS_ADD sysevent. This sysevent + * is consumed by the datalink sysevent module which in + * turn generates the RCM_RESOURCE_LINK_NEW RCM event. + */ + dlmgmt_post_sysevent(ESC_DATALINK_PHYS_ADD, retvalp->lr_linkid); + } + + retvalp->lr_err = err; } static void diff --git a/usr/src/cmd/dlmgmtd/dlmgmt_main.c b/usr/src/cmd/dlmgmtd/dlmgmt_main.c index 43e627d4f0..15472f670d 100644 --- a/usr/src/cmd/dlmgmtd/dlmgmt_main.c +++ b/usr/src/cmd/dlmgmtd/dlmgmt_main.c @@ -24,8 +24,6 @@ * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" - /* * The dlmgmtd daemon is started by the datalink-management SMF service. * This daemon is used to manage <link name, linkid> mapping and the @@ -251,8 +249,11 @@ dlmgmt_init_privileges() if ((dld_control_fd = open(DLD_CONTROL_DEV, O_RDWR)) < 0) return (errno); + /* + * The PRIV_SYS_CONFIG privilege is needed to post sysevents. + */ if (__init_daemon_priv(PU_RESETGROUPS|PU_CLEARLIMITSET, UID_DLADM, - GID_SYS, PRIV_SYS_NET_CONFIG, NULL) == -1) { + GID_SYS, PRIV_SYS_NET_CONFIG, PRIV_SYS_CONFIG, NULL) == -1) { (void) close(dld_control_fd); dld_control_fd = -1; return (EPERM); diff --git a/usr/src/cmd/rcm_daemon/common/network_rcm.c b/usr/src/cmd/rcm_daemon/common/network_rcm.c index 406eb4ff03..b3199ed936 100644 --- a/usr/src/cmd/rcm_daemon/common/network_rcm.c +++ b/usr/src/cmd/rcm_daemon/common/network_rcm.c @@ -23,8 +23,6 @@ * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" - /* * This RCM module adds support to the RCM framework for an abstract * namespace for network devices (DLPI providers). @@ -56,20 +54,6 @@ #define CACHE_STALE 1 /* flags */ #define CACHE_NEW 2 /* flags */ -/* devfsadm attach nvpair values */ -#define PROP_NV_DDI_NETWORK "ddi_network" - -/* - * Global NIC list to be configured after DR-attach - */ -struct ni_list { - struct ni_list *next; - char dev[MAXNAMELEN]; /* device instance name (le0, ie0, etc.) */ -}; - -static struct ni_list *nil_head = NULL; /* Global new if list */ -static mutex_t nil_lock; /* NIC list lock */ - /* operations */ #define NET_OFFLINE 1 #define NET_ONLINE 2 @@ -91,12 +75,6 @@ static net_cache_t cache_tail; static mutex_t cache_lock; static int events_registered = 0; -struct devfs_minor_data { - int32_t minor_type; - char *minor_name; - char *minor_node_type; -}; - /* module interface routines */ static int net_register(rcm_handle_t *); static int net_unregister(rcm_handle_t *); @@ -123,9 +101,6 @@ static void cache_remove(net_cache_t *node); static net_cache_t *cache_lookup(const char *resource); static void free_node(net_cache_t *); static void cache_insert(net_cache_t *); -static int notify_new_link(rcm_handle_t *, const char *); -static void process_minor(char *, int, struct devfs_minor_data *); -static int process_nvlist(rcm_handle_t *, nvlist_t *); /* * Module-Private data @@ -210,15 +185,15 @@ net_register(rcm_handle_t *hd) * getting attached, so we get attach event notifications */ if (!events_registered) { - if (rcm_register_event(hd, RCM_RESOURCE_NETWORK_NEW, 0, NULL) + if (rcm_register_event(hd, RCM_RESOURCE_LINK_NEW, 0, NULL) != RCM_SUCCESS) { rcm_log_message(RCM_ERROR, _("NET: failed to register %s\n"), - RCM_RESOURCE_NETWORK_NEW); + RCM_RESOURCE_LINK_NEW); return (RCM_FAILURE); } else { rcm_log_message(RCM_DEBUG, _("NET: registered %s\n"), - RCM_RESOURCE_NETWORK_NEW); + RCM_RESOURCE_LINK_NEW); events_registered++; } } @@ -256,15 +231,15 @@ net_unregister(rcm_handle_t *hd) * Need to unregister interest in all new resources */ if (events_registered) { - if (rcm_unregister_event(hd, RCM_RESOURCE_NETWORK_NEW, 0) + if (rcm_unregister_event(hd, RCM_RESOURCE_LINK_NEW, 0) != RCM_SUCCESS) { rcm_log_message(RCM_ERROR, _("NET: failed to unregister %s\n"), - RCM_RESOURCE_NETWORK_NEW); + RCM_RESOURCE_LINK_NEW); return (RCM_FAILURE); } else { rcm_log_message(RCM_DEBUG, _("NET: unregistered %s\n"), - RCM_RESOURCE_NETWORK_NEW); + RCM_RESOURCE_LINK_NEW); events_registered--; } } @@ -821,22 +796,16 @@ free_cache(void) * net_notify_event - Project private implementation to receive new * resource events. It intercepts all new resource * events. If the new resource is a network resource, - * pass up a event for the resource. The new resource - * need not be cached, since it is done at register again. + * update the physical link cache. */ /*ARGSUSED*/ static int net_notify_event(rcm_handle_t *hd, char *rsrc, id_t id, uint_t flags, char **errorp, nvlist_t *nvl, rcm_info_t **depend_info) { - assert(hd != NULL); - assert(rsrc != NULL); - assert(id == (id_t)0); - assert(nvl != NULL); - rcm_log_message(RCM_TRACE1, _("NET: notify_event(%s)\n"), rsrc); - if (strcmp(rsrc, RCM_RESOURCE_NETWORK_NEW) != 0) { + if (strcmp(rsrc, RCM_RESOURCE_LINK_NEW) != 0) { rcm_log_message(RCM_INFO, _("NET: unrecognized event for %s\n"), rsrc); errno = EINVAL; @@ -846,254 +815,8 @@ net_notify_event(rcm_handle_t *hd, char *rsrc, id_t id, uint_t flags, /* Update cache to reflect latest physical links */ update_cache(hd); - /* Process the nvlist for the event */ - if (process_nvlist(hd, nvl) != 0) { - rcm_log_message(RCM_WARNING, - _("NET: Error processing resource attributes(%s)\n"), rsrc); - rcm_log_message(RCM_WARNING, - _("NET: One or more devices may not be configured.\n")); - } - rcm_log_message(RCM_TRACE1, _("NET: notify_event: device configuration complete\n")); return (RCM_SUCCESS); } - -/* - * process_nvlist() - Determine network interfaces on a new attach by - * processing the nvlist - */ -static int -process_nvlist(rcm_handle_t *hd, nvlist_t *nvl) -{ - nvpair_t *nvp = NULL; - char *driver; - char *devfspath; - int32_t instance; - char *minor_byte_array; /* packed nvlist of minor_data */ - uint_t nminor; /* # of minor nodes */ - struct devfs_minor_data *mdata; - nvlist_t *mnvl; - nvpair_t *mnvp = NULL; - struct ni_list *nilp, *next; - - rcm_log_message(RCM_TRACE1, "NET: process_nvlist\n"); - - while ((nvp = nvlist_next_nvpair(nvl, nvp)) != NULL) { - /* Get driver name */ - if (strcmp(nvpair_name(nvp), RCM_NV_DRIVER_NAME) == 0) { - if (nvpair_value_string(nvp, &driver) != 0) { - rcm_log_message(RCM_WARNING, - _("NET: cannot get driver name\n")); - return (-1); - } - } - /* Get instance */ - if (strcmp(nvpair_name(nvp), RCM_NV_INSTANCE) == 0) { - if (nvpair_value_int32(nvp, &instance) != 0) { - rcm_log_message(RCM_WARNING, - _("NET: cannot get device instance\n")); - return (-1); - } - } - /* Get devfspath */ - if (strcmp(nvpair_name(nvp), RCM_NV_DEVFS_PATH) == 0) { - if (nvpair_value_string(nvp, &devfspath) != 0) { - rcm_log_message(RCM_WARNING, - _("NET: cannot get device path\n")); - return (-1); - } - if (strncmp("/pseudo", devfspath, - strlen("/pseudo")) == 0) { - /* Ignore pseudo devices, not really NICs */ - rcm_log_message(RCM_DEBUG, - _("NET: ignoring pseudo device %s\n"), - devfspath); - return (0); - } - } - - /* Get minor data */ - if (strcmp(nvpair_name(nvp), RCM_NV_MINOR_DATA) == 0) { - if (nvpair_value_byte_array(nvp, - (uchar_t **)&minor_byte_array, &nminor) != 0) { - rcm_log_message(RCM_WARNING, - _("NET: cannot get device minor data\n")); - return (-1); - } - if (nvlist_unpack(minor_byte_array, - nminor, &mnvl, 0) != 0) { - rcm_log_message(RCM_WARNING, - _("NET: cannot get minor node data\n")); - return (-1); - } - mdata = (struct devfs_minor_data *)calloc(1, - sizeof (struct devfs_minor_data)); - if (mdata == NULL) { - rcm_log_message(RCM_WARNING, - _("NET: calloc error(%s)\n"), - strerror(errno)); - nvlist_free(mnvl); - return (-1); - } - /* Enumerate minor node data */ - while ((mnvp = nvlist_next_nvpair(mnvl, mnvp)) != - NULL) { - /* Get minor type */ - if (strcmp(nvpair_name(mnvp), - RCM_NV_MINOR_TYPE) == 0) { - if (nvpair_value_int32(mnvp, - &mdata->minor_type) != 0) { - rcm_log_message(RCM_WARNING, - _("NET: cannot get minor " - "type \n")); - nvlist_free(mnvl); - return (-1); - } - } - /* Get minor name */ - if (strcmp(nvpair_name(mnvp), - RCM_NV_MINOR_NAME) == 0) { - if (nvpair_value_string(mnvp, - &mdata->minor_name) != 0) { - rcm_log_message(RCM_WARNING, - _("NET: cannot get minor " - "name \n")); - nvlist_free(mnvl); - return (-1); - } - } - /* Get minor node type */ - if (strcmp(nvpair_name(mnvp), - RCM_NV_MINOR_NODE_TYPE) == 0) { - if (nvpair_value_string(mnvp, - &mdata->minor_node_type) != 0) { - rcm_log_message(RCM_WARNING, - _("NET: cannot get minor " - "node type \n")); - nvlist_free(mnvl); - return (-1); - } - } - } - (void) process_minor(driver, instance, mdata); - nvlist_free(mnvl); - } - } - - (void) mutex_lock(&nil_lock); - - /* Notify the event for all new devices found, then clean up the list */ - for (nilp = nil_head; nilp != NULL; nilp = next) { - if (notify_new_link(hd, nilp->dev) != 0) { - rcm_log_message(RCM_ERROR, - _(": Notify %s event failed (%s)\n"), - RCM_RESOURCE_LINK_NEW, nilp->dev); - } - next = nilp->next; - free(nilp); - } - nil_head = NULL; - - (void) mutex_unlock(&nil_lock); - - rcm_log_message(RCM_TRACE1, _("NET: process_nvlist success\n")); - return (0); -} - -static void -process_minor(char *name, int instance, struct devfs_minor_data *mdata) -{ - char dev[MAXNAMELEN]; - struct ni_list **pp; - struct ni_list *p; - - rcm_log_message(RCM_TRACE1, _("NET: process_minor %s%d\n"), - name, instance); - - if ((mdata->minor_node_type != NULL) && - strcmp(mdata->minor_node_type, PROP_NV_DDI_NETWORK) != 0) { - /* Process network devices only */ - return; - } - - (void) snprintf(dev, sizeof (dev), "%s%d", name, instance); - - /* Add new interface to the list */ - (void) mutex_lock(&nil_lock); - for (pp = &nil_head; (p = *pp) != NULL; pp = &(p->next)) { - if (strcmp(dev, p->dev) == 0) - break; - } - if (p != NULL) { - rcm_log_message(RCM_TRACE1, - _("NET: secondary node - ignoring\n")); - goto done; - } - - /* Add new device to the list */ - if ((p = malloc(sizeof (struct ni_list))) == NULL) { - rcm_log_message(RCM_ERROR, _("NET: malloc failure(%s)\n"), - strerror(errno)); - goto done; - } - (void) strncpy(p->dev, dev, sizeof (p->dev)); - p->next = NULL; - *pp = p; - - rcm_log_message(RCM_TRACE1, _("NET: added new node %s\n"), dev); -done: - (void) mutex_unlock(&nil_lock); -} - -/* - * Notify the RCM_RESOURCE_LINK_NEW event to other modules. - * Return 0 on success, -1 on failure. - */ -static int -notify_new_link(rcm_handle_t *hd, const char *dev) -{ - nvlist_t *nvl = NULL; - datalink_id_t linkid; - uint64_t id; - int ret = -1; - - rcm_log_message(RCM_TRACE1, _("NET: notify_new_link %s\n"), dev); - if (dladm_dev2linkid(dev, &linkid) != DLADM_STATUS_OK) { - rcm_log_message(RCM_TRACE1, - _("NET: new link %s has not attached yet\n"), dev); - ret = 0; - goto done; - } - - id = linkid; - if ((nvlist_alloc(&nvl, 0, 0) != 0) || - (nvlist_add_uint64(nvl, RCM_NV_LINKID, id) != 0)) { - rcm_log_message(RCM_ERROR, - _("NET: failed to construct nvlist for %s\n"), dev); - goto done; - } - - /* - * Reset the active linkprop of this specific link. - */ - (void) dladm_init_linkprop(linkid, B_FALSE); - - rcm_log_message(RCM_TRACE1, _("NET: notify new link %u (%s)\n"), - linkid, dev); - - if (rcm_notify_event(hd, RCM_RESOURCE_LINK_NEW, 0, nvl, NULL) != - RCM_SUCCESS) { - rcm_log_message(RCM_ERROR, - _("NET: failed to notify %s event for %s\n"), - RCM_RESOURCE_LINK_NEW, dev); - goto done; - } - - ret = 0; -done: - if (nvl != NULL) - nvlist_free(nvl); - return (ret); -} diff --git a/usr/src/cmd/syseventd/modules/Makefile b/usr/src/cmd/syseventd/modules/Makefile index f54659eab3..f1e8b25e00 100644 --- a/usr/src/cmd/syseventd/modules/Makefile +++ b/usr/src/cmd/syseventd/modules/Makefile @@ -19,9 +19,7 @@ # CDDL HEADER END # # -#ident "%Z%%M% %I% %E% SMI" -# -# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # cmd/syseventd/modules/Makefile @@ -30,6 +28,7 @@ .PARALLEL: SUBDIRS= \ + datalink_mod \ devfsadmd_mod \ sysevent_conf_mod \ sysevent_reg_mod \ diff --git a/usr/src/cmd/syseventd/modules/datalink_mod/Makefile b/usr/src/cmd/syseventd/modules/datalink_mod/Makefile new file mode 100644 index 0000000000..5c847665ae --- /dev/null +++ b/usr/src/cmd/syseventd/modules/datalink_mod/Makefile @@ -0,0 +1,41 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# + +LIBRARY= datalink_mod + +include ../Makefile.com + +LDLIBS += -lnvpair -lrcm + +.KEEP_STATE: + +all: $(DYNLIB) + +install: all \ + $(ROOTLIBSYSEVENTDIR) \ + $(ROOTLIBDIR) \ + $(ROOTLIBS) + +include ../Makefile.targ diff --git a/usr/src/cmd/syseventd/modules/datalink_mod/datalink_mod.c b/usr/src/cmd/syseventd/modules/datalink_mod/datalink_mod.c new file mode 100644 index 0000000000..520b68226f --- /dev/null +++ b/usr/src/cmd/syseventd/modules/datalink_mod/datalink_mod.c @@ -0,0 +1,89 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * datalink syseventd module. + * + * The purpose of this module is to identify all datalink related events, + * and react accordingly. + */ + +#include <errno.h> +#include <sys/sysevent/eventdefs.h> +#include <string.h> +#include <libnvpair.h> +#include <librcm.h> +#include <libsysevent.h> + +static rcm_handle_t *rcm_hdl = NULL; + +/*ARGSUSED*/ +static int +datalink_deliver_event(sysevent_t *ev, int unused) +{ + const char *class = sysevent_get_class_name(ev); + const char *subclass = sysevent_get_subclass_name(ev); + nvlist_t *nvl; + int err = 0; + + if (strcmp(class, EC_DATALINK) != 0 || + strcmp(subclass, ESC_DATALINK_PHYS_ADD) != 0) { + return (0); + } + + if (sysevent_get_attr_list(ev, &nvl) != 0) + return (EINVAL); + + if (rcm_notify_event(rcm_hdl, RCM_RESOURCE_LINK_NEW, 0, nvl, NULL) != + RCM_SUCCESS) { + err = EINVAL; + } + + nvlist_free(nvl); + return (err); +} + +static struct slm_mod_ops datalink_mod_ops = { + SE_MAJOR_VERSION, + SE_MINOR_VERSION, + SE_MAX_RETRY_LIMIT, + datalink_deliver_event +}; + +struct slm_mod_ops * +slm_init() +{ + if (rcm_alloc_handle(NULL, 0, NULL, &rcm_hdl) != RCM_SUCCESS) + return (NULL); + + return (&datalink_mod_ops); +} + +void +slm_fini() +{ + (void) rcm_free_handle(rcm_hdl); + rcm_hdl = NULL; +} diff --git a/usr/src/lib/libdevinfo/device_info.h b/usr/src/lib/libdevinfo/device_info.h index d53a5b86f8..32e65ac8d8 100644 --- a/usr/src/lib/libdevinfo/device_info.h +++ b/usr/src/lib/libdevinfo/device_info.h @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -33,8 +33,6 @@ #ifndef _DEVICE_INFO_H #define _DEVICE_INFO_H -#pragma ident "%Z%%M% %I% %E% SMI" - #ifdef __cplusplus extern "C" { #endif @@ -179,7 +177,7 @@ extern int devfs_rm_minor_perm(char *, void (*)(minorperm_err_t, int)); #define DCA_FREE_LIST 0x000000002 #define DCA_LOAD_DRV 0x000000004 #define DCA_CHECK_TYPE 0x000000010 -#define DCA_NOTIFY_RCM 0x000000020 +/* UNUSED was DCA_NOTIFY_RCM 0x000000020 (can be recycled) */ #define DCA_FLUSH_PATHINST 0x000000040 #define DCA_HOT_PLUG 0x000000080 #define DCA_DEVLINK_SYNC 0x000000100 diff --git a/usr/src/lib/librcm/librcm.h b/usr/src/lib/librcm/librcm.h index 49ca304a08..6cd4c91409 100644 --- a/usr/src/lib/librcm/librcm.h +++ b/usr/src/lib/librcm/librcm.h @@ -26,8 +26,6 @@ #ifndef _LIBRCM_H #define _LIBRCM_H -#pragma ident "%Z%%M% %I% %E% SMI" - #include <libnvpair.h> #include <sys/types.h> #include <sys/processor.h> @@ -97,20 +95,10 @@ extern "C" { #define RCM_CLIENT_NAME "rcm.client_name" #define RCM_CLIENT_EXPORTS "rcm.client_exports" -/* Resource name to register for new resources */ -#define RCM_RESOURCE_NETWORK_NEW "SUNW_event/resource/new/network" /* Resource name to register for new links come up */ #define RCM_RESOURCE_LINK_NEW "SUNW_event/resource/new/link" /* name-value pair definitions for rcm_notify_event() */ -#define RCM_NV_DRIVER_NAME "driver_name" -#define RCM_NV_INSTANCE "instance" -#define RCM_NV_NODE_NAME "node_name" -#define RCM_NV_DEVFS_PATH "devfs_path" -#define RCM_NV_MINOR_DATA "minor_data" -#define RCM_NV_MINOR_TYPE "minor_type" -#define RCM_NV_MINOR_NAME "minor_name" -#define RCM_NV_MINOR_NODE_TYPE "minor_node_type" #define RCM_NV_LINKID "linkid" /* diff --git a/usr/src/pkgdefs/SUNWcsu/prototype_com b/usr/src/pkgdefs/SUNWcsu/prototype_com index 1705cd5a93..22506a1f15 100644 --- a/usr/src/pkgdefs/SUNWcsu/prototype_com +++ b/usr/src/pkgdefs/SUNWcsu/prototype_com @@ -22,8 +22,6 @@ # Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # -# ident "%Z%%M% %I% %E% SMI" -# # This required package information file contains a list of package contents. # The 'pkgmk' command uses this file to identify the contents of a package # and their location on the development machine when building the package. @@ -677,6 +675,7 @@ s none usr/lib/secure/32=. d none usr/lib/security 755 root bin d none usr/lib/sysevent 755 root bin d none usr/lib/sysevent/modules 755 root bin +f none usr/lib/sysevent/modules/datalink_mod.so 755 root bin f none usr/lib/sysevent/modules/devfsadmd_mod.so 755 root bin f none usr/lib/sysevent/modules/sysevent_conf_mod.so 755 root bin f none usr/lib/sysevent/modules/sysevent_reg_mod.so 755 root bin diff --git a/usr/src/uts/common/io/softmac/softmac_main.c b/usr/src/uts/common/io/softmac/softmac_main.c index 5cdc70db12..d325e3b4c6 100644 --- a/usr/src/uts/common/io/softmac/softmac_main.c +++ b/usr/src/uts/common/io/softmac/softmac_main.c @@ -23,8 +23,6 @@ * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" - /* * The softmac driver is used to "unify" non-GLDv3 drivers to the GLDv3 * framework. It also creates the kernel datalink structure for each @@ -63,7 +61,8 @@ static mod_hash_t *softmac_hash; #define SOFTMAC_HASHSZ 64 -static void softmac_mac_register(void *); +static void softmac_create_task(void *); +static void softmac_mac_register(softmac_t *); static int softmac_create_datalink(softmac_t *); static int softmac_m_start(void *); static void softmac_m_stop(void *); @@ -147,10 +146,8 @@ softmac_create(dev_info_t *dip, dev_t dev) char devname[MAXNAMELEN]; softmac_t *softmac; softmac_dev_t *softmac_dev = NULL; - datalink_id_t linkid; int index; int ppa, err = 0; - mac_handle_t mh; /* * Force the softmac driver to be attached. @@ -264,14 +261,6 @@ softmac_create(dev_info_t *dip, dev_t dev) rw_exit(&softmac_hash_lock); /* - * Inform dlmgmtd of this link so that softmac_hold_device() is able - * to know the existence of this link. This could fail if dlmgmtd - * is not yet started. - */ - (void) dls_mgmt_create(devname, makedevice(ddi_driver_major(dip), - ppa + 1), DATALINK_CLASS_PHYS, DL_OTHER, B_TRUE, &linkid); - - /* * No lock is needed for access this softmac pointer, as pre-detach and * post-attach won't happen at the same time. */ @@ -290,58 +279,26 @@ softmac_create(dev_info_t *dip, dev_t dev) return (0); } - if (!GLDV3_DRV(ddi_driver_major(dip))) { - - /* - * Note that this function could be called as a result of - * a open() system call, and spec_open() already locked the - * snode (SLOCKED is set). Therefore, we must start a - * taskq to finish the rest of work to sidestep the risk - * that our ldi_open_by_dev() call would again try to hold - * the same lock. - * - * If all the minor nodes have been attached, start the taskq - * to finish the rest of the work. - */ - ASSERT(softmac->smac_taskq == NULL); - softmac->smac_taskq = taskq_dispatch(system_taskq, - softmac_mac_register, softmac, TQ_SLEEP); - mutex_exit(&softmac->smac_mutex); - return (0); - } - - if ((err = mac_open(softmac->smac_devname, &mh)) != 0) - goto done; - - softmac->smac_media = (mac_info(mh))->mi_nativemedia; - softmac->smac_mh = mh; - - /* - * We can safely release the reference on the mac because - * this mac will only be unregistered and destroyed when - * the device detaches, and the softmac will be destroyed - * before then (in the pre-detach routine of the device). - */ - mac_close(mh); - /* - * Create the GLDv3 datalink for this mac. + * All of the minor nodes have been attached; start a taskq + * to do the rest of the work. We use a taskq instead of of + * doing the work here because: + * + * - We could be called as a result of an open() system call + * where spec_open() already SLOCKED the snode. Using a taskq + * sidesteps the risk that our ldi_open_by_dev() call would + * deadlock trying to set SLOCKED on the snode again. + * + * - The devfs design requires no interruptible function calls + * in the device post-attach routine, but we need to make an + * (interruptible) upcall. Using a taskq to make the upcall + * sidesteps this. */ - err = softmac_create_datalink(softmac); - -done: - if (err != 0) { - softmac->smac_mh = NULL; - kmem_free(softmac_dev, sizeof (softmac_dev_t)); - softmac->smac_softmac[index] = NULL; - --softmac->smac_attachok_cnt; - } - ASSERT(!(softmac->smac_flags & SOFTMAC_ATTACH_DONE)); - softmac->smac_flags |= SOFTMAC_ATTACH_DONE; - softmac->smac_attacherr = err; - cv_broadcast(&softmac->smac_cv); + ASSERT(softmac->smac_taskq == NULL); + softmac->smac_taskq = taskq_dispatch(system_taskq, + softmac_create_task, softmac, TQ_SLEEP); mutex_exit(&softmac->smac_mutex); - return (err); + return (0); } static boolean_t @@ -442,15 +399,23 @@ softmac_create_datalink(softmac_t *softmac) ASSERT(MUTEX_HELD(&softmac->smac_mutex)); /* - * First provide the media type of the physical link to dlmgmtd. - * - * If the new <linkname, linkid> mapping operation failed with EBADF - * or ENOENT, it might because the dlmgmtd was not started in time - * (e.g., diskless boot); ignore the failure and continue. The - * mapping will be recreated once the daemon has started. + * Inform dlmgmtd of this link so that softmac_hold_device() is able + * to know the existence of this link. If this failed with EBADF, + * it might be because dlmgmtd was not started in time (e.g., + * diskless boot); ignore the failure and continue to create + * the GLDv3 datalink if needed. + */ + err = dls_mgmt_create(softmac->smac_devname, + makedevice(softmac->smac_umajor, softmac->smac_uppa + 1), + DATALINK_CLASS_PHYS, DL_OTHER, B_TRUE, &linkid); + if (err != 0 && err != EBADF) + return (err); + + /* + * Provide the media type of the physical link to dlmgmtd. */ - if (((err = softmac_update_info(softmac, &linkid)) != 0) && - (err != EBADF) && (err != ENOENT)) { + if ((err != EBADF) && + ((err = softmac_update_info(softmac, &linkid)) != 0)) { return (err); } @@ -470,6 +435,47 @@ softmac_create_datalink(softmac_t *softmac) return (0); } +static void +softmac_create_task(void *arg) +{ + softmac_t *softmac = arg; + mac_handle_t mh; + int err; + + if (!GLDV3_DRV(softmac->smac_umajor)) { + softmac_mac_register(softmac); + return; + } + + if ((err = mac_open(softmac->smac_devname, &mh)) != 0) + goto done; + + mutex_enter(&softmac->smac_mutex); + softmac->smac_media = (mac_info(mh))->mi_nativemedia; + softmac->smac_mh = mh; + + /* + * We can safely release the reference on the mac because + * this mac will only be unregistered and destroyed when + * the device detaches, and the softmac will be destroyed + * before then (in the pre-detach routine of the device). + */ + mac_close(mh); + + /* + * Create the GLDv3 datalink for this mac. + */ + err = softmac_create_datalink(softmac); + +done: + ASSERT(!(softmac->smac_flags & SOFTMAC_ATTACH_DONE)); + softmac->smac_flags |= SOFTMAC_ATTACH_DONE; + softmac->smac_attacherr = err; + softmac->smac_taskq = NULL; + cv_broadcast(&softmac->smac_cv); + mutex_exit(&softmac->smac_mutex); +} + /* * This function is only called for legacy devices. It: * 1. registers the MAC for the legacy devices whose media type is supported @@ -477,9 +483,8 @@ softmac_create_datalink(softmac_t *softmac) * 2. creates the GLDv3 datalink if the media type is supported by GLDv3. */ static void -softmac_mac_register(void *arg) +softmac_mac_register(softmac_t *softmac) { - softmac_t *softmac = arg; softmac_dev_t *softmac_dev; dev_t dev; ldi_handle_t lh = NULL; diff --git a/usr/src/uts/common/sys/sysevent/eventdefs.h b/usr/src/uts/common/sys/sysevent/eventdefs.h index 71565d933c..ac21686e84 100644 --- a/usr/src/uts/common/sys/sysevent/eventdefs.h +++ b/usr/src/uts/common/sys/sysevent/eventdefs.h @@ -26,8 +26,6 @@ #ifndef _SYS_SYSEVENT_EVENTDEFS_H #define _SYS_SYSEVENT_EVENTDEFS_H -#pragma ident "%Z%%M% %I% %E% SMI" - #ifdef __cplusplus extern "C" { #endif @@ -53,6 +51,7 @@ extern "C" { #define EC_DEV_STATUS "EC_dev_status" /* device status event class */ #define EC_FM "EC_fm" /* FMA error report event */ #define EC_ZFS "EC_zfs" /* ZFS event */ +#define EC_DATALINK "EC_datalink" /* datalink event */ /* * The following event class is reserved for exclusive use @@ -236,6 +235,11 @@ extern "C" { #define ESC_ZFS_VDEV_CHECK "ESC_ZFS_vdev_check" #define ESC_ZFS_CONFIG_SYNC "ESC_ZFS_config_sync" +/* + * datalink subclass definitions. + */ +#define ESC_DATALINK_PHYS_ADD "ESC_datalink_phys_add" /* new physical link */ + #ifdef __cplusplus } #endif |