root/net/batman-adv/log.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. batadv_log_char_addr
  2. batadv_emit_log_char
  3. __printf
  4. batadv_log_open
  5. batadv_log_release
  6. batadv_log_empty
  7. batadv_log_read
  8. batadv_log_poll
  9. batadv_debug_log_setup
  10. batadv_debug_log_cleanup
  11. batadv_debug_log

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

/* [<][>][^][v][top][bottom][index][help] */