ftrace: Fix possible warning on checking all pages used in ftrace_process_locs()
commit26efd79c46
upstream. As comments in ftrace_process_locs(), there may be NULL pointers in mcount_loc section: > Some architecture linkers will pad between > the different mcount_loc sections of different > object files to satisfy alignments. > Skip any NULL pointers. After commit20e5227e9f
("ftrace: allow NULL pointers in mcount_loc"), NULL pointers will be accounted when allocating ftrace pages but skipped before adding into ftrace pages, this may result in some pages not being used. Then after commit706c81f87f
("ftrace: Remove extra helper functions"), warning may occur at: WARN_ON(pg->next); To fix it, only warn for case that no pointers skipped but pages not used up, then free those unused pages after releasing ftrace_lock. Link: https://lore.kernel.org/linux-trace-kernel/20230712060452.3175675-1-zhengyejian1@huawei.com Cc: stable@vger.kernel.org Fixes:706c81f87f
("ftrace: Remove extra helper functions") Suggested-by: Steven Rostedt <rostedt@goodmis.org> Signed-off-by: Zheng Yejian <zhengyejian1@huawei.com> Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
8b0b63fdac
commit
99fe81d219
|
@ -3213,6 +3213,22 @@ static int ftrace_allocate_records(struct ftrace_page *pg, int count)
|
|||
return cnt;
|
||||
}
|
||||
|
||||
static void ftrace_free_pages(struct ftrace_page *pages)
|
||||
{
|
||||
struct ftrace_page *pg = pages;
|
||||
|
||||
while (pg) {
|
||||
if (pg->records) {
|
||||
free_pages((unsigned long)pg->records, pg->order);
|
||||
ftrace_number_of_pages -= 1 << pg->order;
|
||||
}
|
||||
pages = pg->next;
|
||||
kfree(pg);
|
||||
pg = pages;
|
||||
ftrace_number_of_groups--;
|
||||
}
|
||||
}
|
||||
|
||||
static struct ftrace_page *
|
||||
ftrace_allocate_pages(unsigned long num_to_init)
|
||||
{
|
||||
|
@ -3251,17 +3267,7 @@ ftrace_allocate_pages(unsigned long num_to_init)
|
|||
return start_pg;
|
||||
|
||||
free_pages:
|
||||
pg = start_pg;
|
||||
while (pg) {
|
||||
if (pg->records) {
|
||||
free_pages((unsigned long)pg->records, pg->order);
|
||||
ftrace_number_of_pages -= 1 << pg->order;
|
||||
}
|
||||
start_pg = pg->next;
|
||||
kfree(pg);
|
||||
pg = start_pg;
|
||||
ftrace_number_of_groups--;
|
||||
}
|
||||
ftrace_free_pages(start_pg);
|
||||
pr_info("ftrace: FAILED to allocate memory for functions\n");
|
||||
return NULL;
|
||||
}
|
||||
|
@ -6666,9 +6672,11 @@ static int ftrace_process_locs(struct module *mod,
|
|||
unsigned long *start,
|
||||
unsigned long *end)
|
||||
{
|
||||
struct ftrace_page *pg_unuse = NULL;
|
||||
struct ftrace_page *start_pg;
|
||||
struct ftrace_page *pg;
|
||||
struct dyn_ftrace *rec;
|
||||
unsigned long skipped = 0;
|
||||
unsigned long count;
|
||||
unsigned long *p;
|
||||
unsigned long addr;
|
||||
|
@ -6731,8 +6739,10 @@ static int ftrace_process_locs(struct module *mod,
|
|||
* object files to satisfy alignments.
|
||||
* Skip any NULL pointers.
|
||||
*/
|
||||
if (!addr)
|
||||
if (!addr) {
|
||||
skipped++;
|
||||
continue;
|
||||
}
|
||||
|
||||
end_offset = (pg->index+1) * sizeof(pg->records[0]);
|
||||
if (end_offset > PAGE_SIZE << pg->order) {
|
||||
|
@ -6746,8 +6756,10 @@ static int ftrace_process_locs(struct module *mod,
|
|||
rec->ip = addr;
|
||||
}
|
||||
|
||||
/* We should have used all pages */
|
||||
WARN_ON(pg->next);
|
||||
if (pg->next) {
|
||||
pg_unuse = pg->next;
|
||||
pg->next = NULL;
|
||||
}
|
||||
|
||||
/* Assign the last page to ftrace_pages */
|
||||
ftrace_pages = pg;
|
||||
|
@ -6769,6 +6781,11 @@ static int ftrace_process_locs(struct module *mod,
|
|||
out:
|
||||
mutex_unlock(&ftrace_lock);
|
||||
|
||||
/* We should have used all pages unless we skipped some */
|
||||
if (pg_unuse) {
|
||||
WARN_ON(!skipped);
|
||||
ftrace_free_pages(pg_unuse);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue