Commit dbefa1f3 authored by Masahiro Yamada's avatar Masahiro Yamada
Browse files

Rename .data.once to .data..once to fix resetting WARN*_ONCE

Commit b1fca27d ("kernel debug: support resetting WARN*_ONCE")
added support for clearing the state of once warnings. However,
it is not functional when CONFIG_LD_DEAD_CODE_DATA_ELIMINATION or
CONFIG_LTO_CLANG is enabled, because .data.once matches the
.data.[0-9a-zA-Z_]* pattern in the DATA_MAIN macro.

Commit cb87481e ("kbuild: linker script do not match C names unless
LD_DEAD_CODE_DATA_ELIMINATION is configured") was introduced to suppress
the issue for the default CONFIG_LD_DEAD_CODE_DATA_ELIMINATION=n case,
providing a minimal fix for stable backporting. We were aware this did
not address the issue for CONFIG_LD_DEAD_CODE_DATA_ELIMINATION=y. The
plan was to apply correct fixes and then revert cb87481e. [1]

Seven years have passed since then, yet the #ifdef workaround remains in
place. Meanwhile, commit b1fca27d introduced the .data.once section,
and commit dc5723b0 ("kbuild: add support for Clang LTO") extended
the #ifdef.

Using a ".." separator in the section name fixes the issue for
CONFIG_LD_DEAD_CODE_DATA_ELIMINATION and CONFIG_LTO_CLANG.

[1]: https://lore.kernel.org/linux-kbuild/CAK7LNASck6BfdLnESxXUeECYL26yUDm0cwRZuM4gmaWUkxjL5g@mail.gmail.com/



Fixes: b1fca27d ("kernel debug: support resetting WARN*_ONCE")
Fixes: dc5723b0 ("kbuild: add support for Clang LTO")
Signed-off-by: default avatarMasahiro Yamada <masahiroy@kernel.org>
parent bb43a599
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -359,7 +359,7 @@ defined(CONFIG_AUTOFDO_CLANG) || defined(CONFIG_PROPELLER_CLANG)
	*(.data..shared_aligned) /* percpu related */			\
	*(.data..unlikely)						\
	__start_once = .;						\
	*(.data.once)							\
	*(.data..once)							\
	__end_once = .;							\
	STRUCT_ALIGN();							\
	*(__tracepoints)						\
+3 −3
Original line number Diff line number Diff line
@@ -46,7 +46,7 @@ void vma_iter_dump_tree(const struct vma_iterator *vmi);
		}							\
	} while (0)
#define VM_WARN_ON_ONCE_PAGE(cond, page)	({			\
	static bool __section(".data.once") __warned;			\
	static bool __section(".data..once") __warned;			\
	int __ret_warn_once = !!(cond);					\
									\
	if (unlikely(__ret_warn_once && !__warned)) {			\
@@ -66,7 +66,7 @@ void vma_iter_dump_tree(const struct vma_iterator *vmi);
	unlikely(__ret_warn);						\
})
#define VM_WARN_ON_ONCE_FOLIO(cond, folio)	({			\
	static bool __section(".data.once") __warned;			\
	static bool __section(".data..once") __warned;			\
	int __ret_warn_once = !!(cond);					\
									\
	if (unlikely(__ret_warn_once && !__warned)) {			\
@@ -77,7 +77,7 @@ void vma_iter_dump_tree(const struct vma_iterator *vmi);
	unlikely(__ret_warn_once);					\
})
#define VM_WARN_ON_ONCE_MM(cond, mm)		({			\
	static bool __section(".data.once") __warned;			\
	static bool __section(".data..once") __warned;			\
	int __ret_warn_once = !!(cond);					\
									\
	if (unlikely(__ret_warn_once && !__warned)) {			\
+2 −2
Original line number Diff line number Diff line
@@ -46,7 +46,7 @@ void __do_once_sleepable_done(bool *done, struct static_key_true *once_key,
#define DO_ONCE(func, ...)						     \
	({								     \
		bool ___ret = false;					     \
		static bool __section(".data.once") ___done = false;	     \
		static bool __section(".data..once") ___done = false;	     \
		static DEFINE_STATIC_KEY_TRUE(___once_key);		     \
		if (static_branch_unlikely(&___once_key)) {		     \
			unsigned long ___flags;				     \
@@ -64,7 +64,7 @@ void __do_once_sleepable_done(bool *done, struct static_key_true *once_key,
#define DO_ONCE_SLEEPABLE(func, ...)						\
	({									\
		bool ___ret = false;						\
		static bool __section(".data.once") ___done = false;		\
		static bool __section(".data..once") ___done = false;		\
		static DEFINE_STATIC_KEY_TRUE(___once_key);			\
		if (static_branch_unlikely(&___once_key)) {			\
			___ret = __do_once_sleepable_start(&___done);		\
+1 −1
Original line number Diff line number Diff line
@@ -12,7 +12,7 @@

#define __ONCE_LITE_IF(condition)					\
	({								\
		static bool __section(".data.once") __already_done;	\
		static bool __section(".data..once") __already_done;	\
		bool __ret_cond = !!(condition);			\
		bool __ret_once = false;				\
									\
+1 −1
Original line number Diff line number Diff line
@@ -27,7 +27,7 @@ void netdev_info(const struct net_device *dev, const char *format, ...);

#define netdev_level_once(level, dev, fmt, ...)			\
do {								\
	static bool __section(".data.once") __print_once;	\
	static bool __section(".data..once") __print_once;	\
								\
	if (!__print_once) {					\
		__print_once = true;				\
Loading