I’ve been heads down for a long time on a new project, but occasionally I do put something back to ON worth blogging about. Recently I’ve been working on some problems which leverage sysevents (libsysevent(3LIB)) as a common transport mechanism. While trying to understand exactly what sysevents were being generated from where, I found the lack of observability astounding. After poking around with DTrace, I found that tracking down the exact semantics was not exactly straightforward. First of all, we have two orthogonal sysevent mechanisms, the original syseventd legacy mechanism, and the more recent general purpose event channel (GPEC) mechanism, used by FMA. On top of this, the sysevent_impl_t structure isn’t exactly straightforward, because all the data is packed together in a single block of memory. Knowing that this would be important for my upcoming work, I decided that adding a stable DTrace sysevent provider would be useful.
The provider has a single probe, sysevent:::post, which fires whenever a sysevent post attempt is made. It doesn’t necessarily indicate that the syevent was successfully queued or received. The probe has the following semantics:
# dtrace -lvP sysevent ID PROVIDER MODULE FUNCTION NAME 44528 sysevent genunix queue_sysevent post Probe Description Attributes Identifier Names: Private Data Semantics: Private Dependency Class: Unknown Argument Attributes Identifier Names: Evolving Data Semantics: Evolving Dependency Class: ISA Argument Types args[0]: syseventchaninfo_t * args[1]: syseventinfo_t *
The ‘syseventchaninfo_t’ translator has a single member, ‘ec_name’,which is the name of the event channel. If this is being posted via the legacy sysevent mechanism, then this member will be NULL. The ‘syeventinfo_t’ translator has three members, ‘se_publisher’, ‘se_class’, and ‘se_subclass’. These mirror the arguments to sysevent_post(). The following script will dump all sysevents posted to syseventd(1M):
#!/usr/sbin/dtrace -s #pragma D option quiet BEGIN { printf("%-30s %-20s %s\n", "PUBLISHER", "CLASS", "SUBCLASS"); } sysevent:::post /args[0]->ec_name == NULL/ { printf("%-30s %-20s %s\n", args[1]->se_publisher, args[1]->se_class, args[1]->se_subclass); }
And the output during a cfgadm -c unconfigure:
PUBLISHER CLASS SUBCLASS SUNW:usr:devfsadmd:100237 EC_dev_remove disk SUNW:usr:devfsadmd:100237 EC_dev_branch ESC_dev_branch_remove SUNW:kern:ddi EC_devfs ESC_devfs_devi_remove
This has already proven quite useful in my ongoing work, and hopefully some other developers out there will also find it useful.
One Response
That’s very cool Eric! I’ve been playing with DTrace to look at devices lately, and this seems like this will be handy. Nice job.