From 55e50c24c9176f1b3d15af94e145456a68e7ecf6 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Mon, 28 Sep 2009 17:36:04 -0700 Subject: Try to build tracequery for all headers at once To mitigate PR10424, we switched to building a separate tracequery module for each tracepoint header, so a bad header wouldn't break all of the others. However, with recent kernels that leads to ~18 make commands, which adds up quickly in time. It's cached, so that's not too bad, but as a developer who rebuilds stap frequently, it gets annoying. If we're going to call 18 makes, it's worth it to start with one bigger make that covers all the headers at once (like we used to). If that one fails, we can still fall back to compiling individually. FWIW, the failing ext4.h header was only created in 2.6.31, and was fixed before 2.6.32, so the specific failure in PR10424 has a fairly small window. * buildrun.cxx (make_tracequery): Just take a single vector of headers. * hash.cxx (find_tracequery_hash): Deal with multiple headers. * tapsets.cxx (tracepoint_builder::get_tracequery_module): Ditto. (tracepoint_builder::init_dw): Attempt all system headers together, and if that fails, try again individually. --- buildrun.cxx | 13 ++++--------- buildrun.h | 3 +-- hash.cxx | 7 ++++--- hash.h | 4 +++- tapsets.cxx | 58 +++++++++++++++++++++++++++++++++++++++++++--------------- 5 files changed, 55 insertions(+), 30 deletions(-) diff --git a/buildrun.cxx b/buildrun.cxx index cebe3b8e..86940643 100644 --- a/buildrun.cxx +++ b/buildrun.cxx @@ -374,8 +374,7 @@ run_pass (systemtap_session& s) // Build a tiny kernel module to query tracepoints int make_tracequery(systemtap_session& s, string& name, - const std::string& header, - const vector& extra_headers) + const vector& headers) { static unsigned tick = 0; string basename("tracequery_kmod_" + lex_cast(++tick)); @@ -415,13 +414,9 @@ make_tracequery(systemtap_session& s, string& name, osrc << "#define DEFINE_TRACE(name, proto, args) \\" << endl; osrc << " DECLARE_TRACE(name, TPPROTO(proto), TPARGS(args))" << endl; - // PR9993: Add extra headers to work around undeclared types in individual - // include/trace/foo.h files - for (unsigned z=0; z\n"; - - // add the requested tracepoint header - osrc << "#include <" << header << ">" << endl; + // add the specified headers + for (unsigned z=0; z\n"; // finish up the module source osrc << "#endif /* CONFIG_TRACEPOINTS */" << endl; diff --git a/buildrun.h b/buildrun.h index bec81aca..318befd7 100644 --- a/buildrun.h +++ b/buildrun.h @@ -15,8 +15,7 @@ int compile_pass (systemtap_session& s); int run_pass (systemtap_session& s); int make_tracequery(systemtap_session& s, std::string& name, - const std::string& header, - const std::vector& extra_headers); + const std::vector& headers); int make_typequery(systemtap_session& s, std::string& module); #endif // BUILDRUN_H diff --git a/hash.cxx b/hash.cxx index df29afed..a4589577 100644 --- a/hash.cxx +++ b/hash.cxx @@ -263,13 +263,14 @@ find_hash (systemtap_session& s, const string& script) string -find_tracequery_hash (systemtap_session& s, const string& header) +find_tracequery_hash (systemtap_session& s, const vector& headers) { hash h; get_base_hash(s, h); - // Add the tracepoint header to the computed hash - h.add_file(header); + // Add the tracepoint headers to the computed hash + for (size_t i = 0; i < headers.size(); ++i) + h.add_file(headers[i]); // Add any custom kbuild flags for (unsigned i = 0; i < s.kbuildflags.size(); i++) diff --git a/hash.h b/hash.h index f52fd89e..6bb1c78a 100644 --- a/hash.h +++ b/hash.h @@ -1,4 +1,5 @@ #include +#include extern "C" { #include @@ -36,7 +37,8 @@ public: }; void find_hash (systemtap_session& s, const std::string& script); -std::string find_tracequery_hash (systemtap_session& s, const std::string& header); +std::string find_tracequery_hash (systemtap_session& s, + const std::vector& headers); std::string find_typequery_hash (systemtap_session& s, const std::string& name); /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */ diff --git a/tapsets.cxx b/tapsets.cxx index bedb267a..dfa5f302 100644 --- a/tapsets.cxx +++ b/tapsets.cxx @@ -6047,7 +6047,8 @@ struct tracepoint_builder: public derived_probe_builder private: dwflpp *dw; bool init_dw(systemtap_session& s); - string get_tracequery_module(systemtap_session& s, const string& header); + string get_tracequery_module(systemtap_session& s, + const vector& headers); public: @@ -6071,16 +6072,21 @@ public: string tracepoint_builder::get_tracequery_module(systemtap_session& s, - const string& header) + const vector& headers) { if (s.verbose > 2) - clog << "Pass 2: getting a tracequery for " << header << endl; + { + clog << "Pass 2: getting a tracequery for " + << headers.size() << " headers:" << endl; + for (size_t i = 0; i < headers.size(); ++i) + clog << " " << headers[i] << endl; + } string tracequery_path; if (s.use_cache) { // see if the cached module exists - tracequery_path = find_tracequery_hash(s, header); + tracequery_path = find_tracequery_hash(s, headers); if (!tracequery_path.empty()) { int fd = open(tracequery_path.c_str(), O_RDONLY); @@ -6096,13 +6102,22 @@ tracepoint_builder::get_tracequery_module(systemtap_session& s, // no cached module, time to make it - size_t root_pos = header.rfind("/include/"); - string short_header = (root_pos != string::npos) ? - header.substr(root_pos + 9) : header; + // PR9993: Add extra headers to work around undeclared types in individual + // include/trace/foo.h files + vector short_headers = tracepoint_extra_headers(); + + // add each requested tracepoint header + for (size_t i = 0; i < headers.size(); ++i) + { + const string &header = headers[i]; + size_t root_pos = header.rfind("/include/"); + short_headers.push_back((root_pos != string::npos) ? + header.substr(root_pos + 9) : + header); + } string tracequery_ko; - int rc = make_tracequery(s, tracequery_ko, short_header, - tracepoint_extra_headers()); + int rc = make_tracequery(s, tracequery_ko, short_headers); if (rc != 0) tracequery_ko = "/dev/null"; @@ -6128,6 +6143,7 @@ tracepoint_builder::init_dw(systemtap_session& s) return true; vector tracequery_modules; + vector system_headers; glob_t trace_glob; string globs[] = { @@ -6145,6 +6161,8 @@ tracepoint_builder::init_dw(systemtap_session& s) string header(trace_glob.gl_pathv[i]); // filter out a few known "internal-only" headers + if (header.find("/define_trace.h") != string::npos) + continue; if (header.find("/ftrace.h") != string::npos) continue; if (header.find("/trace_events.h") != string::npos) @@ -6152,16 +6170,26 @@ tracepoint_builder::init_dw(systemtap_session& s) if (header.find("_event_types.h") != string::npos) continue; - string tracequery_path = get_tracequery_module(s, header); - - /* NB: An empty tracequery means that the - * header didn't even compile correctly. */ - if (get_file_size(tracequery_path)) - tracequery_modules.push_back(tracequery_path); + system_headers.push_back(header); } globfree(&trace_glob); } + // First attempt to do all system headers in one go + string tracequery_path = get_tracequery_module(s, system_headers); + // NB: An empty tracequery means that the header didn't compile correctly + if (get_file_size(tracequery_path)) + tracequery_modules.push_back(tracequery_path); + else + // Otherwise try to do them one at a time (PR10424) + for (size_t i = 0; i < system_headers.size(); ++i) + { + vector one_header(1, system_headers[i]); + tracequery_path = get_tracequery_module(s, one_header); + if (get_file_size(tracequery_path)) + tracequery_modules.push_back(tracequery_path); + } + // TODO: consider other sources of tracepoint headers too, like from // a command-line parameter or some environment or .systemtaprc -- cgit