Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 285059
b: refs/heads/master
c: 3208230
h: refs/heads/master
i:
  285057: c6a6091
  285055: cb71898
v: v3
  • Loading branch information
Steven Rostedt authored and Steven Rostedt committed Dec 21, 2011
1 parent 6a5b101 commit 68914b3
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 53 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: c88fd8634ea68e74c7d19fd2621b4078fd22864c
refs/heads/master: 3208230983a0ee3d95be22d463257e530c684956
1 change: 0 additions & 1 deletion trunk/include/linux/ftrace.h
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,6 @@ extern int ftrace_text_reserved(void *start, void *end);

enum {
FTRACE_FL_ENABLED = (1 << 30),
FTRACE_FL_FREE = (1 << 31),
};

#define FTRACE_FL_MASK (0x3UL << 30)
Expand Down
100 changes: 49 additions & 51 deletions trunk/kernel/trace/ftrace.c
Original file line number Diff line number Diff line change
Expand Up @@ -996,8 +996,6 @@ struct ftrace_page {
static struct ftrace_page *ftrace_pages_start;
static struct ftrace_page *ftrace_pages;

static struct dyn_ftrace *ftrace_free_records;

static struct ftrace_func_entry *
ftrace_lookup_ip(struct ftrace_hash *hash, unsigned long ip)
{
Expand Down Expand Up @@ -1421,32 +1419,8 @@ static void ftrace_hash_rec_enable(struct ftrace_ops *ops,
__ftrace_hash_rec_update(ops, filter_hash, 1);
}

static void ftrace_free_rec(struct dyn_ftrace *rec)
{
rec->freelist = ftrace_free_records;
ftrace_free_records = rec;
rec->flags |= FTRACE_FL_FREE;
}

static struct dyn_ftrace *ftrace_alloc_dyn_node(unsigned long ip)
{
struct dyn_ftrace *rec;

/* First check for freed records */
if (ftrace_free_records) {
rec = ftrace_free_records;

if (unlikely(!(rec->flags & FTRACE_FL_FREE))) {
FTRACE_WARN_ON_ONCE(1);
ftrace_free_records = NULL;
return NULL;
}

ftrace_free_records = rec->freelist;
memset(rec, 0, sizeof(*rec));
return rec;
}

if (ftrace_pages->index == ENTRIES_PER_PAGE) {
if (!ftrace_pages->next) {
/* allocate another page */
Expand Down Expand Up @@ -1639,10 +1613,6 @@ static void ftrace_replace_code(int update)
return;

do_for_each_ftrace_rec(pg, rec) {
/* Skip over free records */
if (rec->flags & FTRACE_FL_FREE)
continue;

failed = __ftrace_replace_code(rec, update);
if (failed) {
ftrace_bug(failed, rec->ip);
Expand Down Expand Up @@ -2007,11 +1977,8 @@ static int ftrace_update_code(struct module *mod)
* Do the initial record conversion from mcount jump
* to the NOP instructions.
*/
if (!ftrace_code_disable(mod, p)) {
ftrace_free_rec(p);
/* Game over */
if (!ftrace_code_disable(mod, p))
break;
}

ftrace_update_cnt++;

Expand All @@ -2026,10 +1993,8 @@ static int ftrace_update_code(struct module *mod)
*/
if (ftrace_start_up && ref) {
int failed = __ftrace_replace_code(p, 1);
if (failed) {
if (failed)
ftrace_bug(failed, p->ip);
ftrace_free_rec(p);
}
}
}

Expand Down Expand Up @@ -2223,9 +2188,7 @@ t_next(struct seq_file *m, void *v, loff_t *pos)
}
} else {
rec = &iter->pg->records[iter->idx++];
if ((rec->flags & FTRACE_FL_FREE) ||

((iter->flags & FTRACE_ITER_FILTER) &&
if (((iter->flags & FTRACE_ITER_FILTER) &&
!(ftrace_lookup_ip(ops->filter_hash, rec->ip))) ||

((iter->flags & FTRACE_ITER_NOTRACE) &&
Expand Down Expand Up @@ -2602,7 +2565,6 @@ match_records(struct ftrace_hash *hash, char *buff,
goto out_unlock;

do_for_each_ftrace_rec(pg, rec) {

if (ftrace_match_record(rec, mod, search, search_len, type)) {
ret = enter_record(hash, rec, not);
if (ret < 0) {
Expand Down Expand Up @@ -3446,9 +3408,6 @@ ftrace_set_func(unsigned long *array, int *idx, char *buffer)

do_for_each_ftrace_rec(pg, rec) {

if (rec->flags & FTRACE_FL_FREE)
continue;

if (ftrace_match_record(rec, NULL, search, search_len, type)) {
/* if it is in the array */
exists = false;
Expand Down Expand Up @@ -3566,6 +3525,27 @@ static int ftrace_process_locs(struct module *mod,
unsigned long flags = 0; /* Shut up gcc */

mutex_lock(&ftrace_lock);
/*
* Core and each module needs their own pages, as
* modules will free them when they are removed.
* Force a new page to be allocated for modules.
*/
if (mod) {
if (!ftrace_pages)
return -ENOMEM;

/*
* If the last page was full, it will be
* allocated anyway.
*/
if (ftrace_pages->index != ENTRIES_PER_PAGE) {
ftrace_pages->next = (void *)get_zeroed_page(GFP_KERNEL);
if (!ftrace_pages->next)
return -ENOMEM;
ftrace_pages = ftrace_pages->next;
}
}

p = start;
while (p < end) {
addr = ftrace_call_adjust(*p++);
Expand Down Expand Up @@ -3599,26 +3579,44 @@ static int ftrace_process_locs(struct module *mod,
}

#ifdef CONFIG_MODULES

#define next_to_ftrace_page(p) container_of(p, struct ftrace_page, next)

void ftrace_release_mod(struct module *mod)
{
struct dyn_ftrace *rec;
struct ftrace_page **last_pg;
struct ftrace_page *pg;

mutex_lock(&ftrace_lock);

if (ftrace_disabled)
goto out_unlock;

do_for_each_ftrace_rec(pg, rec) {
/*
* Each module has its own ftrace_pages, remove
* them from the list.
*/
last_pg = &ftrace_pages_start;
for (pg = ftrace_pages_start; pg; pg = *last_pg) {
rec = &pg->records[0];
if (within_module_core(rec->ip, mod)) {
/*
* rec->ip is changed in ftrace_free_rec()
* It should not between s and e if record was freed.
* As core pages are first, the first
* page should never be a module page.
*/
FTRACE_WARN_ON(rec->flags & FTRACE_FL_FREE);
ftrace_free_rec(rec);
}
} while_for_each_ftrace_rec();
if (WARN_ON(pg == ftrace_pages_start))
goto out_unlock;

/* Check if we are deleting the last page */
if (pg == ftrace_pages)
ftrace_pages = next_to_ftrace_page(last_pg);

*last_pg = pg->next;
free_page((unsigned long)pg);
} else
last_pg = &pg->next;
}
out_unlock:
mutex_unlock(&ftrace_lock);
}
Expand Down

0 comments on commit 68914b3

Please sign in to comment.