162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-or-later */ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright (C) 2005 Oracle. All rights reserved. 462306a36Sopenharmony_ci */ 562306a36Sopenharmony_ci 662306a36Sopenharmony_ci#ifndef O2CLUSTER_MASKLOG_H 762306a36Sopenharmony_ci#define O2CLUSTER_MASKLOG_H 862306a36Sopenharmony_ci 962306a36Sopenharmony_ci/* 1062306a36Sopenharmony_ci * For now this is a trivial wrapper around printk() that gives the critical 1162306a36Sopenharmony_ci * ability to enable sets of debugging output at run-time. In the future this 1262306a36Sopenharmony_ci * will almost certainly be redirected to relayfs so that it can pay a 1362306a36Sopenharmony_ci * substantially lower heisenberg tax. 1462306a36Sopenharmony_ci * 1562306a36Sopenharmony_ci * Callers associate the message with a bitmask and a global bitmask is 1662306a36Sopenharmony_ci * maintained with help from /proc. If any of the bits match the message is 1762306a36Sopenharmony_ci * output. 1862306a36Sopenharmony_ci * 1962306a36Sopenharmony_ci * We must have efficient bit tests on i386 and it seems gcc still emits crazy 2062306a36Sopenharmony_ci * code for the 64bit compare. It emits very good code for the dual unsigned 2162306a36Sopenharmony_ci * long tests, though, completely avoiding tests that can never pass if the 2262306a36Sopenharmony_ci * caller gives a constant bitmask that fills one of the longs with all 0s. So 2362306a36Sopenharmony_ci * the desire is to have almost all of the calls decided on by comparing just 2462306a36Sopenharmony_ci * one of the longs. This leads to having infrequently given bits that are 2562306a36Sopenharmony_ci * frequently matched in the high bits. 2662306a36Sopenharmony_ci * 2762306a36Sopenharmony_ci * _ERROR and _NOTICE are used for messages that always go to the console and 2862306a36Sopenharmony_ci * have appropriate KERN_ prefixes. We wrap these in our function instead of 2962306a36Sopenharmony_ci * just calling printk() so that this can eventually make its way through 3062306a36Sopenharmony_ci * relayfs along with the debugging messages. Everything else gets KERN_DEBUG. 3162306a36Sopenharmony_ci * The inline tests and macro dance give GCC the opportunity to quite cleverly 3262306a36Sopenharmony_ci * only emit the appropriage printk() when the caller passes in a constant 3362306a36Sopenharmony_ci * mask, as is almost always the case. 3462306a36Sopenharmony_ci * 3562306a36Sopenharmony_ci * All this bitmask nonsense is managed from the files under 3662306a36Sopenharmony_ci * /sys/fs/o2cb/logmask/. Reading the files gives a straightforward 3762306a36Sopenharmony_ci * indication of which bits are allowed (allow) or denied (off/deny). 3862306a36Sopenharmony_ci * ENTRY deny 3962306a36Sopenharmony_ci * EXIT deny 4062306a36Sopenharmony_ci * TCP off 4162306a36Sopenharmony_ci * MSG off 4262306a36Sopenharmony_ci * SOCKET off 4362306a36Sopenharmony_ci * ERROR allow 4462306a36Sopenharmony_ci * NOTICE allow 4562306a36Sopenharmony_ci * 4662306a36Sopenharmony_ci * Writing changes the state of a given bit and requires a strictly formatted 4762306a36Sopenharmony_ci * single write() call: 4862306a36Sopenharmony_ci * 4962306a36Sopenharmony_ci * write(fd, "allow", 5); 5062306a36Sopenharmony_ci * 5162306a36Sopenharmony_ci * Echoing allow/deny/off string into the logmask files can flip the bits 5262306a36Sopenharmony_ci * on or off as expected; here is the bash script for example: 5362306a36Sopenharmony_ci * 5462306a36Sopenharmony_ci * log_mask="/sys/fs/o2cb/log_mask" 5562306a36Sopenharmony_ci * for node in ENTRY EXIT TCP MSG SOCKET ERROR NOTICE; do 5662306a36Sopenharmony_ci * echo allow >"$log_mask"/"$node" 5762306a36Sopenharmony_ci * done 5862306a36Sopenharmony_ci * 5962306a36Sopenharmony_ci * The debugfs.ocfs2 tool can also flip the bits with the -l option: 6062306a36Sopenharmony_ci * 6162306a36Sopenharmony_ci * debugfs.ocfs2 -l TCP allow 6262306a36Sopenharmony_ci */ 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ci/* for task_struct */ 6562306a36Sopenharmony_ci#include <linux/sched.h> 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_ci/* bits that are frequently given and infrequently matched in the low word */ 6862306a36Sopenharmony_ci/* NOTE: If you add a flag, you need to also update masklog.c! */ 6962306a36Sopenharmony_ci#define ML_TCP 0x0000000000000001ULL /* net cluster/tcp.c */ 7062306a36Sopenharmony_ci#define ML_MSG 0x0000000000000002ULL /* net network messages */ 7162306a36Sopenharmony_ci#define ML_SOCKET 0x0000000000000004ULL /* net socket lifetime */ 7262306a36Sopenharmony_ci#define ML_HEARTBEAT 0x0000000000000008ULL /* hb all heartbeat tracking */ 7362306a36Sopenharmony_ci#define ML_HB_BIO 0x0000000000000010ULL /* hb io tracing */ 7462306a36Sopenharmony_ci#define ML_DLMFS 0x0000000000000020ULL /* dlm user dlmfs */ 7562306a36Sopenharmony_ci#define ML_DLM 0x0000000000000040ULL /* dlm general debugging */ 7662306a36Sopenharmony_ci#define ML_DLM_DOMAIN 0x0000000000000080ULL /* dlm domain debugging */ 7762306a36Sopenharmony_ci#define ML_DLM_THREAD 0x0000000000000100ULL /* dlm domain thread */ 7862306a36Sopenharmony_ci#define ML_DLM_MASTER 0x0000000000000200ULL /* dlm master functions */ 7962306a36Sopenharmony_ci#define ML_DLM_RECOVERY 0x0000000000000400ULL /* dlm master functions */ 8062306a36Sopenharmony_ci#define ML_DLM_GLUE 0x0000000000000800ULL /* ocfs2 dlm glue layer */ 8162306a36Sopenharmony_ci#define ML_VOTE 0x0000000000001000ULL /* ocfs2 node messaging */ 8262306a36Sopenharmony_ci#define ML_CONN 0x0000000000002000ULL /* net connection management */ 8362306a36Sopenharmony_ci#define ML_QUORUM 0x0000000000004000ULL /* net connection quorum */ 8462306a36Sopenharmony_ci#define ML_BASTS 0x0000000000008000ULL /* dlmglue asts and basts */ 8562306a36Sopenharmony_ci#define ML_CLUSTER 0x0000000000010000ULL /* cluster stack */ 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_ci/* bits that are infrequently given and frequently matched in the high word */ 8862306a36Sopenharmony_ci#define ML_ERROR 0x1000000000000000ULL /* sent to KERN_ERR */ 8962306a36Sopenharmony_ci#define ML_NOTICE 0x2000000000000000ULL /* setn to KERN_NOTICE */ 9062306a36Sopenharmony_ci#define ML_KTHREAD 0x4000000000000000ULL /* kernel thread activity */ 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_ci#define MLOG_INITIAL_AND_MASK (ML_ERROR|ML_NOTICE) 9362306a36Sopenharmony_ci#ifndef MLOG_MASK_PREFIX 9462306a36Sopenharmony_ci#define MLOG_MASK_PREFIX 0 9562306a36Sopenharmony_ci#endif 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci/* 9862306a36Sopenharmony_ci * When logging is disabled, force the bit test to 0 for anything other 9962306a36Sopenharmony_ci * than errors and notices, allowing gcc to remove the code completely. 10062306a36Sopenharmony_ci * When enabled, allow all masks. 10162306a36Sopenharmony_ci */ 10262306a36Sopenharmony_ci#if defined(CONFIG_OCFS2_DEBUG_MASKLOG) 10362306a36Sopenharmony_ci#define ML_ALLOWED_BITS ~0 10462306a36Sopenharmony_ci#else 10562306a36Sopenharmony_ci#define ML_ALLOWED_BITS (ML_ERROR|ML_NOTICE) 10662306a36Sopenharmony_ci#endif 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_ci#define MLOG_MAX_BITS 64 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_cistruct mlog_bits { 11162306a36Sopenharmony_ci unsigned long words[MLOG_MAX_BITS / BITS_PER_LONG]; 11262306a36Sopenharmony_ci}; 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_ciextern struct mlog_bits mlog_and_bits, mlog_not_bits; 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_ci#if BITS_PER_LONG == 32 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_ci#define __mlog_test_u64(mask, bits) \ 11962306a36Sopenharmony_ci ( (u32)(mask & 0xffffffff) & bits.words[0] || \ 12062306a36Sopenharmony_ci ((u64)(mask) >> 32) & bits.words[1] ) 12162306a36Sopenharmony_ci#define __mlog_set_u64(mask, bits) do { \ 12262306a36Sopenharmony_ci bits.words[0] |= (u32)(mask & 0xffffffff); \ 12362306a36Sopenharmony_ci bits.words[1] |= (u64)(mask) >> 32; \ 12462306a36Sopenharmony_ci} while (0) 12562306a36Sopenharmony_ci#define __mlog_clear_u64(mask, bits) do { \ 12662306a36Sopenharmony_ci bits.words[0] &= ~((u32)(mask & 0xffffffff)); \ 12762306a36Sopenharmony_ci bits.words[1] &= ~((u64)(mask) >> 32); \ 12862306a36Sopenharmony_ci} while (0) 12962306a36Sopenharmony_ci#define MLOG_BITS_RHS(mask) { \ 13062306a36Sopenharmony_ci { \ 13162306a36Sopenharmony_ci [0] = (u32)(mask & 0xffffffff), \ 13262306a36Sopenharmony_ci [1] = (u64)(mask) >> 32, \ 13362306a36Sopenharmony_ci } \ 13462306a36Sopenharmony_ci} 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_ci#else /* 32bit long above, 64bit long below */ 13762306a36Sopenharmony_ci 13862306a36Sopenharmony_ci#define __mlog_test_u64(mask, bits) ((mask) & bits.words[0]) 13962306a36Sopenharmony_ci#define __mlog_set_u64(mask, bits) do { \ 14062306a36Sopenharmony_ci bits.words[0] |= (mask); \ 14162306a36Sopenharmony_ci} while (0) 14262306a36Sopenharmony_ci#define __mlog_clear_u64(mask, bits) do { \ 14362306a36Sopenharmony_ci bits.words[0] &= ~(mask); \ 14462306a36Sopenharmony_ci} while (0) 14562306a36Sopenharmony_ci#define MLOG_BITS_RHS(mask) { { (mask) } } 14662306a36Sopenharmony_ci 14762306a36Sopenharmony_ci#endif 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_ci__printf(4, 5) 15062306a36Sopenharmony_civoid __mlog_printk(const u64 *m, const char *func, int line, 15162306a36Sopenharmony_ci const char *fmt, ...); 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_ci/* 15462306a36Sopenharmony_ci * Testing before the __mlog_printk call lets the compiler eliminate the 15562306a36Sopenharmony_ci * call completely when (m & ML_ALLOWED_BITS) is 0. 15662306a36Sopenharmony_ci */ 15762306a36Sopenharmony_ci#define mlog(mask, fmt, ...) \ 15862306a36Sopenharmony_cido { \ 15962306a36Sopenharmony_ci u64 _m = MLOG_MASK_PREFIX | (mask); \ 16062306a36Sopenharmony_ci if (_m & ML_ALLOWED_BITS) \ 16162306a36Sopenharmony_ci __mlog_printk(&_m, __func__, __LINE__, fmt, \ 16262306a36Sopenharmony_ci ##__VA_ARGS__); \ 16362306a36Sopenharmony_ci} while (0) 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_ci#define mlog_ratelimited(mask, fmt, ...) \ 16662306a36Sopenharmony_cido { \ 16762306a36Sopenharmony_ci static DEFINE_RATELIMIT_STATE(_rs, \ 16862306a36Sopenharmony_ci DEFAULT_RATELIMIT_INTERVAL, \ 16962306a36Sopenharmony_ci DEFAULT_RATELIMIT_BURST); \ 17062306a36Sopenharmony_ci if (__ratelimit(&_rs)) \ 17162306a36Sopenharmony_ci mlog(mask, fmt, ##__VA_ARGS__); \ 17262306a36Sopenharmony_ci} while (0) 17362306a36Sopenharmony_ci 17462306a36Sopenharmony_ci#define mlog_errno(st) ({ \ 17562306a36Sopenharmony_ci int _st = (st); \ 17662306a36Sopenharmony_ci if (_st != -ERESTARTSYS && _st != -EINTR && \ 17762306a36Sopenharmony_ci _st != AOP_TRUNCATED_PAGE && _st != -ENOSPC && \ 17862306a36Sopenharmony_ci _st != -EDQUOT) \ 17962306a36Sopenharmony_ci mlog(ML_ERROR, "status = %lld\n", (long long)_st); \ 18062306a36Sopenharmony_ci _st; \ 18162306a36Sopenharmony_ci}) 18262306a36Sopenharmony_ci 18362306a36Sopenharmony_ci#define mlog_bug_on_msg(cond, fmt, args...) do { \ 18462306a36Sopenharmony_ci if (cond) { \ 18562306a36Sopenharmony_ci mlog(ML_ERROR, "bug expression: " #cond "\n"); \ 18662306a36Sopenharmony_ci mlog(ML_ERROR, fmt, ##args); \ 18762306a36Sopenharmony_ci BUG(); \ 18862306a36Sopenharmony_ci } \ 18962306a36Sopenharmony_ci} while (0) 19062306a36Sopenharmony_ci 19162306a36Sopenharmony_ci#include <linux/kobject.h> 19262306a36Sopenharmony_ci#include <linux/sysfs.h> 19362306a36Sopenharmony_ciint mlog_sys_init(struct kset *o2cb_subsys); 19462306a36Sopenharmony_civoid mlog_sys_shutdown(void); 19562306a36Sopenharmony_ci 19662306a36Sopenharmony_ci#endif /* O2CLUSTER_MASKLOG_H */ 197