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