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