summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog25
-rw-r--r--Makefile.am2
-rw-r--r--Makefile.in8
-rw-r--r--NEWS9
-rwxr-xr-xconfigure3
-rw-r--r--configure.ac2
-rw-r--r--elaborate.cxx45
-rw-r--r--main.cxx13
-rw-r--r--runtime/ChangeLog8
-rw-r--r--runtime/task_finder.c120
-rw-r--r--stap-server.8.in177
-rw-r--r--tapset/ChangeLog10
-rw-r--r--tapset/nfs_proc.stp124
-rw-r--r--tapsets.cxx114
-rw-r--r--testsuite/ChangeLog6
-rw-r--r--testsuite/systemtap.base/utrace_p5.exp27
16 files changed, 483 insertions, 210 deletions
diff --git a/ChangeLog b/ChangeLog
index e346a764..d9eccaef 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,28 @@
+2008-08-29 Dave Brolley <brolley@redhat.com>
+
+ * stap-server.8.in: New man page.
+ * NEWS: Announce the availability of the client/server.
+ * Makefile.am (man_MANS): Add stap-server.8.
+ * configure.ac (AC_CONFIG_FILE): Add stap-server.8.
+ * Makefile.in: Regenerated.
+ * configure: Regenerated.
+
+2008-08-29 Stan Cox <scox@redhat.com>
+
+ * elaborate.cxx (add_global_var_display): Repopulate symbol/type info.
+
+2008-08-29 David Smith <dsmith@redhat.com>
+
+ * tapsets.cxx (utrace_derived_probe_group::emit_probe_decl):
+ Pushed quiesce logic down into the task_finder layer.
+ (utrace_derived_probe_group::emit_module_decls): Removed quiesce
+ handler routines. Syscall probe handler detaches if systemtap
+ state isn't correct.
+
+2008-08-29 Wenji Huang <wenji.huang@oracle.com>
+
+ * main.cxx (printscript): Print variable name and type for listing mode.
+
2008-08-28 Frank Ch. Eigler <fche@elastic.org>
* elaborate.cxx (add_global_var_display): Render array indexes
diff --git a/Makefile.am b/Makefile.am
index 867066bb..fe0fc408 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -10,7 +10,7 @@ AM_CPPFLAGS = -DBINDIR='"$(bindir)"' -DPKGDATADIR='"${pkgdatadir}"' -DPKGLIBDIR=
AM_CFLAGS = -D_GNU_SOURCE -fexceptions -Wall -Werror -Wunused -Wformat=2 -W
AM_CXXFLAGS = -Wall -Werror
-man_MANS = stap.1 stapprobes.5 stapfuncs.5 stapvars.5 stapex.5 staprun.8 man/stapprobes.iosched.5 man/stapprobes.netdev.5 man/stapprobes.nfs.5 man/stapprobes.nfsd.5 man/stapprobes.pagefault.5 man/stapprobes.process.5 man/stapprobes.rpc.5 man/stapprobes.scsi.5 man/stapprobes.signal.5 man/stapprobes.socket.5 man/stapprobes.tcp.5 man/stapprobes.udp.5
+man_MANS = stap.1 stapprobes.5 stapfuncs.5 stapvars.5 stapex.5 staprun.8 stap-server.8 man/stapprobes.iosched.5 man/stapprobes.netdev.5 man/stapprobes.nfs.5 man/stapprobes.nfsd.5 man/stapprobes.pagefault.5 man/stapprobes.process.5 man/stapprobes.rpc.5 man/stapprobes.scsi.5 man/stapprobes.signal.5 man/stapprobes.socket.5 man/stapprobes.tcp.5 man/stapprobes.udp.5
# see also configure.ac
bin_PROGRAMS = stap staprun
diff --git a/Makefile.in b/Makefile.in
index 1d3225b8..ebd158dc 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -50,7 +50,7 @@ DIST_COMMON = INSTALL NEWS README AUTHORS ChangeLog \
$(srcdir)/config.in $(srcdir)/stap.1.in \
$(srcdir)/stapprobes.5.in $(srcdir)/stapfuncs.5.in \
$(srcdir)/stapvars.5.in $(srcdir)/stapex.5.in \
- $(srcdir)/staprun.8.in \
+ $(srcdir)/staprun.8.in $(srcdir)/stap-server.8.in \
$(top_srcdir)/man/stapprobes.iosched.5.in \
$(top_srcdir)/man/stapprobes.netdev.5.in \
$(top_srcdir)/man/stapprobes.nfs.5.in \
@@ -72,7 +72,7 @@ am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \
mkinstalldirs = $(install_sh) -d
CONFIG_HEADER = config.h
CONFIG_CLEAN_FILES = stap.1 stapprobes.5 stapfuncs.5 stapvars.5 \
- stapex.5 staprun.8 man/stapprobes.iosched.5 \
+ stapex.5 staprun.8 stap-server.8 man/stapprobes.iosched.5 \
man/stapprobes.netdev.5 man/stapprobes.nfs.5 \
man/stapprobes.nfsd.5 man/stapprobes.pagefault.5 \
man/stapprobes.process.5 man/stapprobes.rpc.5 \
@@ -260,7 +260,7 @@ pkglibexecdir = ${libexecdir}/${PACKAGE}
AM_CPPFLAGS = -DBINDIR='"$(bindir)"' -DPKGDATADIR='"${pkgdatadir}"' -DPKGLIBDIR='"$(pkglibexecdir)"'
AM_CFLAGS = -D_GNU_SOURCE -fexceptions -Wall -Werror -Wunused -Wformat=2 -W
AM_CXXFLAGS = -Wall -Werror
-man_MANS = stap.1 stapprobes.5 stapfuncs.5 stapvars.5 stapex.5 staprun.8 man/stapprobes.iosched.5 man/stapprobes.netdev.5 man/stapprobes.nfs.5 man/stapprobes.nfsd.5 man/stapprobes.pagefault.5 man/stapprobes.process.5 man/stapprobes.rpc.5 man/stapprobes.scsi.5 man/stapprobes.signal.5 man/stapprobes.socket.5 man/stapprobes.tcp.5 man/stapprobes.udp.5
+man_MANS = stap.1 stapprobes.5 stapfuncs.5 stapvars.5 stapex.5 staprun.8 stap-server.8 man/stapprobes.iosched.5 man/stapprobes.netdev.5 man/stapprobes.nfs.5 man/stapprobes.nfsd.5 man/stapprobes.pagefault.5 man/stapprobes.process.5 man/stapprobes.rpc.5 man/stapprobes.scsi.5 man/stapprobes.signal.5 man/stapprobes.socket.5 man/stapprobes.tcp.5 man/stapprobes.udp.5
bin_SCRIPTS = stap-client stap-server stap-serverd stap-find-servers stap-start-server stap-find-or-start-server stap-stop-server
stap_SOURCES = main.cxx \
parse.cxx staptree.cxx elaborate.cxx translate.cxx \
@@ -388,6 +388,8 @@ stapex.5: $(top_builddir)/config.status $(srcdir)/stapex.5.in
cd $(top_builddir) && $(SHELL) ./config.status $@
staprun.8: $(top_builddir)/config.status $(srcdir)/staprun.8.in
cd $(top_builddir) && $(SHELL) ./config.status $@
+stap-server.8: $(top_builddir)/config.status $(srcdir)/stap-server.8.in
+ cd $(top_builddir) && $(SHELL) ./config.status $@
man/stapprobes.iosched.5: $(top_builddir)/config.status $(top_srcdir)/man/stapprobes.iosched.5.in
cd $(top_builddir) && $(SHELL) ./config.status $@
man/stapprobes.netdev.5: $(top_builddir)/config.status $(top_srcdir)/man/stapprobes.netdev.5.in
diff --git a/NEWS b/NEWS
index 398964d9..fec89559 100644
--- a/NEWS
+++ b/NEWS
@@ -1,5 +1,14 @@
* What's new
+- Prototype systemtap client and compile server are now available.
+ These allow you to compile a systemtap module on a host other than
+ the one which it will be run, providing the client and server
+ are compatible. Other than using a server for passes 1 through
+ 4, the client behaves like the 'stap' front end itself. This
+ means, among other things, that the client will automatically
+ load the resulting module on the local host unless -p[1234]
+ was specified. See stap-server(8) for more details.
+
- Global variables which are written to but never read are now
automatically displayed when the session does a shutdown. For example:
diff --git a/configure b/configure
index d1fe6a30..71413615 100755
--- a/configure
+++ b/configure
@@ -7190,7 +7190,7 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
ac_config_headers="$ac_config_headers config.h:config.in"
-ac_config_files="$ac_config_files Makefile doc/Makefile stap.1 stapprobes.5 stapfuncs.5 stapvars.5 stapex.5 staprun.8 man/stapprobes.iosched.5 man/stapprobes.netdev.5 man/stapprobes.nfs.5 man/stapprobes.nfsd.5 man/stapprobes.pagefault.5 man/stapprobes.process.5 man/stapprobes.rpc.5 man/stapprobes.scsi.5 man/stapprobes.signal.5 man/stapprobes.socket.5 man/stapprobes.tcp.5 man/stapprobes.udp.5"
+ac_config_files="$ac_config_files Makefile doc/Makefile stap.1 stapprobes.5 stapfuncs.5 stapvars.5 stapex.5 staprun.8 stap-server.8 man/stapprobes.iosched.5 man/stapprobes.netdev.5 man/stapprobes.nfs.5 man/stapprobes.nfsd.5 man/stapprobes.pagefault.5 man/stapprobes.process.5 man/stapprobes.rpc.5 man/stapprobes.scsi.5 man/stapprobes.signal.5 man/stapprobes.socket.5 man/stapprobes.tcp.5 man/stapprobes.udp.5"
subdirs="$subdirs testsuite"
@@ -7824,6 +7824,7 @@ do
"stapvars.5") CONFIG_FILES="$CONFIG_FILES stapvars.5" ;;
"stapex.5") CONFIG_FILES="$CONFIG_FILES stapex.5" ;;
"staprun.8") CONFIG_FILES="$CONFIG_FILES staprun.8" ;;
+ "stap-server.8") CONFIG_FILES="$CONFIG_FILES stap-server.8" ;;
"man/stapprobes.iosched.5") CONFIG_FILES="$CONFIG_FILES man/stapprobes.iosched.5" ;;
"man/stapprobes.netdev.5") CONFIG_FILES="$CONFIG_FILES man/stapprobes.netdev.5" ;;
"man/stapprobes.nfs.5") CONFIG_FILES="$CONFIG_FILES man/stapprobes.nfs.5" ;;
diff --git a/configure.ac b/configure.ac
index 4ad54f7c..123ac657 100644
--- a/configure.ac
+++ b/configure.ac
@@ -231,7 +231,7 @@ AC_CHECK_HEADERS([tr1/unordered_map])
AC_LANG_POP(C++)
AC_CONFIG_HEADERS([config.h:config.in])
-AC_CONFIG_FILES(Makefile doc/Makefile stap.1 stapprobes.5 stapfuncs.5 stapvars.5 stapex.5 staprun.8 man/stapprobes.iosched.5 man/stapprobes.netdev.5 man/stapprobes.nfs.5 man/stapprobes.nfsd.5 man/stapprobes.pagefault.5 man/stapprobes.process.5 man/stapprobes.rpc.5 man/stapprobes.scsi.5 man/stapprobes.signal.5 man/stapprobes.socket.5 man/stapprobes.tcp.5 man/stapprobes.udp.5)
+AC_CONFIG_FILES(Makefile doc/Makefile stap.1 stapprobes.5 stapfuncs.5 stapvars.5 stapex.5 staprun.8 stap-server.8 man/stapprobes.iosched.5 man/stapprobes.netdev.5 man/stapprobes.nfs.5 man/stapprobes.nfsd.5 man/stapprobes.pagefault.5 man/stapprobes.process.5 man/stapprobes.rpc.5 man/stapprobes.scsi.5 man/stapprobes.signal.5 man/stapprobes.socket.5 man/stapprobes.tcp.5 man/stapprobes.udp.5)
AC_CONFIG_SUBDIRS(testsuite)
AC_OUTPUT
diff --git a/elaborate.cxx b/elaborate.cxx
index 88133c31..7ecba049 100644
--- a/elaborate.cxx
+++ b/elaborate.cxx
@@ -1170,6 +1170,7 @@ void add_global_var_display (systemtap_session& s)
probe_point::component* c = new probe_point::component("end");
token* print_tok = new token;
vector<derived_probe*> dps;
+ block *b = new block;
pl->components.push_back (c);
token* p_tok = new token;
@@ -1206,17 +1207,7 @@ void add_global_var_display (systemtap_session& s)
expr_statement* feb = new expr_statement;
feb->value = pf;
feb->tok = print_tok;
- block *b = new block;
b->statements.push_back(feb);
- p->body = b;
-
- derive_probes (s, p, dps);
-
- // Repopulate the type info. Should semantic_pass_types do this?
- ((class symbol*)
- ((class print_format*)
- ((class expr_statement*)
- ((class block*)dps[0]->body)->statements[0])->value)->args[0])->type = g_sym->type;
}
else // Array
{
@@ -1283,44 +1274,28 @@ void add_global_var_display (systemtap_session& s)
pf->components = print_format::string_to_components(pf->raw_components);
expr_statement* feb = new expr_statement;
feb->value = pf;
- block *b = new block;
fe->base = g_sym;
fe->block = (statement*)feb;
b->statements.push_back(fe);
- p->body = b;
-
- derive_probes (s, p, dps);
-
- // Repopulate the type info. Should semantic_pass_types do this?
- print_format* dpf = ((print_format*)
- ((expr_statement*)
- ((foreach_loop*)
- ((block*)dps[0]->body)->statements[0])->block)->value);
- for (int i=0; i < idx_count; i++)
- {
- // printf argument types
- dpf->args[i]->type = l->index_types[i];
- // arrayindex indices types
- ((struct arrayindex*)dpf->args[idx_count])->indexes[i]->type = l->index_types[i];
- dps[0]->locals.push_back(idx_v[i]);
- }
- // arrayindex type
- dpf->args[idx_count]->type = l->type;
}
- symresolution_info sym (s);
- sym.current_function = 0;
- sym.current_probe = dps[0];
- dps[0]->body->visit (& sym);
-
// Add created probe
+ p->body = b;
+ derive_probes (s, p, dps);
for (unsigned i = 0; i < dps.size(); i++)
{
derived_probe* dp = dps[i];
s.probes.push_back (dp);
dp->join_group (s);
}
+ // Repopulate symbol and type info
+ symresolution_info sym (s);
+ sym.current_function = 0;
+ sym.current_probe = dps[0];
+ dps[0]->body->visit (& sym);
+ semantic_pass_types(s);
+ // Mark that variable is read
vut.read.insert (l);
}
}
diff --git a/main.cxx b/main.cxx
index 8807a03d..11244d8d 100644
--- a/main.cxx
+++ b/main.cxx
@@ -179,6 +179,18 @@ printscript(systemtap_session& s, ostream& o)
if (seen.find (pp) == seen.end())
{
o << pp << endl;
+ if (s.verbose) {
+ for (unsigned j=0; j<p->locals.size(); j++)
+ {
+ vardecl* v = p->locals[j];
+ if (j>0)
+ o << ", ";
+ else
+ o << " ";
+ v->printsig (o);
+ }
+ o << endl;
+ }
seen.insert (pp);
}
}
@@ -581,6 +593,7 @@ main (int argc, char * const argv [])
case 'l':
s.suppress_warnings = true;
s.listing_mode = true;
+ s.unoptimized = true;
s.last_pass = 2;
if (have_script)
{
diff --git a/runtime/ChangeLog b/runtime/ChangeLog
index 926e05d9..b7e44a0f 100644
--- a/runtime/ChangeLog
+++ b/runtime/ChangeLog
@@ -1,3 +1,11 @@
+2008-08-29 David Smith <dsmith@redhat.com>
+
+ * task_finder.c (__stp_utrace_attach_match_filename): Don't call
+ the callback when the interesting thread is found, call it when
+ the tread is quiesced.
+ (stap_start_task_finder): Ditto.
+ (__stp_utrace_task_finder_target_quiesce): Call the callback.
+
2008-08-26 David Smith <dsmith@redhat.com>
* autoconf-d_path-path.c: New file.
diff --git a/runtime/task_finder.c b/runtime/task_finder.c
index b8a0ae7f..9c0dd55b 100644
--- a/runtime/task_finder.c
+++ b/runtime/task_finder.c
@@ -351,23 +351,41 @@ __stp_get_mm_path(struct mm_struct *mm, char *buf, int buflen)
return rc;
}
+/*
+ * All user threads get an engine with __STP_TASK_FINDER_EVENTS events
+ * attached to it so the task_finder layer can monitor new thread
+ * creation/death.
+ */
#define __STP_TASK_FINDER_EVENTS (UTRACE_EVENT(CLONE) \
| UTRACE_EVENT(EXEC) \
| UTRACE_EVENT(DEATH))
-#define __STP_ATTACHED_TASK_BASE_EVENTS (UTRACE_EVENT(DEATH))
-
-#define __STP_ATTACHED_TASK_VM_BASE_EVENTS (__STP_ATTACHED_TASK_BASE_EVENTS \
- | UTRACE_EVENT(SYSCALL_ENTRY) \
- | UTRACE_EVENT(SYSCALL_EXIT))
-
-#define __STP_ATTACHED_TASK_VM_EVENTS (__STP_ATTACHED_TASK_BASE_EVENTS \
- | UTRACE_STOP \
- | UTRACE_EVENT(QUIESCE))
-
-#define __STP_ATTACHED_TASK_EVENTS(tgt) \
- ((((tgt)->vm_callback) == NULL) ? __STP_ATTACHED_TASK_BASE_EVENTS \
- : __STP_ATTACHED_TASK_VM_EVENTS)
+/*
+ * __STP_TASK_BASE_EVENTS: base events for stap_task_finder_target's
+ * without a vm_callback
+ *
+ * __STP_TASK_VM_BASE_EVENTS: base events for
+ * stap_task_finder_target's with a vm_callback
+ */
+#define __STP_TASK_BASE_EVENTS (UTRACE_EVENT(DEATH))
+
+#define __STP_TASK_VM_BASE_EVENTS (__STP_TASK_BASE_EVENTS \
+ | UTRACE_EVENT(SYSCALL_ENTRY)\
+ | UTRACE_EVENT(SYSCALL_EXIT))
+
+/*
+ * All "interesting" threads get an engine with
+ * __STP_ATTACHED_TASK_EVENTS events attached to it. After the thread
+ * quiesces, we reset the events to __STP_ATTACHED_TASK_BASE_EVENTS
+ * events.
+ */
+#define __STP_ATTACHED_TASK_EVENTS (__STP_TASK_BASE_EVENTS \
+ | UTRACE_STOP \
+ | UTRACE_EVENT(QUIESCE))
+
+#define __STP_ATTACHED_TASK_BASE_EVENTS(tgt) \
+ ((((tgt)->vm_callback) == NULL) ? __STP_TASK_BASE_EVENTS \
+ : __STP_TASK_VM_BASE_EVENTS)
static int
stap_utrace_attach(struct task_struct *tsk,
@@ -454,31 +472,40 @@ __stp_utrace_attach_match_filename(struct task_struct *tsk,
if (cb_tgt == NULL)
continue;
- if (cb_tgt->callback != NULL) {
- int rc = cb_tgt->callback(cb_tgt, tsk,
- register_p,
- process_p);
- if (rc != 0) {
- _stp_error("callback for %d failed: %d",
- (int)tsk->pid, rc);
- break;
- }
- }
-
// Set up events we need for attached tasks.
+ // When register_p is set, we won't actually
+ // call the callback here - we'll call it when
+ // the thread gets quiesced. When register_p
+ // isn't set, we can go ahead and call the
+ // callback.
if (register_p) {
rc = stap_utrace_attach(tsk, &cb_tgt->ops,
cb_tgt,
- __STP_ATTACHED_TASK_EVENTS(cb_tgt));
+ __STP_ATTACHED_TASK_EVENTS);
if (rc != 0 && rc != EPERM)
break;
cb_tgt->engine_attached = 1;
}
else {
+ if (cb_tgt->callback != NULL) {
+ rc = cb_tgt->callback(cb_tgt, tsk,
+ register_p,
+ process_p);
+ if (rc != 0) {
+ _stp_error("callback for %d failed: %d",
+ (int)tsk->pid, rc);
+ break;
+ }
+ }
+
rc = stap_utrace_detach(tsk, &cb_tgt->ops);
if (rc != 0)
break;
- cb_tgt->engine_attached = 0;
+
+ // Note that we don't want to set
+ // engine_attached to 0 here - only
+ // when *all* threads using this
+ // engine have been detached.
}
}
}
@@ -695,18 +722,32 @@ __stp_utrace_task_finder_target_quiesce(enum utrace_resume_action action,
struct stap_task_finder_target *tgt = engine->data;
int rc;
- // Turn off quiesce handling (and turn on syscall handling).
- rc = utrace_set_events(tsk, engine, __STP_ATTACHED_TASK_VM_BASE_EVENTS);
+ if (atomic_read(&__stp_task_finder_state) != __STP_TF_RUNNING) {
+ debug_task_finder_detach();
+ return UTRACE_DETACH;
+ }
+
+ if (tgt == NULL)
+ return UTRACE_DETACH;
+
+ // Turn off quiesce handling
+ rc = utrace_set_events(tsk, engine,
+ __STP_ATTACHED_TASK_BASE_EVENTS(tgt));
if (rc != 0)
_stp_error("utrace_set_events returned error %d on pid %d",
rc, (int)tsk->pid);
- if (atomic_read(&__stp_task_finder_state) != __STP_TF_RUNNING) {
- debug_task_finder_detach();
- return UTRACE_DETACH;
+ if (tgt->callback != NULL) {
+ /* Call the callback. Assume that if the thread is a
+ * thread group leader, it is a process. */
+ rc = tgt->callback(tgt, tsk, 1, (tsk->pid == tsk->tgid));
+ if (rc != 0) {
+ _stp_error("callback for %d failed: %d",
+ (int)tsk->pid, rc);
+ }
}
- if (tgt != NULL && tgt->vm_callback != NULL) {
+ if (tgt->vm_callback != NULL) {
struct mm_struct *mm;
char *mmpath_buf;
char *mmpath;
@@ -1159,24 +1200,11 @@ stap_start_task_finder(void)
callback_list);
if (cb_tgt == NULL)
continue;
-
- // Call the callback. Assume that if
- // the thread is a thread group
- // leader, it is a process.
- if (cb_tgt->callback != NULL) {
- rc = cb_tgt->callback(cb_tgt, tsk, 1,
- (tsk->pid == tsk->tgid));
- if (rc != 0) {
- _stp_error("attach callback for %d failed: %d",
- (int)tsk->pid, rc);
- goto stf_err;
- }
- }
// Set up events we need for attached tasks.
rc = stap_utrace_attach(tsk, &cb_tgt->ops,
cb_tgt,
- __STP_ATTACHED_TASK_EVENTS(cb_tgt));
+ __STP_ATTACHED_TASK_EVENTS);
if (rc != 0 && rc != EPERM)
goto stf_err;
cb_tgt->engine_attached = 1;
diff --git a/stap-server.8.in b/stap-server.8.in
new file mode 100644
index 00000000..9bfaa789
--- /dev/null
+++ b/stap-server.8.in
@@ -0,0 +1,177 @@
+.\" -*- nroff -*-
+.TH STAP-SERVER 8 @DATE@ "Red Hat"
+.SH NAME
+stap-server \- systemtap server and related utilities
+
+.SH SYNOPSIS
+
+.br
+.B stap-start-server
+.br
+.B stap-find-servers
+[
+.B --all
+]
+.br
+.B stap-find-or-start-server
+.br
+.B stap-stop-server
+.I PID
+.br
+.B stap-client
+[
+.I ARGUMENTS
+]
+
+.SH DESCRIPTION
+
+The systemtap server listens for connections from
+.I stap-client
+on the local network and accepts requests to run the
+.I stap
+front end.
+
+.PP
+The
+.I stap-start-server
+program attempts to start a systemtap server (
+.I stap-serverd
+) on the local host. Upon
+successful startup, the server listens for connections on a random port and
+advertises its presence on the local network using the
+.I avahi
+daemon. If the server is successfully started, its process id is
+echoed to stdout and the exit code is 0. Otherwise, nothing is echoed and the exit code is 1.
+
+.PP
+The
+.I stap-find-servers
+program attempts to find systemtap servers running on the local network.
+The details of any servers found are echoed to stdout.
+If servers are found, then the exit code is 0, otherwise it is 1.
+
+.PP
+The
+.I stap-find-or-start-server
+program attempts to find a compatible systemtap server running on the local network
+using
+.I stap-find-servers.
+If a compatible server is found,
+.I stap-find-or-start-server
+echos '0' to stdout and the exit code is 0. Otherwise
+.I stap-find-or-start-server
+attempts to start a server on the local network using
+.I stap-start-server.
+If successful, the process id of the new server is echoed to stdout and the
+exit code is 0. If no server can be found or started, nothing is echoed
+to stdout and the exit code is 1.
+
+.PP
+The
+.I stap-stop-server
+program verifies that the given process id is that of a running systemtap server
+on the local host and, if so, attempts to shut down the server by sending it the
+SIGTERM signal. If a process id is provided and it is that of a running systemtap
+server, the exit code is 0. Otherwise the exit code is 1.
+.I stap-stop-server
+does not verify that the server actually shuts down.
+
+.PP
+The
+.I stap-client
+program is analagous to the
+.I stap
+front end except that it attempts to find a compatible systemtap server on the
+local network and then attempts to use that server for actions related to
+passes 1 through 4. Pass 5 actions, if requested, are performed on the localhost
+using
+.I staprun
+. Upon successful completion, the exit code is 0. Otherwise the exit code
+is 1.
+
+.SH OPTIONS
+The
+.I stap-find-servers
+program supports the following option. Any other option
+is ignored.
+.TP
+.B \--all
+Instructs
+.I stap-find-servers
+to report all systemtap servers on the local network regardless of compatibility.
+The default behavior is to report only servers which are compatible with
+systemtap on the local host.
+
+.SH ARGUMENTS
+The
+.I stap-stop-server
+program requires a process id argument which identifies the server to be stopped.
+
+.PP
+The
+.I stap-client
+program accepts the same arguments and options as the
+.I stap
+front end.
+
+.SH EXAMPLES
+See the
+.IR stapex (5)
+manual page for a collection of sample scripts.
+.PP
+Here is a very basic example of how to use
+.I stap-client.
+.PP
+To find out if a compatible systemtap server is running on your local network
+.PP
+\& $ stap-find-servers
+.PP
+If no servers are reported, you can start one using
+.PP
+\& $ stap-start-server
+.PP
+You could also have accomplished both of the previous two steps using
+.PP
+\& $ stap-find-or-start-server
+.PP
+To compile and execute a simple example using the server
+.PP
+\& $ stap-client \-e \[aq]probe begin { printf("Hello World!\\n"); exit() }\[aq]
+.br
+\& Hello World!
+.PP
+If a process id was echoed by
+.I stap-start-server
+or
+.I stap-find-or-start-server
+then you can stop the server using
+.PP
+\& $ stap-stop-server PID
+.PP
+where PID is the process id that was echoed.
+
+
+.SH SAFETY AND SECURITY
+Systemtap is an administrative tool. It exposes kernel internal data
+structures and potentially private user information. See the
+.IR stap (1)
+manual page for additional information on safety and security.
+
+.PP
+The systemtap server and its related utilities are prototypes only. NO NETWORK
+SECURITY OF ANY KIND IS CURRENTLY PROVIDED. These programs should only be used
+among trusted hosts on a trusted network.
+
+.SH SEE ALSO
+.IR stap (1),
+.IR staprun (8),
+.IR stapprobes (5),
+.IR stapfuncs (5),
+.IR stapex (5),
+
+.SH BUGS
+Use the Bugzilla link off of the project web page or our mailing list.
+.nh
+.BR http://sources.redhat.com/systemtap/ ", " <systemtap@sources.redhat.com> .
+.hy
+
diff --git a/tapset/ChangeLog b/tapset/ChangeLog
index 85b0ff96..bac3bf3e 100644
--- a/tapset/ChangeLog
+++ b/tapset/ChangeLog
@@ -1,3 +1,7 @@
+2008-09-01 Zhaolei <zhaolei@cn.fujitsu.com>
+ * nfs_proc.stp: Fix memory access error in nfs.proc.read_setup,
+ nfs.proc.write_setup and nfs.proc.commit_setup.
+
2008-08-28 Zhaolei <zhaolei@cn.fujitsu.com>
* socket.stp: Make _get_sock_addr return correct address in kernel
before 2.6.16.
@@ -8,12 +12,12 @@
2008-08-04 Wenji Huang <wenji.huang@oracle.com>
- * syscall.stp: Change $path to $pathname for 2.6.27.
- * syscall2.stp: Ditto.
+ * syscall.stp: Change $path to $pathname for 2.6.27.
+ * syscall2.stp: Ditto.
2008-08-03 Wenji Huang <wenji.huang@oracle.com>
- * vfs.stp(add_to_page_cache): Correct for 2.6.27.
+ * vfs.stp(add_to_page_cache): Correct for 2.6.27.
2008-07-25 Zhaolei <zhaolei@cn.fujitsu.com>
diff --git a/tapset/nfs_proc.stp b/tapset/nfs_proc.stp
index 6ffdf646..4f841836 100644
--- a/tapset/nfs_proc.stp
+++ b/tapset/nfs_proc.stp
@@ -4,39 +4,81 @@
%}
%{
+/*Get rpc_clnt from inode, same as kernel function NFS_CLIENT*/
+ struct rpc_clnt *_stap_NFS_CLIENT(struct inode *inode, struct context * __restrict__ c);
+/*Get ip address from a rpc_clnt*/
+ __u32 _get_ip_from_client(struct rpc_clnt *clnt, struct context * __restrict__ c);
+/*Get protocol types from a rpc_clnt*/
+ int _get_prot_from_client(struct rpc_clnt *clnt, struct context * __restrict__ c);
/*Get ip address from a rpc_task*/
__u32 get_ip(struct rpc_task *, struct context * __restrict__);
/*Get protocol types from a rpc_task*/
int get_prot(struct rpc_task *, struct context * __restrict__);
%}
%{
- __u32 get_ip(struct rpc_task * task, struct context * __restrict__ c)
- {
- struct rpc_clnt * tk_client;
- struct rpc_xprt * cl_xprt;
- struct sockaddr_in *addr;
- tk_client = kread(&(task->tk_client));
- cl_xprt= kread(&(tk_client->cl_xprt));
- addr = (struct sockaddr_in *)&(cl_xprt->addr);
- if (kread(&(addr->sin_family)) != AF_INET)
- /* Now consider ipv4 only */
- return 0;
- return kread(&(addr->sin_addr.s_addr));
+ struct rpc_clnt *_stap_NFS_CLIENT(struct inode *inode, struct context * __restrict__ c) {
+ struct super_block *i_sb;
+ struct nfs_server *server;
+ i_sb = kread(&(inode->i_sb));
+ server = kread(&(i_sb->s_fs_info));
+ return kread(&(server->client));
+ CATCH_DEREF_FAULT();
+ return NULL;
+ }
+
+ __u32 _get_ip_from_client(struct rpc_clnt *clnt, struct context * __restrict__ c) {
+ struct rpc_xprt * cl_xprt;
+ struct sockaddr_in *addr;
+ cl_xprt= kread(&(clnt->cl_xprt));
+ addr = (struct sockaddr_in *)&(cl_xprt->addr);
+ if (kread(&(addr->sin_family)) != AF_INET)
+ /* Now consider ipv4 only */
+ return 0;
+ return kread(&(addr->sin_addr.s_addr));
+ CATCH_DEREF_FAULT();
+ return -1;
+ }
+
+ int _get_prot_from_client(struct rpc_clnt *clnt, struct context * __restrict__ c) {
+ struct rpc_xprt * cl_xprt;
+ cl_xprt= kread(&(clnt->cl_xprt));
+ return kread(&(cl_xprt->prot));
+ CATCH_DEREF_FAULT();
+ return -1;
+ }
+
+ __u32 get_ip(struct rpc_task * task, struct context * __restrict__ c) {
+ struct rpc_clnt * clnt;
+ clnt = kread(&(task->tk_client));
+ return _get_ip_from_client(clnt, c);
CATCH_DEREF_FAULT();
return -1;
- }
- int get_prot(struct rpc_task * task, struct context * __restrict__ c)
- {
- struct rpc_clnt * tk_client;
- struct rpc_xprt * cl_xprt;
- tk_client = kread(&(task->tk_client));
- cl_xprt= kread(&(tk_client->cl_xprt));
-
- return kread(&(cl_xprt->prot));
+ }
+
+ int get_prot(struct rpc_task * task, struct context * __restrict__ c) {
+ struct rpc_clnt * clnt;
+ clnt = kread(&(task->tk_client));
+ return _get_prot_from_client(clnt, c);
CATCH_DEREF_FAULT();
return -1;
}
%}
+
+function stap_NFS_CLIENT:long(inode:long) %{ /* pure */
+ struct inode *inode = (struct inode *)(long)THIS->inode;
+ THIS->__retvalue = (long)_stap_NFS_CLIENT(inode, CONTEXT);
+%}
+
+function get_ip_from_client:long(clnt:long) %{ /* pure */
+ struct rpc_clnt *clnt = (struct rpc_clnt *)(long)THIS->clnt;
+ THIS->__retvalue = _get_ip_from_client(clnt, CONTEXT);
+%}
+
+function get_prot_from_client:long(clnt:long) %{ /* pure */
+ struct rpc_clnt *clnt = (struct rpc_clnt *)(long)THIS->clnt;
+ THIS->__retvalue = _get_prot_from_client(clnt, CONTEXT);
+%}
+
/*
0:get ip address
1:get proto
@@ -656,8 +698,9 @@ probe nfs.proc.read_setup.return = nfs.proc2.read_setup.return ,
probe nfs.proc2.read_setup = kernel.function("nfs_proc_read_setup") ?,
module("nfs").function("nfs_proc_read_setup")?
{
- server_ip = __nfs_read_data_info($data,0)
- prot = __nfs_read_data_info($data,1)
+ client = stap_NFS_CLIENT($data->inode)
+ server_ip = get_ip_from_client(client)
+ prot = get_prot_from_client(client)
version =2
count = $data->args->count
@@ -680,8 +723,9 @@ probe nfs.proc2.read_setup.return = kernel.function("nfs_proc_read_setup").retur
probe nfs.proc3.read_setup = kernel.function("nfs3_proc_read_setup") ?,
module("nfs").function("nfs3_proc_read_setup")?
{
- server_ip = __nfs_read_data_info($data,0)
- prot = __nfs_read_data_info($data,1)
+ client = stap_NFS_CLIENT($data->inode)
+ server_ip = get_ip_from_client(client)
+ prot = get_prot_from_client(client)
version =3
fh =
@@ -705,8 +749,9 @@ probe nfs.proc3.read_setup.return = kernel.function("nfs3_proc_read_setup").retu
probe nfs.proc4.read_setup = kernel.function("nfs4_proc_read_setup") ?,
module("nfs").function("nfs4_proc_read_setup")?
{
- server_ip = __nfs_read_data_info($data,0)
- prot = __nfs_read_data_info($data,1)
+ client = stap_NFS_CLIENT($data->inode)
+ server_ip = get_ip_from_client(client)
+ prot = get_prot_from_client(client)
version =4
count = $data->args->count
@@ -877,8 +922,9 @@ probe nfs.proc.write_setup.return = nfs.proc2.write_setup.return,
probe nfs.proc2.write_setup = kernel.function("nfs_proc_write_setup") ?,
module("nfs").function("nfs_proc_write_setup") ?
{
- server_ip = __nfs_write_data_info($data,0)
- prot = __nfs_write_data_info($data,1)
+ client = stap_NFS_CLIENT($data->inode)
+ server_ip = get_ip_from_client(client)
+ prot = get_prot_from_client(client)
version =2
count = $data->args->count
@@ -901,8 +947,9 @@ probe nfs.proc2.write_setup.return = kernel.function("nfs_proc_write_setup").ret
probe nfs.proc3.write_setup = kernel.function("nfs3_proc_write_setup") ?,
module("nfs").function("nfs3_proc_write_setup") ?
{
- server_ip = __nfs_write_data_info($data,0)
- prot = __nfs_write_data_info($data,1)
+ client = stap_NFS_CLIENT($data->inode)
+ server_ip = get_ip_from_client(client)
+ prot = get_prot_from_client(client)
version =3
count = $data->args->count
@@ -925,8 +972,9 @@ probe nfs.proc3.write_setup.return = kernel.function("nfs3_proc_write_setup").re
probe nfs.proc4.write_setup = kernel.function("nfs4_proc_write_setup") ?,
module("nfs").function("nfs4_proc_write_setup") ?
{
- server_ip = __nfs_write_data_info($data,0)
- prot = __nfs_write_data_info($data,1)
+ client = stap_NFS_CLIENT($data->inode)
+ server_ip = get_ip_from_client(client)
+ prot = get_prot_from_client(client)
version =4
count = $data->args->count
@@ -1100,8 +1148,9 @@ probe nfs.proc.commit_setup.return =nfs.proc3.commit_setup.return,
probe nfs.proc3.commit_setup = kernel.function("nfs3_proc_commit_setup") ?,
module("nfs").function("nfs3_proc_commit_setup") ?
{
- server_ip = __nfs_write_data_info($data,0)
- prot = __nfs_write_data_info($data,1)
+ client = stap_NFS_CLIENT($data->inode)
+ server_ip = get_ip_from_client(client)
+ prot = get_prot_from_client(client)
version =3
count = $data->args->count
@@ -1123,8 +1172,9 @@ probe nfs.proc3.commit_setup.return = kernel.function("nfs3_proc_commit_setup")
probe nfs.proc4.commit_setup = kernel.function("nfs4_proc_commit_setup") ?,
module("nfs").function("nfs4_proc_commit_setup") ?
{
- server_ip = __nfs_write_data_info($data,0)
- prot = __nfs_write_data_info($data,1)
+ client = stap_NFS_CLIENT($data->inode)
+ server_ip = get_ip_from_client(client)
+ prot = get_prot_from_client(client)
version =4
count = $data->args->count
diff --git a/tapsets.cxx b/tapsets.cxx
index 3c67eed7..8f5ed287 100644
--- a/tapsets.cxx
+++ b/tapsets.cxx
@@ -6072,17 +6072,13 @@ utrace_derived_probe_group::emit_probe_decl (systemtap_session& s,
// Handle flags
switch (p->flags)
{
- // Look in _stp_utrace_probe_cb for description of why quiesce is
- // used here.
+ // Notice that we'll just call the probe directly when we get
+ // notified, since the task_finder layer stops the thread for us.
case UDPF_BEGIN: // process begin
s.op->line() << " .flags=(UDPF_BEGIN),";
- s.op->line() << " .ops={ .report_quiesce=stap_utrace_probe_quiesce },";
- s.op->line() << " .events=(UTRACE_STOP|UTRACE_EVENT(QUIESCE)),";
break;
case UDPF_THREAD_BEGIN: // thread begin
s.op->line() << " .flags=(UDPF_THREAD_BEGIN),";
- s.op->line() << " .ops={ .report_quiesce=stap_utrace_probe_quiesce },";
- s.op->line() << " .events=(UTRACE_STOP|UTRACE_EVENT(QUIESCE)),";
break;
// Notice we're not setting up a .ops/.report_death handler for
@@ -6097,17 +6093,17 @@ utrace_derived_probe_group::emit_probe_decl (systemtap_session& s,
// For UDPF_SYSCALL/UDPF_SYSCALL_RETURN probes, the .report_death
// handler isn't strictly necessary. However, it helps to keep
- // our attaches/detaches symmetrical. Notice we're using quiesce
- // as a workaround for bug 6841.
+ // our attaches/detaches symmetrical. Since the task_finder layer
+ // stops the thread, that works around bug 6841.
case UDPF_SYSCALL:
s.op->line() << " .flags=(UDPF_SYSCALL),";
- s.op->line() << " .ops={ .report_syscall_entry=stap_utrace_probe_syscall, .report_death=stap_utrace_task_finder_report_death, .report_quiesce=stap_utrace_probe_syscall_quiesce },";
- s.op->line() << " .events=(UTRACE_STOP|UTRACE_EVENT(QUIESCE)|UTRACE_EVENT(DEATH)),";
+ s.op->line() << " .ops={ .report_syscall_entry=stap_utrace_probe_syscall, .report_death=stap_utrace_task_finder_report_death },";
+ s.op->line() << " .events=(UTRACE_EVENT(SYSCALL_ENTRY)|UTRACE_EVENT(DEATH)),";
break;
case UDPF_SYSCALL_RETURN:
s.op->line() << " .flags=(UDPF_SYSCALL_RETURN),";
- s.op->line() << " .ops={ .report_syscall_exit=stap_utrace_probe_syscall, .report_death=stap_utrace_task_finder_report_death, .report_quiesce=stap_utrace_probe_syscall_quiesce },";
- s.op->line() << " .events=(UTRACE_STOP|UTRACE_EVENT(QUIESCE)|UTRACE_EVENT(DEATH)),";
+ s.op->line() << " .ops={ .report_syscall_exit=stap_utrace_probe_syscall, .report_death=stap_utrace_task_finder_report_death },";
+ s.op->line() << " .events=(UTRACE_EVENT(SYSCALL_EXIT)|UTRACE_EVENT(DEATH)),";
break;
case UDPF_NONE:
@@ -6192,32 +6188,10 @@ utrace_derived_probe_group::emit_module_decls (systemtap_session& s)
s.op->newline(-1) << "};";
- // Output handler function for UDPF_BEGIN and UDPF_THREAD_BEGIN
- if (flags_seen[UDPF_BEGIN] || flags_seen[UDPF_THREAD_BEGIN])
- {
- s.op->newline() << "#ifdef UTRACE_ORIG_VERSION";
- s.op->newline() << "static u32 stap_utrace_probe_quiesce(struct utrace_attached_engine *engine, struct task_struct *tsk) {";
- s.op->newline() << "#else";
- s.op->newline() << "static u32 stap_utrace_probe_quiesce(enum utrace_resume_action action, struct utrace_attached_engine *engine, struct task_struct *tsk, unsigned long event) {";
- s.op->newline() << "#endif";
- s.op->indent(1);
- s.op->newline() << "struct stap_utrace_probe *p = (struct stap_utrace_probe *)engine->data;";
-
- common_probe_entryfn_prologue (s.op, "STAP_SESSION_RUNNING");
- s.op->newline() << "c->probe_point = p->pp;";
-
- // call probe function
- s.op->newline() << "(*p->ph) (c);";
- common_probe_entryfn_epilogue (s.op);
-
- // we're detaching, so utrace automatically restarts the thread.
- s.op->newline() << "debug_task_finder_detach();";
- s.op->newline() << "return UTRACE_DETACH;";
- s.op->newline(-1) << "}";
- }
-
- // Output handler function for UDPF_END and UDPF_THREAD_END
- if (flags_seen[UDPF_END] || flags_seen[UDPF_THREAD_END])
+ // Output handler function for UDPF_BEGIN, UDPF_THREAD_BEGIN,
+ // UDPF_END, and UDPF_THREAD_END
+ if (flags_seen[UDPF_BEGIN] || flags_seen[UDPF_THREAD_BEGIN]
+ || flags_seen[UDPF_END] || flags_seen[UDPF_THREAD_END])
{
s.op->newline() << "static void stap_utrace_probe_handler(struct task_struct *tsk, struct stap_utrace_probe *p) {";
s.op->indent(1);
@@ -6237,33 +6211,6 @@ utrace_derived_probe_group::emit_module_decls (systemtap_session& s)
if (flags_seen[UDPF_SYSCALL] || flags_seen[UDPF_SYSCALL_RETURN])
{
s.op->newline() << "#ifdef UTRACE_ORIG_VERSION";
- s.op->newline() << "static u32 stap_utrace_probe_syscall_quiesce(struct utrace_attached_engine *engine, struct task_struct *tsk) {";
- s.op->newline() << "#else";
- s.op->newline() << "static u32 stap_utrace_probe_syscall_quiesce(enum utrace_resume_action action, struct utrace_attached_engine *engine, struct task_struct *tsk, unsigned long event) {";
- s.op->newline() << "#endif";
- s.op->indent(1);
- s.op->newline() << "struct stap_utrace_probe *p = (struct stap_utrace_probe *)engine->data;";
- s.op->newline() << "int rc = 0;";
-
- // Turn off quiesce handling and turn on either syscall entry
- // or exit events.
- s.op->newline() << "if (p->flags == UDPF_SYSCALL)";
- s.op->indent(1);
- s.op->newline() << "rc = utrace_set_events(tsk, engine, UTRACE_EVENT(SYSCALL_ENTRY)|UTRACE_EVENT(DEATH));";
- s.op->indent(-1);
- s.op->newline() << "else if (p->flags == UDPF_SYSCALL_RETURN)";
- s.op->indent(1);
- s.op->newline() << "rc = utrace_set_events(tsk, engine, UTRACE_EVENT(SYSCALL_EXIT)|UTRACE_EVENT(DEATH));";
- s.op->indent(-1);
- s.op->newline() << "if (rc != 0)";
- s.op->indent(1);
- s.op->newline() << "_stp_error(\"utrace_set_events returned error %d on pid %d\", rc, (int)tsk->pid);";
- s.op->indent(-1);
-
- s.op->newline() << "return UTRACE_RESUME;";
- s.op->newline(-1) << "}";
-
- s.op->newline() << "#ifdef UTRACE_ORIG_VERSION";
s.op->newline() << "static u32 stap_utrace_probe_syscall(struct utrace_attached_engine *engine, struct task_struct *tsk, struct pt_regs *regs) {";
s.op->newline() << "#else";
s.op->newline() << "static u32 stap_utrace_probe_syscall(enum utrace_resume_action action, struct utrace_attached_engine *engine, struct task_struct *tsk, struct pt_regs *regs) {";
@@ -6280,6 +6227,11 @@ utrace_derived_probe_group::emit_module_decls (systemtap_session& s)
s.op->newline() << "(*p->ph) (c);";
common_probe_entryfn_epilogue (s.op);
+ s.op->newline() << "if ((atomic_read (&session_state) != STAP_SESSION_STARTING) && (atomic_read (&session_state) != STAP_SESSION_RUNNING)) {";
+ s.op->indent(1);
+ s.op->newline() << "debug_task_finder_detach();";
+ s.op->newline() << "return UTRACE_DETACH;";
+ s.op->newline(-1) << "}";
s.op->newline() << "return UTRACE_RESUME;";
s.op->newline(-1) << "}";
}
@@ -6308,11 +6260,7 @@ utrace_derived_probe_group::emit_module_decls (systemtap_session& s)
s.op->indent(1);
s.op->newline() << "if (process_p) {";
s.op->indent(1);
- s.op->newline() << "rc = stap_utrace_attach(tsk, &p->ops, p, p->events);";
- s.op->newline() << "if (rc == 0) {";
- s.op->indent(1);
- s.op->newline() << "p->engine_attached = 1;";
- s.op->newline(-1) << "}";
+ s.op->newline() << "stap_utrace_probe_handler(tsk, p);";
s.op->newline(-1) << "}";
s.op->newline() << "break;";
s.op->indent(-1);
@@ -6323,11 +6271,7 @@ utrace_derived_probe_group::emit_module_decls (systemtap_session& s)
s.op->indent(1);
s.op->newline() << "if (! process_p) {";
s.op->indent(1);
- s.op->newline() << "rc = stap_utrace_attach(tsk, &p->ops, p, p->events);";
- s.op->newline() << "if (rc == 0) {";
- s.op->indent(1);
- s.op->newline() << "p->engine_attached = 1;";
- s.op->newline(-1) << "}";
+ s.op->newline() << "stap_utrace_probe_handler(tsk, p);";
s.op->newline(-1) << "}";
s.op->newline() << "break;";
s.op->indent(-1);
@@ -6368,7 +6312,8 @@ utrace_derived_probe_group::emit_module_decls (systemtap_session& s)
s.op->newline(-1) << "}";
// Since this engine could be attached to multiple threads, don't
- // call stap_utrace_detach_ops() here.
+ // call stap_utrace_detach_ops() here, only call
+ // stap_utrace_detach() as necessary.
s.op->newline() << "else {";
s.op->indent(1);
s.op->newline() << "switch (p->flags) {";
@@ -6397,15 +6342,18 @@ utrace_derived_probe_group::emit_module_decls (systemtap_session& s)
s.op->indent(-1);
}
- // For begin/thread_begin probes, at deregistration time we'll try
- // to detach. This will only be necessary if the new thread/process
- // got killed before the probe got run in the UTRACE_EVENT(QUIESCE)
- // handler.
- if (flags_seen[UDPF_BEGIN] || flags_seen[UDPF_THREAD_BEGIN]
- || flags_seen[UDPF_SYSCALL] || flags_seen[UDPF_SYSCALL_RETURN])
- {
+ // For begin/thread_begin probes, we don't need to do anything.
+ if (flags_seen[UDPF_BEGIN] || flags_seen[UDPF_THREAD_BEGIN])
+ {
s.op->newline() << "case UDPF_BEGIN:";
s.op->newline() << "case UDPF_THREAD_BEGIN:";
+ s.op->indent(1);
+ s.op->newline() << "break;";
+ s.op->indent(-1);
+ }
+
+ if (flags_seen[UDPF_SYSCALL] || flags_seen[UDPF_SYSCALL_RETURN])
+ {
s.op->newline() << "case UDPF_SYSCALL:";
s.op->newline() << "case UDPF_SYSCALL_RETURN:";
s.op->indent(1);
diff --git a/testsuite/ChangeLog b/testsuite/ChangeLog
index e6649a36..a0e19521 100644
--- a/testsuite/ChangeLog
+++ b/testsuite/ChangeLog
@@ -1,3 +1,9 @@
+2008-08-29 David Smith <dsmith@redhat.com>
+
+ PR6841
+ * systemtap.base/utrace_p5.exp: Added system-wide syscall test for
+ bug 6841 fix.
+
2008-08-27 Stan Cox <scox@redhat.com>
* systemtap.base/global_end.exp: New.
diff --git a/testsuite/systemtap.base/utrace_p5.exp b/testsuite/systemtap.base/utrace_p5.exp
index fcd617fe..33281350 100644
--- a/testsuite/systemtap.base/utrace_p5.exp
+++ b/testsuite/systemtap.base/utrace_p5.exp
@@ -73,6 +73,23 @@ set thread_end_script {
}
set thread_end_script_output "thread_ends = \\d+\r\n"
+# Script that tests the bug 6841 fix.
+set bz6841_script {
+ global proc,name
+ probe begin { printf("systemtap starting probe\n") }
+ probe process.syscall {
+ proc[pid()] <<< 1
+ name[pid()] = execname()
+ }
+ probe end { printf("systemtap ending probe\n")
+ foreach(p+ in proc) {
+ printf("%s(%d) issues syscall %d times\n",
+ name[p], p, @sum(proc[p]))
+ }
+ }
+}
+set bz6841_script_output ".+ issues syscall \\d+ times\r\n"
+
# Try to find utrace_attach symbol in /proc/kallsyms
set path "/proc/kallsyms"
if {! [catch {exec grep -q utrace_attach $path} dummy]} {
@@ -182,5 +199,15 @@ if {$utrace_support_found == 0} {
-e $script
}
+set TEST_NAME "UTRACE_P5_07"
+if {$utrace_support_found == 0} {
+ untested "$TEST_NAME : no kernel utrace support found"
+} elseif {![installtest_p]} {
+ untested "$TEST_NAME"
+} else {
+ stap_run $TEST_NAME run_utrace_p5_multi $bz6841_script_output \
+ -e $bz6841_script
+}
+
# Cleanup
exec rm -f $exepath $multi_exepath