Unverified Commit 56672746 authored by openeuler-ci-bot's avatar openeuler-ci-bot Committed by Gitee
Browse files

!1448 Tracing fixes

Merge Pull Request from: @ci-robot 
 
PR sync from: Zheng Yejian <zhengyejian1@huawei.com>
https://mailweb.openeuler.org/hyperkitty/list/kernel@openeuler.org/message/REOTE3BIB3EUEAL5WCIOUTDVJ5RVAC3N/ 
Tracing fixes:
- Fix a deadloop in reading trace_pipe that was caused by a mismatch
  between ring_buffer_empty() returning false which then asked to
  read the data, but the read code uses rb_num_of_entries() that
  returned zero, and causing an infinite "retry".

- Fix a warning caused by not using all pages allocated to store
  ftrace functions, where this can happen if the linker inserts a bunch of
  "NULL" entries, causing the accounting of how many pages needed
  to be off.

- Fix memory leak in freeing iter->temp in tracing_release_pipe().

Linus Torvalds (1):
  ftrace: Store the order of pages allocated in ftrace_page

Zheng Yejian (3):
  ring-buffer: Fix deadloop issue on reading trace_pipe
  tracing: Fix memory leak of iter->temp when reading trace_pipe
  ftrace: Fix possible warning on checking all pages used in
    ftrace_process_locs()


-- 
2.25.1
 
https://gitee.com/openeuler/kernel/issues/I7KXY9
https://gitee.com/openeuler/kernel/issues/I7KYPM
https://gitee.com/openeuler/kernel/issues/I7L517 
 
Link:https://gitee.com/openeuler/kernel/pulls/1448

 

Reviewed-by: default avatarXu Kuohai <xukuohai@huawei.com>
Signed-off-by: default avatarJialin Zhang <zhangjialin11@huawei.com>
parents c27ef0ce 1f47d0a7
Loading
Loading
Loading
Loading
+44 −28
Original line number Diff line number Diff line
@@ -1092,7 +1092,7 @@ struct ftrace_page {
	struct ftrace_page	*next;
	struct dyn_ftrace	*records;
	int			index;
	int			size;
	int			order;
};

#define ENTRY_SIZE sizeof(struct dyn_ftrace)
@@ -3189,7 +3189,7 @@ static int ftrace_allocate_records(struct ftrace_page *pg, int count)
	ftrace_number_of_groups++;

	cnt = (PAGE_SIZE << order) / ENTRY_SIZE;
	pg->size = cnt;
	pg->order = order;

	if (cnt > count)
		cnt = count;
@@ -3197,12 +3197,27 @@ 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)
{
	struct ftrace_page *start_pg;
	struct ftrace_page *pg;
	int order;
	int cnt;

	if (!num_to_init)
@@ -3236,17 +3251,7 @@ ftrace_allocate_pages(unsigned long num_to_init)
	return start_pg;

 free_pages:
	pg = start_pg;
	while (pg) {
		order = get_count_order(pg->size / ENTRIES_PER_PAGE);
		if (order >= 0)
			free_pages((unsigned long)pg->records, order);
		start_pg = pg->next;
		kfree(pg);
		pg = start_pg;
		ftrace_number_of_pages -= 1 << order;
		ftrace_number_of_groups--;
	}
	ftrace_free_pages(start_pg);
	pr_info("ftrace: FAILED to allocate memory for functions\n");
	return NULL;
}
@@ -6192,9 +6197,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;
@@ -6240,6 +6247,7 @@ static int ftrace_process_locs(struct module *mod,
	p = start;
	pg = start_pg;
	while (p < end) {
		unsigned long end_offset;
		addr = ftrace_call_adjust(*p++);
		/*
		 * Some architecture linkers will pad between
@@ -6247,10 +6255,13 @@ static int ftrace_process_locs(struct module *mod,
		 * object files to satisfy alignments.
		 * Skip any NULL pointers.
		 */
		if (!addr)
		if (!addr) {
			skipped++;
			continue;
		}

		if (pg->index == pg->size) {
		end_offset = (pg->index+1) * sizeof(pg->records[0]);
		if (end_offset > PAGE_SIZE << pg->order) {
			/* We should have allocated enough */
			if (WARN_ON(!pg->next))
				break;
@@ -6261,8 +6272,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;
@@ -6284,6 +6297,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;
}

@@ -6419,7 +6437,6 @@ void ftrace_release_mod(struct module *mod)
	struct ftrace_page **last_pg;
	struct ftrace_page *tmp_page = NULL;
	struct ftrace_page *pg;
	int order;

	mutex_lock(&ftrace_lock);

@@ -6470,12 +6487,12 @@ void ftrace_release_mod(struct module *mod)
		/* Needs to be called outside of ftrace_lock */
		clear_mod_from_hashes(pg);

		order = get_count_order(pg->size / ENTRIES_PER_PAGE);
		if (order >= 0)
			free_pages((unsigned long)pg->records, order);
		if (pg->records) {
			free_pages((unsigned long)pg->records, pg->order);
			ftrace_number_of_pages -= 1 << pg->order;
		}
		tmp_page = pg->next;
		kfree(pg);
		ftrace_number_of_pages -= 1 << order;
		ftrace_number_of_groups--;
	}
}
@@ -6793,7 +6810,6 @@ void ftrace_free_mem(struct module *mod, void *start_ptr, void *end_ptr)
	struct ftrace_mod_map *mod_map = NULL;
	struct ftrace_init_func *func, *func_next;
	struct list_head clear_hash;
	int order;

	INIT_LIST_HEAD(&clear_hash);

@@ -6831,10 +6847,10 @@ void ftrace_free_mem(struct module *mod, void *start_ptr, void *end_ptr)
		ftrace_update_tot_cnt--;
		if (!pg->index) {
			*last_pg = pg->next;
			order = get_count_order(pg->size / ENTRIES_PER_PAGE);
			if (order >= 0)
				free_pages((unsigned long)pg->records, order);
			ftrace_number_of_pages -= 1 << order;
			if (pg->records) {
				free_pages((unsigned long)pg->records, pg->order);
				ftrace_number_of_pages -= 1 << pg->order;
			}
			ftrace_number_of_groups--;
			kfree(pg);
			pg = container_of(last_pg, struct ftrace_page, next);
+15 −9
Original line number Diff line number Diff line
@@ -4950,28 +4950,34 @@ unsigned long ring_buffer_size(struct trace_buffer *buffer, int cpu)
}
EXPORT_SYMBOL_GPL(ring_buffer_size);

static void rb_clear_buffer_page(struct buffer_page *page)
{
	local_set(&page->write, 0);
	local_set(&page->entries, 0);
	rb_init_page(page->page);
	page->read = 0;
}

static void
rb_reset_cpu(struct ring_buffer_per_cpu *cpu_buffer)
{
	struct buffer_page *page;

	rb_head_page_deactivate(cpu_buffer);

	cpu_buffer->head_page
		= list_entry(cpu_buffer->pages, struct buffer_page, list);
	local_set(&cpu_buffer->head_page->write, 0);
	local_set(&cpu_buffer->head_page->entries, 0);
	local_set(&cpu_buffer->head_page->page->commit, 0);

	cpu_buffer->head_page->read = 0;
	rb_clear_buffer_page(cpu_buffer->head_page);
	list_for_each_entry(page, cpu_buffer->pages, list) {
		rb_clear_buffer_page(page);
	}

	cpu_buffer->tail_page = cpu_buffer->head_page;
	cpu_buffer->commit_page = cpu_buffer->head_page;

	INIT_LIST_HEAD(&cpu_buffer->reader_page->list);
	INIT_LIST_HEAD(&cpu_buffer->new_pages);
	local_set(&cpu_buffer->reader_page->write, 0);
	local_set(&cpu_buffer->reader_page->entries, 0);
	local_set(&cpu_buffer->reader_page->page->commit, 0);
	cpu_buffer->reader_page->read = 0;
	rb_clear_buffer_page(cpu_buffer->reader_page);

	local_set(&cpu_buffer->entries_bytes, 0);
	local_set(&cpu_buffer->overrun, 0);
+1 −0
Original line number Diff line number Diff line
@@ -6272,6 +6272,7 @@ static int tracing_release_pipe(struct inode *inode, struct file *file)
	mutex_unlock(&trace_types_lock);

	free_cpumask_var(iter->started);
	kfree(iter->temp);
	mutex_destroy(&iter->mutex);
	kfree(iter);