Logo Search packages:      
Sourcecode: batman-adv version File versions

log.c

/*
 * Copyright (C) 2007-2008 B.A.T.M.A.N. contributors:
 * Marek Lindner, Simon Wunderlich
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of version 2 of the GNU General Public
 * License as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 * 02110-1301, USA
 *
 */





#include "main.h"
#include "log.h"


#define LOG_BUF_MASK (log_buf_len-1)
#define LOG_BUF(idx) (log_buf[(idx) & LOG_BUF_MASK])



static char log_buf[LOG_BUF_LEN];
static int log_buf_len = LOG_BUF_LEN;
static unsigned long log_start = 0;
static unsigned long log_end = 0;
volatile uint8_t log_level = 0;

static DEFINE_SPINLOCK(logbuf_lock);

struct file_operations proc_log_operations = {
      .open           = log_open,
      .release        = log_release,
      .read           = log_read,
      .write          = log_write,
      .poll           = log_poll,
};

static DECLARE_WAIT_QUEUE_HEAD(log_wait);


static void emit_log_char(char c)
{
      LOG_BUF(log_end) = c;
      log_end++;

      if (log_end - log_start > log_buf_len)
            log_start = log_end - log_buf_len;
}

static int fdebug_log(char *fmt, ...)
{
      int printed_len;
      char *p;
      va_list args;
      static char debug_log_buf[256];
      unsigned long flags;

      spin_lock_irqsave(&logbuf_lock, flags);
      va_start(args, fmt);
      printed_len = vscnprintf(debug_log_buf, sizeof(debug_log_buf), fmt, args);
      va_end(args);

      for (p = debug_log_buf; *p != 0; p++)
            emit_log_char(*p);

      spin_unlock_irqrestore(&logbuf_lock, flags);

      wake_up(&log_wait);

      return 0;
}


int debug_log(int type, char *fmt, ...)
{
      va_list args;
      int retval = 0;
      char tmp_log_buf[256];

      /* only critical information get into the official kernel log */
      if (type == LOG_TYPE_CRIT) {
            va_start(args, fmt);
            vscnprintf(tmp_log_buf, sizeof(tmp_log_buf), fmt, args);
            printk("batman-adv: %s", tmp_log_buf);
            va_end(args);
      }

      if ((type == LOG_TYPE_CRIT) || (log_level & type)) {
            va_start(args, fmt);
            vscnprintf(tmp_log_buf, sizeof(tmp_log_buf), fmt, args);
            fdebug_log("[%10u] %s", (jiffies / HZ), tmp_log_buf);
            va_end(args);
      }

      return retval;
}

int log_open(struct inode * inode, struct file * file)
{
      inc_module_count();
      return 0;
}

int log_release(struct inode * inode, struct file * file)
{
      dec_module_count();
      return 0;
}

ssize_t log_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
{
      int error, i = 0;
      char c;
      unsigned long flags;

      if ((file->f_flags & O_NONBLOCK) && !(log_end - log_start))
            return -EAGAIN;

      if ((!buf) || (count < 0))
            return -EINVAL;

      if (count == 0)
            return 0;

      if (!access_ok(VERIFY_WRITE, buf, count))
            return -EFAULT;

      error = wait_event_interruptible(log_wait, (log_start - log_end));

      if (error)
            return error;

      spin_lock_irqsave(&logbuf_lock, flags);

      while ((!error) && (log_start != log_end) && (i < count)) {
            c = LOG_BUF(log_start);

            log_start++;

            spin_unlock(&logbuf_lock);

            error = __put_user(c,buf);

            buf++;
            i++;

            spin_lock(&logbuf_lock);
      }

      spin_unlock_irqrestore(&logbuf_lock, flags);

      if (!error)
            return i;

      return error;
}

ssize_t log_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
{
      return count;
}

unsigned int log_poll(struct file *file, poll_table *wait)
{
      poll_wait(file, &log_wait, wait);

      if (log_end - log_start)
            return POLLIN | POLLRDNORM;

      return 0;
}


Generated by  Doxygen 1.6.0   Back to index