xref: /OK3568_Linux_fs/kernel/fs/ocfs2/cluster/masklog.h (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /* SPDX-License-Identifier: GPL-2.0-or-later */
2*4882a593Smuzhiyun /* -*- mode: c; c-basic-offset: 8; -*-
3*4882a593Smuzhiyun  * vim: noexpandtab sw=8 ts=8 sts=0:
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * Copyright (C) 2005 Oracle.  All rights reserved.
6*4882a593Smuzhiyun  */
7*4882a593Smuzhiyun 
8*4882a593Smuzhiyun #ifndef O2CLUSTER_MASKLOG_H
9*4882a593Smuzhiyun #define O2CLUSTER_MASKLOG_H
10*4882a593Smuzhiyun 
11*4882a593Smuzhiyun /*
12*4882a593Smuzhiyun  * For now this is a trivial wrapper around printk() that gives the critical
13*4882a593Smuzhiyun  * ability to enable sets of debugging output at run-time.  In the future this
14*4882a593Smuzhiyun  * will almost certainly be redirected to relayfs so that it can pay a
15*4882a593Smuzhiyun  * substantially lower heisenberg tax.
16*4882a593Smuzhiyun  *
17*4882a593Smuzhiyun  * Callers associate the message with a bitmask and a global bitmask is
18*4882a593Smuzhiyun  * maintained with help from /proc.  If any of the bits match the message is
19*4882a593Smuzhiyun  * output.
20*4882a593Smuzhiyun  *
21*4882a593Smuzhiyun  * We must have efficient bit tests on i386 and it seems gcc still emits crazy
22*4882a593Smuzhiyun  * code for the 64bit compare.  It emits very good code for the dual unsigned
23*4882a593Smuzhiyun  * long tests, though, completely avoiding tests that can never pass if the
24*4882a593Smuzhiyun  * caller gives a constant bitmask that fills one of the longs with all 0s.  So
25*4882a593Smuzhiyun  * the desire is to have almost all of the calls decided on by comparing just
26*4882a593Smuzhiyun  * one of the longs.  This leads to having infrequently given bits that are
27*4882a593Smuzhiyun  * frequently matched in the high bits.
28*4882a593Smuzhiyun  *
29*4882a593Smuzhiyun  * _ERROR and _NOTICE are used for messages that always go to the console and
30*4882a593Smuzhiyun  * have appropriate KERN_ prefixes.  We wrap these in our function instead of
31*4882a593Smuzhiyun  * just calling printk() so that this can eventually make its way through
32*4882a593Smuzhiyun  * relayfs along with the debugging messages.  Everything else gets KERN_DEBUG.
33*4882a593Smuzhiyun  * The inline tests and macro dance give GCC the opportunity to quite cleverly
34*4882a593Smuzhiyun  * only emit the appropriage printk() when the caller passes in a constant
35*4882a593Smuzhiyun  * mask, as is almost always the case.
36*4882a593Smuzhiyun  *
37*4882a593Smuzhiyun  * All this bitmask nonsense is managed from the files under
38*4882a593Smuzhiyun  * /sys/fs/o2cb/logmask/.  Reading the files gives a straightforward
39*4882a593Smuzhiyun  * indication of which bits are allowed (allow) or denied (off/deny).
40*4882a593Smuzhiyun  * 	ENTRY deny
41*4882a593Smuzhiyun  * 	EXIT deny
42*4882a593Smuzhiyun  * 	TCP off
43*4882a593Smuzhiyun  * 	MSG off
44*4882a593Smuzhiyun  * 	SOCKET off
45*4882a593Smuzhiyun  * 	ERROR allow
46*4882a593Smuzhiyun  * 	NOTICE allow
47*4882a593Smuzhiyun  *
48*4882a593Smuzhiyun  * Writing changes the state of a given bit and requires a strictly formatted
49*4882a593Smuzhiyun  * single write() call:
50*4882a593Smuzhiyun  *
51*4882a593Smuzhiyun  * 	write(fd, "allow", 5);
52*4882a593Smuzhiyun  *
53*4882a593Smuzhiyun  * Echoing allow/deny/off string into the logmask files can flip the bits
54*4882a593Smuzhiyun  * on or off as expected; here is the bash script for example:
55*4882a593Smuzhiyun  *
56*4882a593Smuzhiyun  * log_mask="/sys/fs/o2cb/log_mask"
57*4882a593Smuzhiyun  * for node in ENTRY EXIT TCP MSG SOCKET ERROR NOTICE; do
58*4882a593Smuzhiyun  *	echo allow >"$log_mask"/"$node"
59*4882a593Smuzhiyun  * done
60*4882a593Smuzhiyun  *
61*4882a593Smuzhiyun  * The debugfs.ocfs2 tool can also flip the bits with the -l option:
62*4882a593Smuzhiyun  *
63*4882a593Smuzhiyun  * debugfs.ocfs2 -l TCP allow
64*4882a593Smuzhiyun  */
65*4882a593Smuzhiyun 
66*4882a593Smuzhiyun /* for task_struct */
67*4882a593Smuzhiyun #include <linux/sched.h>
68*4882a593Smuzhiyun 
69*4882a593Smuzhiyun /* bits that are frequently given and infrequently matched in the low word */
70*4882a593Smuzhiyun /* NOTE: If you add a flag, you need to also update masklog.c! */
71*4882a593Smuzhiyun #define ML_TCP		0x0000000000000001ULL /* net cluster/tcp.c */
72*4882a593Smuzhiyun #define ML_MSG		0x0000000000000002ULL /* net network messages */
73*4882a593Smuzhiyun #define ML_SOCKET	0x0000000000000004ULL /* net socket lifetime */
74*4882a593Smuzhiyun #define ML_HEARTBEAT	0x0000000000000008ULL /* hb all heartbeat tracking */
75*4882a593Smuzhiyun #define ML_HB_BIO	0x0000000000000010ULL /* hb io tracing */
76*4882a593Smuzhiyun #define ML_DLMFS	0x0000000000000020ULL /* dlm user dlmfs */
77*4882a593Smuzhiyun #define ML_DLM		0x0000000000000040ULL /* dlm general debugging */
78*4882a593Smuzhiyun #define ML_DLM_DOMAIN	0x0000000000000080ULL /* dlm domain debugging */
79*4882a593Smuzhiyun #define ML_DLM_THREAD	0x0000000000000100ULL /* dlm domain thread */
80*4882a593Smuzhiyun #define ML_DLM_MASTER	0x0000000000000200ULL /* dlm master functions */
81*4882a593Smuzhiyun #define ML_DLM_RECOVERY	0x0000000000000400ULL /* dlm master functions */
82*4882a593Smuzhiyun #define ML_DLM_GLUE	0x0000000000000800ULL /* ocfs2 dlm glue layer */
83*4882a593Smuzhiyun #define ML_VOTE		0x0000000000001000ULL /* ocfs2 node messaging  */
84*4882a593Smuzhiyun #define ML_CONN		0x0000000000002000ULL /* net connection management */
85*4882a593Smuzhiyun #define ML_QUORUM	0x0000000000004000ULL /* net connection quorum */
86*4882a593Smuzhiyun #define ML_BASTS	0x0000000000008000ULL /* dlmglue asts and basts */
87*4882a593Smuzhiyun #define ML_CLUSTER	0x0000000000010000ULL /* cluster stack */
88*4882a593Smuzhiyun 
89*4882a593Smuzhiyun /* bits that are infrequently given and frequently matched in the high word */
90*4882a593Smuzhiyun #define ML_ERROR	0x1000000000000000ULL /* sent to KERN_ERR */
91*4882a593Smuzhiyun #define ML_NOTICE	0x2000000000000000ULL /* setn to KERN_NOTICE */
92*4882a593Smuzhiyun #define ML_KTHREAD	0x4000000000000000ULL /* kernel thread activity */
93*4882a593Smuzhiyun 
94*4882a593Smuzhiyun #define MLOG_INITIAL_AND_MASK (ML_ERROR|ML_NOTICE)
95*4882a593Smuzhiyun #ifndef MLOG_MASK_PREFIX
96*4882a593Smuzhiyun #define MLOG_MASK_PREFIX 0
97*4882a593Smuzhiyun #endif
98*4882a593Smuzhiyun 
99*4882a593Smuzhiyun /*
100*4882a593Smuzhiyun  * When logging is disabled, force the bit test to 0 for anything other
101*4882a593Smuzhiyun  * than errors and notices, allowing gcc to remove the code completely.
102*4882a593Smuzhiyun  * When enabled, allow all masks.
103*4882a593Smuzhiyun  */
104*4882a593Smuzhiyun #if defined(CONFIG_OCFS2_DEBUG_MASKLOG)
105*4882a593Smuzhiyun #define ML_ALLOWED_BITS ~0
106*4882a593Smuzhiyun #else
107*4882a593Smuzhiyun #define ML_ALLOWED_BITS (ML_ERROR|ML_NOTICE)
108*4882a593Smuzhiyun #endif
109*4882a593Smuzhiyun 
110*4882a593Smuzhiyun #define MLOG_MAX_BITS 64
111*4882a593Smuzhiyun 
112*4882a593Smuzhiyun struct mlog_bits {
113*4882a593Smuzhiyun 	unsigned long words[MLOG_MAX_BITS / BITS_PER_LONG];
114*4882a593Smuzhiyun };
115*4882a593Smuzhiyun 
116*4882a593Smuzhiyun extern struct mlog_bits mlog_and_bits, mlog_not_bits;
117*4882a593Smuzhiyun 
118*4882a593Smuzhiyun #if BITS_PER_LONG == 32
119*4882a593Smuzhiyun 
120*4882a593Smuzhiyun #define __mlog_test_u64(mask, bits)			\
121*4882a593Smuzhiyun 	( (u32)(mask & 0xffffffff) & bits.words[0] || 	\
122*4882a593Smuzhiyun 	  ((u64)(mask) >> 32) & bits.words[1] )
123*4882a593Smuzhiyun #define __mlog_set_u64(mask, bits) do {			\
124*4882a593Smuzhiyun 	bits.words[0] |= (u32)(mask & 0xffffffff);	\
125*4882a593Smuzhiyun        	bits.words[1] |= (u64)(mask) >> 32;		\
126*4882a593Smuzhiyun } while (0)
127*4882a593Smuzhiyun #define __mlog_clear_u64(mask, bits) do {		\
128*4882a593Smuzhiyun 	bits.words[0] &= ~((u32)(mask & 0xffffffff));	\
129*4882a593Smuzhiyun        	bits.words[1] &= ~((u64)(mask) >> 32);		\
130*4882a593Smuzhiyun } while (0)
131*4882a593Smuzhiyun #define MLOG_BITS_RHS(mask) {				\
132*4882a593Smuzhiyun 	{						\
133*4882a593Smuzhiyun 		[0] = (u32)(mask & 0xffffffff),		\
134*4882a593Smuzhiyun 		[1] = (u64)(mask) >> 32,		\
135*4882a593Smuzhiyun 	}						\
136*4882a593Smuzhiyun }
137*4882a593Smuzhiyun 
138*4882a593Smuzhiyun #else /* 32bit long above, 64bit long below */
139*4882a593Smuzhiyun 
140*4882a593Smuzhiyun #define __mlog_test_u64(mask, bits)	((mask) & bits.words[0])
141*4882a593Smuzhiyun #define __mlog_set_u64(mask, bits) do {		\
142*4882a593Smuzhiyun 	bits.words[0] |= (mask);		\
143*4882a593Smuzhiyun } while (0)
144*4882a593Smuzhiyun #define __mlog_clear_u64(mask, bits) do {	\
145*4882a593Smuzhiyun 	bits.words[0] &= ~(mask);		\
146*4882a593Smuzhiyun } while (0)
147*4882a593Smuzhiyun #define MLOG_BITS_RHS(mask) { { (mask) } }
148*4882a593Smuzhiyun 
149*4882a593Smuzhiyun #endif
150*4882a593Smuzhiyun 
151*4882a593Smuzhiyun __printf(4, 5)
152*4882a593Smuzhiyun void __mlog_printk(const u64 *m, const char *func, int line,
153*4882a593Smuzhiyun 		   const char *fmt, ...);
154*4882a593Smuzhiyun 
155*4882a593Smuzhiyun /*
156*4882a593Smuzhiyun  * Testing before the __mlog_printk call lets the compiler eliminate the
157*4882a593Smuzhiyun  * call completely when (m & ML_ALLOWED_BITS) is 0.
158*4882a593Smuzhiyun  */
159*4882a593Smuzhiyun #define mlog(mask, fmt, ...)						\
160*4882a593Smuzhiyun do {									\
161*4882a593Smuzhiyun 	u64 _m = MLOG_MASK_PREFIX | (mask);				\
162*4882a593Smuzhiyun 	if (_m & ML_ALLOWED_BITS)					\
163*4882a593Smuzhiyun 		__mlog_printk(&_m, __func__, __LINE__, fmt,		\
164*4882a593Smuzhiyun 			      ##__VA_ARGS__);				\
165*4882a593Smuzhiyun } while (0)
166*4882a593Smuzhiyun 
167*4882a593Smuzhiyun #define mlog_ratelimited(mask, fmt, ...)				\
168*4882a593Smuzhiyun do {									\
169*4882a593Smuzhiyun 	static DEFINE_RATELIMIT_STATE(_rs,				\
170*4882a593Smuzhiyun 				      DEFAULT_RATELIMIT_INTERVAL,	\
171*4882a593Smuzhiyun 				      DEFAULT_RATELIMIT_BURST);		\
172*4882a593Smuzhiyun 	if (__ratelimit(&_rs))						\
173*4882a593Smuzhiyun 		mlog(mask, fmt, ##__VA_ARGS__);				\
174*4882a593Smuzhiyun } while (0)
175*4882a593Smuzhiyun 
176*4882a593Smuzhiyun #define mlog_errno(st) ({						\
177*4882a593Smuzhiyun 	int _st = (st);							\
178*4882a593Smuzhiyun 	if (_st != -ERESTARTSYS && _st != -EINTR &&			\
179*4882a593Smuzhiyun 	    _st != AOP_TRUNCATED_PAGE && _st != -ENOSPC &&		\
180*4882a593Smuzhiyun 	    _st != -EDQUOT)						\
181*4882a593Smuzhiyun 		mlog(ML_ERROR, "status = %lld\n", (long long)_st);	\
182*4882a593Smuzhiyun 	_st;								\
183*4882a593Smuzhiyun })
184*4882a593Smuzhiyun 
185*4882a593Smuzhiyun #define mlog_bug_on_msg(cond, fmt, args...) do {			\
186*4882a593Smuzhiyun 	if (cond) {							\
187*4882a593Smuzhiyun 		mlog(ML_ERROR, "bug expression: " #cond "\n");		\
188*4882a593Smuzhiyun 		mlog(ML_ERROR, fmt, ##args);				\
189*4882a593Smuzhiyun 		BUG();							\
190*4882a593Smuzhiyun 	}								\
191*4882a593Smuzhiyun } while (0)
192*4882a593Smuzhiyun 
193*4882a593Smuzhiyun #include <linux/kobject.h>
194*4882a593Smuzhiyun #include <linux/sysfs.h>
195*4882a593Smuzhiyun int mlog_sys_init(struct kset *o2cb_subsys);
196*4882a593Smuzhiyun void mlog_sys_shutdown(void);
197*4882a593Smuzhiyun 
198*4882a593Smuzhiyun #endif /* O2CLUSTER_MASKLOG_H */
199