Skip to content

Commit 84fe739

Browse files
committed
Merge branch 'do_once_lite'
Tanner Love says: ==================== net: update netdev_rx_csum_fault() print dump only once First patch implements DO_ONCE_LITE to abstract uses of the ".data.once" trick. It is defined in its own, new header file -- rather than alongside the existing DO_ONCE in include/linux/once.h -- because include/linux/once.h includes include/linux/jump_label.h, and this causes the build to break for some architectures if include/linux/once.h is included in include/linux/printk.h or include/asm-generic/bug.h. Second patch uses DO_ONCE_LITE in netdev_rx_csum_fault to print dump only once. ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents b74ef9f + 127d735 commit 84fe739

File tree

6 files changed

+49
-75
lines changed

6 files changed

+49
-75
lines changed

fs/xfs/xfs_message.h

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
#ifndef __XFS_MESSAGE_H
33
#define __XFS_MESSAGE_H 1
44

5+
#include <linux/once_lite.h>
6+
57
struct xfs_mount;
68

79
extern __printf(2, 3)
@@ -41,16 +43,7 @@ do { \
4143
} while (0)
4244

4345
#define xfs_printk_once(func, dev, fmt, ...) \
44-
({ \
45-
static bool __section(".data.once") __print_once; \
46-
bool __ret_print_once = !__print_once; \
47-
\
48-
if (!__print_once) { \
49-
__print_once = true; \
50-
func(dev, fmt, ##__VA_ARGS__); \
51-
} \
52-
unlikely(__ret_print_once); \
53-
})
46+
DO_ONCE_LITE(func, dev, fmt, ##__VA_ARGS__)
5447

5548
#define xfs_emerg_ratelimited(dev, fmt, ...) \
5649
xfs_printk_ratelimited(xfs_emerg, dev, fmt, ##__VA_ARGS__)

include/asm-generic/bug.h

Lines changed: 7 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
#include <linux/compiler.h>
66
#include <linux/instrumentation.h>
7+
#include <linux/once_lite.h>
78

89
#define CUT_HERE "------------[ cut here ]------------\n"
910

@@ -140,39 +141,15 @@ void __warn(const char *file, int line, void *caller, unsigned taint,
140141
})
141142

142143
#ifndef WARN_ON_ONCE
143-
#define WARN_ON_ONCE(condition) ({ \
144-
static bool __section(".data.once") __warned; \
145-
int __ret_warn_once = !!(condition); \
146-
\
147-
if (unlikely(__ret_warn_once && !__warned)) { \
148-
__warned = true; \
149-
WARN_ON(1); \
150-
} \
151-
unlikely(__ret_warn_once); \
152-
})
144+
#define WARN_ON_ONCE(condition) \
145+
DO_ONCE_LITE_IF(condition, WARN_ON, 1)
153146
#endif
154147

155-
#define WARN_ONCE(condition, format...) ({ \
156-
static bool __section(".data.once") __warned; \
157-
int __ret_warn_once = !!(condition); \
158-
\
159-
if (unlikely(__ret_warn_once && !__warned)) { \
160-
__warned = true; \
161-
WARN(1, format); \
162-
} \
163-
unlikely(__ret_warn_once); \
164-
})
148+
#define WARN_ONCE(condition, format...) \
149+
DO_ONCE_LITE_IF(condition, WARN, 1, format)
165150

166-
#define WARN_TAINT_ONCE(condition, taint, format...) ({ \
167-
static bool __section(".data.once") __warned; \
168-
int __ret_warn_once = !!(condition); \
169-
\
170-
if (unlikely(__ret_warn_once && !__warned)) { \
171-
__warned = true; \
172-
WARN_TAINT(1, taint, format); \
173-
} \
174-
unlikely(__ret_warn_once); \
175-
})
151+
#define WARN_TAINT_ONCE(condition, taint, format...) \
152+
DO_ONCE_LITE_IF(condition, WARN_TAINT, 1, taint, format)
176153

177154
#else /* !CONFIG_BUG */
178155
#ifndef HAVE_ARCH_BUG

include/linux/once_lite.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/* SPDX-License-Identifier: GPL-2.0 */
2+
#ifndef _LINUX_ONCE_LITE_H
3+
#define _LINUX_ONCE_LITE_H
4+
5+
#include <linux/types.h>
6+
7+
/* Call a function once. Similar to DO_ONCE(), but does not use jump label
8+
* patching via static keys.
9+
*/
10+
#define DO_ONCE_LITE(func, ...) \
11+
DO_ONCE_LITE_IF(true, func, ##__VA_ARGS__)
12+
#define DO_ONCE_LITE_IF(condition, func, ...) \
13+
({ \
14+
static bool __section(".data.once") __already_done; \
15+
bool __ret_do_once = !!(condition); \
16+
\
17+
if (unlikely(__ret_do_once && !__already_done)) { \
18+
__already_done = true; \
19+
func(__VA_ARGS__); \
20+
} \
21+
unlikely(__ret_do_once); \
22+
})
23+
24+
#endif /* _LINUX_ONCE_LITE_H */

include/linux/printk.h

Lines changed: 3 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include <linux/linkage.h>
99
#include <linux/cache.h>
1010
#include <linux/ratelimit_types.h>
11+
#include <linux/once_lite.h>
1112

1213
extern const char linux_banner[];
1314
extern const char linux_proc_banner[];
@@ -436,27 +437,9 @@ extern int kptr_restrict;
436437

437438
#ifdef CONFIG_PRINTK
438439
#define printk_once(fmt, ...) \
439-
({ \
440-
static bool __section(".data.once") __print_once; \
441-
bool __ret_print_once = !__print_once; \
442-
\
443-
if (!__print_once) { \
444-
__print_once = true; \
445-
printk(fmt, ##__VA_ARGS__); \
446-
} \
447-
unlikely(__ret_print_once); \
448-
})
440+
DO_ONCE_LITE(printk, fmt, ##__VA_ARGS__)
449441
#define printk_deferred_once(fmt, ...) \
450-
({ \
451-
static bool __section(".data.once") __print_once; \
452-
bool __ret_print_once = !__print_once; \
453-
\
454-
if (!__print_once) { \
455-
__print_once = true; \
456-
printk_deferred(fmt, ##__VA_ARGS__); \
457-
} \
458-
unlikely(__ret_print_once); \
459-
})
442+
DO_ONCE_LITE(printk_deferred, fmt, ##__VA_ARGS__)
460443
#else
461444
#define printk_once(fmt, ...) \
462445
no_printk(fmt, ##__VA_ARGS__)

kernel/trace/trace.h

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include <linux/irq_work.h>
2121
#include <linux/workqueue.h>
2222
#include <linux/ctype.h>
23+
#include <linux/once_lite.h>
2324

2425
#ifdef CONFIG_FTRACE_SYSCALLS
2526
#include <asm/unistd.h> /* For NR_SYSCALLS */
@@ -99,16 +100,8 @@ enum trace_type {
99100
#include "trace_entries.h"
100101

101102
/* Use this for memory failure errors */
102-
#define MEM_FAIL(condition, fmt, ...) ({ \
103-
static bool __section(".data.once") __warned; \
104-
int __ret_warn_once = !!(condition); \
105-
\
106-
if (unlikely(__ret_warn_once && !__warned)) { \
107-
__warned = true; \
108-
pr_err("ERROR: " fmt, ##__VA_ARGS__); \
109-
} \
110-
unlikely(__ret_warn_once); \
111-
})
103+
#define MEM_FAIL(condition, fmt, ...) \
104+
DO_ONCE_LITE_IF(condition, pr_err, "ERROR: " fmt, ##__VA_ARGS__)
112105

113106
/*
114107
* syscalls are special, and need special handling, this is why

net/core/dev.c

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,7 @@
148148
#include <net/devlink.h>
149149
#include <linux/pm_runtime.h>
150150
#include <linux/prandom.h>
151+
#include <linux/once_lite.h>
151152

152153
#include "net-sysfs.h"
153154

@@ -3487,13 +3488,16 @@ EXPORT_SYMBOL(__skb_gso_segment);
34873488

34883489
/* Take action when hardware reception checksum errors are detected. */
34893490
#ifdef CONFIG_BUG
3491+
static void do_netdev_rx_csum_fault(struct net_device *dev, struct sk_buff *skb)
3492+
{
3493+
pr_err("%s: hw csum failure\n", dev ? dev->name : "<unknown>");
3494+
skb_dump(KERN_ERR, skb, true);
3495+
dump_stack();
3496+
}
3497+
34903498
void netdev_rx_csum_fault(struct net_device *dev, struct sk_buff *skb)
34913499
{
3492-
if (net_ratelimit()) {
3493-
pr_err("%s: hw csum failure\n", dev ? dev->name : "<unknown>");
3494-
skb_dump(KERN_ERR, skb, true);
3495-
dump_stack();
3496-
}
3500+
DO_ONCE_LITE(do_netdev_rx_csum_fault, dev, skb);
34973501
}
34983502
EXPORT_SYMBOL(netdev_rx_csum_fault);
34993503
#endif

0 commit comments

Comments
 (0)