Tracing fixes for 5.14-rc2:
- Fix deadloop in ring buffer because of using stale "read" variable - Fix synthetic event use of field_pos as boolean and not an index - Fixed histogram special var "cpu" overriding event fields called "cpu" - Cleaned up error prone logic in alloc_synth_event() - Removed call to synchronize_rcu_tasks_rude() when not needed - Removed redundant initialization of a local variable "ret" - Fixed kernel crash when updating tracepoint callbacks of different priorities. -----BEGIN PGP SIGNATURE----- iIoEABYIADIWIQRRSw7ePDh/lE+zeZMp5XQQmuv6qgUCYPrGTxQccm9zdGVkdEBn b29kbWlzLm9yZwAKCRAp5XQQmuv6qusoAQDZkMo/vBFZgNGcL8GNCFpOF9HcV7QI JtBU+UG5GY2LagD/SEFEoG1o9UwKnIaBwr7qxGvrPgg8jKWtK/HEVFU94wk= =EVfM -----END PGP SIGNATURE----- Merge tag 'trace-v5.14-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace Pull tracing fixes from Steven Rostedt: - Fix deadloop in ring buffer because of using stale "read" variable - Fix synthetic event use of field_pos as boolean and not an index - Fixed histogram special var "cpu" overriding event fields called "cpu" - Cleaned up error prone logic in alloc_synth_event() - Removed call to synchronize_rcu_tasks_rude() when not needed - Removed redundant initialization of a local variable "ret" - Fixed kernel crash when updating tracepoint callbacks of different priorities. * tag 'trace-v5.14-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace: tracepoints: Update static_call before tp_funcs when adding a tracepoint ftrace: Remove redundant initialization of variable ret ftrace: Avoid synchronize_rcu_tasks_rude() call when not necessary tracing: Clean up alloc_synth_event() tracing/histogram: Rename "cpu" to "common_cpu" tracing: Synthetic event field_pos is an index not a boolean tracing: Fix bug in rb_per_cpu_empty() that might cause deadloop.
This commit is contained in:
commit
05daae0fb0
@ -191,7 +191,7 @@ Documentation written by Tom Zanussi
|
||||
with the event, in nanoseconds. May be
|
||||
modified by .usecs to have timestamps
|
||||
interpreted as microseconds.
|
||||
cpu int the cpu on which the event occurred.
|
||||
common_cpu int the cpu on which the event occurred.
|
||||
====================== ==== =======================================
|
||||
|
||||
Extended error information
|
||||
|
@ -5985,7 +5985,8 @@ ftrace_graph_release(struct inode *inode, struct file *file)
|
||||
* infrastructure to do the synchronization, thus we must do it
|
||||
* ourselves.
|
||||
*/
|
||||
synchronize_rcu_tasks_rude();
|
||||
if (old_hash != EMPTY_HASH)
|
||||
synchronize_rcu_tasks_rude();
|
||||
|
||||
free_ftrace_hash(old_hash);
|
||||
}
|
||||
@ -7544,7 +7545,7 @@ int ftrace_is_dead(void)
|
||||
*/
|
||||
int register_ftrace_function(struct ftrace_ops *ops)
|
||||
{
|
||||
int ret = -1;
|
||||
int ret;
|
||||
|
||||
ftrace_ops_init(ops);
|
||||
|
||||
|
@ -3880,10 +3880,30 @@ static bool rb_per_cpu_empty(struct ring_buffer_per_cpu *cpu_buffer)
|
||||
if (unlikely(!head))
|
||||
return true;
|
||||
|
||||
return reader->read == rb_page_commit(reader) &&
|
||||
(commit == reader ||
|
||||
(commit == head &&
|
||||
head->read == rb_page_commit(commit)));
|
||||
/* Reader should exhaust content in reader page */
|
||||
if (reader->read != rb_page_commit(reader))
|
||||
return false;
|
||||
|
||||
/*
|
||||
* If writers are committing on the reader page, knowing all
|
||||
* committed content has been read, the ring buffer is empty.
|
||||
*/
|
||||
if (commit == reader)
|
||||
return true;
|
||||
|
||||
/*
|
||||
* If writers are committing on a page other than reader page
|
||||
* and head page, there should always be content to read.
|
||||
*/
|
||||
if (commit != head)
|
||||
return false;
|
||||
|
||||
/*
|
||||
* Writers are committing on the head page, we just need
|
||||
* to care about there're committed data, and the reader will
|
||||
* swap reader page with head page when it is to read data.
|
||||
*/
|
||||
return rb_page_commit(commit) == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -5609,6 +5609,10 @@ static const char readme_msg[] =
|
||||
"\t [:name=histname1]\n"
|
||||
"\t [:<handler>.<action>]\n"
|
||||
"\t [if <filter>]\n\n"
|
||||
"\t Note, special fields can be used as well:\n"
|
||||
"\t common_timestamp - to record current timestamp\n"
|
||||
"\t common_cpu - to record the CPU the event happened on\n"
|
||||
"\n"
|
||||
"\t When a matching event is hit, an entry is added to a hash\n"
|
||||
"\t table using the key(s) and value(s) named, and the value of a\n"
|
||||
"\t sum called 'hitcount' is incremented. Keys and values\n"
|
||||
|
@ -1111,7 +1111,7 @@ static const char *hist_field_name(struct hist_field *field,
|
||||
field->flags & HIST_FIELD_FL_ALIAS)
|
||||
field_name = hist_field_name(field->operands[0], ++level);
|
||||
else if (field->flags & HIST_FIELD_FL_CPU)
|
||||
field_name = "cpu";
|
||||
field_name = "common_cpu";
|
||||
else if (field->flags & HIST_FIELD_FL_EXPR ||
|
||||
field->flags & HIST_FIELD_FL_VAR_REF) {
|
||||
if (field->system) {
|
||||
@ -1991,14 +1991,24 @@ parse_field(struct hist_trigger_data *hist_data, struct trace_event_file *file,
|
||||
hist_data->enable_timestamps = true;
|
||||
if (*flags & HIST_FIELD_FL_TIMESTAMP_USECS)
|
||||
hist_data->attrs->ts_in_usecs = true;
|
||||
} else if (strcmp(field_name, "cpu") == 0)
|
||||
} else if (strcmp(field_name, "common_cpu") == 0)
|
||||
*flags |= HIST_FIELD_FL_CPU;
|
||||
else {
|
||||
field = trace_find_event_field(file->event_call, field_name);
|
||||
if (!field || !field->size) {
|
||||
hist_err(tr, HIST_ERR_FIELD_NOT_FOUND, errpos(field_name));
|
||||
field = ERR_PTR(-EINVAL);
|
||||
goto out;
|
||||
/*
|
||||
* For backward compatibility, if field_name
|
||||
* was "cpu", then we treat this the same as
|
||||
* common_cpu.
|
||||
*/
|
||||
if (strcmp(field_name, "cpu") == 0) {
|
||||
*flags |= HIST_FIELD_FL_CPU;
|
||||
} else {
|
||||
hist_err(tr, HIST_ERR_FIELD_NOT_FOUND,
|
||||
errpos(field_name));
|
||||
field = ERR_PTR(-EINVAL);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
out:
|
||||
@ -5085,7 +5095,7 @@ static void hist_field_print(struct seq_file *m, struct hist_field *hist_field)
|
||||
seq_printf(m, "%s=", hist_field->var.name);
|
||||
|
||||
if (hist_field->flags & HIST_FIELD_FL_CPU)
|
||||
seq_puts(m, "cpu");
|
||||
seq_puts(m, "common_cpu");
|
||||
else if (field_name) {
|
||||
if (hist_field->flags & HIST_FIELD_FL_VAR_REF ||
|
||||
hist_field->flags & HIST_FIELD_FL_ALIAS)
|
||||
|
@ -893,15 +893,13 @@ static struct synth_event *alloc_synth_event(const char *name, int n_fields,
|
||||
dyn_event_init(&event->devent, &synth_event_ops);
|
||||
|
||||
for (i = 0, j = 0; i < n_fields; i++) {
|
||||
fields[i]->field_pos = i;
|
||||
event->fields[i] = fields[i];
|
||||
|
||||
if (fields[i]->is_dynamic) {
|
||||
event->dynamic_fields[j] = fields[i];
|
||||
event->dynamic_fields[j]->field_pos = i;
|
||||
if (fields[i]->is_dynamic)
|
||||
event->dynamic_fields[j++] = fields[i];
|
||||
event->n_dynamic_fields++;
|
||||
}
|
||||
}
|
||||
event->n_dynamic_fields = j;
|
||||
event->n_fields = n_fields;
|
||||
out:
|
||||
return event;
|
||||
|
@ -14,10 +14,10 @@ struct synth_field {
|
||||
char *name;
|
||||
size_t size;
|
||||
unsigned int offset;
|
||||
unsigned int field_pos;
|
||||
bool is_signed;
|
||||
bool is_string;
|
||||
bool is_dynamic;
|
||||
bool field_pos;
|
||||
};
|
||||
|
||||
struct synth_event {
|
||||
|
@ -299,8 +299,8 @@ static int tracepoint_add_func(struct tracepoint *tp,
|
||||
* a pointer to it. This array is referenced by __DO_TRACE from
|
||||
* include/linux/tracepoint.h using rcu_dereference_sched().
|
||||
*/
|
||||
rcu_assign_pointer(tp->funcs, tp_funcs);
|
||||
tracepoint_update_call(tp, tp_funcs, false);
|
||||
rcu_assign_pointer(tp->funcs, tp_funcs);
|
||||
static_key_enable(&tp->key);
|
||||
|
||||
release_probes(old);
|
||||
|
Loading…
x
Reference in New Issue
Block a user