masklog.h 11 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
/* -*- mode: c; c-basic-offset: 8; -*-
 * vim: noexpandtab sw=8 ts=8 sts=0:
 *
 * Copyright (C) 2005 Oracle.  All rights reserved.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public
 * License along with this program; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 021110-1307, USA.
 */

#ifndef O2CLUSTER_MASKLOG_H
#define O2CLUSTER_MASKLOG_H

/*
 * For now this is a trivial wrapper around printk() that gives the critical
 * ability to enable sets of debugging output at run-time.  In the future this
 * will almost certainly be redirected to relayfs so that it can pay a
 * substantially lower heisenberg tax.
 *
 * Callers associate the message with a bitmask and a global bitmask is
 * maintained with help from /proc.  If any of the bits match the message is
 * output.
 *
 * We must have efficient bit tests on i386 and it seems gcc still emits crazy
 * code for the 64bit compare.  It emits very good code for the dual unsigned
 * long tests, though, completely avoiding tests that can never pass if the
 * caller gives a constant bitmask that fills one of the longs with all 0s.  So
 * the desire is to have almost all of the calls decided on by comparing just
 * one of the longs.  This leads to having infrequently given bits that are
 * frequently matched in the high bits.
 *
 * _ERROR and _NOTICE are used for messages that always go to the console and
 * have appropriate KERN_ prefixes.  We wrap these in our function instead of
 * just calling printk() so that this can eventually make its way through
 * relayfs along with the debugging messages.  Everything else gets KERN_DEBUG.
 * The inline tests and macro dance give GCC the opportunity to quite cleverly
 * only emit the appropriage printk() when the caller passes in a constant
 * mask, as is almost always the case.
 *
Coly Li's avatar
Coly Li committed
51
52
53
54
55
 * All this bitmask nonsense is managed from the files under
 * /sys/fs/o2cb/logmask/.  Reading the files gives a straightforward
 * indication of which bits are allowed (allow) or denied (off/deny).
 * 	ENTRY deny
 * 	EXIT deny
56
57
58
 * 	TCP off
 * 	MSG off
 * 	SOCKET off
Coly Li's avatar
Coly Li committed
59
60
 * 	ERROR allow
 * 	NOTICE allow
61
62
63
64
 *
 * Writing changes the state of a given bit and requires a strictly formatted
 * single write() call:
 *
Coly Li's avatar
Coly Li committed
65
 * 	write(fd, "allow", 5);
66
 *
Coly Li's avatar
Coly Li committed
67
68
 * Echoing allow/deny/off string into the logmask files can flip the bits
 * on or off as expected; here is the bash script for example:
69
 *
Coly Li's avatar
Coly Li committed
70
71
72
73
 * log_mask="/sys/fs/o2cb/log_mask"
 * for node in ENTRY EXIT TCP MSG SOCKET ERROR NOTICE; do
 *	echo allow >"$log_mask"/"$node"
 * done
74
 *
Coly Li's avatar
Coly Li committed
75
76
77
 * The debugfs.ocfs2 tool can also flip the bits with the -l option:
 *
 * debugfs.ocfs2 -l TCP allow
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
 */

/* for task_struct */
#include <linux/sched.h>

/* bits that are frequently given and infrequently matched in the low word */
/* NOTE: If you add a flag, you need to also update mlog.c! */
#define ML_ENTRY	0x0000000000000001ULL /* func call entry */
#define ML_EXIT		0x0000000000000002ULL /* func call exit */
#define ML_TCP		0x0000000000000004ULL /* net cluster/tcp.c */
#define ML_MSG		0x0000000000000008ULL /* net network messages */
#define ML_SOCKET	0x0000000000000010ULL /* net socket lifetime */
#define ML_HEARTBEAT	0x0000000000000020ULL /* hb all heartbeat tracking */
#define ML_HB_BIO	0x0000000000000040ULL /* hb io tracing */
#define ML_DLMFS	0x0000000000000080ULL /* dlm user dlmfs */
#define ML_DLM		0x0000000000000100ULL /* dlm general debugging */
#define ML_DLM_DOMAIN	0x0000000000000200ULL /* dlm domain debugging */
#define ML_DLM_THREAD	0x0000000000000400ULL /* dlm domain thread */
#define ML_DLM_MASTER	0x0000000000000800ULL /* dlm master functions */
#define ML_DLM_RECOVERY	0x0000000000001000ULL /* dlm master functions */
#define ML_AIO		0x0000000000002000ULL /* ocfs2 aio read and write */
#define ML_JOURNAL	0x0000000000004000ULL /* ocfs2 journalling functions */
#define ML_DISK_ALLOC	0x0000000000008000ULL /* ocfs2 disk allocation */
#define ML_SUPER	0x0000000000010000ULL /* ocfs2 mount / umount */
#define ML_FILE_IO	0x0000000000020000ULL /* ocfs2 file I/O */
#define ML_EXTENT_MAP	0x0000000000040000ULL /* ocfs2 extent map caching */
#define ML_DLM_GLUE	0x0000000000080000ULL /* ocfs2 dlm glue layer */
#define ML_BH_IO	0x0000000000100000ULL /* ocfs2 buffer I/O */
#define ML_UPTODATE	0x0000000000200000ULL /* ocfs2 caching sequence #'s */
#define ML_NAMEI	0x0000000000400000ULL /* ocfs2 directory / namespace */
#define ML_INODE	0x0000000000800000ULL /* ocfs2 inode manipulation */
#define ML_VOTE		0x0000000001000000ULL /* ocfs2 node messaging  */
#define ML_DCACHE	0x0000000002000000ULL /* ocfs2 dcache operations */
#define ML_CONN		0x0000000004000000ULL /* net connection management */
#define ML_QUORUM	0x0000000008000000ULL /* net connection quorum */
#define ML_EXPORT	0x0000000010000000ULL /* ocfs2 export operations */
114
#define ML_XATTR	0x0000000020000000ULL /* ocfs2 extended attributes */
115
#define ML_QUOTA	0x0000000040000000ULL /* ocfs2 quota operations */
Tao Ma's avatar
Tao Ma committed
116
#define ML_REFCOUNT	0x0000000080000000ULL /* refcount tree operations */
117
#define ML_BASTS	0x0000001000000000ULL /* dlmglue asts and basts */
118
119
120
121
/* bits that are infrequently given and frequently matched in the high word */
#define ML_ERROR	0x0000000100000000ULL /* sent to KERN_ERR */
#define ML_NOTICE	0x0000000200000000ULL /* setn to KERN_NOTICE */
#define ML_KTHREAD	0x0000000400000000ULL /* kernel thread activity */
122
123
#define ML_RESERVATIONS	0x0000000800000000ULL /* ocfs2 alloc reservations */
#define ML_CLUSTER	0x0000001000000000ULL /* cluster stack */
124
125
126
127
128
129
130

#define MLOG_INITIAL_AND_MASK (ML_ERROR|ML_NOTICE)
#define MLOG_INITIAL_NOT_MASK (ML_ENTRY|ML_EXIT)
#ifndef MLOG_MASK_PREFIX
#define MLOG_MASK_PREFIX 0
#endif

131
132
133
134
135
136
137
138
139
140
141
/*
 * When logging is disabled, force the bit test to 0 for anything other
 * than errors and notices, allowing gcc to remove the code completely.
 * When enabled, allow all masks.
 */
#if defined(CONFIG_OCFS2_DEBUG_MASKLOG)
#define ML_ALLOWED_BITS ~0
#else
#define ML_ALLOWED_BITS (ML_ERROR|ML_NOTICE)
#endif

142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
#define MLOG_MAX_BITS 64

struct mlog_bits {
	unsigned long words[MLOG_MAX_BITS / BITS_PER_LONG];
};

extern struct mlog_bits mlog_and_bits, mlog_not_bits;

#if BITS_PER_LONG == 32

#define __mlog_test_u64(mask, bits)			\
	( (u32)(mask & 0xffffffff) & bits.words[0] || 	\
	  ((u64)(mask) >> 32) & bits.words[1] )
#define __mlog_set_u64(mask, bits) do {			\
	bits.words[0] |= (u32)(mask & 0xffffffff);	\
       	bits.words[1] |= (u64)(mask) >> 32;		\
} while (0)
#define __mlog_clear_u64(mask, bits) do {		\
	bits.words[0] &= ~((u32)(mask & 0xffffffff));	\
       	bits.words[1] &= ~((u64)(mask) >> 32);		\
} while (0)
#define MLOG_BITS_RHS(mask) {				\
	{						\
		[0] = (u32)(mask & 0xffffffff),		\
		[1] = (u64)(mask) >> 32,		\
	}						\
}

#else /* 32bit long above, 64bit long below */

#define __mlog_test_u64(mask, bits)	((mask) & bits.words[0])
#define __mlog_set_u64(mask, bits) do {		\
	bits.words[0] |= (mask);		\
} while (0)
#define __mlog_clear_u64(mask, bits) do {	\
	bits.words[0] &= ~(mask);		\
} while (0)
#define MLOG_BITS_RHS(mask) { { (mask) } }

#endif

/*
 * smp_processor_id() "helpfully" screams when called outside preemptible
 * regions in current kernels.  sles doesn't have the variants that don't
 * scream.  just do this instead of trying to guess which we're building
 * against.. *sigh*.
 */
#define __mlog_cpu_guess ({		\
	unsigned long _cpu = get_cpu();	\
	put_cpu();			\
	_cpu;				\
})

/* In the following two macros, the whitespace after the ',' just
 * before ##args is intentional. Otherwise, gcc 2.95 will eat the
 * previous token if args expands to nothing.
 */
#define __mlog_printk(level, fmt, args...)				\
200
201
202
	printk(level "(%s,%u,%lu):%s:%d " fmt, current->comm,		\
	       task_pid_nr(current), __mlog_cpu_guess,			\
	       __PRETTY_FUNCTION__, __LINE__ , ##args)
203
204
205

#define mlog(mask, fmt, args...) do {					\
	u64 __m = MLOG_MASK_PREFIX | (mask);				\
206
207
	if ((__m & ML_ALLOWED_BITS) &&					\
	    __mlog_test_u64(__m, mlog_and_bits) &&			\
208
209
210
211
212
213
214
215
216
217
218
219
	    !__mlog_test_u64(__m, mlog_not_bits)) {			\
		if (__m & ML_ERROR)					\
			__mlog_printk(KERN_ERR, "ERROR: "fmt , ##args);	\
		else if (__m & ML_NOTICE)				\
			__mlog_printk(KERN_NOTICE, fmt , ##args);	\
		else __mlog_printk(KERN_INFO, fmt , ##args);		\
	}								\
} while (0)

#define mlog_errno(st) do {						\
	int _st = (st);							\
	if (_st != -ERESTARTSYS && _st != -EINTR &&			\
220
	    _st != AOP_TRUNCATED_PAGE && _st != -ENOSPC)		\
221
222
223
		mlog(ML_ERROR, "status = %lld\n", (long long)_st);	\
} while (0)

224
#if defined(CONFIG_OCFS2_DEBUG_MASKLOG)
225
226
227
228
229
230
231
232
#define mlog_entry(fmt, args...) do {					\
	mlog(ML_ENTRY, "ENTRY:" fmt , ##args);				\
} while (0)

#define mlog_entry_void() do {						\
	mlog(ML_ENTRY, "ENTRY:\n");					\
} while (0)

Andrew Morton's avatar
Andrew Morton committed
233
234
/*
 * We disable this for sparse.
235
 */
Andrew Morton's avatar
Andrew Morton committed
236
#if !defined(__CHECKER__)
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
#define mlog_exit(st) do {						     \
	if (__builtin_types_compatible_p(typeof(st), unsigned long))	     \
		mlog(ML_EXIT, "EXIT: %lu\n", (unsigned long) (st));	     \
	else if (__builtin_types_compatible_p(typeof(st), signed long))      \
		mlog(ML_EXIT, "EXIT: %ld\n", (signed long) (st));	     \
	else if (__builtin_types_compatible_p(typeof(st), unsigned int)	     \
		 || __builtin_types_compatible_p(typeof(st), unsigned short) \
		 || __builtin_types_compatible_p(typeof(st), unsigned char)) \
		mlog(ML_EXIT, "EXIT: %u\n", (unsigned int) (st));	     \
	else if (__builtin_types_compatible_p(typeof(st), signed int)	     \
		 || __builtin_types_compatible_p(typeof(st), signed short)   \
		 || __builtin_types_compatible_p(typeof(st), signed char))   \
		mlog(ML_EXIT, "EXIT: %d\n", (signed int) (st));		     \
	else if (__builtin_types_compatible_p(typeof(st), long long))	     \
		mlog(ML_EXIT, "EXIT: %lld\n", (long long) (st));	     \
	else								     \
		mlog(ML_EXIT, "EXIT: %llu\n", (unsigned long long) (st));    \
} while (0)
#else
#define mlog_exit(st) do {						     \
	mlog(ML_EXIT, "EXIT: %lld\n", (long long) (st));		     \
} while (0)
#endif

#define mlog_exit_ptr(ptr) do {						\
	mlog(ML_EXIT, "EXIT: %p\n", ptr);				\
} while (0)

#define mlog_exit_void() do {						\
	mlog(ML_EXIT, "EXIT\n");					\
} while (0)
268
269
270
271
272
273
274
#else
#define mlog_entry(...)  do { } while (0)
#define mlog_entry_void(...)  do { } while (0)
#define mlog_exit(...)  do { } while (0)
#define mlog_exit_ptr(...)  do { } while (0)
#define mlog_exit_void(...)  do { } while (0)
#endif  /* defined(CONFIG_OCFS2_DEBUG_MASKLOG) */
275
276
277
278
279
280
281
282
283
284
285

#define mlog_bug_on_msg(cond, fmt, args...) do {			\
	if (cond) {							\
		mlog(ML_ERROR, "bug expression: " #cond "\n");		\
		mlog(ML_ERROR, fmt, ##args);				\
		BUG();							\
	}								\
} while (0)

#include <linux/kobject.h>
#include <linux/sysfs.h>
286
int mlog_sys_init(struct kset *o2cb_subsys);
287
288
289
void mlog_sys_shutdown(void);

#endif /* O2CLUSTER_MASKLOG_H */