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