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);
 }