diff options
author | Frank Ch. Eigler <fche@elastic.org> | 2008-09-01 13:46:27 -0400 |
---|---|---|
committer | Frank Ch. Eigler <fche@elastic.org> | 2008-09-01 13:46:27 -0400 |
commit | aa3c05113d831a4e5d58287f9f2f9d605bf8693e (patch) | |
tree | 850b215d67d0621fbfb575dc34aca3bf3bc1fa0a | |
parent | 6f4c12753354d3e0f6b18d6290e1bf89c5084c5c (diff) | |
parent | 5e314609f46deb737967305f59356243cb65c310 (diff) | |
download | systemtap-steved-aa3c05113d831a4e5d58287f9f2f9d605bf8693e.tar.gz systemtap-steved-aa3c05113d831a4e5d58287f9f2f9d605bf8693e.tar.xz systemtap-steved-aa3c05113d831a4e5d58287f9f2f9d605bf8693e.zip |
Merge commit 'origin/master' into pr4225
* commit 'origin/master':
Fix memory access error in nfs.proc.read_setup, nfs.proc.write_setup and nfs.proc.commit_setup
Update NEWS regarding the systemtap client/server.
New man page for the systemtap client/server and related utilities.
Repopulate symbol/type info.
Pushed quiesce logic down into the task_finder layer.
Added bug 6841 fix utrace syscall test.
PR6731: improve listing mode to list variables
-rw-r--r-- | ChangeLog | 25 | ||||
-rw-r--r-- | Makefile.am | 2 | ||||
-rw-r--r-- | Makefile.in | 8 | ||||
-rw-r--r-- | NEWS | 9 | ||||
-rwxr-xr-x | configure | 3 | ||||
-rw-r--r-- | configure.ac | 2 | ||||
-rw-r--r-- | elaborate.cxx | 45 | ||||
-rw-r--r-- | main.cxx | 13 | ||||
-rw-r--r-- | runtime/ChangeLog | 8 | ||||
-rw-r--r-- | runtime/task_finder.c | 120 | ||||
-rw-r--r-- | stap-server.8.in | 177 | ||||
-rw-r--r-- | tapset/ChangeLog | 10 | ||||
-rw-r--r-- | tapset/nfs_proc.stp | 124 | ||||
-rw-r--r-- | tapsets.cxx | 114 | ||||
-rw-r--r-- | testsuite/ChangeLog | 6 | ||||
-rw-r--r-- | testsuite/systemtap.base/utrace_p5.exp | 27 |
16 files changed, 483 insertions, 210 deletions
@@ -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 @@ -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: @@ -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); } } @@ -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 |