summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorguanglei <guanglei>2006-05-18 10:07:15 +0000
committerguanglei <guanglei>2006-05-18 10:07:15 +0000
commit739aa6f5209c3756d42de8380107f49891044bd8 (patch)
treea607b009430c3b89908fe8d8b948e50addeed441
parente55fe027da6703dd1222b2503f2a89cdb30eeea5 (diff)
downloadsystemtap-steved-739aa6f5209c3756d42de8380107f49891044bd8.tar.gz
systemtap-steved-739aa6f5209c3756d42de8380107f49891044bd8.tar.xz
systemtap-steved-739aa6f5209c3756d42de8380107f49891044bd8.zip
Check into CVS the tracing specific tapsets used by LKET.
And some minor changes to current tapsets
-rw-r--r--tapset/ChangeLog7
-rw-r--r--tapset/LKET/Changelog7
-rwxr-xr-xtapset/LKET/hookid_defs.stp107
-rwxr-xr-xtapset/LKET/ioscheduler.stp182
-rwxr-xr-xtapset/LKET/lket_trace.stp129
-rwxr-xr-xtapset/LKET/netdev.stp66
-rwxr-xr-xtapset/LKET/pagefault.stp22
-rwxr-xr-xtapset/LKET/process.stp68
-rwxr-xr-xtapset/LKET/scsi.stp206
-rwxr-xr-xtapset/LKET/syscalls.stp41
-rwxr-xr-xtapset/LKET/tskdispatch.stp71
-rwxr-xr-xtapset/LKET/utils.stp33
-rw-r--r--tapset/context.stp4
-rw-r--r--tapset/ppc64/syscalls.stp3
-rw-r--r--tapset/scheduler.stp6
15 files changed, 951 insertions, 1 deletions
diff --git a/tapset/ChangeLog b/tapset/ChangeLog
index aa5fef32..8491b460 100644
--- a/tapset/ChangeLog
+++ b/tapset/ChangeLog
@@ -1,5 +1,12 @@
2006-05-18 Li Guanglei <guanglei@cn.ibm.com>
+ * tapset/LKET/*: tracing tapsets of LKET
+ * tapset/context.stp: add stp_pid() func
+ * tapset/ppc64/syscalls.stp: add conditional preprocessing
+ since sys64_time is removed from kernel >= 2.6.1
+
+2006-05-18 Li Guanglei <guanglei@cn.ibm.com>
+
* tapset/tskschedule.stp: deleted, merge into scheduler.stp
* tapset/scheduler.stp: incorporate tskschedule.stp
diff --git a/tapset/LKET/Changelog b/tapset/LKET/Changelog
new file mode 100644
index 00000000..af1b9dab
--- /dev/null
+++ b/tapset/LKET/Changelog
@@ -0,0 +1,7 @@
+2006-05-18 Li Guanglei <guanglei@cn.ibm.com>
+
+ Initial version by Li Guanglei.
+ * hookid_defs.stp, ioscheduler.stp, lket_trace.stp, netdev.stp,
+ pagefault.stp, process.stp, scsi.stp, syscalls.stp, tskdispatch.stp,
+ utils.stp
+
diff --git a/tapset/LKET/hookid_defs.stp b/tapset/LKET/hookid_defs.stp
new file mode 100755
index 00000000..dc6f7749
--- /dev/null
+++ b/tapset/LKET/hookid_defs.stp
@@ -0,0 +1,107 @@
+global
+ /* syscall */
+ GROUP_SYSCALL,
+ HOOKID_SYSCALL_ENTRY, HOOKID_SYSCALL_RETURN,
+
+ /* process creation */
+ GROUP_PROCESS,
+ HOOKID_PROCESS_SNAPSHOT, HOOKID_PROCESS_FORK,
+ HOOKID_PROCESS_EXECVE,
+
+ /* io scheduler */
+ GROUP_IOSCHED,
+ HOOKID_IOSCHED_NEXT_REQ, HOOKID_IOSCHED_ADD_REQ,
+ HOOKID_IOSCHED_REMOVE_REQ,
+
+ /* task dispatching */
+ GROUP_TASK,
+ HOOKID_TASK_CTXSWITCH, HOOKID_TASK_CPUIDLE,
+
+ /* scsi */
+ GROUP_SCSI,
+ HOOKID_SCSI_IOENTRY, HOOKID_SCSI_IO_TO_LLD,
+ HOOKID_SCSI_IODONE_BY_LLD, HOOKID_SCSI_IOCOMP_BY_MIDLEVEL,
+
+ /* page fault */
+ GROUP_PAGEFAULT,
+ HOOKID_PAGEFAULT,
+
+ /* network device */
+ GROUP_NETDEV,
+ HOOKID_NETDEV_RECEIVE, HOOKID_NETDEV_TRANSMIT
+%{
+/* used in embedded c codes */
+
+/* Group ID Definitions */
+int _GROUP_SYSCALL = 1;
+int _GROUP_PROCESS = 2;
+int _GROUP_IOSCHED = 3;
+int _GROUP_TASK = 4;
+int _GROUP_SCSI = 5;
+int _GROUP_PAGEFAULT = 6;
+int _GROUP_NETDEV = 7;
+
+/* hookIDs defined inside each group */
+int _HOOKID_SYSCALL_ENTRY = 1;
+int _HOOKID_SYSCALL_RETURN = 2;
+
+int _HOOKID_PROCESS_SNAPSHOT = 1;
+int _HOOKID_PROCESS_EXECVE = 2;
+int _HOOKID_PROCESS_FORK = 3;
+
+int _HOOKID_IOSCHED_NEXT_REQ = 1;
+int _HOOKID_IOSCHED_ADD_REQ = 2;
+int _HOOKID_IOSCHED_REMOVE_REQ = 3;
+
+int _HOOKID_TASK_CTXSWITCH = 1;
+int _HOOKID_TASK_CPUIDLE = 2;
+
+int _HOOKID_SCSI_IOENTRY = 1;
+int _HOOKID_SCSI_IO_TO_LLD = 2;
+int _HOOKID_SCSI_IODONE_BY_LLD = 3;
+int _HOOKID_SCSI_IOCOMP_BY_MIDLEVEL = 4;
+
+int _HOOKID_PAGEFAULT = 1;
+
+int _HOOKID_NETDEV_RECEIVE = 1;
+int _HOOKID_NETDEV_TRANSMIT = 2;
+
+%}
+
+probe begin
+{
+ GROUP_SYSCALL = 1
+ HOOKID_SYSCALL_ENTRY = 1
+ HOOKID_SYSCALL_RETURN = 2
+
+ GROUP_PROCESS = 2
+ HOOKID_PROCESS_SNAPSHOT = 1
+ HOOKID_PROCESS_EXECVE = 2
+ HOOKID_PROCESS_FORK = 3
+
+ GROUP_IOSCHED = 3
+ HOOKID_IOSCHED_NEXT_REQ = 1
+ HOOKID_IOSCHED_ADD_REQ = 2
+ HOOKID_IOSCHED_REMOVE_REQ = 3
+
+ GROUP_TASK = 4
+ HOOKID_TASK_CTXSWITCH = 1
+ HOOKID_TASK_CPUIDLE = 2
+
+ GROUP_SCSI = 5
+ HOOKID_SCSI_IOENTRY = 1
+ HOOKID_SCSI_IO_TO_LLD = 2
+ HOOKID_SCSI_IODONE_BY_LLD = 3
+ HOOKID_SCSI_IOCOMP_BY_MIDLEVEL = 4
+
+ GROUP_PAGEFAULT = 6
+ HOOKID_PAGEFAULT = 1
+
+ GROUP_NETDEV = 7
+ HOOKID_NETDEV_RECEIVE = 1
+ HOOKID_NETDEV_TRANSMIT = 2
+
+ lket_trace_init()
+
+ process_snapshot()
+}
diff --git a/tapset/LKET/ioscheduler.stp b/tapset/LKET/ioscheduler.stp
new file mode 100755
index 00000000..8e238a8d
--- /dev/null
+++ b/tapset/LKET/ioscheduler.stp
@@ -0,0 +1,182 @@
+// Copyright (C) 2005, 2006 IBM Corp.
+//
+// This file is part of systemtap, and is free software. You can
+// redistribute it and/or modify it under the terms of the GNU General
+// Public License (GPL); either version 2, or (at your option) any
+// later version.
+
+/* only print backtrace for elv_add_request & elv_next_request*/
+probe addevent.ioscheduler
+ = addevent.ioscheduler.elv_next_request,
+ addevent.ioscheduler.elv_completed_request,
+ addevent.ioscheduler.elv_add_request
+{
+}
+
+/* when a request is retrieved from request queue */
+probe addevent.ioscheduler.elv_next_request
+ += ioscheduler.elv_next_request
+{
+ if(filter_by_pid() == 1 ) {
+ log_ioscheduler_tracedata_elv_next(HOOKID_IOSCHED_NEXT_REQ, $q, backtrace)
+ }
+}
+
+
+/* when a request is added to the request queue */
+probe addevent.ioscheduler.elv_add_request
+ += ioscheduler.elv_add_request
+{
+ if(filter_by_pid() == 1 ) {
+ log_ioscheduler_tracedata_others(HOOKID_IOSCHED_ADD_REQ, $q, $rq, backtrace)
+ }
+}
+
+/* when a request is completed */
+probe addevent.ioscheduler.elv_completed_request
+ = ioscheduler.elv_completed_request
+{
+ if(filter_by_pid() == 1 ) {
+ log_ioscheduler_tracedata_others(HOOKID_IOSCHED_REMOVE_REQ, $q, $rq, backtrace)
+ }
+}
+
+
+%{
+#include <linux/blkdev.h>
+#include <linux/elevator.h>
+%}
+
+/* log the data specific to __elv_add_request and elv_remove_request */
+%( kernel_v >= "2.6.10" %?
+
+function log_ioscheduler_tracedata_others(var_id:long, var_q:long, var_rq:long, backtrace:long)
+%{
+ struct request *rq = (struct request *)((long)THIS->var_rq);
+ struct request_queue *q = (struct request_queue *)((long)THIS->var_q);
+
+ /* elevator name|major|minor| */
+
+ /* only print backtrace for elv_add_request */
+ if(THIS->backtrace == 1) {
+ String str = _stp_string_init (0);
+ _stp_stack_sprint (str, CONTEXT->regs, 0);
+
+ _lket_trace(_GROUP_IOSCHED, THIS->var_id, "%0s%1b%1b%0s", q->elevator->elevator_type->elevator_name,
+ rq->rq_disk->major, rq->rq_disk->first_minor, _stp_string_ptr(str));
+ } else {
+ _lket_trace(_GROUP_IOSCHED, THIS->var_id, "%0s%1b%1b", q->elevator->elevator_type->elevator_name,
+ rq->rq_disk->major, rq->rq_disk->first_minor);
+ }
+%}
+
+%:
+
+function log_ioscheduler_tracedata_others(var_id:long, var_q:long, var_rq:long, backtrace:long)
+%{
+ struct request *rq = (struct request *)((long)THIS->var_rq);
+ struct request_queue *q = (struct request_queue *)((long)THIS->var_q);
+
+ /* elevator name|major|minor| */
+
+ /* only print backtrace for elv_add_request */
+ if(THIS->backtrace == 1) {
+ String str = _stp_string_init (0);
+ _stp_stack_sprint (str, CONTEXT->regs, 0);
+
+ _lket_trace(_GROUP_IOSCHED, THIS->var_id, "%0s%1b%1b%0s", q->elevator.elevator_name,
+ rq->rq_disk->major, rq->rq_disk->first_minor, _stp_string_ptr(str));
+ } else {
+ _lket_trace(_GROUP_IOSCHED, THIS->var_id, "%0s%1b%1b", q->elevator.elevator_name,
+ rq->rq_disk->major, rq->rq_disk->first_minor);
+ }
+%}
+
+%)
+
+/* log the data specific to elv_next_request, for kernel == 2.6.9 */
+%( kernel_v >= "2.6.10" %?
+
+/* log the data specific to elv_next_request , for kernel > 2.6.9*/
+function log_ioscheduler_tracedata_elv_next(var_id:long, var:long, backtrace:long)
+%{
+
+ struct request_queue *q;
+ struct request *rq;
+
+ q = (struct request_queue *)((long)THIS->var);
+
+ /* If there is a request in the request queue:
+ elevator name|major|minor|
+ if there is no request in the request queue:
+ elevator name|empty|
+ */
+
+ if(THIS->backtrace == 1) {
+ String str = _stp_string_init (0);
+ _stp_stack_sprint (str, CONTEXT->regs, 0);
+
+ if(list_empty(&(q->queue_head))) {
+ _lket_trace(_GROUP_IOSCHED, THIS->var_id, "%0s%1b%1b%0s",
+ q->elevator->elevator_type->elevator_name, -1, -1, _stp_string_ptr(str));
+ } else {
+ rq = list_entry_rq(q->queue_head.next);
+ _lket_trace(_GROUP_IOSCHED, THIS->var_id, "%0s%1b%1b%0s",
+ q->elevator->elevator_type->elevator_name, rq->rq_disk->major,
+ rq->rq_disk->first_minor, _stp_string_ptr(str));
+ }
+ } else {
+ if(list_empty(&(q->queue_head))) {
+ _lket_trace(_GROUP_IOSCHED, THIS->var_id, "%0s%1b%1b",
+ q->elevator->elevator_type->elevator_name, -1, -1);
+ } else {
+ rq = list_entry_rq(q->queue_head.next);
+ _lket_trace(_GROUP_IOSCHED, THIS->var_id, "%0s%1b%1b",
+ q->elevator->elevator_type->elevator_name, rq->rq_disk->major,
+ rq->rq_disk->first_minor);
+ }
+
+ }
+%}
+
+%:
+
+function log_ioscheduler_tracedata_elv_next(var_id:long, var:long, backtrace:long)
+%{
+
+ struct request_queue *q;
+ struct request *rq;
+
+ q = (struct request_queue *)((long)THIS->var);
+
+ /* If there is a request in the request queue:
+ elevator name|major|minor|
+ if there is no request in the request queue:
+ elevator name|empty|
+ */
+ if(THIS->backtrace == 1) {
+ String str = _stp_string_init (0);
+ _stp_stack_sprint (str, CONTEXT->regs, 0);
+
+ if(list_empty(&(q->queue_head))) {
+ _lket_trace(_GROUP_IOSCHED, THIS->var_id, "%0s%1b%1b%0s",
+ q->elevator.elevator_name, -1, -1, _stp_string_ptr(str));
+ } else {
+ rq = list_entry_rq(q->queue_head.next);
+ _lket_trace(_GROUP_IOSCHED, THIS->var_id, "%0s%1b%1b%0s", q->elevator.elevator_name,
+ rq->rq_disk->major, rq->rq_disk->first_minor, _stp_string_ptr(str));
+ }
+ } else {
+ if(list_empty(&(q->queue_head))) {
+ _lket_trace(_GROUP_IOSCHED, THIS->var_id, "%0s%1b%1b",
+ q->elevator.elevator_name, -1, -1);
+ } else {
+ rq = list_entry_rq(q->queue_head.next);
+ _lket_trace(_GROUP_IOSCHED, THIS->var_id, "%0s%1b%1b", q->elevator.elevator_name,
+ rq->rq_disk->major, rq->rq_disk->first_minor);
+ }
+ }
+
+%}
+
+%)
diff --git a/tapset/LKET/lket_trace.stp b/tapset/LKET/lket_trace.stp
new file mode 100755
index 00000000..d06d09d2
--- /dev/null
+++ b/tapset/LKET/lket_trace.stp
@@ -0,0 +1,129 @@
+// Copyright (C) 2005, 2006 IBM Corp.
+//
+// This file is part of systemtap, and is free software. You can
+// redistribute it and/or modify it under the terms of the GNU General
+// Public License (GPL); either version 2, or (at your option) any
+// later version.
+
+function lket_trace_header_init()
+%{
+
+/* header info for binary format*/
+#if !defined(ASCII_TRACE) && !defined(ASCII_TRACE_LEGACY)
+
+#define MAGIC_NUMBER 0xAEFCDB6B
+#define LKET_TRACE_VER_MAJOR 0x01
+#define LKET_TRACE_VER_MINOR 0x01 /* used for user customization */
+#define LITTLE_ENDIAN 0x01
+#define BIG_ENDIAN 0x02
+#define BITS_WIDTH 64 /* 32-bit or 64-bit environment*/
+
+#define LKET_HEADER_LEN 0 /* fake number, bin_write will fill in the
+ actual length of trace header */
+
+ _stp_printf("%4b%2n%1b%1b%1b%1b", MAGIC_NUMBER, LKET_HEADER_LEN, LKET_TRACE_VER_MAJOR,
+ LKET_TRACE_VER_MINOR, BIG_ENDIAN, BITS_WIDTH);
+ _stp_print_flush();
+#endif
+
+%}
+
+function lket_trace_init()
+{
+ lket_trace_header_init()
+}
+
+%{
+#ifndef __LKET_TRACE__
+#define __LKET_TRACE__
+
+#define STP_BIN_PACKET 1
+
+
+#define MAX_FMT_LEN 128
+char newfmt[MAX_FMT_LEN] = "\n%d|%d|%d|%d|%d|%d|%d|%d";
+#define NEW_FMT_START 24
+
+void fmt_change(char *oldfmt)
+{
+ char *old_ptr, *new_ptr;
+
+ old_ptr = oldfmt;
+ new_ptr = newfmt + NEW_FMT_START;
+
+ while(*old_ptr != 0 && (new_ptr - newfmt) < MAX_FMT_LEN) {
+ if(*old_ptr != '%') {
+ *new_ptr++ = *old_ptr++;
+ continue;
+ } else {
+ *new_ptr++ = '|'; /* delimier to make it readable */
+ *new_ptr++ = *old_ptr++;
+ while( *old_ptr == 'L' || *old_ptr == 'l'
+ || isdigit(*old_ptr) ) {
+ *new_ptr++ = *old_ptr++;
+ }
+ if( *old_ptr == 'b') {
+ if(isdigit(*(old_ptr-1))) {
+ if(*(old_ptr-1) == '1' ||
+ *(old_ptr-1) == '2' ||
+ *(old_ptr-1) == '3' ||
+ *(old_ptr-1) == '4') {
+ new_ptr--;
+ } else if(*(old_ptr-1) == '8') {
+ *--new_ptr='l';
+ *++new_ptr='l';
+ new_ptr++;
+ }
+ }
+ *new_ptr++ = 'd';
+ old_ptr++;
+ }
+ else if ( *old_ptr == 's') {
+ if(isdigit(*(old_ptr-1)) && *(old_ptr-1)=='0')
+ new_ptr--;
+ *new_ptr++ = 's';
+ old_ptr++;
+ } else
+ *new_ptr++ = *old_ptr++;
+ }
+ }
+ *new_ptr=0;
+}
+
+/* trace data in ASCII format
+ Format of the common prefix of the trace data:
+ groupid|subhookid|sec|usec|tgid|ppid|pid|cpuid|
+*/
+#if defined(ASCII_TRACE)
+
+#define _lket_trace(GroupID, hookID, fmt, args...) do { \
+ struct timeval tv; \
+ do_gettimeofday (&tv); \
+ fmt_change(fmt); \
+ _stp_printf(newfmt, \
+ GroupID, hookID, tv.tv_sec, tv.tv_usec, current->tgid, \
+ current->parent->pid, current->pid, \
+ current->thread_info->cpu, args);\
+} while(0)
+
+#else //binary trace
+
+static inline int this_event_len(void)
+{
+ return 0;
+}
+
+/* we use 2 bytes to store the length. 256 may be not enough for backtrace event */
+#define _lket_trace(GroupID, hookID, fmt, args...) do { \
+ struct timeval tv; \
+ do_gettimeofday (&tv); \
+ _stp_printf("%1b%2n%1b%1b%4b%4b%4b%4b%4b%1b"fmt, \
+ (int64_t)STP_BIN_PACKET, (int64_t)GroupID, (int64_t)hookID, \
+ (int64_t)tv.tv_sec, (int64_t)tv.tv_usec, (int64_t)current->tgid, \
+ (int64_t)current->parent->pid, (int64_t)current->pid, \
+ (int64_t)current->thread_info->cpu, args);\
+} while(0)
+
+#endif
+#endif
+%}
diff --git a/tapset/LKET/netdev.stp b/tapset/LKET/netdev.stp
new file mode 100755
index 00000000..04413b23
--- /dev/null
+++ b/tapset/LKET/netdev.stp
@@ -0,0 +1,66 @@
+// Copyright (C) 2005, 2006 IBM Corp.
+//
+// This file is part of systemtap, and is free software. You can
+// redistribute it and/or modify it under the terms of the GNU General
+// Public License (GPL); either version 2, or (at your option) any
+// later version
+
+%{
+#include <linux/netdevice.h>
+%}
+
+probe addevent.netdev
+ = addevent.netdev.receive, addevent.netdev.transmit
+{
+}
+
+/* Main device receive routine, be called when packet arrives on network device */
+probe addevent.netdev.receive
+ = netdev.receive
+{
+ /* no need to filter by pid */
+ log_netdev_extra(HOOKID_NETDEV_RECEIVE,$skb, backtrace)
+}
+
+/* Queue a buffer for transmission to a network device */
+probe addevent.netdev.transmit
+ += netdev.transmit
+{
+ if(filter_by_pid() == 1 ) {
+ log_netdev_extra(HOOKID_NETDEV_TRANSMIT, $skb, backtrace)
+ }
+}
+
+function log_netdev_extra(var_id:long, var:long, backtrace:long)
+%{
+ struct sk_buff *skb = (struct sk_buff *)THIS->var;
+
+ /* dev_name | Length of actual data | protocol | Buffer size
+
+ skb->protocol is:
+ 0800 IP
+ 8100 802.1Q VLAN
+ 0001 802.3
+ 0002 AX.25
+ 0004 802.2
+ 8035 RARP
+ 0005 SNAP
+ 0805 X.25
+ 0806 ARP
+ 8137 IPX
+ 0009 Localtalk
+ 86DD IPv6
+ */
+
+ /* only print backtrace for netdev.transmit */
+ if(THIS->backtrace == 1) {
+ String str = _stp_string_init (0);
+ _stp_stack_sprint (str, CONTEXT->regs, 0);
+
+ _lket_trace(_GROUP_NETDEV, THIS->var_id, "%0s%4b%2b%4b%0s", skb->dev->name,
+ skb->len, skb->protocol, skb->truesize, _stp_string_ptr(str));
+ } else {
+ _lket_trace(_GROUP_NETDEV, THIS->var_id, "%0s%4b%2b%4b", skb->dev->name,
+ skb->len, skb->protocol, skb->truesize);
+ }
+%}
diff --git a/tapset/LKET/pagefault.stp b/tapset/LKET/pagefault.stp
new file mode 100755
index 00000000..2ac44af0
--- /dev/null
+++ b/tapset/LKET/pagefault.stp
@@ -0,0 +1,22 @@
+// networking tapset
+// Copyright (C) 2005, 2006 IBM Corp.
+//
+// This file is part of systemtap, and is free software. You can
+// redistribute it and/or modify it under the terms of the GNU General
+// Public License (GPL); either version 2, or (at your option) any
+// later version.
+
+function log_pagefault_tracedata(var_id:long, var_addr:long, var_rwflag:long)
+%{
+ _lket_trace(_GROUP_PAGEFAULT, THIS->var_id, "%8b%1b", (long)(THIS->var_addr), (THIS->var_rwflag)?1:0);
+%}
+
+
+/* Record the page fault event */
+probe addevent.pagefault
+ = pagefault
+{
+ if(filter_by_pid() == 1 ) {
+ log_pagefault_tracedata(HOOKID_PAGEFAULT, $address, $write_access)
+ }
+}
diff --git a/tapset/LKET/process.stp b/tapset/LKET/process.stp
new file mode 100755
index 00000000..e17a5514
--- /dev/null
+++ b/tapset/LKET/process.stp
@@ -0,0 +1,68 @@
+// Copyright (C) 2005, 2006 IBM Corp.
+//
+// This file is part of systemtap, and is free software. You can
+// redistribute it and/or modify it under the terms of the GNU General
+// Public License (GPL); either version 2, or (at your option) any
+// later version.
+
+/* record the newly created process name */
+function log_execve_tracedata(var_id:long, var:long)
+%{
+ long tmp=(long)THIS->var;
+ _lket_trace(_GROUP_PROCESS, THIS->var_id, "%0s", (char *)tmp);
+%}
+
+
+/* record the newly forked process id */
+function log_fork_tracedata(var_id:long, var:long)
+%{
+ pid_t pid = (pid_t)THIS->var;
+ _lket_trace(_GROUP_PROCESS, THIS->var_id, "%4b", pid);
+%}
+
+
+/************************************************************
+* This function could be used to take a snapshot of all the *
+* processes. It's not a probe, so the data format doesn't *
+* follow the format used by probe handlers *
+************************************************************/
+function process_snapshot()
+%{
+ struct task_struct *tsk;
+ struct list_head *cur, *head;
+ head = &(current->tasks);
+
+ /* iterate all the processes, and record the pid and process
+ name for each entry */
+ list_for_each(cur, head) {
+ tsk = (struct task_struct *)(list_entry(cur, struct task_struct, tasks));
+ _lket_trace(_GROUP_PROCESS, _HOOKID_PROCESS_SNAPSHOT, "%4b%0s", tsk->pid, tsk->comm);
+ _stp_print_flush();
+ }
+%}
+
+
+probe addevent.process
+ = addevent.process.fork, addevent.process.execve
+{
+}
+
+/*
+ we should capture both do_execve for 64-bit app
+ and compat_do_execve for 32-bit app
+*/
+probe addevent.process.execve
+ = process.exec
+{
+ if(filter_by_pid() == 1 ) {
+ log_execve_tracedata(HOOKID_PROCESS_EXECVE, $filename)
+ }
+}
+
+probe addevent.process.fork
+ = process.create
+{
+ if(filter_by_pid() == 1 ) {
+ log_fork_tracedata(HOOKID_PROCESS_FORK, new_pid)
+ }
+}
diff --git a/tapset/LKET/scsi.stp b/tapset/LKET/scsi.stp
new file mode 100755
index 00000000..0f38b33c
--- /dev/null
+++ b/tapset/LKET/scsi.stp
@@ -0,0 +1,206 @@
+// Copyright (C) 2005, 2006 IBM Corp.
+//
+// This file is part of systemtap, and is free software. You can
+// redistribute it and/or modify it under the terms of the GNU General
+// Public License (GPL); either version 2, or (at your option) any
+// later version
+
+/***********************************************************
+* Trace the following activities of scsi layer: *
+* 1. I/O Entry *
+* 2. Issuing I/O to LLD *
+* 3. I/O done by LLD *
+* 4. I/O Complete *
+* *
+***********************************************************/
+
+%{
+#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>
+%}
+
+probe addevent.scsi
+ = addevent.scsi.ioentry,
+ addevent.scsi.iodispatching,
+ addevent.scsi.iodone,
+ addevent.scsi.iocompleted
+{
+}
+
+/* mid-layer prepare a IO request */
+probe addevent.scsi.ioentry
+ += scsi.ioentry
+{
+ log_scsi_ioentry(HOOKID_SCSI_IOENTRY, $q, $req, backtrace)
+}
+
+/* Dispatch a command to the low-level driver. */
+probe addevent.scsi.iodispatching
+ += scsi.iodispatching
+{
+ log_scsi_dispatch(HOOKID_SCSI_IO_TO_LLD, $cmd, backtrace)
+}
+
+/* I/O is done by low-level driver*/
+probe addevent.scsi.iodone
+ = scsi.iodone
+{
+ /* scsi timer check. We should record the hook only
+ * when the timer is inactive. But there's a gap between
+ * the checking and the actual calling of scsi_delete_timer.
+ */
+ if( scsi_timer_pending($cmd) == 1) {
+ log_scsi_iodone_extra(HOOKID_SCSI_IODONE_BY_LLD, $cmd)
+ }
+}
+
+/* mid-layer processes the completed IO */
+probe addevent.scsi.iocompleted
+ = scsi.iocompleted
+{
+ log_scsi_iocompleted(HOOKID_SCSI_IOCOMP_BY_MIDLEVEL, $cmd, $good_bytes)
+}
+
+/* log the info about scsi io entry */
+function log_scsi_ioentry(var_id:long, var_q:long, var_rq:long, backtrace:long)
+%{
+ struct request_queue *q = (struct request_queue *)((long)THIS->var_q);
+ struct request *rq = (struct request *)((long)THIS->var_rq);
+ struct scsi_device *sdev = (struct scsi_device *)(q->queuedata);
+
+ /*
+ major|minor|scsi_device_state|
+ */
+ if(THIS->backtrace == 1) {
+ String str = _stp_string_init (0);
+ _stp_stack_sprint (str, CONTEXT->regs, 0);
+ _lket_trace(_GROUP_SCSI, THIS->var_id, "%1b%1b%1b%0s", rq->rq_disk->major,
+ rq->rq_disk->first_minor, sdev->sdev_state, _stp_string_ptr(str));
+ } else {
+ _lket_trace(_GROUP_SCSI, THIS->var_id, "%1b%1b%1b", rq->rq_disk->major,
+ rq->rq_disk->first_minor, sdev->sdev_state);
+ }
+%}
+
+/* log the info about scsi_dispatching_cmd
+ *
+ *
+ * Now we can use cmd->serial_number as cmd identifier
+ * But according to the comments of struct scsi_cmnd, it's
+ * a better to use cmd->pid since cmd->serial_number will be killed one
+ * day in the future
+ *
+ * But when scsi_dispatch_cmd is called, cmd->serial_number is still not
+ * initialized.
+ *
+ * For kernel >= 2.6.12, it will be set later by calling scsi_cmd_get_serial.
+ * So I choose to record cmd->device->host->cmd_pid. But there is a gap between
+ * the time when cmd->device->host->cmd_pid is retrieved at the beginning of
+ * scsi_dispatch_cmd and the actual calling of scsi_cmd_get_serial.
+ *
+ * For kernel <=2.6.9, it will be set by a global counter.
+ *
+ * NOTE: The kernel version need further investigation.
+ */
+
+/* sdev_state|scsi_info|data_direction|request_buffer|request_bufflen|cmd_identifier| */
+%( kernel_v >= "2.6.12" %?
+function log_scsi_dispatch(var_id:long, var:long, backtrace:long)
+%{
+ struct scsi_cmnd *cmd = (struct scsi_cmnd *)((long)THIS->var);
+ int scsi_info;
+
+ scsi_info = ((cmd->device->host->host_no & 0xFF) << 24) |
+ ((cmd->device->channel & 0xFF) << 16) |
+ ((cmd->device->lun & 0xFF) << 8) |
+ (cmd->device->id & 0xFF);
+
+ /* sdev_state|scsi_info|data_direction|cmd_identifier|request_buffer|request_bufflen
+ *
+ * sdev_state could be: SDEV_DEL, SDEV_BLOCK or something else.
+ * Instead of skipping SDEV_DEL & SDEV_BLOCK, I choose to log them
+ */
+
+ if(THIS->backtrace == 1) {
+ String str = _stp_string_init (0);
+ _stp_stack_sprint (str, CONTEXT->regs, 0);
+
+ _lket_trace(_GROUP_SCSI, THIS->var_id, "%1b%4b%1b%8b%4b%8b%0s", cmd->device->sdev_state,
+ scsi_info, cmd->sc_data_direction, cmd->request_buffer, cmd->request_bufflen,
+ cmd->device->host->cmd_pid, _stp_string_ptr(str));
+ } else {
+
+ _lket_trace(_GROUP_SCSI, THIS->var_id, "%1b%4b%1b%8b%4b%8b", cmd->device->sdev_state,
+ scsi_info, cmd->sc_data_direction, cmd->request_buffer, cmd->request_bufflen,
+ cmd->device->host->cmd_pid);
+ }
+
+%}
+%:
+
+function log_scsi_dispatch(var_id:long, var:long, backtrace:long)
+%{
+ struct scsi_cmnd *cmd = (struct scsi_cmnd *)((long)THIS->var);
+ int scsi_info;
+
+ scsi_info = ((cmd->device->host->host_no & 0xFF) << 24) |
+ ((cmd->device->channel & 0xFF) << 16) |
+ ((cmd->device->lun & 0xFF) << 8) |
+ (cmd->device->id & 0xFF);
+
+ /* sdev_state|scsi_info|data_direction|cmd_identifier|request_buffer|request_bufflen
+ *
+ * sdev_state could be: SDEV_DEL, SDEV_BLOCK or something else.
+ * Instead of skipping SDEV_DEL & SDEV_BLOCK, I choose to log them
+ */
+
+ /* systemTap failed to access global variable. So I temporarily use 0.
+ _stp_printf("%d|", scsi_pid);
+ */
+ if(THIS->backtrace == 1) {
+ String str = _stp_string_init (0);
+ _stp_stack_sprint (str, CONTEXT->regs, 0);
+
+ _lket_trace(_GROUP_SCSI, THIS->var_id, "%1b%4b%1b%8b%4b%8b%0s", cmd->device->sdev_state, scsi_info,
+ cmd->sc_data_direction, cmd->request_buffer, cmd->request_bufflen, 0, _stp_string_ptr(str));
+ } else {
+ _lket_trace(_GROUP_SCSI, THIS->var_id, "%1b%4b%1b%8b%4b%8b", cmd->device->sdev_state, scsi_info,
+ cmd->sc_data_direction, cmd->request_buffer, cmd->request_bufflen, 0);
+ }
+%}
+%)
+
+/* log the info about scsi_done */
+function log_scsi_iodone_extra(var_id:long, var:long)
+%{
+ struct scsi_cmnd *cmd = (struct scsi_cmnd *)((long)THIS->var);
+ int scsi_info;
+
+ 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| */
+ _lket_trace(_GROUP_SCSI, THIS->var_id, "%4b%1b%8b", scsi_info, cmd->sc_data_direction, cmd->pid);
+%}
+
+/* log the info about scsi_dispatching_cmd */
+function log_scsi_iocompleted(var_id:long, var_cmd:long, var_goodbytes:long)
+%{
+ struct scsi_cmnd *cmd = (struct scsi_cmnd *)((long)THIS->var_cmd);
+ int 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 */
+ _lket_trace(_GROUP_SCSI, THIS->var_id, "%4b%1b%8b%4b", scsi_info, cmd->sc_data_direction, cmd->pid, goodbytes);
+%}
diff --git a/tapset/LKET/syscalls.stp b/tapset/LKET/syscalls.stp
new file mode 100755
index 00000000..7215f4f5
--- /dev/null
+++ b/tapset/LKET/syscalls.stp
@@ -0,0 +1,41 @@
+// Copyright (C) 2005, 2006 IBM Corp.
+//
+// This file is part of systemtap, and is free software. You can
+// redistribute it and/or modify it under the terms of the GNU General
+// Public License (GPL); either version 2, or (at your option) any
+// later version.
+
+probe addevent.syscall
+ = addevent.syscall.entry, addevent.syscall.return
+{
+}
+
+/* log the system call name */
+function log_syscall_tracedata(var_id:long, name:string, backtrace:long)
+%{
+ if(THIS->backtrace == 1) {
+ String str = _stp_string_init (0);
+ _stp_stack_sprint (str, CONTEXT->regs, 0);
+
+ _lket_trace(_GROUP_SYSCALL, THIS->var_id, "%0s%0s", THIS->name, _stp_string_ptr(str));
+ } else {
+ _lket_trace(_GROUP_SYSCALL, THIS->var_id, "%0s", THIS->name);
+ }
+%}
+
+
+probe addevent.syscall.entry
+ += syscall.*
+{
+ if(filter_by_pid() == 1 ) {
+ log_syscall_tracedata(HOOKID_SYSCALL_ENTRY, name, backtrace)
+ }
+}
+
+probe addevent.syscall.return
+ += syscall.*.return
+{
+ if(filter_by_pid() == 1 ) {
+ log_syscall_tracedata(HOOKID_SYSCALL_RETURN, name, backtrace)
+ }
+}
diff --git a/tapset/LKET/tskdispatch.stp b/tapset/LKET/tskdispatch.stp
new file mode 100755
index 00000000..bb758144
--- /dev/null
+++ b/tapset/LKET/tskdispatch.stp
@@ -0,0 +1,71 @@
+// Copyright (C) 2005, 2006 IBM Corp.
+//
+// This file is part of systemtap, and is free software. You can
+// redistribute it and/or modify it under the terms of the GNU General
+// Public License (GPL); either version 2, or (at your option) any
+// later version.
+
+/**********************************************************
+* Dispatching when the cpu is idle or when a new process *
+* is chosen to run. *
+* *
+* The actual locations for these two kinds of events are *
+* the labels go_idle and switch_tasks inside the function *
+* schedule. But currently SystemTap doesn't support *
+* specifying probe points by label. *
+* *
+**********************************************************/
+probe addevent.tskdispatch
+ = addevent.tskdispatch.ctxswitch,
+ addevent.tskdispatch.cpuidle
+{
+}
+
+/* Only applicable to SMP systems */
+probe addevent.tskdispatch.cpuidle
+ += scheduler.balance
+{
+ /* we didn't call filter_by_pid() here,
+ so that we can get all the idle events
+ despite how the cpu enters idle */
+ log_cpuidle_tracedata(HOOKID_TASK_CPUIDLE, backtrace)
+}
+
+probe addevent.tskdispatch.ctxswitch
+ = scheduler.ctxswitch
+{
+ target_pid = target()
+ cur_pid = pid()
+ if( stp_pid() != cur_pid ) { /* skip stpd itself */
+ if(target_pid == 0 || (target_pid !=0 && ($prev->pid == target_pid
+ || $new->pid == target_pid))) {
+ log_ctxswitch_tracedata(HOOKID_TASK_CTXSWITCH, $prev, $new)
+ }
+ }
+}
+
+function log_ctxswitch_tracedata(var_id:long, prev:long, next_pid:long)
+%{
+ struct task_struct *prev_tsk, *next_tsk;
+
+ prev_tsk = (struct task_struct *)((long)THIS->prev);
+ next_tsk = (struct task_struct *)((long)THIS->next_pid);
+
+ _lket_trace(_GROUP_TASK, THIS->var_id, "%4b%4b%1b", prev_tsk->pid, next_tsk->pid, prev_tsk->state);
+%}
+
+function log_cpuidle_tracedata(var_id:long, backtrace:long)
+%{
+ struct task_struct *cur = current;
+
+ if(THIS->backtrace == 1) {
+ String str = _stp_string_init (0);
+ _stp_stack_sprint (str, CONTEXT->regs, 0);
+ _lket_trace(_GROUP_TASK, THIS->var_id, "%4b%0s", cur->pid, _stp_string_ptr(str));
+ } else {
+ _lket_trace(_GROUP_TASK, THIS->var_id, "%4b", cur->pid);
+ }
+%}
+
+
+
diff --git a/tapset/LKET/utils.stp b/tapset/LKET/utils.stp
new file mode 100755
index 00000000..0006246e
--- /dev/null
+++ b/tapset/LKET/utils.stp
@@ -0,0 +1,33 @@
+// Copyright (C) 2005, 2006 IBM Corp.
+//
+// This file is part of systemtap, and is free software. You can
+// redistribute it and/or modify it under the terms of the GNU General
+// Public License (GPL); either version 2, or (at your option) any
+// later version.
+
+/* data tracing filter by pid
+ return:
+ 1 - if continue to log the raw data
+ 0 - return without logging the raw data
+ */
+function filter_by_pid:long()
+%{
+ struct task_struct *cur = current;
+
+ if(cur->tgid != _stp_pid) {
+ /* to trace a specific process if we explicitly specify
+ which process we want to trace by:
+ 1. stap -c "process_to_trace" ...
+ 2. stap -x pid_to_trace ...
+ else we will trace all the processes
+ */
+ if( _stp_target != 0 && cur->tgid != _stp_target) {
+ THIS->__retvalue = 0;
+ return;
+ }
+
+ THIS->__retvalue = 1;
+ } else /*skip the events generated by stap itself*/
+ THIS->__retvalue = 0;
+ return;
+%}
diff --git a/tapset/context.stp b/tapset/context.stp
index 00629900..9a46df19 100644
--- a/tapset/context.stp
+++ b/tapset/context.stp
@@ -136,3 +136,7 @@ function target:long () %{ /* pure */
%}
function returnval () { return retval () } # deprecated
+
+function stp_pid:long () %{ /* pure */
+ THIS->__retvalue = _stp_pid;
+%}
diff --git a/tapset/ppc64/syscalls.stp b/tapset/ppc64/syscalls.stp
index 52b97c50..41a31580 100644
--- a/tapset/ppc64/syscalls.stp
+++ b/tapset/ppc64/syscalls.stp
@@ -1779,6 +1779,8 @@ probe syscall.old32_readdir.return =
#
# time_t sys64_time(time_t __user * tloc)
#
+%( kernel_v <= "2.6.15" %?
+
probe syscall.sys64_time = kernel.function("sys64_time") {
name = "sys64_time"
/* FIXME */
@@ -1789,6 +1791,7 @@ probe syscall.sys64_time.return = kernel.function("sys64_time").return {
name = "sys64_time"
retstr = returnstr(1)
}
+%)
# ppc64_personality ________________________________________
#
# long ppc64_personality(unsigned long personality)
diff --git a/tapset/scheduler.stp b/tapset/scheduler.stp
index 08581332..442a8105 100644
--- a/tapset/scheduler.stp
+++ b/tapset/scheduler.stp
@@ -110,7 +110,11 @@ probe scheduler.balance = kernel.inline("idle_balance") {}
/* probe scheduler.ctxswitch
*
* Fires when there is a context switch
- *
+
+ * Currently systemTap can't access arguments of inline
+ * functions. So we choose to probe __switch_to instead
+ * of context_switch()
+
* Arguments:
* prev_pid: The pid of the process to be switched out
* next_pid: The pid of the process to be switched in