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