重置WARN_ONCE

参考

当WARN_ONCE或者WARN_ON_ONCE被第一次触发时,会输出调用栈,后面就不会了。可以使用下面的命令重置,这样再次触发时,还可以输出一次调用栈:

echo 1 > /sys/kernel/debug/clear_warn_once

相关的实现在kernel\panic.c:

/* Support resetting WARN*_ONCE state */

static int clear_warn_once_set(void *data, u64 val)
{
	generic_bug_clear_once();
	memset(__start_once, 0, __end_once - __start_once);
	return 0;
}

DEFINE_DEBUGFS_ATTRIBUTE(clear_warn_once_fops, NULL, clear_warn_once_set,
			 "%lld\n");

其中generic_bug_clear_once在lib\bug.c中:

static void clear_once_table(struct bug_entry *start, struct bug_entry *end)
{
	struct bug_entry *bug;

	for (bug = start; bug < end; bug++)
		bug->flags &= ~BUGFLAG_DONE;
}

void generic_bug_clear_once(void)
{
#ifdef CONFIG_MODULES
	struct module *mod;

	rcu_read_lock_sched();
	list_for_each_entry_rcu(mod, &module_bug_list, bug_list)
		clear_once_table(mod->bug_table,
				 mod->bug_table + mod->num_bugs);
	rcu_read_unlock_sched();
#endif

	clear_once_table(__start___bug_table, __stop___bug_table);
}

在clear_warn_once_set中做了两件事:

  1. 调用generic_bug_clear_once把模块以及内核自己的所有的bug_entry->flags成员的BUGFLAG_DONE位清除

  2. 将内核的*(.data.once)段的内容清0

也就是说,WARN_ON_ONCE或者WARN_ONCE会利用上面两种数据段的内容来判断是否需要输出上下文信息,这个在后面的文章中再分析。

posted @ 2023-12-05 17:48  dolinux  阅读(446)  评论(0)    收藏  举报