xref: /linux/net/batman-adv/log.c (revision d331a739949992043b135fcfba649196b397ec3b)
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"
44*d331a739SSven Eckelmann #include "trace.h"
4500caf6a2SSven Eckelmann 
46ba412080SSven Eckelmann #define BATADV_LOG_BUFF_MASK (batadv_log_buff_len - 1)
47ba412080SSven Eckelmann 
48ba412080SSven Eckelmann static const int batadv_log_buff_len = BATADV_LOG_BUF_LEN;
49ba412080SSven Eckelmann 
50ba412080SSven Eckelmann static char *batadv_log_char_addr(struct batadv_priv_debug_log *debug_log,
51ba412080SSven Eckelmann 				  size_t idx)
52ba412080SSven Eckelmann {
53ba412080SSven Eckelmann 	return &debug_log->log_buff[idx & BATADV_LOG_BUFF_MASK];
54ba412080SSven Eckelmann }
55ba412080SSven Eckelmann 
56ba412080SSven Eckelmann static void batadv_emit_log_char(struct batadv_priv_debug_log *debug_log,
57ba412080SSven Eckelmann 				 char c)
58ba412080SSven Eckelmann {
59ba412080SSven Eckelmann 	char *char_addr;
60ba412080SSven Eckelmann 
61ba412080SSven Eckelmann 	char_addr = batadv_log_char_addr(debug_log, debug_log->log_end);
62ba412080SSven Eckelmann 	*char_addr = c;
63ba412080SSven Eckelmann 	debug_log->log_end++;
64ba412080SSven Eckelmann 
65ba412080SSven Eckelmann 	if (debug_log->log_end - debug_log->log_start > batadv_log_buff_len)
66ba412080SSven Eckelmann 		debug_log->log_start = debug_log->log_end - batadv_log_buff_len;
67ba412080SSven Eckelmann }
68ba412080SSven Eckelmann 
69ba412080SSven Eckelmann __printf(2, 3)
70ba412080SSven Eckelmann static int batadv_fdebug_log(struct batadv_priv_debug_log *debug_log,
71ba412080SSven Eckelmann 			     const char *fmt, ...)
72ba412080SSven Eckelmann {
73ba412080SSven Eckelmann 	va_list args;
74ba412080SSven Eckelmann 	static char debug_log_buf[256];
75ba412080SSven Eckelmann 	char *p;
76ba412080SSven Eckelmann 
77ba412080SSven Eckelmann 	if (!debug_log)
78ba412080SSven Eckelmann 		return 0;
79ba412080SSven Eckelmann 
80ba412080SSven Eckelmann 	spin_lock_bh(&debug_log->lock);
81ba412080SSven Eckelmann 	va_start(args, fmt);
82ba412080SSven Eckelmann 	vscnprintf(debug_log_buf, sizeof(debug_log_buf), fmt, args);
83ba412080SSven Eckelmann 	va_end(args);
84ba412080SSven Eckelmann 
85ba412080SSven Eckelmann 	for (p = debug_log_buf; *p != 0; p++)
86ba412080SSven Eckelmann 		batadv_emit_log_char(debug_log, *p);
87ba412080SSven Eckelmann 
88ba412080SSven Eckelmann 	spin_unlock_bh(&debug_log->lock);
89ba412080SSven Eckelmann 
90ba412080SSven Eckelmann 	wake_up(&debug_log->queue_wait);
91ba412080SSven Eckelmann 
92ba412080SSven Eckelmann 	return 0;
93ba412080SSven Eckelmann }
94ba412080SSven Eckelmann 
95ff15c27cSSven Eckelmann /**
96ff15c27cSSven Eckelmann  * batadv_debug_log() - Add debug log entry
97ff15c27cSSven Eckelmann  * @bat_priv: the bat priv with all the soft interface information
98ff15c27cSSven Eckelmann  * @fmt: format string
99ff15c27cSSven Eckelmann  *
100ff15c27cSSven Eckelmann  * Return: 0 on success or negative error number in case of failure
101ff15c27cSSven Eckelmann  */
102ba412080SSven Eckelmann int batadv_debug_log(struct batadv_priv *bat_priv, const char *fmt, ...)
103ba412080SSven Eckelmann {
104*d331a739SSven Eckelmann 	struct va_format vaf;
105ba412080SSven Eckelmann 	va_list args;
106ba412080SSven Eckelmann 
107ba412080SSven Eckelmann 	va_start(args, fmt);
108*d331a739SSven Eckelmann 
109*d331a739SSven Eckelmann 	vaf.fmt = fmt;
110*d331a739SSven Eckelmann 	vaf.va = &args;
111*d331a739SSven Eckelmann 
112*d331a739SSven Eckelmann 	batadv_fdebug_log(bat_priv->debug_log, "[%10u] %pV",
113*d331a739SSven Eckelmann 			  jiffies_to_msecs(jiffies), &vaf);
114*d331a739SSven Eckelmann 
115*d331a739SSven Eckelmann 	trace_batadv_dbg(bat_priv, &vaf);
116*d331a739SSven Eckelmann 
117ba412080SSven Eckelmann 	va_end(args);
118ba412080SSven Eckelmann 
119ba412080SSven Eckelmann 	return 0;
120ba412080SSven Eckelmann }
121ba412080SSven Eckelmann 
122ba412080SSven Eckelmann static int batadv_log_open(struct inode *inode, struct file *file)
123ba412080SSven Eckelmann {
124ba412080SSven Eckelmann 	if (!try_module_get(THIS_MODULE))
125ba412080SSven Eckelmann 		return -EBUSY;
126ba412080SSven Eckelmann 
127*d331a739SSven Eckelmann 	batadv_debugfs_deprecated(file,
128*d331a739SSven Eckelmann 				  "Use tracepoint batadv:batadv_dbg instead\n");
12900caf6a2SSven Eckelmann 
130ba412080SSven Eckelmann 	nonseekable_open(inode, file);
131ba412080SSven Eckelmann 	file->private_data = inode->i_private;
132ba412080SSven Eckelmann 	return 0;
133ba412080SSven Eckelmann }
134ba412080SSven Eckelmann 
135ba412080SSven Eckelmann static int batadv_log_release(struct inode *inode, struct file *file)
136ba412080SSven Eckelmann {
137ba412080SSven Eckelmann 	module_put(THIS_MODULE);
138ba412080SSven Eckelmann 	return 0;
139ba412080SSven Eckelmann }
140ba412080SSven Eckelmann 
141ba412080SSven Eckelmann static bool batadv_log_empty(struct batadv_priv_debug_log *debug_log)
142ba412080SSven Eckelmann {
143ba412080SSven Eckelmann 	return !(debug_log->log_start - debug_log->log_end);
144ba412080SSven Eckelmann }
145ba412080SSven Eckelmann 
146ba412080SSven Eckelmann static ssize_t batadv_log_read(struct file *file, char __user *buf,
147ba412080SSven Eckelmann 			       size_t count, loff_t *ppos)
148ba412080SSven Eckelmann {
149ba412080SSven Eckelmann 	struct batadv_priv *bat_priv = file->private_data;
150ba412080SSven Eckelmann 	struct batadv_priv_debug_log *debug_log = bat_priv->debug_log;
151ba412080SSven Eckelmann 	int error, i = 0;
152ba412080SSven Eckelmann 	char *char_addr;
153ba412080SSven Eckelmann 	char c;
154ba412080SSven Eckelmann 
155ba412080SSven Eckelmann 	if ((file->f_flags & O_NONBLOCK) && batadv_log_empty(debug_log))
156ba412080SSven Eckelmann 		return -EAGAIN;
157ba412080SSven Eckelmann 
158ba412080SSven Eckelmann 	if (!buf)
159ba412080SSven Eckelmann 		return -EINVAL;
160ba412080SSven Eckelmann 
161ba412080SSven Eckelmann 	if (count == 0)
162ba412080SSven Eckelmann 		return 0;
163ba412080SSven Eckelmann 
164ba412080SSven Eckelmann 	if (!access_ok(VERIFY_WRITE, buf, count))
165ba412080SSven Eckelmann 		return -EFAULT;
166ba412080SSven Eckelmann 
167ba412080SSven Eckelmann 	error = wait_event_interruptible(debug_log->queue_wait,
168ba412080SSven Eckelmann 					 (!batadv_log_empty(debug_log)));
169ba412080SSven Eckelmann 
170ba412080SSven Eckelmann 	if (error)
171ba412080SSven Eckelmann 		return error;
172ba412080SSven Eckelmann 
173ba412080SSven Eckelmann 	spin_lock_bh(&debug_log->lock);
174ba412080SSven Eckelmann 
175ba412080SSven Eckelmann 	while ((!error) && (i < count) &&
176ba412080SSven Eckelmann 	       (debug_log->log_start != debug_log->log_end)) {
177ba412080SSven Eckelmann 		char_addr = batadv_log_char_addr(debug_log,
178ba412080SSven Eckelmann 						 debug_log->log_start);
179ba412080SSven Eckelmann 		c = *char_addr;
180ba412080SSven Eckelmann 
181ba412080SSven Eckelmann 		debug_log->log_start++;
182ba412080SSven Eckelmann 
183ba412080SSven Eckelmann 		spin_unlock_bh(&debug_log->lock);
184ba412080SSven Eckelmann 
185ba412080SSven Eckelmann 		error = __put_user(c, buf);
186ba412080SSven Eckelmann 
187ba412080SSven Eckelmann 		spin_lock_bh(&debug_log->lock);
188ba412080SSven Eckelmann 
189ba412080SSven Eckelmann 		buf++;
190ba412080SSven Eckelmann 		i++;
191ba412080SSven Eckelmann 	}
192ba412080SSven Eckelmann 
193ba412080SSven Eckelmann 	spin_unlock_bh(&debug_log->lock);
194ba412080SSven Eckelmann 
195ba412080SSven Eckelmann 	if (!error)
196ba412080SSven Eckelmann 		return i;
197ba412080SSven Eckelmann 
198ba412080SSven Eckelmann 	return error;
199ba412080SSven Eckelmann }
200ba412080SSven Eckelmann 
201ade994f4SAl Viro static __poll_t batadv_log_poll(struct file *file, poll_table *wait)
202ba412080SSven Eckelmann {
203ba412080SSven Eckelmann 	struct batadv_priv *bat_priv = file->private_data;
204ba412080SSven Eckelmann 	struct batadv_priv_debug_log *debug_log = bat_priv->debug_log;
205ba412080SSven Eckelmann 
206ba412080SSven Eckelmann 	poll_wait(file, &debug_log->queue_wait, wait);
207ba412080SSven Eckelmann 
208ba412080SSven Eckelmann 	if (!batadv_log_empty(debug_log))
209a9a08845SLinus Torvalds 		return EPOLLIN | EPOLLRDNORM;
210ba412080SSven Eckelmann 
211ba412080SSven Eckelmann 	return 0;
212ba412080SSven Eckelmann }
213ba412080SSven Eckelmann 
214ba412080SSven Eckelmann static const struct file_operations batadv_log_fops = {
215ba412080SSven Eckelmann 	.open           = batadv_log_open,
216ba412080SSven Eckelmann 	.release        = batadv_log_release,
217ba412080SSven Eckelmann 	.read           = batadv_log_read,
218ba412080SSven Eckelmann 	.poll           = batadv_log_poll,
219ba412080SSven Eckelmann 	.llseek         = no_llseek,
220ba412080SSven Eckelmann };
221ba412080SSven Eckelmann 
222ff15c27cSSven Eckelmann /**
223ff15c27cSSven Eckelmann  * batadv_debug_log_setup() - Initialize debug log
224ff15c27cSSven Eckelmann  * @bat_priv: the bat priv with all the soft interface information
225ff15c27cSSven Eckelmann  *
226ff15c27cSSven Eckelmann  * Return: 0 on success or negative error number in case of failure
227ff15c27cSSven Eckelmann  */
228ba412080SSven Eckelmann int batadv_debug_log_setup(struct batadv_priv *bat_priv)
229ba412080SSven Eckelmann {
230ba412080SSven Eckelmann 	struct dentry *d;
231ba412080SSven Eckelmann 
232ba412080SSven Eckelmann 	if (!bat_priv->debug_dir)
233ba412080SSven Eckelmann 		goto err;
234ba412080SSven Eckelmann 
235ba412080SSven Eckelmann 	bat_priv->debug_log = kzalloc(sizeof(*bat_priv->debug_log), GFP_ATOMIC);
236ba412080SSven Eckelmann 	if (!bat_priv->debug_log)
237ba412080SSven Eckelmann 		goto err;
238ba412080SSven Eckelmann 
239ba412080SSven Eckelmann 	spin_lock_init(&bat_priv->debug_log->lock);
240ba412080SSven Eckelmann 	init_waitqueue_head(&bat_priv->debug_log->queue_wait);
241ba412080SSven Eckelmann 
242507b37cfSSven Eckelmann 	d = debugfs_create_file("log", 0400, bat_priv->debug_dir, bat_priv,
243ba412080SSven Eckelmann 				&batadv_log_fops);
244ba412080SSven Eckelmann 	if (!d)
245ba412080SSven Eckelmann 		goto err;
246ba412080SSven Eckelmann 
247ba412080SSven Eckelmann 	return 0;
248ba412080SSven Eckelmann 
249ba412080SSven Eckelmann err:
250ba412080SSven Eckelmann 	return -ENOMEM;
251ba412080SSven Eckelmann }
252ba412080SSven Eckelmann 
253ff15c27cSSven Eckelmann /**
254ff15c27cSSven Eckelmann  * batadv_debug_log_cleanup() - Destroy debug log
255ff15c27cSSven Eckelmann  * @bat_priv: the bat priv with all the soft interface information
256ff15c27cSSven Eckelmann  */
257ba412080SSven Eckelmann void batadv_debug_log_cleanup(struct batadv_priv *bat_priv)
258ba412080SSven Eckelmann {
259ba412080SSven Eckelmann 	kfree(bat_priv->debug_log);
260ba412080SSven Eckelmann 	bat_priv->debug_log = NULL;
261ba412080SSven Eckelmann }
262