masklog.h 8.7 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.
 *
C
Coly Li 已提交
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
C
Coly Li 已提交
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:
 *
C
Coly Li 已提交
65
 * 	write(fd, "allow", 5);
66
 *
C
Coly Li 已提交
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
 *
C
Coly Li 已提交
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
 *
C
Coly Li 已提交
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
 */

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

/* bits that are frequently given and infrequently matched in the low word */
S
Sunil Mushran 已提交
84
/* NOTE: If you add a flag, you need to also update masklog.c! */
85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108
#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_SUPER	0x0000000000010000ULL /* ocfs2 mount / umount */
#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_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 */
109
#define ML_XATTR	0x0000000020000000ULL /* ocfs2 extended attributes */
110
#define ML_QUOTA	0x0000000040000000ULL /* ocfs2 quota operations */
S
Sunil Mushran 已提交
111 112 113 114
#define ML_BASTS	0x0000000100000000ULL /* dlmglue asts and basts */
#define ML_RESERVATIONS	0x0000000200000000ULL /* ocfs2 alloc reservations */
#define ML_CLUSTER	0x0000000400000000ULL /* cluster stack */

115
/* bits that are infrequently given and frequently matched in the high word */
S
Sunil Mushran 已提交
116 117 118
#define ML_ERROR	0x1000000000000000ULL /* sent to KERN_ERR */
#define ML_NOTICE	0x2000000000000000ULL /* setn to KERN_NOTICE */
#define ML_KTHREAD	0x4000000000000000ULL /* kernel thread activity */
119 120 121 122 123 124

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

125 126 127 128 129 130 131 132 133 134 135
/*
 * 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

136 137 138 139 140 141 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
#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...)				\
194 195 196
	printk(level "(%s,%u,%lu):%s:%d " fmt, current->comm,		\
	       task_pid_nr(current), __mlog_cpu_guess,			\
	       __PRETTY_FUNCTION__, __LINE__ , ##args)
197 198 199

#define mlog(mask, fmt, args...) do {					\
	u64 __m = MLOG_MASK_PREFIX | (mask);				\
200 201
	if ((__m & ML_ALLOWED_BITS) &&					\
	    __mlog_test_u64(__m, mlog_and_bits) &&			\
202 203 204 205 206 207 208 209 210 211 212 213
	    !__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 &&			\
214
	    _st != AOP_TRUNCATED_PAGE && _st != -ENOSPC)		\
215 216 217 218 219 220 221 222 223 224 225 226 227
		mlog(ML_ERROR, "status = %lld\n", (long long)_st);	\
} while (0)

#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>
228
int mlog_sys_init(struct kset *o2cb_subsys);
229 230 231
void mlog_sys_shutdown(void);

#endif /* O2CLUSTER_MASKLOG_H */