Rename .data.once to .data..once to fix resetting WARN*_ONCE
authorMasahiro Yamada <masahiroy@kernel.org>
Wed, 6 Nov 2024 16:14:41 +0000 (01:14 +0900)
committerMasahiro Yamada <masahiroy@kernel.org>
Wed, 27 Nov 2024 00:38:27 +0000 (09:38 +0900)
Commit b1fca27d384e ("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 cb87481ee89d ("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 cb87481ee89d. [1]

Seven years have passed since then, yet the #ifdef workaround remains in
place. Meanwhile, commit b1fca27d384e introduced the .data.once section,
and commit dc5723b02e52 ("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: b1fca27d384e ("kernel debug: support resetting WARN*_ONCE")
Fixes: dc5723b02e52 ("kbuild: add support for Clang LTO")
Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
include/asm-generic/vmlinux.lds.h
include/linux/mmdebug.h
include/linux/once.h
include/linux/once_lite.h
include/net/net_debug.h
mm/internal.h

index 3c9dc1f..5450401 100644 (file)
@@ -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)                                                \
index 39a7714..d7cb1e5 100644 (file)
@@ -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)) {                   \
index bc714d4..30346fc 100644 (file)
@@ -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);           \
index b7bce49..27de7bc 100644 (file)
@@ -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;                                \
                                                                        \
index 1e74684..4a79204 100644 (file)
@@ -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;                            \
index 93083bb..a23f7b1 100644 (file)
@@ -48,7 +48,7 @@ struct folio_batch;
  * when we specify __GFP_NOWARN.
  */
 #define WARN_ON_ONCE_GFP(cond, gfp)    ({                              \
-       static bool __section(".data.once") __warned;                   \
+       static bool __section(".data..once") __warned;                  \
        int __ret_warn_once = !!(cond);                                 \
                                                                        \
        if (unlikely(!(gfp & __GFP_NOWARN) && __ret_warn_once && !__warned)) { \