summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjacobs <none@none>2007-03-19 11:35:26 -0700
committerjacobs <none@none>2007-03-19 11:35:26 -0700
commitf05faa4ea8df92014407b88058ffeb988a32b6fd (patch)
tree50ebee3f07d2e385abf687295ddd8e441fd25729
parent4e942d8cd27c7f8bb80549d7c2564445f19ba4a3 (diff)
downloadillumos-gate-f05faa4ea8df92014407b88058ffeb988a32b6fd.tar.gz
6533722 devfsadmd and hald are off to the races
-rw-r--r--usr/src/cmd/devfsadm/devfsadm.c91
-rw-r--r--usr/src/cmd/devfsadm/devfsadm_impl.h12
2 files changed, 93 insertions, 10 deletions
diff --git a/usr/src/cmd/devfsadm/devfsadm.c b/usr/src/cmd/devfsadm/devfsadm.c
index 63d88dad62..d443b88a20 100644
--- a/usr/src/cmd/devfsadm/devfsadm.c
+++ b/usr/src/cmd/devfsadm/devfsadm.c
@@ -245,6 +245,12 @@ static int s_stat(const char *, struct stat *);
static int is_blank(char *);
+/* sysevent queue related globals */
+static mutex_t syseventq_mutex = DEFAULTMUTEX;
+static syseventq_t *syseventq_front;
+static syseventq_t *syseventq_back;
+static void process_syseventq();
+
int
main(int argc, char *argv[])
{
@@ -966,7 +972,7 @@ devi_tree_walk(struct dca_impl *dcip, int flags, char *ev_subclass)
* Log sysevent and notify RCM.
*/
if (ev_subclass)
- build_and_log_event(EC_DEV_ADD, ev_subclass, dcip->dci_root,
+ build_and_enq_event(EC_DEV_ADD, ev_subclass, dcip->dci_root,
node);
if ((dcip->dci_flags & DCA_NOTIFY_RCM) && rcm_hdl)
@@ -1324,6 +1330,9 @@ lock_dev(void)
invalidate_enumerate_cache();
rm_all_links_from_cache();
(void) di_devlink_close(&devlink_cache, DI_LINK_ERROR);
+
+ /* send any sysevents that were queued up. */
+ process_syseventq();
}
/*
@@ -1395,6 +1404,12 @@ unlock_dev(int flag)
if (update_database)
(void) di_devlink_update(devlink_cache);
(void) di_devlink_close(&devlink_cache, 0);
+
+ /*
+ * now that the devlinks db cache has been flushed, it is safe
+ * to send any sysevents that were queued up.
+ */
+ process_syseventq();
}
exit_dev_lock();
@@ -1578,7 +1593,7 @@ event_handler(sysevent_t *ev)
if (strcmp(ESC_DEVFS_DEVI_ADD, subclass) == 0) {
add_minor_pathname(path, NULL, dev_ev_subclass);
if (branch_event) {
- build_and_log_event(EC_DEV_BRANCH,
+ build_and_enq_event(EC_DEV_BRANCH,
ESC_DEV_BRANCH_ADD, path, DI_NODE_NIL);
}
@@ -1592,7 +1607,7 @@ event_handler(sysevent_t *ev)
hot_cleanup(path, NULL, dev_ev_subclass,
driver_name, instance);
if (branch_event) {
- build_and_log_event(EC_DEV_BRANCH,
+ build_and_enq_event(EC_DEV_BRANCH,
ESC_DEV_BRANCH_REMOVE, path, DI_NODE_NIL);
}
}
@@ -1612,7 +1627,7 @@ event_handler(sysevent_t *ev)
dev_ev_subclass = ESC_DEV_BRANCH_REMOVE;
lock_dev();
- build_and_log_event(EC_DEV_BRANCH, dev_ev_subclass, path,
+ build_and_enq_event(EC_DEV_BRANCH, dev_ev_subclass, path,
DI_NODE_NIL);
unlock_dev(CACHE_STATE);
} else
@@ -3826,6 +3841,10 @@ enter_dev_lock()
* database code may hold.
*/
(void) di_devlink_close(&devlink_cache, 0);
+
+ /* send any sysevents that were queued up. */
+ process_syseventq();
+
if (fcntl(dev_lock_fd, F_SETLKW, &lock) == -1) {
err_print(LOCK_FAILED, dev_lockfile,
strerror(errno));
@@ -8046,12 +8065,69 @@ log_event(char *class, char *subclass, nvlist_t *nvl)
}
}
+/*
+ * When devfsadmd needs to generate sysevents, they are queued for later
+ * delivery this allows them to be delivered after the devlinks db cache has
+ * been flushed guaranteeing that applications consuming these events have
+ * access to an accurate devlinks db. The queue is a FIFO, sysevents to be
+ * inserted in the front of the queue and consumed off the back.
+ */
+static void
+enqueue_sysevent(char *class, char *subclass, nvlist_t *nvl)
+{
+ syseventq_t *tmp;
+
+ if ((tmp = s_zalloc(sizeof (*tmp))) == NULL)
+ return;
+
+ tmp->class = s_strdup(class);
+ tmp->subclass = s_strdup(subclass);
+ tmp->nvl = nvl;
+
+ (void) mutex_lock(&syseventq_mutex);
+ if (syseventq_front != NULL)
+ syseventq_front->next = tmp;
+ else
+ syseventq_back = tmp;
+ syseventq_front = tmp;
+ (void) mutex_unlock(&syseventq_mutex);
+}
+
+static void
+process_syseventq()
+{
+ (void) mutex_lock(&syseventq_mutex);
+ while (syseventq_back != NULL) {
+ syseventq_t *tmp = syseventq_back;
+
+ vprint(CHATTY_MID, "sending queued event: %s, %s\n",
+ tmp->class, tmp->subclass);
+
+ log_event(tmp->class, tmp->subclass, tmp->nvl);
+
+ if (tmp->class != NULL)
+ free(tmp->class);
+ if (tmp->subclass != NULL)
+ free(tmp->subclass);
+ if (tmp->nvl != NULL)
+ nvlist_free(tmp->nvl);
+ syseventq_back = syseventq_back->next;
+ if (syseventq_back == NULL)
+ syseventq_front = NULL;
+ free(tmp);
+ }
+ (void) mutex_unlock(&syseventq_mutex);
+}
+
static void
-build_and_log_event(char *class, char *subclass, char *node_path,
- di_node_t node)
+build_and_enq_event(char *class, char *subclass, char *node_path,
+ di_node_t node)
{
nvlist_t *nvl;
+ vprint(CHATTY_MID, "build_and_enq_event(%s, %s, %s, 0x%8.8x)\n",
+ class, subclass, node_path, (int)node);
+
if (node != DI_NODE_NIL)
nvl = build_event_attributes(class, subclass, node_path, node,
di_driver_name(node), di_instance(node));
@@ -8060,8 +8136,7 @@ build_and_log_event(char *class, char *subclass, char *node_path,
NULL, -1);
if (nvl) {
- log_event(class, subclass, nvl);
- nvlist_free(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 71f167d230..20cf90891c 100644
--- a/usr/src/cmd/devfsadm/devfsadm_impl.h
+++ b/usr/src/cmd/devfsadm/devfsadm_impl.h
@@ -109,7 +109,7 @@ extern "C" {
#define DEVFSADM_DEFAULT_FILE "/etc/default/devfsadm"
-#define MINOR_FINI_TIMEOUT_DEFAULT 3
+#define MINOR_FINI_TIMEOUT_DEFAULT 2
#define SYNCH_DOOR_PERMS (S_IRUSR | S_IWUSR)
@@ -362,6 +362,14 @@ struct rcm_eventq {
struct rcm_eventq *next;
};
+/* sysevent queue related */
+typedef struct syseventq_s {
+ struct syseventq_s *next;
+ char *class;
+ char *subclass;
+ nvlist_t *nvl;
+} syseventq_t;
+
static int devfsadm_enumerate_int_start(char *devfs_path,
int index, char **buf, devfsadm_enumerate_t rules[],
int nrules, char *start);
@@ -493,7 +501,7 @@ static int (*librcm_notify_event)(rcm_handle_t *, char *, uint_t, nvlist_t *,
static nvlist_t *build_event_attributes(char *, char *, char *,
di_node_t, char *, int);
static void log_event(char *, char *, nvlist_t *);
-static void build_and_log_event(char *, char *, char *, di_node_t);
+static void build_and_enq_event(char *, char *, char *, di_node_t);
static void read_logindevperm_file(void);
static void set_logindev_perms(char *devlink);