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