This is the mail archive of the
systemtap@sourceware.org
mailing list for the systemtap project.
ideas of filter in Linux Kernel Event Trace tool
- From: "Guanglei Li" <guanglei at cn dot ibm dot com>
- To: <systemtap at sources dot redhat dot com>
- Cc: "Martin Peschke" <mp3 at de dot ibm dot com>, <jrs at us dot ibm dot com>
- Date: Fri, 13 Jan 2006 23:18:10 +0800
- Subject: ideas of filter in Linux Kernel Event Trace tool
Hi folks,
As discussed in the topic "per-entity statistics", I think it's better for this trace tool to have a flexible filter
facility. So that the user could filter out those events he doesn't care about, and at the same time, it also helps
reduce the overhead of this trace tool.
But an easy-to-use and flexible filter facility is not so easy to design. After thinking about this, I come up with a
priliminary idea. And I hope to hear more ideas and suggestions about the filter facility in this trace tool.
the filter codes make use of macros passed by -D options of stap.
I inline the modified scsi.stp to demonstrate thisidea. To make it simple, I deleted some probes & functions from
scsi.stp.
To use the filter functionalities of scsi event hook, you could just:
stap sample.stp -D FILTER_SCSI_HOST=0 -D FILTER_SCSI_CHANNEL=1 -I tapsets/
then systemtap will only probe those scsi event whose host no is 0 and channel no is 1
---------sample.stp-------
probe addevent.scsi.iocompleted { }
---------tapsets/scsi.stp---------
%{
#include <linux/types.h>
#include <scsi/scsi_cmnd.h>
#include <scsi/scsi_device.h>
#include <scsi/scsi_host.h>
#include <linux/timer.h>
#include <linux/blkdev.h>
%}
/* mid-layer processes the completed IO */
probe addevent.scsi.iocompleted
= module("scsi_mod").function("scsi_io_completion")
{
if( filter_by_scsi_host($cmd->device->host->host_no)
&& filter_by_scsi_channel($cmd->device->channel)
&& filter_by_scsi_lun($cmd->device->lun) )
{
log_tracedata_common(HOOKID_SCSI_IOCOMP_BY_MIDLEVEL)
log_scsi_iocompleted_extra($cmd, $good_bytes)
}
/* for demo, should be deleted */
else
{
log("scsi skipped")
}
}
function filter_by_scsi_host:long(var:long)
%{
#ifdef FILTER_SCSI_HOST
if( (long)(THIS->var) == FILTER_SCSI_HOST)
THIS->__retvalue = 1;
else
THIS->__retvalue = 0;
#else
THIS->__retvalue = 1;
#endif
%}
function filter_by_scsi_channel:long(var:long)
%{
#ifdef FILTER_SCSI_CHANNEL
if( (long)(THIS->var) == FILTER_SCSI_CHANNEL)
THIS->__retvalue = 1;
else
THIS->__retvalue = 0;
#else
THIS->__retvalue = 1;
#endif
%}
function filter_by_scsi_lun:long(var:long)
%{
#ifdef FILTER_SCSI_LUN
if( (long)(THIS->var) == FILTER_SCSI_LUN)
THIS->__retvalue = 1;
else
THIS->__retvalue = 0;
#else
THIS->__retvalue = 1;
#endif
%}
/* log the info about scsi_dispatching_cmd */
function log_scsi_iocompleted_extra(var_cmd:long, var_goodbytes:long)
%{
struct scsi_cmnd *cmd = (struct scsi_cmnd *)((long)THIS->var_cmd);
long long scsi_info;
unsigned long goodbytes = (unsigned long)(THIS->var_goodbytes);
scsi_info = ((cmd->device->host->host_no & 0xFF) << 24) |
((cmd->device->channel & 0xFF) << 16) |
((cmd->device->lun & 0xFF) << 8) |
(cmd->device->id & 0xFF);
/* scsi_info|data_direction|cmd_identifier|goodbytes */
_stp_printf("%lld|%d|%d|%u", scsi_info, cmd->sc_data_direction, cmd->pid, goodbytes);
%}