Print this page
OS-90 Kernel should generate events when device gets retired / unretired.
re #13613 rb4516 Tunables needs volatile keyword
@@ -19,10 +19,11 @@
* CDDL HEADER END
*/
/*
* Copyright (c) 1990, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
*/
/*
* modctl system call for loadable module support.
*/
@@ -62,10 +63,12 @@
#include <sys/debug.h>
#include <sys/cpuvar.h>
#include <sys/sysmacros.h>
#include <sys/sysevent.h>
#include <sys/sysevent_impl.h>
+#include <sys/sysevent/eventdefs.h>
+#include <sys/sysevent/dev.h>
#include <sys/instance.h>
#include <sys/modhash.h>
#include <sys/modhash_impl.h>
#include <sys/dacf_impl.h>
#include <sys/vfs.h>
@@ -130,11 +133,11 @@
int modunload_active_count;
int modunload_disable_count;
int isminiroot; /* set if running as miniroot */
int modrootloaded; /* set after root driver and fs are loaded */
-int moddebug = 0x0; /* debug flags for module writers */
+volatile int moddebug = 0x0; /* debug flags for module writers */
int swaploaded; /* set after swap driver and fs are loaded */
int bop_io_quiesced = 0; /* set when BOP I/O can no longer be used */
int last_module_id;
clock_t mod_uninstall_interval = 0;
int mod_uninstall_pass_max = 6;
@@ -965,10 +968,56 @@
kmem_free(constraints, len);
return (array);
}
+
+static void
+publish_retire_event(char *path, int retire)
+{
+ sysevent_t *ev;
+ sysevent_id_t eid;
+ sysevent_value_t se_val;
+ sysevent_attr_list_t *ev_attr_list = NULL;
+
+ ev = sysevent_alloc(EC_DEV_STATUS,
+ retire ? ESC_DEV_RETIRE : ESC_DEV_UNRETIRE, EC_DEVFS, SE_SLEEP);
+ if (ev == NULL) {
+ goto fail;
+ }
+
+ se_val.value_type = SE_DATA_TYPE_STRING;
+ se_val.value.sv_string = path;
+
+ if (sysevent_add_attr(&ev_attr_list, DEV_PHYS_PATH,
+ &se_val, SE_SLEEP) != 0) {
+ goto fail;
+ }
+
+ if (sysevent_attach_attributes(ev, ev_attr_list) != 0) {
+ goto fail;
+ }
+
+ if (log_sysevent(ev, SE_SLEEP, &eid) != 0) {
+ goto fail;
+ }
+
+ sysevent_free(ev);
+ return;
+
+fail:
+
+ cmn_err(CE_WARN, "failed to log device %s event for %s",
+ retire ? "retire" : "unretire", path);
+
+ if (ev_attr_list != NULL) {
+ sysevent_free_attr(ev_attr_list);
+ }
+
+ sysevent_free(ev);
+}
+
/*ARGSUSED*/
static int
modctl_retire(char *path, char *uconstraints, size_t ulen)
{
char *pathbuf;
@@ -1045,10 +1094,13 @@
return (retval);
}
if (moddebug & MODDEBUG_RETIRE)
cmn_err(CE_NOTE, "Persisted retire of device: %s", devpath);
+ /* Issue sysevent. */
+ publish_retire_event(devpath, 1);
+
kmem_free(devpath, strlen(devpath) + 1);
return (0);
}
static int
@@ -1142,10 +1194,13 @@
if (retval != 0) {
cmn_err(CE_WARN, "cannot unretire device: error %d, path %s\n",
retval, devpath);
}
+ /* Issue sysevent. */
+ publish_retire_event(devpath, 0);
+
kmem_free(devpath, strlen(devpath) + 1);
return (retval);
}