Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 42c8e86c authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull tracing updates from Steven Rostedt:
 "Nothing new in development for this release. These are mostly fixes
  that were found during development of changes for the next merge
  window and fixes that were sent to me late in the last cycle"

* tag 'trace-v4.14' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace:
  tracing: Apply trace_clock changes to instance max buffer
  tracing: Fix clear of RECORDED_TGID flag when disabling trace event
  tracing: Add barrier to trace_printk() buffer nesting modification
  ftrace: Fix memleak when unregistering dynamic ops when tracing disabled
  ftrace: Fix selftest goto location on error
  ftrace: Zero out ftrace hashes when a module is removed
  tracing: Only have rmmod clear buffers that its events were active in
  ftrace: Fix debug preempt config name in stack_tracer_{en,dis}able
parents 3aea311c 170b3b10
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -307,7 +307,7 @@ DECLARE_PER_CPU(int, disable_stack_tracer);
static inline void stack_tracer_disable(void)
{
	/* Preemption or interupts must be disabled */
	if (IS_ENABLED(CONFIG_PREEMPT_DEBUG))
	if (IS_ENABLED(CONFIG_DEBUG_PREEMPT))
		WARN_ON_ONCE(!preempt_count() || !irqs_disabled());
	this_cpu_inc(disable_stack_tracer);
}
@@ -320,7 +320,7 @@ static inline void stack_tracer_disable(void)
 */
static inline void stack_tracer_enable(void)
{
	if (IS_ENABLED(CONFIG_PREEMPT_DEBUG))
	if (IS_ENABLED(CONFIG_DEBUG_PREEMPT))
		WARN_ON_ONCE(!preempt_count() || !irqs_disabled());
	this_cpu_dec(disable_stack_tracer);
}
+3 −5
Original line number Diff line number Diff line
@@ -217,7 +217,6 @@ enum {
	TRACE_EVENT_FL_CAP_ANY_BIT,
	TRACE_EVENT_FL_NO_SET_FILTER_BIT,
	TRACE_EVENT_FL_IGNORE_ENABLE_BIT,
	TRACE_EVENT_FL_WAS_ENABLED_BIT,
	TRACE_EVENT_FL_TRACEPOINT_BIT,
	TRACE_EVENT_FL_KPROBE_BIT,
	TRACE_EVENT_FL_UPROBE_BIT,
@@ -229,9 +228,6 @@ enum {
 *  CAP_ANY	  - Any user can enable for perf
 *  NO_SET_FILTER - Set when filter has error and is to be ignored
 *  IGNORE_ENABLE - For trace internal events, do not enable with debugfs file
 *  WAS_ENABLED   - Set and stays set when an event was ever enabled
 *                    (used for module unloading, if a module event is enabled,
 *                     it is best to clear the buffers that used it).
 *  TRACEPOINT    - Event is a tracepoint
 *  KPROBE        - Event is a kprobe
 *  UPROBE        - Event is a uprobe
@@ -241,7 +237,6 @@ enum {
	TRACE_EVENT_FL_CAP_ANY		= (1 << TRACE_EVENT_FL_CAP_ANY_BIT),
	TRACE_EVENT_FL_NO_SET_FILTER	= (1 << TRACE_EVENT_FL_NO_SET_FILTER_BIT),
	TRACE_EVENT_FL_IGNORE_ENABLE	= (1 << TRACE_EVENT_FL_IGNORE_ENABLE_BIT),
	TRACE_EVENT_FL_WAS_ENABLED	= (1 << TRACE_EVENT_FL_WAS_ENABLED_BIT),
	TRACE_EVENT_FL_TRACEPOINT	= (1 << TRACE_EVENT_FL_TRACEPOINT_BIT),
	TRACE_EVENT_FL_KPROBE		= (1 << TRACE_EVENT_FL_KPROBE_BIT),
	TRACE_EVENT_FL_UPROBE		= (1 << TRACE_EVENT_FL_UPROBE_BIT),
@@ -306,6 +301,7 @@ enum {
	EVENT_FILE_FL_TRIGGER_MODE_BIT,
	EVENT_FILE_FL_TRIGGER_COND_BIT,
	EVENT_FILE_FL_PID_FILTER_BIT,
	EVENT_FILE_FL_WAS_ENABLED_BIT,
};

/*
@@ -321,6 +317,7 @@ enum {
 *  TRIGGER_MODE  - When set, invoke the triggers associated with the event
 *  TRIGGER_COND  - When set, one or more triggers has an associated filter
 *  PID_FILTER    - When set, the event is filtered based on pid
 *  WAS_ENABLED   - Set when enabled to know to clear trace on module removal
 */
enum {
	EVENT_FILE_FL_ENABLED		= (1 << EVENT_FILE_FL_ENABLED_BIT),
@@ -333,6 +330,7 @@ enum {
	EVENT_FILE_FL_TRIGGER_MODE	= (1 << EVENT_FILE_FL_TRIGGER_MODE_BIT),
	EVENT_FILE_FL_TRIGGER_COND	= (1 << EVENT_FILE_FL_TRIGGER_COND_BIT),
	EVENT_FILE_FL_PID_FILTER	= (1 << EVENT_FILE_FL_PID_FILTER_BIT),
	EVENT_FILE_FL_WAS_ENABLED	= (1 << EVENT_FILE_FL_WAS_ENABLED_BIT),
};

struct trace_event_file {
+61 −7
Original line number Diff line number Diff line
@@ -2828,13 +2828,14 @@ static int ftrace_shutdown(struct ftrace_ops *ops, int command)

	if (!command || !ftrace_enabled) {
		/*
		 * If these are per_cpu ops, they still need their
		 * per_cpu field freed. Since, function tracing is
		 * If these are dynamic or per_cpu ops, they still
		 * need their data freed. Since, function tracing is
		 * not currently active, we can just free them
		 * without synchronizing all CPUs.
		 */
		if (ops->flags & FTRACE_OPS_FL_PER_CPU)
			per_cpu_ops_free(ops);
		if (ops->flags & (FTRACE_OPS_FL_DYNAMIC | FTRACE_OPS_FL_PER_CPU))
			goto free_ops;

		return 0;
	}

@@ -2900,6 +2901,7 @@ static int ftrace_shutdown(struct ftrace_ops *ops, int command)
		if (IS_ENABLED(CONFIG_PREEMPT))
			synchronize_rcu_tasks();

 free_ops:
		arch_ftrace_trampoline_free(ops);

		if (ops->flags & FTRACE_OPS_FL_PER_CPU)
@@ -5690,10 +5692,51 @@ static int referenced_filters(struct dyn_ftrace *rec)
	return cnt;
}

static void
clear_mod_from_hash(struct ftrace_page *pg, struct ftrace_hash *hash)
{
	struct ftrace_func_entry *entry;
	struct dyn_ftrace *rec;
	int i;

	if (ftrace_hash_empty(hash))
		return;

	for (i = 0; i < pg->index; i++) {
		rec = &pg->records[i];
		entry = __ftrace_lookup_ip(hash, rec->ip);
		/*
		 * Do not allow this rec to match again.
		 * Yeah, it may waste some memory, but will be removed
		 * if/when the hash is modified again.
		 */
		if (entry)
			entry->ip = 0;
	}
}

/* Clear any records from hashs */
static void clear_mod_from_hashes(struct ftrace_page *pg)
{
	struct trace_array *tr;

	mutex_lock(&trace_types_lock);
	list_for_each_entry(tr, &ftrace_trace_arrays, list) {
		if (!tr->ops || !tr->ops->func_hash)
			continue;
		mutex_lock(&tr->ops->func_hash->regex_lock);
		clear_mod_from_hash(pg, tr->ops->func_hash->filter_hash);
		clear_mod_from_hash(pg, tr->ops->func_hash->notrace_hash);
		mutex_unlock(&tr->ops->func_hash->regex_lock);
	}
	mutex_unlock(&trace_types_lock);
}

void ftrace_release_mod(struct module *mod)
{
	struct dyn_ftrace *rec;
	struct ftrace_page **last_pg;
	struct ftrace_page *tmp_page = NULL;
	struct ftrace_page *pg;
	int order;

@@ -5723,14 +5766,25 @@ void ftrace_release_mod(struct module *mod)

			ftrace_update_tot_cnt -= pg->index;
			*last_pg = pg->next;
			order = get_count_order(pg->size / ENTRIES_PER_PAGE);
			free_pages((unsigned long)pg->records, order);
			kfree(pg);

			pg->next = tmp_page;
			tmp_page = pg;
		} else
			last_pg = &pg->next;
	}
 out_unlock:
	mutex_unlock(&ftrace_lock);

	for (pg = tmp_page; pg; pg = tmp_page) {

		/* Needs to be called outside of ftrace_lock */
		clear_mod_from_hashes(pg);

		order = get_count_order(pg->size / ENTRIES_PER_PAGE);
		free_pages((unsigned long)pg->records, order);
		tmp_page = pg->next;
		kfree(pg);
	}
}

void ftrace_module_enable(struct module *mod)
+11 −2
Original line number Diff line number Diff line
@@ -1702,6 +1702,9 @@ void tracing_reset_all_online_cpus(void)
	struct trace_array *tr;

	list_for_each_entry(tr, &ftrace_trace_arrays, list) {
		if (!tr->clear_trace)
			continue;
		tr->clear_trace = false;
		tracing_reset_online_cpus(&tr->trace_buffer);
#ifdef CONFIG_TRACER_MAX_TRACE
		tracing_reset_online_cpus(&tr->max_buffer);
@@ -2799,11 +2802,17 @@ static char *get_trace_buf(void)
	if (!buffer || buffer->nesting >= 4)
		return NULL;

	return &buffer->buffer[buffer->nesting++][0];
	buffer->nesting++;

	/* Interrupts must see nesting incremented before we use the buffer */
	barrier();
	return &buffer->buffer[buffer->nesting][0];
}

static void put_trace_buf(void)
{
	/* Don't let the decrement of nesting leak before this */
	barrier();
	this_cpu_dec(trace_percpu_buffer->nesting);
}

@@ -6220,7 +6229,7 @@ static int tracing_set_clock(struct trace_array *tr, const char *clockstr)
	tracing_reset_online_cpus(&tr->trace_buffer);

#ifdef CONFIG_TRACER_MAX_TRACE
	if (tr->flags & TRACE_ARRAY_FL_GLOBAL && tr->max_buffer.buffer)
	if (tr->max_buffer.buffer)
		ring_buffer_set_clock(tr->max_buffer.buffer, trace_clocks[i].func);
	tracing_reset_online_cpus(&tr->max_buffer);
#endif
+1 −0
Original line number Diff line number Diff line
@@ -245,6 +245,7 @@ struct trace_array {
	int			stop_count;
	int			clock_id;
	int			nr_topts;
	bool			clear_trace;
	struct tracer		*current_trace;
	unsigned int		trace_flags;
	unsigned char		trace_flags_index[TRACE_FLAGS_MAX_SIZE];
Loading