Skip to content

Commit

Permalink
ftrace: limit use of check pages
Browse files Browse the repository at this point in the history
The check_pages function is called often enough that it can cause problems
with trace outputs or even bringing the system to a halt.

This patch limits the check_pages to the places that are most likely to
have problems. The check is made at the flip between the global array and
the max save array, as well as when the size of the buffers changes and
the self tests.

This patch also removes the BUG_ON from check_pages and replaces it with
a WARN_ON and disabling of the tracer.

Signed-off-by: Steven Rostedt <srostedt@redhat.com>
Cc: pq@iki.fi
Cc: proski@gnu.org
Cc: sandmann@redhat.com
Cc: a.p.zijlstra@chello.nl
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
  • Loading branch information
Steven Rostedt authored and Thomas Gleixner committed May 26, 2008
1 parent c6531cc commit 19384c0
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 9 deletions.
32 changes: 23 additions & 9 deletions kernel/trace/trace.c
Original file line number Diff line number Diff line change
Expand Up @@ -249,24 +249,32 @@ __update_max_tr(struct trace_array *tr, struct task_struct *tsk, int cpu)
tracing_record_cmdline(current);
}

#define CHECK_COND(cond) \
if (unlikely(cond)) { \
tracing_disabled = 1; \
WARN_ON(1); \
return -1; \
}

/**
* check_pages - integrity check of trace buffers
*
* As a safty measure we check to make sure the data pages have not
* been corrupted. TODO: configure to disable this because it adds
* a bit of overhead.
* been corrupted.
*/
void check_pages(struct trace_array_cpu *data)
int check_pages(struct trace_array_cpu *data)
{
struct page *page, *tmp;

BUG_ON(data->trace_pages.next->prev != &data->trace_pages);
BUG_ON(data->trace_pages.prev->next != &data->trace_pages);
CHECK_COND(data->trace_pages.next->prev != &data->trace_pages);
CHECK_COND(data->trace_pages.prev->next != &data->trace_pages);

list_for_each_entry_safe(page, tmp, &data->trace_pages, lru) {
BUG_ON(page->lru.next->prev != &page->lru);
BUG_ON(page->lru.prev->next != &page->lru);
CHECK_COND(page->lru.next->prev != &page->lru);
CHECK_COND(page->lru.prev->next != &page->lru);
}

return 0;
}

/**
Expand All @@ -280,7 +288,6 @@ void *head_page(struct trace_array_cpu *data)
{
struct page *page;

check_pages(data);
if (list_empty(&data->trace_pages))
return NULL;

Expand Down Expand Up @@ -2566,7 +2573,7 @@ tracing_entries_write(struct file *filp, const char __user *ubuf,
{
unsigned long val;
char buf[64];
int ret;
int i, ret;

if (cnt >= sizeof(buf))
return -EINVAL;
Expand Down Expand Up @@ -2635,8 +2642,15 @@ tracing_entries_write(struct file *filp, const char __user *ubuf,
trace_free_page();
}

/* check integrity */
for_each_tracing_cpu(i)
check_pages(global_trace.data[i]);

filp->f_pos += cnt;

/* If check pages failed, return ENOMEM */
if (tracing_disabled)
cnt = -ENOMEM;
out:
max_tr.entries = global_trace.entries;
mutex_unlock(&trace_types_lock);
Expand Down
1 change: 1 addition & 0 deletions kernel/trace/trace_selftest.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ trace_test_buffer_cpu(struct trace_array *tr, struct trace_array_cpu *data)
page = list_entry(data->trace_pages.next, struct page, lru);
entries = page_address(page);

check_pages(data);
if (head_page(data) != entries)
goto failed;

Expand Down

0 comments on commit 19384c0

Please sign in to comment.