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