Merge tag 'trace-v5.2' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace
Pull tracing updates from Steven Rostedt: "The major changes in this tracing update includes: - Removal of non-DYNAMIC_FTRACE from 32bit x86 - Removal of mcount support from x86 - Emulating a call from int3 on x86_64, fixes live kernel patching - Consolidated Tracing Error logs file Minor updates: - Removal of klp_check_compiler_support() - kdb ftrace dumping output changes - Accessing and creating ftrace instances from inside the kernel - Clean up of #define if macro - Introduction of TRACE_EVENT_NOP() to disable trace events based on config options And other minor fixes and clean ups" * tag 'trace-v5.2' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace: (44 commits) x86: Hide the int3_emulate_call/jmp functions from UML livepatch: Remove klp_check_compiler_support() ftrace/x86: Remove mcount support ftrace/x86_32: Remove support for non DYNAMIC_FTRACE tracing: Simplify "if" macro code tracing: Fix documentation about disabling options using trace_options tracing: Replace kzalloc with kcalloc tracing: Fix partial reading of trace event's id file tracing: Allow RCU to run between postponed startup tests tracing: Fix white space issues in parse_pred() function tracing: Eliminate const char[] auto variables ring-buffer: Fix mispelling of Calculate tracing: probeevent: Fix to make the type of $comm string tracing: probeevent: Do not accumulate on ret variable tracing: uprobes: Re-enable $comm support for uprobe events ftrace/x86_64: Emulate call function while updating in breakpoint handler x86_64: Allow breakpoints to emulate call instructions x86_64: Add gap to int3 to allow for call emulation tracing: kdb: Allow ftdump to skip all but the last few entries tracing: Add trace_total_entries() / trace_total_entries_cpu() ...
This commit is contained in:
@@ -1727,6 +1727,10 @@ static __init int init_trace_selftests(void)
|
||||
pr_info("Running postponed tracer tests:\n");
|
||||
|
||||
list_for_each_entry_safe(p, n, &postponed_selftests, list) {
|
||||
/* This loop can take minutes when sanitizers are enabled, so
|
||||
* lets make sure we allow RCU processing.
|
||||
*/
|
||||
cond_resched();
|
||||
ret = run_tracer_selftest(p->type);
|
||||
/* If the test fails, then warn and remove from available_tracers */
|
||||
if (ret < 0) {
|
||||
@@ -3045,6 +3049,7 @@ void trace_printk_init_buffers(void)
|
||||
if (global_trace.trace_buffer.buffer)
|
||||
tracing_start_cmdline_record();
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(trace_printk_init_buffers);
|
||||
|
||||
void trace_printk_start_comm(void)
|
||||
{
|
||||
@@ -3205,6 +3210,7 @@ int trace_array_printk(struct trace_array *tr,
|
||||
va_end(ap);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(trace_array_printk);
|
||||
|
||||
__printf(3, 4)
|
||||
int trace_array_printk_buf(struct ring_buffer *buffer,
|
||||
@@ -3482,34 +3488,69 @@ static void s_stop(struct seq_file *m, void *p)
|
||||
trace_event_read_unlock();
|
||||
}
|
||||
|
||||
static void
|
||||
get_total_entries_cpu(struct trace_buffer *buf, unsigned long *total,
|
||||
unsigned long *entries, int cpu)
|
||||
{
|
||||
unsigned long count;
|
||||
|
||||
count = ring_buffer_entries_cpu(buf->buffer, cpu);
|
||||
/*
|
||||
* If this buffer has skipped entries, then we hold all
|
||||
* entries for the trace and we need to ignore the
|
||||
* ones before the time stamp.
|
||||
*/
|
||||
if (per_cpu_ptr(buf->data, cpu)->skipped_entries) {
|
||||
count -= per_cpu_ptr(buf->data, cpu)->skipped_entries;
|
||||
/* total is the same as the entries */
|
||||
*total = count;
|
||||
} else
|
||||
*total = count +
|
||||
ring_buffer_overrun_cpu(buf->buffer, cpu);
|
||||
*entries = count;
|
||||
}
|
||||
|
||||
static void
|
||||
get_total_entries(struct trace_buffer *buf,
|
||||
unsigned long *total, unsigned long *entries)
|
||||
{
|
||||
unsigned long count;
|
||||
unsigned long t, e;
|
||||
int cpu;
|
||||
|
||||
*total = 0;
|
||||
*entries = 0;
|
||||
|
||||
for_each_tracing_cpu(cpu) {
|
||||
count = ring_buffer_entries_cpu(buf->buffer, cpu);
|
||||
/*
|
||||
* If this buffer has skipped entries, then we hold all
|
||||
* entries for the trace and we need to ignore the
|
||||
* ones before the time stamp.
|
||||
*/
|
||||
if (per_cpu_ptr(buf->data, cpu)->skipped_entries) {
|
||||
count -= per_cpu_ptr(buf->data, cpu)->skipped_entries;
|
||||
/* total is the same as the entries */
|
||||
*total += count;
|
||||
} else
|
||||
*total += count +
|
||||
ring_buffer_overrun_cpu(buf->buffer, cpu);
|
||||
*entries += count;
|
||||
get_total_entries_cpu(buf, &t, &e, cpu);
|
||||
*total += t;
|
||||
*entries += e;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned long trace_total_entries_cpu(struct trace_array *tr, int cpu)
|
||||
{
|
||||
unsigned long total, entries;
|
||||
|
||||
if (!tr)
|
||||
tr = &global_trace;
|
||||
|
||||
get_total_entries_cpu(&tr->trace_buffer, &total, &entries, cpu);
|
||||
|
||||
return entries;
|
||||
}
|
||||
|
||||
unsigned long trace_total_entries(struct trace_array *tr)
|
||||
{
|
||||
unsigned long total, entries;
|
||||
|
||||
if (!tr)
|
||||
tr = &global_trace;
|
||||
|
||||
get_total_entries(&tr->trace_buffer, &total, &entries);
|
||||
|
||||
return entries;
|
||||
}
|
||||
|
||||
static void print_lat_help_header(struct seq_file *m)
|
||||
{
|
||||
seq_puts(m, "# _------=> CPU# \n"
|
||||
@@ -3548,25 +3589,18 @@ static void print_func_help_header_irq(struct trace_buffer *buf, struct seq_file
|
||||
unsigned int flags)
|
||||
{
|
||||
bool tgid = flags & TRACE_ITER_RECORD_TGID;
|
||||
const char tgid_space[] = " ";
|
||||
const char space[] = " ";
|
||||
const char *space = " ";
|
||||
int prec = tgid ? 10 : 2;
|
||||
|
||||
print_event_info(buf, m);
|
||||
|
||||
seq_printf(m, "# %s _-----=> irqs-off\n",
|
||||
tgid ? tgid_space : space);
|
||||
seq_printf(m, "# %s / _----=> need-resched\n",
|
||||
tgid ? tgid_space : space);
|
||||
seq_printf(m, "# %s| / _---=> hardirq/softirq\n",
|
||||
tgid ? tgid_space : space);
|
||||
seq_printf(m, "# %s|| / _--=> preempt-depth\n",
|
||||
tgid ? tgid_space : space);
|
||||
seq_printf(m, "# %s||| / delay\n",
|
||||
tgid ? tgid_space : space);
|
||||
seq_printf(m, "# TASK-PID %sCPU# |||| TIMESTAMP FUNCTION\n",
|
||||
tgid ? " TGID " : space);
|
||||
seq_printf(m, "# | | %s | |||| | |\n",
|
||||
tgid ? " | " : space);
|
||||
seq_printf(m, "# %.*s _-----=> irqs-off\n", prec, space);
|
||||
seq_printf(m, "# %.*s / _----=> need-resched\n", prec, space);
|
||||
seq_printf(m, "# %.*s| / _---=> hardirq/softirq\n", prec, space);
|
||||
seq_printf(m, "# %.*s|| / _--=> preempt-depth\n", prec, space);
|
||||
seq_printf(m, "# %.*s||| / delay\n", prec, space);
|
||||
seq_printf(m, "# TASK-PID %.*sCPU# |||| TIMESTAMP FUNCTION\n", prec, " TGID ");
|
||||
seq_printf(m, "# | | %.*s | |||| | |\n", prec, " | ");
|
||||
}
|
||||
|
||||
void
|
||||
@@ -4692,6 +4726,7 @@ static const char readme_msg[] =
|
||||
" trace_pipe\t\t- A consuming read to see the contents of the buffer\n"
|
||||
" current_tracer\t- function and latency tracers\n"
|
||||
" available_tracers\t- list of configured tracers for current_tracer\n"
|
||||
" error_log\t- error log for failed commands (that support it)\n"
|
||||
" buffer_size_kb\t- view and modify size of per cpu buffer\n"
|
||||
" buffer_total_size_kb - view total size of all cpu buffers\n\n"
|
||||
" trace_clock\t\t-change the clock used to order events\n"
|
||||
@@ -4712,7 +4747,7 @@ static const char readme_msg[] =
|
||||
" instances\t\t- Make sub-buffers with: mkdir instances/foo\n"
|
||||
"\t\t\t Remove sub-buffer with rmdir\n"
|
||||
" trace_options\t\t- Set format or modify how tracing happens\n"
|
||||
"\t\t\t Disable an option by adding a suffix 'no' to the\n"
|
||||
"\t\t\t Disable an option by prefixing 'no' to the\n"
|
||||
"\t\t\t option name\n"
|
||||
" saved_cmdlines_size\t- echo command number in here to store comm-pid list\n"
|
||||
#ifdef CONFIG_DYNAMIC_FTRACE
|
||||
@@ -6296,13 +6331,13 @@ tracing_mark_write(struct file *filp, const char __user *ubuf,
|
||||
struct ring_buffer *buffer;
|
||||
struct print_entry *entry;
|
||||
unsigned long irq_flags;
|
||||
const char faulted[] = "<faulted>";
|
||||
ssize_t written;
|
||||
int size;
|
||||
int len;
|
||||
|
||||
/* Used in tracing_mark_raw_write() as well */
|
||||
#define FAULTED_SIZE (sizeof(faulted) - 1) /* '\0' is already accounted for */
|
||||
#define FAULTED_STR "<faulted>"
|
||||
#define FAULTED_SIZE (sizeof(FAULTED_STR) - 1) /* '\0' is already accounted for */
|
||||
|
||||
if (tracing_disabled)
|
||||
return -EINVAL;
|
||||
@@ -6334,7 +6369,7 @@ tracing_mark_write(struct file *filp, const char __user *ubuf,
|
||||
|
||||
len = __copy_from_user_inatomic(&entry->buf, ubuf, cnt);
|
||||
if (len) {
|
||||
memcpy(&entry->buf, faulted, FAULTED_SIZE);
|
||||
memcpy(&entry->buf, FAULTED_STR, FAULTED_SIZE);
|
||||
cnt = FAULTED_SIZE;
|
||||
written = -EFAULT;
|
||||
} else
|
||||
@@ -6375,7 +6410,6 @@ tracing_mark_raw_write(struct file *filp, const char __user *ubuf,
|
||||
struct ring_buffer_event *event;
|
||||
struct ring_buffer *buffer;
|
||||
struct raw_data_entry *entry;
|
||||
const char faulted[] = "<faulted>";
|
||||
unsigned long irq_flags;
|
||||
ssize_t written;
|
||||
int size;
|
||||
@@ -6415,7 +6449,7 @@ tracing_mark_raw_write(struct file *filp, const char __user *ubuf,
|
||||
len = __copy_from_user_inatomic(&entry->id, ubuf, cnt);
|
||||
if (len) {
|
||||
entry->id = -1;
|
||||
memcpy(&entry->buf, faulted, FAULTED_SIZE);
|
||||
memcpy(&entry->buf, FAULTED_STR, FAULTED_SIZE);
|
||||
written = -EFAULT;
|
||||
} else
|
||||
written = cnt;
|
||||
@@ -6868,6 +6902,238 @@ static const struct file_operations snapshot_raw_fops = {
|
||||
|
||||
#endif /* CONFIG_TRACER_SNAPSHOT */
|
||||
|
||||
#define TRACING_LOG_ERRS_MAX 8
|
||||
#define TRACING_LOG_LOC_MAX 128
|
||||
|
||||
#define CMD_PREFIX " Command: "
|
||||
|
||||
struct err_info {
|
||||
const char **errs; /* ptr to loc-specific array of err strings */
|
||||
u8 type; /* index into errs -> specific err string */
|
||||
u8 pos; /* MAX_FILTER_STR_VAL = 256 */
|
||||
u64 ts;
|
||||
};
|
||||
|
||||
struct tracing_log_err {
|
||||
struct list_head list;
|
||||
struct err_info info;
|
||||
char loc[TRACING_LOG_LOC_MAX]; /* err location */
|
||||
char cmd[MAX_FILTER_STR_VAL]; /* what caused err */
|
||||
};
|
||||
|
||||
static DEFINE_MUTEX(tracing_err_log_lock);
|
||||
|
||||
struct tracing_log_err *get_tracing_log_err(struct trace_array *tr)
|
||||
{
|
||||
struct tracing_log_err *err;
|
||||
|
||||
if (tr->n_err_log_entries < TRACING_LOG_ERRS_MAX) {
|
||||
err = kzalloc(sizeof(*err), GFP_KERNEL);
|
||||
if (!err)
|
||||
err = ERR_PTR(-ENOMEM);
|
||||
tr->n_err_log_entries++;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
err = list_first_entry(&tr->err_log, struct tracing_log_err, list);
|
||||
list_del(&err->list);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
* err_pos - find the position of a string within a command for error careting
|
||||
* @cmd: The tracing command that caused the error
|
||||
* @str: The string to position the caret at within @cmd
|
||||
*
|
||||
* Finds the position of the first occurence of @str within @cmd. The
|
||||
* return value can be passed to tracing_log_err() for caret placement
|
||||
* within @cmd.
|
||||
*
|
||||
* Returns the index within @cmd of the first occurence of @str or 0
|
||||
* if @str was not found.
|
||||
*/
|
||||
unsigned int err_pos(char *cmd, const char *str)
|
||||
{
|
||||
char *found;
|
||||
|
||||
if (WARN_ON(!strlen(cmd)))
|
||||
return 0;
|
||||
|
||||
found = strstr(cmd, str);
|
||||
if (found)
|
||||
return found - cmd;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* tracing_log_err - write an error to the tracing error log
|
||||
* @tr: The associated trace array for the error (NULL for top level array)
|
||||
* @loc: A string describing where the error occurred
|
||||
* @cmd: The tracing command that caused the error
|
||||
* @errs: The array of loc-specific static error strings
|
||||
* @type: The index into errs[], which produces the specific static err string
|
||||
* @pos: The position the caret should be placed in the cmd
|
||||
*
|
||||
* Writes an error into tracing/error_log of the form:
|
||||
*
|
||||
* <loc>: error: <text>
|
||||
* Command: <cmd>
|
||||
* ^
|
||||
*
|
||||
* tracing/error_log is a small log file containing the last
|
||||
* TRACING_LOG_ERRS_MAX errors (8). Memory for errors isn't allocated
|
||||
* unless there has been a tracing error, and the error log can be
|
||||
* cleared and have its memory freed by writing the empty string in
|
||||
* truncation mode to it i.e. echo > tracing/error_log.
|
||||
*
|
||||
* NOTE: the @errs array along with the @type param are used to
|
||||
* produce a static error string - this string is not copied and saved
|
||||
* when the error is logged - only a pointer to it is saved. See
|
||||
* existing callers for examples of how static strings are typically
|
||||
* defined for use with tracing_log_err().
|
||||
*/
|
||||
void tracing_log_err(struct trace_array *tr,
|
||||
const char *loc, const char *cmd,
|
||||
const char **errs, u8 type, u8 pos)
|
||||
{
|
||||
struct tracing_log_err *err;
|
||||
|
||||
if (!tr)
|
||||
tr = &global_trace;
|
||||
|
||||
mutex_lock(&tracing_err_log_lock);
|
||||
err = get_tracing_log_err(tr);
|
||||
if (PTR_ERR(err) == -ENOMEM) {
|
||||
mutex_unlock(&tracing_err_log_lock);
|
||||
return;
|
||||
}
|
||||
|
||||
snprintf(err->loc, TRACING_LOG_LOC_MAX, "%s: error: ", loc);
|
||||
snprintf(err->cmd, MAX_FILTER_STR_VAL,"\n" CMD_PREFIX "%s\n", cmd);
|
||||
|
||||
err->info.errs = errs;
|
||||
err->info.type = type;
|
||||
err->info.pos = pos;
|
||||
err->info.ts = local_clock();
|
||||
|
||||
list_add_tail(&err->list, &tr->err_log);
|
||||
mutex_unlock(&tracing_err_log_lock);
|
||||
}
|
||||
|
||||
static void clear_tracing_err_log(struct trace_array *tr)
|
||||
{
|
||||
struct tracing_log_err *err, *next;
|
||||
|
||||
mutex_lock(&tracing_err_log_lock);
|
||||
list_for_each_entry_safe(err, next, &tr->err_log, list) {
|
||||
list_del(&err->list);
|
||||
kfree(err);
|
||||
}
|
||||
|
||||
tr->n_err_log_entries = 0;
|
||||
mutex_unlock(&tracing_err_log_lock);
|
||||
}
|
||||
|
||||
static void *tracing_err_log_seq_start(struct seq_file *m, loff_t *pos)
|
||||
{
|
||||
struct trace_array *tr = m->private;
|
||||
|
||||
mutex_lock(&tracing_err_log_lock);
|
||||
|
||||
return seq_list_start(&tr->err_log, *pos);
|
||||
}
|
||||
|
||||
static void *tracing_err_log_seq_next(struct seq_file *m, void *v, loff_t *pos)
|
||||
{
|
||||
struct trace_array *tr = m->private;
|
||||
|
||||
return seq_list_next(v, &tr->err_log, pos);
|
||||
}
|
||||
|
||||
static void tracing_err_log_seq_stop(struct seq_file *m, void *v)
|
||||
{
|
||||
mutex_unlock(&tracing_err_log_lock);
|
||||
}
|
||||
|
||||
static void tracing_err_log_show_pos(struct seq_file *m, u8 pos)
|
||||
{
|
||||
u8 i;
|
||||
|
||||
for (i = 0; i < sizeof(CMD_PREFIX) - 1; i++)
|
||||
seq_putc(m, ' ');
|
||||
for (i = 0; i < pos; i++)
|
||||
seq_putc(m, ' ');
|
||||
seq_puts(m, "^\n");
|
||||
}
|
||||
|
||||
static int tracing_err_log_seq_show(struct seq_file *m, void *v)
|
||||
{
|
||||
struct tracing_log_err *err = v;
|
||||
|
||||
if (err) {
|
||||
const char *err_text = err->info.errs[err->info.type];
|
||||
u64 sec = err->info.ts;
|
||||
u32 nsec;
|
||||
|
||||
nsec = do_div(sec, NSEC_PER_SEC);
|
||||
seq_printf(m, "[%5llu.%06u] %s%s", sec, nsec / 1000,
|
||||
err->loc, err_text);
|
||||
seq_printf(m, "%s", err->cmd);
|
||||
tracing_err_log_show_pos(m, err->info.pos);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct seq_operations tracing_err_log_seq_ops = {
|
||||
.start = tracing_err_log_seq_start,
|
||||
.next = tracing_err_log_seq_next,
|
||||
.stop = tracing_err_log_seq_stop,
|
||||
.show = tracing_err_log_seq_show
|
||||
};
|
||||
|
||||
static int tracing_err_log_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct trace_array *tr = inode->i_private;
|
||||
int ret = 0;
|
||||
|
||||
if (trace_array_get(tr) < 0)
|
||||
return -ENODEV;
|
||||
|
||||
/* If this file was opened for write, then erase contents */
|
||||
if ((file->f_mode & FMODE_WRITE) && (file->f_flags & O_TRUNC))
|
||||
clear_tracing_err_log(tr);
|
||||
|
||||
if (file->f_mode & FMODE_READ) {
|
||||
ret = seq_open(file, &tracing_err_log_seq_ops);
|
||||
if (!ret) {
|
||||
struct seq_file *m = file->private_data;
|
||||
m->private = tr;
|
||||
} else {
|
||||
trace_array_put(tr);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t tracing_err_log_write(struct file *file,
|
||||
const char __user *buffer,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
return count;
|
||||
}
|
||||
|
||||
static const struct file_operations tracing_err_log_fops = {
|
||||
.open = tracing_err_log_open,
|
||||
.write = tracing_err_log_write,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = tracing_release_generic_tr,
|
||||
};
|
||||
|
||||
static int tracing_buffers_open(struct inode *inode, struct file *filp)
|
||||
{
|
||||
struct trace_array *tr = inode->i_private;
|
||||
@@ -8033,7 +8299,7 @@ static void update_tracer_options(struct trace_array *tr)
|
||||
mutex_unlock(&trace_types_lock);
|
||||
}
|
||||
|
||||
static int instance_mkdir(const char *name)
|
||||
struct trace_array *trace_array_create(const char *name)
|
||||
{
|
||||
struct trace_array *tr;
|
||||
int ret;
|
||||
@@ -8072,6 +8338,7 @@ static int instance_mkdir(const char *name)
|
||||
INIT_LIST_HEAD(&tr->systems);
|
||||
INIT_LIST_HEAD(&tr->events);
|
||||
INIT_LIST_HEAD(&tr->hist_vars);
|
||||
INIT_LIST_HEAD(&tr->err_log);
|
||||
|
||||
if (allocate_trace_buffers(tr, trace_buf_size) < 0)
|
||||
goto out_free_tr;
|
||||
@@ -8097,7 +8364,7 @@ static int instance_mkdir(const char *name)
|
||||
mutex_unlock(&trace_types_lock);
|
||||
mutex_unlock(&event_mutex);
|
||||
|
||||
return 0;
|
||||
return tr;
|
||||
|
||||
out_free_tr:
|
||||
free_trace_buffers(tr);
|
||||
@@ -8109,33 +8376,21 @@ static int instance_mkdir(const char *name)
|
||||
mutex_unlock(&trace_types_lock);
|
||||
mutex_unlock(&event_mutex);
|
||||
|
||||
return ret;
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(trace_array_create);
|
||||
|
||||
static int instance_mkdir(const char *name)
|
||||
{
|
||||
return PTR_ERR_OR_ZERO(trace_array_create(name));
|
||||
}
|
||||
|
||||
static int instance_rmdir(const char *name)
|
||||
static int __remove_instance(struct trace_array *tr)
|
||||
{
|
||||
struct trace_array *tr;
|
||||
int found = 0;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
mutex_lock(&event_mutex);
|
||||
mutex_lock(&trace_types_lock);
|
||||
|
||||
ret = -ENODEV;
|
||||
list_for_each_entry(tr, &ftrace_trace_arrays, list) {
|
||||
if (tr->name && strcmp(tr->name, name) == 0) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found)
|
||||
goto out_unlock;
|
||||
|
||||
ret = -EBUSY;
|
||||
if (tr->ref || (tr->current_trace && tr->current_trace->ref))
|
||||
goto out_unlock;
|
||||
return -EBUSY;
|
||||
|
||||
list_del(&tr->list);
|
||||
|
||||
@@ -8161,10 +8416,46 @@ static int instance_rmdir(const char *name)
|
||||
free_cpumask_var(tr->tracing_cpumask);
|
||||
kfree(tr->name);
|
||||
kfree(tr);
|
||||
tr = NULL;
|
||||
|
||||
ret = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int trace_array_destroy(struct trace_array *tr)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!tr)
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&event_mutex);
|
||||
mutex_lock(&trace_types_lock);
|
||||
|
||||
ret = __remove_instance(tr);
|
||||
|
||||
mutex_unlock(&trace_types_lock);
|
||||
mutex_unlock(&event_mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(trace_array_destroy);
|
||||
|
||||
static int instance_rmdir(const char *name)
|
||||
{
|
||||
struct trace_array *tr;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&event_mutex);
|
||||
mutex_lock(&trace_types_lock);
|
||||
|
||||
ret = -ENODEV;
|
||||
list_for_each_entry(tr, &ftrace_trace_arrays, list) {
|
||||
if (tr->name && strcmp(tr->name, name) == 0) {
|
||||
ret = __remove_instance(tr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
out_unlock:
|
||||
mutex_unlock(&trace_types_lock);
|
||||
mutex_unlock(&event_mutex);
|
||||
|
||||
@@ -8254,6 +8545,9 @@ init_tracer_tracefs(struct trace_array *tr, struct dentry *d_tracer)
|
||||
tr, &snapshot_fops);
|
||||
#endif
|
||||
|
||||
trace_create_file("error_log", 0644, d_tracer,
|
||||
tr, &tracing_err_log_fops);
|
||||
|
||||
for_each_tracing_cpu(cpu)
|
||||
tracing_init_tracefs_percpu(tr, cpu);
|
||||
|
||||
@@ -8839,6 +9133,7 @@ __init static int tracer_alloc_buffers(void)
|
||||
INIT_LIST_HEAD(&global_trace.systems);
|
||||
INIT_LIST_HEAD(&global_trace.events);
|
||||
INIT_LIST_HEAD(&global_trace.hist_vars);
|
||||
INIT_LIST_HEAD(&global_trace.err_log);
|
||||
list_add(&global_trace.list, &ftrace_trace_arrays);
|
||||
|
||||
apply_trace_boot_options();
|
||||
|
Verwijs in nieuw issue
Block a user