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

Commit b1fca27d38 ("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 cb87481ee8 ("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 cb87481ee8. [1]

Seven years have passed since then, yet the #ifdef workaround remains in
place. Meanwhile, commit b1fca27d38 introduced the .data.once section,
and commit dc5723b02e ("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: b1fca27d38 ("kernel debug: support resetting WARN*_ONCE")
Fixes: dc5723b02e ("kbuild: add support for Clang LTO")
Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
This commit is contained in:
Masahiro Yamada 2024-11-07 01:14:41 +09:00
parent bb43a59944
commit dbefa1f31a
6 changed files with 9 additions and 9 deletions

View File

@ -359,7 +359,7 @@ defined(CONFIG_AUTOFDO_CLANG) || defined(CONFIG_PROPELLER_CLANG)
*(.data..shared_aligned) /* percpu related */ \ *(.data..shared_aligned) /* percpu related */ \
*(.data..unlikely) \ *(.data..unlikely) \
__start_once = .; \ __start_once = .; \
*(.data.once) \ *(.data..once) \
__end_once = .; \ __end_once = .; \
STRUCT_ALIGN(); \ STRUCT_ALIGN(); \
*(__tracepoints) \ *(__tracepoints) \

View File

@ -46,7 +46,7 @@ void vma_iter_dump_tree(const struct vma_iterator *vmi);
} \ } \
} while (0) } while (0)
#define VM_WARN_ON_ONCE_PAGE(cond, page) ({ \ #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); \ int __ret_warn_once = !!(cond); \
\ \
if (unlikely(__ret_warn_once && !__warned)) { \ if (unlikely(__ret_warn_once && !__warned)) { \
@ -66,7 +66,7 @@ void vma_iter_dump_tree(const struct vma_iterator *vmi);
unlikely(__ret_warn); \ unlikely(__ret_warn); \
}) })
#define VM_WARN_ON_ONCE_FOLIO(cond, folio) ({ \ #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); \ int __ret_warn_once = !!(cond); \
\ \
if (unlikely(__ret_warn_once && !__warned)) { \ if (unlikely(__ret_warn_once && !__warned)) { \
@ -77,7 +77,7 @@ void vma_iter_dump_tree(const struct vma_iterator *vmi);
unlikely(__ret_warn_once); \ unlikely(__ret_warn_once); \
}) })
#define VM_WARN_ON_ONCE_MM(cond, mm) ({ \ #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); \ int __ret_warn_once = !!(cond); \
\ \
if (unlikely(__ret_warn_once && !__warned)) { \ if (unlikely(__ret_warn_once && !__warned)) { \

View File

@ -46,7 +46,7 @@ void __do_once_sleepable_done(bool *done, struct static_key_true *once_key,
#define DO_ONCE(func, ...) \ #define DO_ONCE(func, ...) \
({ \ ({ \
bool ___ret = false; \ bool ___ret = false; \
static bool __section(".data.once") ___done = false; \ static bool __section(".data..once") ___done = false; \
static DEFINE_STATIC_KEY_TRUE(___once_key); \ static DEFINE_STATIC_KEY_TRUE(___once_key); \
if (static_branch_unlikely(&___once_key)) { \ if (static_branch_unlikely(&___once_key)) { \
unsigned long ___flags; \ 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, ...) \ #define DO_ONCE_SLEEPABLE(func, ...) \
({ \ ({ \
bool ___ret = false; \ bool ___ret = false; \
static bool __section(".data.once") ___done = false; \ static bool __section(".data..once") ___done = false; \
static DEFINE_STATIC_KEY_TRUE(___once_key); \ static DEFINE_STATIC_KEY_TRUE(___once_key); \
if (static_branch_unlikely(&___once_key)) { \ if (static_branch_unlikely(&___once_key)) { \
___ret = __do_once_sleepable_start(&___done); \ ___ret = __do_once_sleepable_start(&___done); \

View File

@ -12,7 +12,7 @@
#define __ONCE_LITE_IF(condition) \ #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_cond = !!(condition); \
bool __ret_once = false; \ bool __ret_once = false; \
\ \

View File

@ -27,7 +27,7 @@ void netdev_info(const struct net_device *dev, const char *format, ...);
#define netdev_level_once(level, dev, fmt, ...) \ #define netdev_level_once(level, dev, fmt, ...) \
do { \ do { \
static bool __section(".data.once") __print_once; \ static bool __section(".data..once") __print_once; \
\ \
if (!__print_once) { \ if (!__print_once) { \
__print_once = true; \ __print_once = true; \

View File

@ -48,7 +48,7 @@ struct folio_batch;
* when we specify __GFP_NOWARN. * when we specify __GFP_NOWARN.
*/ */
#define WARN_ON_ONCE_GFP(cond, gfp) ({ \ #define WARN_ON_ONCE_GFP(cond, gfp) ({ \
static bool __section(".data.once") __warned; \ static bool __section(".data..once") __warned; \
int __ret_warn_once = !!(cond); \ int __ret_warn_once = !!(cond); \
\ \
if (unlikely(!(gfp & __GFP_NOWARN) && __ret_warn_once && !__warned)) { \ if (unlikely(!(gfp & __GFP_NOWARN) && __ret_warn_once && !__warned)) { \