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.