1. 07 Aug, 2020 1 commit
  2. 06 Aug, 2020 1 commit
  3. 05 Aug, 2020 1 commit
    • Steven Rostedt (VMware)'s avatar
      tracing: Use trace_sched_process_free() instead of exit() for pid tracing · afcab636
      Steven Rostedt (VMware) authored
      On exit, if a process is preempted after the trace_sched_process_exit()
      tracepoint but before the process is done exiting, then when it gets
      scheduled in, the function tracers will not filter it properly against the
      function tracing pid filters.
      
      That is because the function tracing pid filters hooks to the
      sched_process_exit() tracepoint to remove the exiting task's pid from the
      filter list. Because the filtering happens at the sched_switch tracepoint,
      when the exiting task schedules back in to finish up the exit, it will no
      longer be in the function pid filtering tables.
      
      This was noticeable in the notrace self tests on a preemptable kernel, as
      the tests would fail as it exits and preempted after being taken off the
      notrace filter table and on scheduling back in it would not be in the
      notrace list, and then the ending of the exit function would trace. The test
      detected this and would fail.
      
      Cc: stable@vger.kernel.org
      Cc: Namhyung Kim <namhyung@kernel.org>
      Fixes: 1e10486f ("ftrace: Add 'function-fork' trace option")
      Fixes: c37775d5 ("tracing: Add infrastructure to allow set_event_pid to follow children"
      Signed-off-by: default avatarSteven Rostedt (VMware) <rostedt@goodmis.org>
      afcab636
  4. 04 Aug, 2020 1 commit
  5. 03 Aug, 2020 10 commits
  6. 31 Jul, 2020 2 commits
  7. 30 Jul, 2020 3 commits
  8. 09 Jul, 2020 2 commits
  9. 02 Jul, 2020 4 commits
    • Steven Rostedt (VMware)'s avatar
      ring-buffer: Do not trigger a WARN if clock going backwards is detected · 29ce2451
      Steven Rostedt (VMware) authored
      After tweaking the ring buffer to be a bit faster, a warning is triggering
      on one of my machines, and causing my tests to fail. This warning is caused
      when the delta (current time stamp minus previous time stamp), is larger
      than the max time held by the ring buffer (59 bits).
      
      If the clock were to go backwards slightly, this would then easily trigger
      this warning. The machine that it triggered on, the clock did go backwards
      by around 450 nanoseconds, and this happened after a recalibration of the
      TSC clock. Now that the ring buffer is faster, it detects this, and the
      delta that is used larger than the max, the warning is triggered and my test
      fails.
      
      To handle the clock going backwards, look at the saved before and after time
      stamps. If they are the same, it means that the current event did not
      interrupt another event, and that those timestamp are of a previous event
      that was recorded. If the max delta is triggered, look at those time stamps,
      make sure they are the same, then use them to compare with the current
      timestamp. If the current timestamp is less than the before/after time
      stamps, then that means the clock being used went backward.
      
      Print out a message that this has happened, but do not warn about it (and
      only print the message once).
      
      Still do the warning if the delta is indeed larger than what can be used.
      
      Also remove the unneeded KERN_WARNING from the WARN_ONCE() print.
      Signed-off-by: default avatarSteven Rostedt (VMware) <rostedt@goodmis.org>
      29ce2451
    • Steven Rostedt (VMware)'s avatar
      ring-buffer: Call trace_clock_local() directly for RETPOLINE kernels · bbeba3e5
      Steven Rostedt (VMware) authored
      After doing some benchmarks and examining the code, I found that the ring
      buffer clock calls were quite expensive, and noticed that it uses
      retpolines. This is because the ring buffer clock is programmable, and can
      be set. But in most cases it simply uses the fastest ns unit clock which is
      the trace_clock_local(). For RETPOLINE builds, checking if the ring buffer
      clock is set to trace_clock_local() and then calling it directly has brought
      the time of an event on my i7 box from an average of 93 nanoseconds an event
      down to 83 nanoseconds an event, and the minimum time from 81 nanoseconds to
      68 nanoseconds!
      Suggested-by: default avatarMathieu Desnoyers <mathieu.desnoyers@efficios.com>
      Signed-off-by: default avatarSteven Rostedt (VMware) <rostedt@goodmis.org>
      bbeba3e5
    • Steven Rostedt (VMware)'s avatar
      ring-buffer: Move the add_timestamp into its own function · 74e87937
      Steven Rostedt (VMware) authored
      Make a helper function rb_add_timestamp() that moves the adding of the
      extended time stamps into its own function. Also, remove the noinline and
      inline for the functions it calls, as recent benchmarks appear they do not
      make a difference (just let gcc decide).
      Signed-off-by: default avatarSteven Rostedt (VMware) <rostedt@goodmis.org>
      74e87937
    • Steven Rostedt (VMware)'s avatar
      ring-buffer: Consolidate add_timestamp to remove some branches · 58fbc3c6
      Steven Rostedt (VMware) authored
      Reorganize a little the logic to handle adding the absolute time stamp,
      extended and forced time stamps, in such a way to remove a branch or two.
      This is just a micro optimization.
      
      Also add before and after time stamps to the rb_event_info structure to
      display those values in the rb_check_timestamps() code, if something were to
      go wrong.
      Suggested-by: default avatarMathieu Desnoyers <mathieu.desnoyers@efficios.com>
      Signed-off-by: default avatarSteven Rostedt (VMware) <rostedt@goodmis.org>
      58fbc3c6
  10. 30 Jun, 2020 10 commits
    • Steven Rostedt (VMware)'s avatar
      ring-buffer: Mark the !tail (crossing a page) as unlikely · 75b21c6d
      Steven Rostedt (VMware) authored
      It is the uncommon case where an event crosses a sub buffer boundary (page)
      mark that check at the end of reserving an event as unlikely.
      Suggested-by: default avatarMathieu Desnoyers <mathieu.desnoyers@efficios.com>
      Signed-off-by: default avatarSteven Rostedt (VMware) <rostedt@goodmis.org>
      75b21c6d
    • Nicholas Piggin's avatar
      ring-buffer: speed up buffer resets by avoiding synchronize_rcu for each CPU · b23d7a5f
      Nicholas Piggin authored
      On a 144 thread system, `perf ftrace` takes about 20 seconds to start
      up, due to calling synchronize_rcu() for each CPU.
      
        cat /proc/108560/stack
          0xc0003e7eb336f470
          __switch_to+0x2e0/0x480
          __wait_rcu_gp+0x20c/0x220
          synchronize_rcu+0x9c/0xc0
          ring_buffer_reset_cpu+0x88/0x2e0
          tracing_reset_online_cpus+0x84/0xe0
          tracing_open+0x1d4/0x1f0
      
      On a system with 10x more threads, it starts to become an annoyance.
      
      Batch these up so we disable all the per-cpu buffers first, then
      synchronize_rcu() once, then reset each of the buffers. This brings
      the time down to about 0.5s.
      
      Link: https://lkml.kernel.org/r/20200625053403.2386972-1-npiggin@gmail.comTested-by: default avatarAnton Blanchard <anton@ozlabs.org>
      Acked-by: default avatarPaul E. McKenney <paulmck@kernel.org>
      Signed-off-by: default avatarNicholas Piggin <npiggin@gmail.com>
      Signed-off-by: default avatarSteven Rostedt (VMware) <rostedt@goodmis.org>
      b23d7a5f
    • Steven Rostedt (VMware)'s avatar
      ring-buffer: Add rb_time_t 64 bit operations for speeding up 32 bit · 10464b4a
      Steven Rostedt (VMware) authored
      After a discussion with the new time algorithm to have nested events still
      have proper time keeping but required using local64_t atomic operations.
      Mathieu was concerned about the performance this would have on 32 bit
      machines, as in most cases, atomic 64 bit operations on them can be
      expensive.
      
      As the ring buffer's timing needs do not require full features of local64_t,
      a wrapper is made to implement a new rb_time_t operation that uses two longs
      on 32 bit machines but still uses the local64_t operations on 64 bit
      machines. There's a switch that can be made in the file to force 64 bit to
      use the 32 bit version just for testing purposes.
      
      All reads do not need to succeed if a read happened while the stamp being
      read is in the process of being updated. The requirement is that all reads
      must succed that were done by an interrupting event (where this event was
      interrupted by another event that did the write). Or if the event itself did
      the write first. That is: rb_time_set(t, x) followed by rb_time_read(t) will
      always succeed (even if it gets interrupted by another event that writes to
      t. The result of the read will be either the previous set, or a set
      performed by an interrupting event.
      
      If the read is done by an event that interrupted another event that was in
      the process of setting the time stamp, and no other event came along to
      write to that time stamp, it will fail and the rb_time_read() will return
      that it failed (the value to read will be undefined).
      
      A set will always write to the time stamp and return with a valid time
      stamp, such that any read after it will be valid.
      
      A cmpxchg may fail if it interrupted an event that was in the process of
      updating the time stamp just like the reads do. Other than that, it will act
      like a normal cmpxchg.
      
      The way this works is that the rb_time_t is made of of three fields. A cnt,
      that gets updated atomically everyting a modification is made. A top that
      represents the most significant 30 bits of the time, and a bottom to
      represent the least significant 30 bits of the time. Notice, that the time
      values is only 60 bits long (where the ring buffer only uses 59 bits, which
      gives us 18 years of nanoseconds!).
      
      The top two bits of both the top and bottom is a 2 bit counter that gets set
      by the value of the least two significant bits of the cnt. A read of the top
      and the bottom where both the top and bottom have the same most significant
      top 2 bits, are considered a match and a valid 60 bit number can be created
      from it. If they do not match, then the number is considered invalid, and
      this must only happen if an event interrupted another event in the midst of
      updating the time stamp.
      
      This is only used for 32 bits machines as 64 bit machines can get better
      performance out of the local64_t. This has been tested heavily by forcing 64
      bit to use this logic.
      
      Link: https://lore.kernel.org/r/20200625225345.18cf5881@oasis.local.home
      Link: http://lkml.kernel.org/r/20200629025259.309232719@goodmis.orgInspired-by: default avatarMathieu Desnoyers <mathieu.desnoyers@efficios.com>
      Signed-off-by: default avatarSteven Rostedt (VMware) <rostedt@goodmis.org>
      10464b4a
    • Steven Rostedt (VMware)'s avatar
      ring-buffer: Incorporate absolute timestamp into add_timestamp logic · 7c4b4a51
      Steven Rostedt (VMware) authored
      Instead of calling out the absolute test for each time to check if the
      ring buffer wants absolute time stamps for all its recording, incorporate it
      with the add_timestamp field and turn it into flags for faster processing
      between wanting a absolute tag and needing to force one.
      
      Link: http://lkml.kernel.org/r/20200629025259.154892368@goodmis.orgSigned-off-by: default avatarSteven Rostedt (VMware) <rostedt@goodmis.org>
      7c4b4a51
    • Steven Rostedt (VMware)'s avatar
      ring-buffer: Have nested events still record running time stamp · a389d86f
      Steven Rostedt (VMware) authored
      Up until now, if an event is interrupted while it is recorded by an
      interrupt, and that interrupt records events, the time of those events will
      all be the same. This is because events only record the delta of the time
      since the previous event (or beginning of a page), and to handle updating
      the time keeping for that of nested events is extremely racy. After years of
      thinking about this and several failed attempts, I finally have a solution
      to solve this puzzle.
      
      The problem is that you need to atomically calculate the delta and then
      update the time stamp you made the delta from, as well as then record it
      into the buffer, all this while at any time an interrupt can come in and
      do the same thing. This is easy to solve with heavy weight atomics, but that
      would be detrimental to the performance of the ring buffer. The current
      state of affairs sacrificed the time deltas for nested events for
      performance.
      
      The reason for previous failed attempts at solving this puzzle was because I
      was trying to completely avoid slow atomic operations like cmpxchg. I final
      came to the conclusion to always avoid cmpxchg is not possible, which is why
      those previous attempts always failed. But it is possible to pick one path
      (the most common case) and avoid cmpxchg in that path, which is the "fast
      path". The most common case is that an event will not be interrupted and
      have other events added into it. An event can detect if it has
      interrupted another event, and for these cases we can make it the slow
      path and use the heavy operations like cmpxchg.
      
      One more player was added to the game that made this possible, and that is
      the "absolute timestamp" (by Tom Zanussi) that allows us to inject a full 59
      bit time stamp. (Of course this breaks if a machine is running for more than
      18 years without a reboot!).
      
      There's barrier() placements around for being paranoid, even when they
      are not needed because of other atomic functions near by. But those
      should not hurt, as if they are not needed, they basically become a nop.
      
      Note, this also makes the race window much smaller, which means there
      are less slow paths to slow down the performance.
      
      The basic idea is that there's two main paths taken.
      
       1) Not being interrupted between time stamps and reserving buffer space.
          In this case, the time stamps taken are true to the location in the
          buffer.
      
       2) Was interrupted by another path between taking time stamps and reserving
          buffer space.
      
      The objective is to know what the delta is from the last reserved location
      in the buffer.
      
      As it is possible to detect if an event is interrupting another event before
      reserving data, space is added to the length to be reserved to inject a full
      time stamp along with the event being reserved.
      
      When an event is not interrupted, the write stamp is always the time of the
      last event written to the buffer.
      
      In path 1, there's two sub paths we care about:
      
       a) The event did not interrupt another event.
       b) The event interrupted another event.
      
      In case a, as the write stamp was read and known to be correct, the delta
      between the current time stamp and the write stamp is the delta between the
      current event and the previously recorded event.
      
      In case b, extra space was reserved to just put the full time stamp into the
      buffer. Which is done, as stated, in this path the time stamp taken is known
      to match the location in the buffer.
      
      In path 2, there's also two sub paths we care about:
      
       a) The event was not interrupted by another event since it reserved space
          on the buffer and re-reading the write stamp.
       b) The event was interrupted by another event.
      
      In case a, the write stamp is that of the last event that interrupted this
      event between taking the time stamps and reserving. As no event came in
      after re-reading the write stamp, that event is known to be the time of the
      event directly before this event and the delta can be the new time stamp and
      the write stamp.
      
      In case b, one or more events came in between reserving the event and
      re-reading he write stamp. Since this event's buffer reservation is between
      other events at this path, there's no way to know what the delta is. But
      because an event interrupted this event after it started, its fine to just
      give a zero delta, and take the same time stamp as the events that happened
      within the event being recorded.
      
      Here's the implementation of the design of this solution:
      
       All this is per cpu, and only needs to worry about nested events (not
       parallel events).
      
      The players:
      
       write_tail: The index in the buffer where new events can be written to.
           It is incremented via local_add() to reserve space for a new event.
      
       before_stamp: A time stamp set by all events before reserving space.
      
       write_stamp: A time stamp updated by events after it has successfully
           reserved space.
      
      	/* Save the current position of write */
       [A]	w = local_read(write_tail);
      	barrier();
      	/* Read both before and write stamps before touching anything */
      	before = local_read(before_stamp);
      	after = local_read(write_stamp);
      	barrier();
      
      	/*
      	 * If before and after are the same, then this event is not
      	 * interrupting a time update. If it is, then reserve space for adding
      	 * a full time stamp (this can turn into a time extend which is
      	 * just an extended time delta but fill up the extra space).
      	 */
      	if (after != before)
      		abs = true;
      
      	ts = clock();
      
      	/* Now update the before_stamp (everyone does this!) */
       [B]	local_set(before_stamp, ts);
      
      	/* Now reserve space on the buffer */
       [C]	write = local_add_return(len, write_tail);
      
      	/* Set tail to be were this event's data is */
      	tail = write - len;
      
       	if (w == tail) {
      
      		/* Nothing interrupted this between A and C */
       [D]		local_set(write_stamp, ts);
      		barrier();
       [E]		save_before = local_read(before_stamp);
      
       		if (!abs) {
      			/* This did not interrupt a time update */
      			delta = ts - after;
      		} else {
      			delta = ts; /* The full time stamp will be in use */
      		}
      		if (ts != save_before) {
      			/* slow path - Was interrupted between C and E */
      			/* The update to write_stamp could have overwritten the update to
      			 * it by the interrupting event, but before and after should be
      			 * the same for all completed top events */
      			after = local_read(write_stamp);
      			if (save_before > after)
      				local_cmpxchg(write_stamp, after, save_before);
      		}
      	} else {
      		/* slow path - Interrupted between A and C */
      
      		after = local_read(write_stamp);
      		temp_ts = clock();
      		barrier();
       [F]		if (write == local_read(write_tail) && after < temp_ts) {
      			/* This was not interrupted since C and F
      			 * The last write_stamp is still valid for the previous event
      			 * in the buffer. */
      			delta = temp_ts - after;
      			/* OK to keep this new time stamp */
      			ts = temp_ts;
      		} else {
      			/* Interrupted between C and F
      			 * Well, there's no use to try to know what the time stamp
      			 * is for the previous event. Just set delta to zero and
      			 * be the same time as that event that interrupted us before
      			 * the reservation of the buffer. */
      
      			delta = 0;
      		}
      		/* No need to use full timestamps here */
      		abs = 0;
      	}
      
      Link: https://lkml.kernel.org/r/20200625094454.732790f7@oasis.local.home
      Link: https://lore.kernel.org/r/20200627010041.517736087@goodmis.org
      Link: http://lkml.kernel.org/r/20200629025258.957440797@goodmis.orgReviewed-by: default avatarMasami Hiramatsu <mhiramat@kernel.org>
      Signed-off-by: default avatarSteven Rostedt (VMware) <rostedt@goodmis.org>
      a389d86f
    • Steven Rostedt (VMware)'s avatar
      tracing: Move pipe reference to trace array instead of current_tracer · 7ef282e0
      Steven Rostedt (VMware) authored
      If a process has the trace_pipe open on a trace_array, the current tracer
      for that trace array should not be changed. This was original enforced by a
      global lock, but when instances were introduced, it was moved to the
      current_trace. But this structure is shared by all instances, and a
      trace_pipe is for a single instance. There's no reason that a process that
      has trace_pipe open on one instance should prevent another instance from
      changing its current tracer. Move the reference counter to the trace_array
      instead.
      
      This is marked as "Fixes" but is more of a clean up than a true fix.
      Backport if you want, but its not critical.
      
      Fixes: cf6ab6d9 ("tracing: Add ref count to tracer for when they are being read by pipe")
      Signed-off-by: default avatarSteven Rostedt (VMware) <rostedt@goodmis.org>
      7ef282e0
    • Wei Yang's avatar
      tracing: not necessary to define DEFINE_EVENT_PRINT to be empty again · e6bc5b3f
      Wei Yang authored
      After the previous cleanup, DEFINE_EVENT_PRINT's definition has no
      relationship with DEFINE_EVENT. So After we re-define DEFINE_EVENT, it
      is not necessary to define DEFINE_EVENT_PRINT to be empty again.
      
      Link: http://lkml.kernel.org/r/20200612092844.56107-5-richard.weiyang@linux.alibaba.comSigned-off-by: default avatarWei Yang <richard.weiyang@linux.alibaba.com>
      Signed-off-by: default avatarSteven Rostedt (VMware) <rostedt@goodmis.org>
      e6bc5b3f
    • Wei Yang's avatar
      tracing: define DEFINE_EVENT_PRINT not related to DEFINE_EVENT · 61df16fc
      Wei Yang authored
      Current definition define DEFINE_EVENT_PRINT to be DEFINE_EVENT.
      Actually, at this point DEFINE_EVENT is already an empty macro. Let's
      cut the relationship between DEFINE_EVENT_PRINT and DEFINE_EVENT.
      
      Link: http://lkml.kernel.org/r/20200612092844.56107-4-richard.weiyang@linux.alibaba.comSigned-off-by: default avatarWei Yang <richard.weiyang@linux.alibaba.com>
      Signed-off-by: default avatarSteven Rostedt (VMware) <rostedt@goodmis.org>
      61df16fc
    • Wei Yang's avatar
      tracing: not necessary re-define DEFINE_EVENT_PRINT · b6f9eb87
      Wei Yang authored
      The definition of DEFINE_EVENT_PRINT is not changed after previous one,
      so not necessary to re-define is as the same form.
      
      Link: http://lkml.kernel.org/r/20200612092844.56107-3-richard.weiyang@linux.alibaba.comSigned-off-by: default avatarWei Yang <richard.weiyang@linux.alibaba.com>
      Signed-off-by: default avatarSteven Rostedt (VMware) <rostedt@goodmis.org>
      b6f9eb87
    • Wei Yang's avatar
      tracing: not necessary to undefine DEFINE_EVENT again · e8cf9c8c
      Wei Yang authored
      After un-define DEFINE_EVENT in Stage 2, DEFINE_EVENT is not defined to a
      specific form. It is not necessary to un-define it again.
      
      Let's skip this.
      
      Link: http://lkml.kernel.org/r/20200612092844.56107-2-richard.weiyang@linux.alibaba.comSigned-off-by: default avatarWei Yang <richard.weiyang@linux.alibaba.com>
      Signed-off-by: default avatarSteven Rostedt (VMware) <rostedt@goodmis.org>
      e8cf9c8c
  11. 29 Jun, 2020 4 commits
  12. 28 Jun, 2020 1 commit