1// SPDX-License-Identifier: GPL-2.0-or-later
2/* -*- mode: c; c-basic-offset: 8; -*-
3 * vim: noexpandtab sw=8 ts=8 sts=0:
4 *
5 * Copyright (C) 2004, 2005 Oracle.  All rights reserved.
6 */
7
8#include <linux/module.h>
9#include <linux/kernel.h>
10#include <linux/proc_fs.h>
11#include <linux/seq_file.h>
12#include <linux/string.h>
13#include <linux/uaccess.h>
14
15#include "masklog.h"
16
17struct mlog_bits mlog_and_bits = MLOG_BITS_RHS(MLOG_INITIAL_AND_MASK);
18EXPORT_SYMBOL_GPL(mlog_and_bits);
19struct mlog_bits mlog_not_bits = MLOG_BITS_RHS(0);
20EXPORT_SYMBOL_GPL(mlog_not_bits);
21
22static ssize_t mlog_mask_show(u64 mask, char *buf)
23{
24	char *state;
25
26	if (__mlog_test_u64(mask, mlog_and_bits))
27		state = "allow";
28	else if (__mlog_test_u64(mask, mlog_not_bits))
29		state = "deny";
30	else
31		state = "off";
32
33	return snprintf(buf, PAGE_SIZE, "%s\n", state);
34}
35
36static ssize_t mlog_mask_store(u64 mask, const char *buf, size_t count)
37{
38	if (!strncasecmp(buf, "allow", 5)) {
39		__mlog_set_u64(mask, mlog_and_bits);
40		__mlog_clear_u64(mask, mlog_not_bits);
41	} else if (!strncasecmp(buf, "deny", 4)) {
42		__mlog_set_u64(mask, mlog_not_bits);
43		__mlog_clear_u64(mask, mlog_and_bits);
44	} else if (!strncasecmp(buf, "off", 3)) {
45		__mlog_clear_u64(mask, mlog_not_bits);
46		__mlog_clear_u64(mask, mlog_and_bits);
47	} else
48		return -EINVAL;
49
50	return count;
51}
52
53void __mlog_printk(const u64 *mask, const char *func, int line,
54		   const char *fmt, ...)
55{
56	struct va_format vaf;
57	va_list args;
58	const char *level;
59	const char *prefix = "";
60
61	if (!__mlog_test_u64(*mask, mlog_and_bits) ||
62	    __mlog_test_u64(*mask, mlog_not_bits))
63		return;
64
65	if (*mask & ML_ERROR) {
66		level = KERN_ERR;
67		prefix = "ERROR: ";
68	} else if (*mask & ML_NOTICE) {
69		level = KERN_NOTICE;
70	} else {
71		level = KERN_INFO;
72	}
73
74	va_start(args, fmt);
75
76	vaf.fmt = fmt;
77	vaf.va = &args;
78
79	printk("%s(%s,%u,%u):%s:%d %s%pV",
80	       level, current->comm, task_pid_nr(current),
81	       raw_smp_processor_id(), func, line, prefix, &vaf);
82
83	va_end(args);
84}
85EXPORT_SYMBOL_GPL(__mlog_printk);
86
87struct mlog_attribute {
88	struct attribute attr;
89	u64 mask;
90};
91
92#define to_mlog_attr(_attr) container_of(_attr, struct mlog_attribute, attr)
93
94#define define_mask(_name) {			\
95	.attr = {				\
96		.name = #_name,			\
97		.mode = S_IRUGO | S_IWUSR,	\
98	},					\
99	.mask = ML_##_name,			\
100}
101
102static struct mlog_attribute mlog_attrs[MLOG_MAX_BITS] = {
103	define_mask(TCP),
104	define_mask(MSG),
105	define_mask(SOCKET),
106	define_mask(HEARTBEAT),
107	define_mask(HB_BIO),
108	define_mask(DLMFS),
109	define_mask(DLM),
110	define_mask(DLM_DOMAIN),
111	define_mask(DLM_THREAD),
112	define_mask(DLM_MASTER),
113	define_mask(DLM_RECOVERY),
114	define_mask(DLM_GLUE),
115	define_mask(VOTE),
116	define_mask(CONN),
117	define_mask(QUORUM),
118	define_mask(BASTS),
119	define_mask(CLUSTER),
120	define_mask(ERROR),
121	define_mask(NOTICE),
122	define_mask(KTHREAD),
123};
124
125static struct attribute *mlog_attr_ptrs[MLOG_MAX_BITS] = {NULL, };
126
127static ssize_t mlog_show(struct kobject *obj, struct attribute *attr,
128			 char *buf)
129{
130	struct mlog_attribute *mlog_attr = to_mlog_attr(attr);
131
132	return mlog_mask_show(mlog_attr->mask, buf);
133}
134
135static ssize_t mlog_store(struct kobject *obj, struct attribute *attr,
136			  const char *buf, size_t count)
137{
138	struct mlog_attribute *mlog_attr = to_mlog_attr(attr);
139
140	return mlog_mask_store(mlog_attr->mask, buf, count);
141}
142
143static const struct sysfs_ops mlog_attr_ops = {
144	.show  = mlog_show,
145	.store = mlog_store,
146};
147
148static struct kobj_type mlog_ktype = {
149	.default_attrs = mlog_attr_ptrs,
150	.sysfs_ops     = &mlog_attr_ops,
151};
152
153static struct kset mlog_kset = {
154	.kobj   = {.ktype = &mlog_ktype},
155};
156
157int mlog_sys_init(struct kset *o2cb_kset)
158{
159	int i = 0;
160
161	while (mlog_attrs[i].attr.mode) {
162		mlog_attr_ptrs[i] = &mlog_attrs[i].attr;
163		i++;
164	}
165	mlog_attr_ptrs[i] = NULL;
166
167	kobject_set_name(&mlog_kset.kobj, "logmask");
168	mlog_kset.kobj.kset = o2cb_kset;
169	return kset_register(&mlog_kset);
170}
171
172void mlog_sys_shutdown(void)
173{
174	kset_unregister(&mlog_kset);
175}
176