summaryrefslogtreecommitdiff
path: root/usr/src/lib/libdiskmgt
diff options
context:
space:
mode:
authorJerry Jelinek <jerry.jelinek@joyent.com>2019-07-29 12:13:24 +0000
committerJerry Jelinek <jerry.jelinek@joyent.com>2019-07-29 12:13:24 +0000
commit17304c0b18b0ddd09fa2283f34a32b031338ff26 (patch)
treee74f22b7bb16647b7e9da94d68bf69aae4e463f4 /usr/src/lib/libdiskmgt
parent4114093726f400cc6f3a5e1fb3c934d55cdf5f66 (diff)
parent5cffb2606ed604b9f1f45d061bc8aa92e0536f70 (diff)
downloadillumos-joyent-17304c0b18b0ddd09fa2283f34a32b031338ff26.tar.gz
[illumos-gate merge]
commit 5cffb2606ed604b9f1f45d061bc8aa92e0536f70 11306 syseventd cores after hot-add of disk commit 508a0e8cf1600b06c1f7361ad76e736710d3fdf8 11257 Add DDI support for Upgradable Firmware Modules 11258 Add libtopo support for Upgradable Firmware Modules Conflicts: usr/src/uts/sparc/ufmtest/Makefile usr/src/uts/sparc/Makefile.sparc usr/src/uts/intel/ufmtest/Makefile usr/src/uts/common/sys/scsi/adapters/mpt_sas/mptsas_var.h usr/src/uts/common/sys/ddi_ufm_impl.h usr/src/uts/common/sys/ddi_ufm.h usr/src/uts/common/io/ufmtest.c usr/src/uts/common/io/ufm.c usr/src/test/os-tests/tests/Makefile usr/src/test/os-tests/runfiles/default.run usr/src/man/man9f/ddi_ufm_image.9f usr/src/man/man9f/Makefile usr/src/man/man9e/ddi_ufm.9e usr/src/man/man9e/Makefile usr/src/man/man7d/ufm.7d usr/src/lib/fm/topo/libtopo/common/topo_mod.c
Diffstat (limited to 'usr/src/lib/libdiskmgt')
-rw-r--r--usr/src/lib/libdiskmgt/common/events.c117
1 files changed, 84 insertions, 33 deletions
diff --git a/usr/src/lib/libdiskmgt/common/events.c b/usr/src/lib/libdiskmgt/common/events.c
index 134abe1846..6874000bea 100644
--- a/usr/src/lib/libdiskmgt/common/events.c
+++ b/usr/src/lib/libdiskmgt/common/events.c
@@ -23,6 +23,9 @@
* Copyright 2004 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
+/*
+ * Copyright 2019 Joyent, Inc.
+ */
#include <stdio.h>
#include <stdlib.h>
@@ -39,11 +42,16 @@
#include "libdiskmgt.h"
#include "disks_private.h"
+#pragma fini(libdiskmgt_fini)
+
struct event_list {
struct event_list *next;
nvlist_t *event;
};
+static mutex_t shp_lock = ERRORCHECKMUTEX;
+static sysevent_handle_t *shp = NULL;
+
static struct event_list *events = NULL;
static int event_error = 0;
static int event_break = 0;
@@ -72,8 +80,10 @@ static sema_t semaphore;
#define WALK_RUNNING 2
#define WALK_WAIT_TIME 60 /* wait 60 seconds */
-static mutex_t walker_lock;
+static mutex_t walker_lock = ERRORCHECKMUTEX;
+static cond_t walker_cv = DEFAULTCV;
static int walker_state = WALK_NONE;
+
static int events_pending = 0;
static int sendevents = 0;
@@ -87,6 +97,31 @@ static void walker(void *arg);
static void(*callback)(nvlist_t *, int) = NULL;
+static boolean_t shutting_down = B_FALSE;
+
+static void
+libdiskmgt_fini(void)
+{
+ mutex_enter(&shp_lock);
+ if (shp != NULL) {
+ sysevent_unsubscribe_event(shp, EC_ALL);
+ sysevent_unbind_handle(shp);
+ shp = NULL;
+ }
+ /*
+ * At this point a new invocation of walker() can't occur. However,
+ * if one was already running then we need to wait for it to finish
+ * because if we allow ourselves to be unloaded out from underneath
+ * it, then bad things will happen.
+ */
+ mutex_enter(&walker_lock);
+ shutting_down = B_TRUE;
+ while (walker_state != WALK_NONE)
+ (void) cond_wait(&walker_cv, &walker_lock);
+
+ mutex_exit(&walker_lock);
+}
+
nvlist_t *
dm_get_event(int *errp)
{
@@ -223,40 +258,44 @@ events_new_slice_event(char *dev, char *type)
int
events_start_event_watcher()
{
- sysevent_handle_t *shp;
const char *subclass_list[1];
+ int ret = -1;
+
+ mutex_enter(&shp_lock);
+ if (shp != NULL) {
+ ret = 0;
+ goto out;
+ }
/* Bind event handler and create subscriber handle */
shp = sysevent_bind_handle(event_handler);
if (shp == NULL) {
- if (dm_debug) {
- /* keep going when we're debugging */
- (void) fprintf(stderr, "ERROR: bind failed %d\n", errno);
- return (0);
- }
- return (errno);
+ if (dm_debug) {
+ (void) fprintf(stderr, "ERROR: sysevent bind failed: "
+ "%d\n", errno);
+ }
+ goto out;
}
subclass_list[0] = ESC_DISK;
- if (sysevent_subscribe_event(shp, EC_DEV_ADD, subclass_list, 1) != 0) {
- if (dm_debug) {
- /* keep going when we're debugging */
- (void) fprintf(stderr, "ERROR: subscribe failed\n");
- return (0);
- }
- return (errno);
- }
- if (sysevent_subscribe_event(shp, EC_DEV_REMOVE, subclass_list, 1)
- != 0) {
- if (dm_debug) {
- /* keep going when we're debugging */
- (void) fprintf(stderr, "ERROR: subscribe failed\n");
- return (0);
- }
- return (errno);
- }
+ if (sysevent_subscribe_event(shp, EC_DEV_ADD, subclass_list, 1) != 0 ||
+ sysevent_subscribe_event(shp, EC_DEV_REMOVE, subclass_list, 1) !=
+ 0) {
+
+ sysevent_unsubscribe_event(shp, EC_ALL);
+ sysevent_unbind_handle(shp);
+ shp = NULL;
- return (0);
+ if (dm_debug) {
+ (void) fprintf(stderr, "ERROR: sysevent subscribe "
+ "failed: %d\n", errno);
+ }
+ goto out;
+ }
+ ret = 0;
+out:
+ mutex_exit(&shp_lock);
+ return (ret);
}
static void
@@ -439,7 +478,7 @@ walk_devtree()
{
thread_t walk_thread;
- (void) mutex_lock(&walker_lock);
+ mutex_enter(&walker_lock);
switch (walker_state) {
case WALK_NONE:
@@ -458,7 +497,7 @@ walk_devtree()
break;
}
- (void) mutex_unlock(&walker_lock);
+ mutex_exit(&walker_lock);
}
/*ARGSUSED*/
@@ -468,16 +507,28 @@ walker(void *arg)
int walk_again = 0;
do {
- /* start by wating for a few seconds to absorb extra events */
+ /* start by waiting for a few seconds to absorb extra events */
(void) sleep(WALK_WAIT_TIME);
- (void) mutex_lock(&walker_lock);
+ mutex_enter(&walker_lock);
+ if (shutting_down) {
+ walker_state = WALK_NONE;
+ (void) cond_broadcast(&walker_cv);
+ mutex_exit(&walker_lock);
+ return;
+ }
walker_state = WALK_RUNNING;
- (void) mutex_unlock(&walker_lock);
+ mutex_exit(&walker_lock);
cache_update(DM_EV_DISK_ADD, NULL);
- (void) mutex_lock(&walker_lock);
+ mutex_enter(&walker_lock);
+ if (shutting_down) {
+ walker_state = WALK_NONE;
+ (void) cond_broadcast(&walker_cv);
+ mutex_exit(&walker_lock);
+ return;
+ }
if (events_pending) {
events_pending = 0;
@@ -488,7 +539,7 @@ walker(void *arg)
walk_again = 0;
}
- (void) mutex_unlock(&walker_lock);
+ mutex_exit(&walker_lock);
} while (walk_again);
}