xref: /linux/net/batman-adv/log.c (revision ba412080fb6461b5a40dbc5e44186ed029d67b8d)
1*ba412080SSven Eckelmann /* Copyright (C) 2010-2016  B.A.T.M.A.N. contributors:
2*ba412080SSven Eckelmann  *
3*ba412080SSven Eckelmann  * Marek Lindner
4*ba412080SSven Eckelmann  *
5*ba412080SSven Eckelmann  * This program is free software; you can redistribute it and/or
6*ba412080SSven Eckelmann  * modify it under the terms of version 2 of the GNU General Public
7*ba412080SSven Eckelmann  * License as published by the Free Software Foundation.
8*ba412080SSven Eckelmann  *
9*ba412080SSven Eckelmann  * This program is distributed in the hope that it will be useful, but
10*ba412080SSven Eckelmann  * WITHOUT ANY WARRANTY; without even the implied warranty of
11*ba412080SSven Eckelmann  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12*ba412080SSven Eckelmann  * General Public License for more details.
13*ba412080SSven Eckelmann  *
14*ba412080SSven Eckelmann  * You should have received a copy of the GNU General Public License
15*ba412080SSven Eckelmann  * along with this program; if not, see <http://www.gnu.org/licenses/>.
16*ba412080SSven Eckelmann  */
17*ba412080SSven Eckelmann 
18*ba412080SSven Eckelmann #include "log.h"
19*ba412080SSven Eckelmann #include "main.h"
20*ba412080SSven Eckelmann 
21*ba412080SSven Eckelmann #include <linux/compiler.h>
22*ba412080SSven Eckelmann #include <linux/debugfs.h>
23*ba412080SSven Eckelmann #include <linux/errno.h>
24*ba412080SSven Eckelmann #include <linux/export.h>
25*ba412080SSven Eckelmann #include <linux/fcntl.h>
26*ba412080SSven Eckelmann #include <linux/fs.h>
27*ba412080SSven Eckelmann #include <linux/jiffies.h>
28*ba412080SSven Eckelmann #include <linux/kernel.h>
29*ba412080SSven Eckelmann #include <linux/module.h>
30*ba412080SSven Eckelmann #include <linux/poll.h>
31*ba412080SSven Eckelmann #include <linux/sched.h> /* for linux/wait.h */
32*ba412080SSven Eckelmann #include <linux/slab.h>
33*ba412080SSven Eckelmann #include <linux/spinlock.h>
34*ba412080SSven Eckelmann #include <linux/stat.h>
35*ba412080SSven Eckelmann #include <linux/stddef.h>
36*ba412080SSven Eckelmann #include <linux/types.h>
37*ba412080SSven Eckelmann #include <linux/uaccess.h>
38*ba412080SSven Eckelmann #include <linux/wait.h>
39*ba412080SSven Eckelmann #include <stdarg.h>
40*ba412080SSven Eckelmann 
41*ba412080SSven Eckelmann #define BATADV_LOG_BUFF_MASK (batadv_log_buff_len - 1)
42*ba412080SSven Eckelmann 
43*ba412080SSven Eckelmann static const int batadv_log_buff_len = BATADV_LOG_BUF_LEN;
44*ba412080SSven Eckelmann 
45*ba412080SSven Eckelmann static char *batadv_log_char_addr(struct batadv_priv_debug_log *debug_log,
46*ba412080SSven Eckelmann 				  size_t idx)
47*ba412080SSven Eckelmann {
48*ba412080SSven Eckelmann 	return &debug_log->log_buff[idx & BATADV_LOG_BUFF_MASK];
49*ba412080SSven Eckelmann }
50*ba412080SSven Eckelmann 
51*ba412080SSven Eckelmann static void batadv_emit_log_char(struct batadv_priv_debug_log *debug_log,
52*ba412080SSven Eckelmann 				 char c)
53*ba412080SSven Eckelmann {
54*ba412080SSven Eckelmann 	char *char_addr;
55*ba412080SSven Eckelmann 
56*ba412080SSven Eckelmann 	char_addr = batadv_log_char_addr(debug_log, debug_log->log_end);
57*ba412080SSven Eckelmann 	*char_addr = c;
58*ba412080SSven Eckelmann 	debug_log->log_end++;
59*ba412080SSven Eckelmann 
60*ba412080SSven Eckelmann 	if (debug_log->log_end - debug_log->log_start > batadv_log_buff_len)
61*ba412080SSven Eckelmann 		debug_log->log_start = debug_log->log_end - batadv_log_buff_len;
62*ba412080SSven Eckelmann }
63*ba412080SSven Eckelmann 
64*ba412080SSven Eckelmann __printf(2, 3)
65*ba412080SSven Eckelmann static int batadv_fdebug_log(struct batadv_priv_debug_log *debug_log,
66*ba412080SSven Eckelmann 			     const char *fmt, ...)
67*ba412080SSven Eckelmann {
68*ba412080SSven Eckelmann 	va_list args;
69*ba412080SSven Eckelmann 	static char debug_log_buf[256];
70*ba412080SSven Eckelmann 	char *p;
71*ba412080SSven Eckelmann 
72*ba412080SSven Eckelmann 	if (!debug_log)
73*ba412080SSven Eckelmann 		return 0;
74*ba412080SSven Eckelmann 
75*ba412080SSven Eckelmann 	spin_lock_bh(&debug_log->lock);
76*ba412080SSven Eckelmann 	va_start(args, fmt);
77*ba412080SSven Eckelmann 	vscnprintf(debug_log_buf, sizeof(debug_log_buf), fmt, args);
78*ba412080SSven Eckelmann 	va_end(args);
79*ba412080SSven Eckelmann 
80*ba412080SSven Eckelmann 	for (p = debug_log_buf; *p != 0; p++)
81*ba412080SSven Eckelmann 		batadv_emit_log_char(debug_log, *p);
82*ba412080SSven Eckelmann 
83*ba412080SSven Eckelmann 	spin_unlock_bh(&debug_log->lock);
84*ba412080SSven Eckelmann 
85*ba412080SSven Eckelmann 	wake_up(&debug_log->queue_wait);
86*ba412080SSven Eckelmann 
87*ba412080SSven Eckelmann 	return 0;
88*ba412080SSven Eckelmann }
89*ba412080SSven Eckelmann 
90*ba412080SSven Eckelmann int batadv_debug_log(struct batadv_priv *bat_priv, const char *fmt, ...)
91*ba412080SSven Eckelmann {
92*ba412080SSven Eckelmann 	va_list args;
93*ba412080SSven Eckelmann 	char tmp_log_buf[256];
94*ba412080SSven Eckelmann 
95*ba412080SSven Eckelmann 	va_start(args, fmt);
96*ba412080SSven Eckelmann 	vscnprintf(tmp_log_buf, sizeof(tmp_log_buf), fmt, args);
97*ba412080SSven Eckelmann 	batadv_fdebug_log(bat_priv->debug_log, "[%10u] %s",
98*ba412080SSven Eckelmann 			  jiffies_to_msecs(jiffies), tmp_log_buf);
99*ba412080SSven Eckelmann 	va_end(args);
100*ba412080SSven Eckelmann 
101*ba412080SSven Eckelmann 	return 0;
102*ba412080SSven Eckelmann }
103*ba412080SSven Eckelmann 
104*ba412080SSven Eckelmann static int batadv_log_open(struct inode *inode, struct file *file)
105*ba412080SSven Eckelmann {
106*ba412080SSven Eckelmann 	if (!try_module_get(THIS_MODULE))
107*ba412080SSven Eckelmann 		return -EBUSY;
108*ba412080SSven Eckelmann 
109*ba412080SSven Eckelmann 	nonseekable_open(inode, file);
110*ba412080SSven Eckelmann 	file->private_data = inode->i_private;
111*ba412080SSven Eckelmann 	return 0;
112*ba412080SSven Eckelmann }
113*ba412080SSven Eckelmann 
114*ba412080SSven Eckelmann static int batadv_log_release(struct inode *inode, struct file *file)
115*ba412080SSven Eckelmann {
116*ba412080SSven Eckelmann 	module_put(THIS_MODULE);
117*ba412080SSven Eckelmann 	return 0;
118*ba412080SSven Eckelmann }
119*ba412080SSven Eckelmann 
120*ba412080SSven Eckelmann static bool batadv_log_empty(struct batadv_priv_debug_log *debug_log)
121*ba412080SSven Eckelmann {
122*ba412080SSven Eckelmann 	return !(debug_log->log_start - debug_log->log_end);
123*ba412080SSven Eckelmann }
124*ba412080SSven Eckelmann 
125*ba412080SSven Eckelmann static ssize_t batadv_log_read(struct file *file, char __user *buf,
126*ba412080SSven Eckelmann 			       size_t count, loff_t *ppos)
127*ba412080SSven Eckelmann {
128*ba412080SSven Eckelmann 	struct batadv_priv *bat_priv = file->private_data;
129*ba412080SSven Eckelmann 	struct batadv_priv_debug_log *debug_log = bat_priv->debug_log;
130*ba412080SSven Eckelmann 	int error, i = 0;
131*ba412080SSven Eckelmann 	char *char_addr;
132*ba412080SSven Eckelmann 	char c;
133*ba412080SSven Eckelmann 
134*ba412080SSven Eckelmann 	if ((file->f_flags & O_NONBLOCK) && batadv_log_empty(debug_log))
135*ba412080SSven Eckelmann 		return -EAGAIN;
136*ba412080SSven Eckelmann 
137*ba412080SSven Eckelmann 	if (!buf)
138*ba412080SSven Eckelmann 		return -EINVAL;
139*ba412080SSven Eckelmann 
140*ba412080SSven Eckelmann 	if (count == 0)
141*ba412080SSven Eckelmann 		return 0;
142*ba412080SSven Eckelmann 
143*ba412080SSven Eckelmann 	if (!access_ok(VERIFY_WRITE, buf, count))
144*ba412080SSven Eckelmann 		return -EFAULT;
145*ba412080SSven Eckelmann 
146*ba412080SSven Eckelmann 	error = wait_event_interruptible(debug_log->queue_wait,
147*ba412080SSven Eckelmann 					 (!batadv_log_empty(debug_log)));
148*ba412080SSven Eckelmann 
149*ba412080SSven Eckelmann 	if (error)
150*ba412080SSven Eckelmann 		return error;
151*ba412080SSven Eckelmann 
152*ba412080SSven Eckelmann 	spin_lock_bh(&debug_log->lock);
153*ba412080SSven Eckelmann 
154*ba412080SSven Eckelmann 	while ((!error) && (i < count) &&
155*ba412080SSven Eckelmann 	       (debug_log->log_start != debug_log->log_end)) {
156*ba412080SSven Eckelmann 		char_addr = batadv_log_char_addr(debug_log,
157*ba412080SSven Eckelmann 						 debug_log->log_start);
158*ba412080SSven Eckelmann 		c = *char_addr;
159*ba412080SSven Eckelmann 
160*ba412080SSven Eckelmann 		debug_log->log_start++;
161*ba412080SSven Eckelmann 
162*ba412080SSven Eckelmann 		spin_unlock_bh(&debug_log->lock);
163*ba412080SSven Eckelmann 
164*ba412080SSven Eckelmann 		error = __put_user(c, buf);
165*ba412080SSven Eckelmann 
166*ba412080SSven Eckelmann 		spin_lock_bh(&debug_log->lock);
167*ba412080SSven Eckelmann 
168*ba412080SSven Eckelmann 		buf++;
169*ba412080SSven Eckelmann 		i++;
170*ba412080SSven Eckelmann 	}
171*ba412080SSven Eckelmann 
172*ba412080SSven Eckelmann 	spin_unlock_bh(&debug_log->lock);
173*ba412080SSven Eckelmann 
174*ba412080SSven Eckelmann 	if (!error)
175*ba412080SSven Eckelmann 		return i;
176*ba412080SSven Eckelmann 
177*ba412080SSven Eckelmann 	return error;
178*ba412080SSven Eckelmann }
179*ba412080SSven Eckelmann 
180*ba412080SSven Eckelmann static unsigned int batadv_log_poll(struct file *file, poll_table *wait)
181*ba412080SSven Eckelmann {
182*ba412080SSven Eckelmann 	struct batadv_priv *bat_priv = file->private_data;
183*ba412080SSven Eckelmann 	struct batadv_priv_debug_log *debug_log = bat_priv->debug_log;
184*ba412080SSven Eckelmann 
185*ba412080SSven Eckelmann 	poll_wait(file, &debug_log->queue_wait, wait);
186*ba412080SSven Eckelmann 
187*ba412080SSven Eckelmann 	if (!batadv_log_empty(debug_log))
188*ba412080SSven Eckelmann 		return POLLIN | POLLRDNORM;
189*ba412080SSven Eckelmann 
190*ba412080SSven Eckelmann 	return 0;
191*ba412080SSven Eckelmann }
192*ba412080SSven Eckelmann 
193*ba412080SSven Eckelmann static const struct file_operations batadv_log_fops = {
194*ba412080SSven Eckelmann 	.open           = batadv_log_open,
195*ba412080SSven Eckelmann 	.release        = batadv_log_release,
196*ba412080SSven Eckelmann 	.read           = batadv_log_read,
197*ba412080SSven Eckelmann 	.poll           = batadv_log_poll,
198*ba412080SSven Eckelmann 	.llseek         = no_llseek,
199*ba412080SSven Eckelmann };
200*ba412080SSven Eckelmann 
201*ba412080SSven Eckelmann int batadv_debug_log_setup(struct batadv_priv *bat_priv)
202*ba412080SSven Eckelmann {
203*ba412080SSven Eckelmann 	struct dentry *d;
204*ba412080SSven Eckelmann 
205*ba412080SSven Eckelmann 	if (!bat_priv->debug_dir)
206*ba412080SSven Eckelmann 		goto err;
207*ba412080SSven Eckelmann 
208*ba412080SSven Eckelmann 	bat_priv->debug_log = kzalloc(sizeof(*bat_priv->debug_log), GFP_ATOMIC);
209*ba412080SSven Eckelmann 	if (!bat_priv->debug_log)
210*ba412080SSven Eckelmann 		goto err;
211*ba412080SSven Eckelmann 
212*ba412080SSven Eckelmann 	spin_lock_init(&bat_priv->debug_log->lock);
213*ba412080SSven Eckelmann 	init_waitqueue_head(&bat_priv->debug_log->queue_wait);
214*ba412080SSven Eckelmann 
215*ba412080SSven Eckelmann 	d = debugfs_create_file("log", S_IFREG | S_IRUSR,
216*ba412080SSven Eckelmann 				bat_priv->debug_dir, bat_priv,
217*ba412080SSven Eckelmann 				&batadv_log_fops);
218*ba412080SSven Eckelmann 	if (!d)
219*ba412080SSven Eckelmann 		goto err;
220*ba412080SSven Eckelmann 
221*ba412080SSven Eckelmann 	return 0;
222*ba412080SSven Eckelmann 
223*ba412080SSven Eckelmann err:
224*ba412080SSven Eckelmann 	return -ENOMEM;
225*ba412080SSven Eckelmann }
226*ba412080SSven Eckelmann 
227*ba412080SSven Eckelmann void batadv_debug_log_cleanup(struct batadv_priv *bat_priv)
228*ba412080SSven Eckelmann {
229*ba412080SSven Eckelmann 	kfree(bat_priv->debug_log);
230*ba412080SSven Eckelmann 	bat_priv->debug_log = NULL;
231*ba412080SSven Eckelmann }
232