xref: /linux/net/batman-adv/log.c (revision 0dacc7fab623be97bda7aefe0d1d8d68cebb4218)
17db7d9f3SSven Eckelmann // SPDX-License-Identifier: GPL-2.0
26b1aea8cSSven Eckelmann /* Copyright (C) 2010-2018  B.A.T.M.A.N. contributors:
3ba412080SSven Eckelmann  *
4ba412080SSven Eckelmann  * Marek Lindner
5ba412080SSven Eckelmann  *
6ba412080SSven Eckelmann  * This program is free software; you can redistribute it and/or
7ba412080SSven Eckelmann  * modify it under the terms of version 2 of the GNU General Public
8ba412080SSven Eckelmann  * License as published by the Free Software Foundation.
9ba412080SSven Eckelmann  *
10ba412080SSven Eckelmann  * This program is distributed in the hope that it will be useful, but
11ba412080SSven Eckelmann  * WITHOUT ANY WARRANTY; without even the implied warranty of
12ba412080SSven Eckelmann  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13ba412080SSven Eckelmann  * General Public License for more details.
14ba412080SSven Eckelmann  *
15ba412080SSven Eckelmann  * You should have received a copy of the GNU General Public License
16ba412080SSven Eckelmann  * along with this program; if not, see <http://www.gnu.org/licenses/>.
17ba412080SSven Eckelmann  */
18ba412080SSven Eckelmann 
19ba412080SSven Eckelmann #include "log.h"
20ba412080SSven Eckelmann #include "main.h"
21ba412080SSven Eckelmann 
22ba412080SSven Eckelmann #include <linux/compiler.h>
23ba412080SSven Eckelmann #include <linux/debugfs.h>
24ba412080SSven Eckelmann #include <linux/errno.h>
2548881ed5SSven Eckelmann #include <linux/eventpoll.h>
26ba412080SSven Eckelmann #include <linux/export.h>
27ba412080SSven Eckelmann #include <linux/fcntl.h>
28ba412080SSven Eckelmann #include <linux/fs.h>
29b92b94acSSven Eckelmann #include <linux/gfp.h>
30ba412080SSven Eckelmann #include <linux/jiffies.h>
31ba412080SSven Eckelmann #include <linux/kernel.h>
32ba412080SSven Eckelmann #include <linux/module.h>
33ba412080SSven Eckelmann #include <linux/poll.h>
34ba412080SSven Eckelmann #include <linux/sched.h> /* for linux/wait.h */
35ba412080SSven Eckelmann #include <linux/slab.h>
36ba412080SSven Eckelmann #include <linux/spinlock.h>
37ba412080SSven Eckelmann #include <linux/stddef.h>
38ba412080SSven Eckelmann #include <linux/types.h>
39ba412080SSven Eckelmann #include <linux/uaccess.h>
40ba412080SSven Eckelmann #include <linux/wait.h>
41ba412080SSven Eckelmann #include <stdarg.h>
42ba412080SSven Eckelmann 
4300caf6a2SSven Eckelmann #include "debugfs.h"
44d331a739SSven Eckelmann #include "trace.h"
4500caf6a2SSven Eckelmann 
46*0dacc7faSSven Eckelmann #ifdef CONFIG_BATMAN_ADV_DEBUGFS
47*0dacc7faSSven Eckelmann 
48ba412080SSven Eckelmann #define BATADV_LOG_BUFF_MASK (batadv_log_buff_len - 1)
49ba412080SSven Eckelmann 
50ba412080SSven Eckelmann static const int batadv_log_buff_len = BATADV_LOG_BUF_LEN;
51ba412080SSven Eckelmann 
52ba412080SSven Eckelmann static char *batadv_log_char_addr(struct batadv_priv_debug_log *debug_log,
53ba412080SSven Eckelmann 				  size_t idx)
54ba412080SSven Eckelmann {
55ba412080SSven Eckelmann 	return &debug_log->log_buff[idx & BATADV_LOG_BUFF_MASK];
56ba412080SSven Eckelmann }
57ba412080SSven Eckelmann 
58ba412080SSven Eckelmann static void batadv_emit_log_char(struct batadv_priv_debug_log *debug_log,
59ba412080SSven Eckelmann 				 char c)
60ba412080SSven Eckelmann {
61ba412080SSven Eckelmann 	char *char_addr;
62ba412080SSven Eckelmann 
63ba412080SSven Eckelmann 	char_addr = batadv_log_char_addr(debug_log, debug_log->log_end);
64ba412080SSven Eckelmann 	*char_addr = c;
65ba412080SSven Eckelmann 	debug_log->log_end++;
66ba412080SSven Eckelmann 
67ba412080SSven Eckelmann 	if (debug_log->log_end - debug_log->log_start > batadv_log_buff_len)
68ba412080SSven Eckelmann 		debug_log->log_start = debug_log->log_end - batadv_log_buff_len;
69ba412080SSven Eckelmann }
70ba412080SSven Eckelmann 
71ba412080SSven Eckelmann __printf(2, 3)
72ba412080SSven Eckelmann static int batadv_fdebug_log(struct batadv_priv_debug_log *debug_log,
73ba412080SSven Eckelmann 			     const char *fmt, ...)
74ba412080SSven Eckelmann {
75ba412080SSven Eckelmann 	va_list args;
76ba412080SSven Eckelmann 	static char debug_log_buf[256];
77ba412080SSven Eckelmann 	char *p;
78ba412080SSven Eckelmann 
79ba412080SSven Eckelmann 	if (!debug_log)
80ba412080SSven Eckelmann 		return 0;
81ba412080SSven Eckelmann 
82ba412080SSven Eckelmann 	spin_lock_bh(&debug_log->lock);
83ba412080SSven Eckelmann 	va_start(args, fmt);
84ba412080SSven Eckelmann 	vscnprintf(debug_log_buf, sizeof(debug_log_buf), fmt, args);
85ba412080SSven Eckelmann 	va_end(args);
86ba412080SSven Eckelmann 
87ba412080SSven Eckelmann 	for (p = debug_log_buf; *p != 0; p++)
88ba412080SSven Eckelmann 		batadv_emit_log_char(debug_log, *p);
89ba412080SSven Eckelmann 
90ba412080SSven Eckelmann 	spin_unlock_bh(&debug_log->lock);
91ba412080SSven Eckelmann 
92ba412080SSven Eckelmann 	wake_up(&debug_log->queue_wait);
93ba412080SSven Eckelmann 
94ba412080SSven Eckelmann 	return 0;
95ba412080SSven Eckelmann }
96ba412080SSven Eckelmann 
97ba412080SSven Eckelmann static int batadv_log_open(struct inode *inode, struct file *file)
98ba412080SSven Eckelmann {
99ba412080SSven Eckelmann 	if (!try_module_get(THIS_MODULE))
100ba412080SSven Eckelmann 		return -EBUSY;
101ba412080SSven Eckelmann 
102d331a739SSven Eckelmann 	batadv_debugfs_deprecated(file,
103d331a739SSven Eckelmann 				  "Use tracepoint batadv:batadv_dbg instead\n");
10400caf6a2SSven Eckelmann 
105ba412080SSven Eckelmann 	nonseekable_open(inode, file);
106ba412080SSven Eckelmann 	file->private_data = inode->i_private;
107ba412080SSven Eckelmann 	return 0;
108ba412080SSven Eckelmann }
109ba412080SSven Eckelmann 
110ba412080SSven Eckelmann static int batadv_log_release(struct inode *inode, struct file *file)
111ba412080SSven Eckelmann {
112ba412080SSven Eckelmann 	module_put(THIS_MODULE);
113ba412080SSven Eckelmann 	return 0;
114ba412080SSven Eckelmann }
115ba412080SSven Eckelmann 
116ba412080SSven Eckelmann static bool batadv_log_empty(struct batadv_priv_debug_log *debug_log)
117ba412080SSven Eckelmann {
118ba412080SSven Eckelmann 	return !(debug_log->log_start - debug_log->log_end);
119ba412080SSven Eckelmann }
120ba412080SSven Eckelmann 
121ba412080SSven Eckelmann static ssize_t batadv_log_read(struct file *file, char __user *buf,
122ba412080SSven Eckelmann 			       size_t count, loff_t *ppos)
123ba412080SSven Eckelmann {
124ba412080SSven Eckelmann 	struct batadv_priv *bat_priv = file->private_data;
125ba412080SSven Eckelmann 	struct batadv_priv_debug_log *debug_log = bat_priv->debug_log;
126ba412080SSven Eckelmann 	int error, i = 0;
127ba412080SSven Eckelmann 	char *char_addr;
128ba412080SSven Eckelmann 	char c;
129ba412080SSven Eckelmann 
130ba412080SSven Eckelmann 	if ((file->f_flags & O_NONBLOCK) && batadv_log_empty(debug_log))
131ba412080SSven Eckelmann 		return -EAGAIN;
132ba412080SSven Eckelmann 
133ba412080SSven Eckelmann 	if (!buf)
134ba412080SSven Eckelmann 		return -EINVAL;
135ba412080SSven Eckelmann 
136ba412080SSven Eckelmann 	if (count == 0)
137ba412080SSven Eckelmann 		return 0;
138ba412080SSven Eckelmann 
139ba412080SSven Eckelmann 	if (!access_ok(VERIFY_WRITE, buf, count))
140ba412080SSven Eckelmann 		return -EFAULT;
141ba412080SSven Eckelmann 
142ba412080SSven Eckelmann 	error = wait_event_interruptible(debug_log->queue_wait,
143ba412080SSven Eckelmann 					 (!batadv_log_empty(debug_log)));
144ba412080SSven Eckelmann 
145ba412080SSven Eckelmann 	if (error)
146ba412080SSven Eckelmann 		return error;
147ba412080SSven Eckelmann 
148ba412080SSven Eckelmann 	spin_lock_bh(&debug_log->lock);
149ba412080SSven Eckelmann 
150ba412080SSven Eckelmann 	while ((!error) && (i < count) &&
151ba412080SSven Eckelmann 	       (debug_log->log_start != debug_log->log_end)) {
152ba412080SSven Eckelmann 		char_addr = batadv_log_char_addr(debug_log,
153ba412080SSven Eckelmann 						 debug_log->log_start);
154ba412080SSven Eckelmann 		c = *char_addr;
155ba412080SSven Eckelmann 
156ba412080SSven Eckelmann 		debug_log->log_start++;
157ba412080SSven Eckelmann 
158ba412080SSven Eckelmann 		spin_unlock_bh(&debug_log->lock);
159ba412080SSven Eckelmann 
160ba412080SSven Eckelmann 		error = __put_user(c, buf);
161ba412080SSven Eckelmann 
162ba412080SSven Eckelmann 		spin_lock_bh(&debug_log->lock);
163ba412080SSven Eckelmann 
164ba412080SSven Eckelmann 		buf++;
165ba412080SSven Eckelmann 		i++;
166ba412080SSven Eckelmann 	}
167ba412080SSven Eckelmann 
168ba412080SSven Eckelmann 	spin_unlock_bh(&debug_log->lock);
169ba412080SSven Eckelmann 
170ba412080SSven Eckelmann 	if (!error)
171ba412080SSven Eckelmann 		return i;
172ba412080SSven Eckelmann 
173ba412080SSven Eckelmann 	return error;
174ba412080SSven Eckelmann }
175ba412080SSven Eckelmann 
176ade994f4SAl Viro static __poll_t batadv_log_poll(struct file *file, poll_table *wait)
177ba412080SSven Eckelmann {
178ba412080SSven Eckelmann 	struct batadv_priv *bat_priv = file->private_data;
179ba412080SSven Eckelmann 	struct batadv_priv_debug_log *debug_log = bat_priv->debug_log;
180ba412080SSven Eckelmann 
181ba412080SSven Eckelmann 	poll_wait(file, &debug_log->queue_wait, wait);
182ba412080SSven Eckelmann 
183ba412080SSven Eckelmann 	if (!batadv_log_empty(debug_log))
184a9a08845SLinus Torvalds 		return EPOLLIN | EPOLLRDNORM;
185ba412080SSven Eckelmann 
186ba412080SSven Eckelmann 	return 0;
187ba412080SSven Eckelmann }
188ba412080SSven Eckelmann 
189ba412080SSven Eckelmann static const struct file_operations batadv_log_fops = {
190ba412080SSven Eckelmann 	.open           = batadv_log_open,
191ba412080SSven Eckelmann 	.release        = batadv_log_release,
192ba412080SSven Eckelmann 	.read           = batadv_log_read,
193ba412080SSven Eckelmann 	.poll           = batadv_log_poll,
194ba412080SSven Eckelmann 	.llseek         = no_llseek,
195ba412080SSven Eckelmann };
196ba412080SSven Eckelmann 
197ff15c27cSSven Eckelmann /**
198ff15c27cSSven Eckelmann  * batadv_debug_log_setup() - Initialize debug log
199ff15c27cSSven Eckelmann  * @bat_priv: the bat priv with all the soft interface information
200ff15c27cSSven Eckelmann  *
201ff15c27cSSven Eckelmann  * Return: 0 on success or negative error number in case of failure
202ff15c27cSSven Eckelmann  */
203ba412080SSven Eckelmann int batadv_debug_log_setup(struct batadv_priv *bat_priv)
204ba412080SSven Eckelmann {
205ba412080SSven Eckelmann 	struct dentry *d;
206ba412080SSven Eckelmann 
207ba412080SSven Eckelmann 	if (!bat_priv->debug_dir)
208ba412080SSven Eckelmann 		goto err;
209ba412080SSven Eckelmann 
210ba412080SSven Eckelmann 	bat_priv->debug_log = kzalloc(sizeof(*bat_priv->debug_log), GFP_ATOMIC);
211ba412080SSven Eckelmann 	if (!bat_priv->debug_log)
212ba412080SSven Eckelmann 		goto err;
213ba412080SSven Eckelmann 
214ba412080SSven Eckelmann 	spin_lock_init(&bat_priv->debug_log->lock);
215ba412080SSven Eckelmann 	init_waitqueue_head(&bat_priv->debug_log->queue_wait);
216ba412080SSven Eckelmann 
217507b37cfSSven Eckelmann 	d = debugfs_create_file("log", 0400, bat_priv->debug_dir, bat_priv,
218ba412080SSven Eckelmann 				&batadv_log_fops);
219ba412080SSven Eckelmann 	if (!d)
220ba412080SSven Eckelmann 		goto err;
221ba412080SSven Eckelmann 
222ba412080SSven Eckelmann 	return 0;
223ba412080SSven Eckelmann 
224ba412080SSven Eckelmann err:
225ba412080SSven Eckelmann 	return -ENOMEM;
226ba412080SSven Eckelmann }
227ba412080SSven Eckelmann 
228ff15c27cSSven Eckelmann /**
229ff15c27cSSven Eckelmann  * batadv_debug_log_cleanup() - Destroy debug log
230ff15c27cSSven Eckelmann  * @bat_priv: the bat priv with all the soft interface information
231ff15c27cSSven Eckelmann  */
232ba412080SSven Eckelmann void batadv_debug_log_cleanup(struct batadv_priv *bat_priv)
233ba412080SSven Eckelmann {
234ba412080SSven Eckelmann 	kfree(bat_priv->debug_log);
235ba412080SSven Eckelmann 	bat_priv->debug_log = NULL;
236ba412080SSven Eckelmann }
237*0dacc7faSSven Eckelmann 
238*0dacc7faSSven Eckelmann #endif /* CONFIG_BATMAN_ADV_DEBUGFS */
239*0dacc7faSSven Eckelmann 
240*0dacc7faSSven Eckelmann /**
241*0dacc7faSSven Eckelmann  * batadv_debug_log() - Add debug log entry
242*0dacc7faSSven Eckelmann  * @bat_priv: the bat priv with all the soft interface information
243*0dacc7faSSven Eckelmann  * @fmt: format string
244*0dacc7faSSven Eckelmann  *
245*0dacc7faSSven Eckelmann  * Return: 0 on success or negative error number in case of failure
246*0dacc7faSSven Eckelmann  */
247*0dacc7faSSven Eckelmann int batadv_debug_log(struct batadv_priv *bat_priv, const char *fmt, ...)
248*0dacc7faSSven Eckelmann {
249*0dacc7faSSven Eckelmann 	struct va_format vaf;
250*0dacc7faSSven Eckelmann 	va_list args;
251*0dacc7faSSven Eckelmann 
252*0dacc7faSSven Eckelmann 	va_start(args, fmt);
253*0dacc7faSSven Eckelmann 
254*0dacc7faSSven Eckelmann 	vaf.fmt = fmt;
255*0dacc7faSSven Eckelmann 	vaf.va = &args;
256*0dacc7faSSven Eckelmann 
257*0dacc7faSSven Eckelmann #ifdef CONFIG_BATMAN_ADV_DEBUGFS
258*0dacc7faSSven Eckelmann 	batadv_fdebug_log(bat_priv->debug_log, "[%10u] %pV",
259*0dacc7faSSven Eckelmann 			  jiffies_to_msecs(jiffies), &vaf);
260*0dacc7faSSven Eckelmann #endif
261*0dacc7faSSven Eckelmann 
262*0dacc7faSSven Eckelmann 	trace_batadv_dbg(bat_priv, &vaf);
263*0dacc7faSSven Eckelmann 
264*0dacc7faSSven Eckelmann 	va_end(args);
265*0dacc7faSSven Eckelmann 
266*0dacc7faSSven Eckelmann 	return 0;
267*0dacc7faSSven Eckelmann }
268