Skip to content

Commit

Permalink
staging: android: logger: Allocate logs dynamically at boot (v3)
Browse files Browse the repository at this point in the history
This changes the log initialization to be dynamic, but still
at boot time.  These changes are a predecessor to implementing
runtime allocation and freeing of logs, to make the Android logger
less hard-coded.

Change from a fixed set of static log structures, to allocation
at init time into a list.  Return proper error numbers on log
allocation failure.

Cc: Brian Swetland <swetland@google.com>
Signed-off-by: Tim Bird <tim.bird@am.sony.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
Tim Bird authored and Greg Kroah-Hartman committed May 10, 2012
1 parent 9a0fbbb commit 10b2419
Showing 1 changed file with 62 additions and 45 deletions.
107 changes: 62 additions & 45 deletions drivers/staging/android/logger.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include <linux/poll.h>
#include <linux/slab.h>
#include <linux/time.h>
#include <linux/vmalloc.h>
#include "logger.h"

#include <asm/ioctls.h>
Expand All @@ -45,8 +46,12 @@ struct logger_log {
size_t w_off; /* current write head offset */
size_t head; /* new readers start here */
size_t size; /* size of the log */
struct list_head logs; /* list of log channels (myself)*/
};

static LIST_HEAD(log_list);


/*
* struct logger_reader - a logging device open for reading
*
Expand Down Expand Up @@ -408,7 +413,15 @@ ssize_t logger_aio_write(struct kiocb *iocb, const struct iovec *iov,
return ret;
}

static struct logger_log *get_log_from_minor(int);
static struct logger_log *get_log_from_minor(int minor)
{
struct logger_log *log;

list_for_each_entry(log, &log_list, logs)
if (log->misc.minor == minor)
return log;
return NULL;
}

/*
* logger_open - the log's open() file operation
Expand Down Expand Up @@ -565,80 +578,84 @@ static const struct file_operations logger_fops = {
};

/*
* Defines a log structure with name 'NAME' and a size of 'SIZE' bytes, which
* must be a power of two, greater than LOGGER_ENTRY_MAX_LEN, and less than
* LONG_MAX minus LOGGER_ENTRY_MAX_LEN.
* Log size must be a power of two, greater than LOGGER_ENTRY_MAX_LEN,
* and less than LONG_MAX minus LOGGER_ENTRY_MAX_LEN.
*/
#define DEFINE_LOGGER_DEVICE(VAR, NAME, SIZE) \
static unsigned char _buf_ ## VAR[SIZE]; \
static struct logger_log VAR = { \
.buffer = _buf_ ## VAR, \
.misc = { \
.minor = MISC_DYNAMIC_MINOR, \
.name = NAME, \
.fops = &logger_fops, \
.parent = NULL, \
}, \
.wq = __WAIT_QUEUE_HEAD_INITIALIZER(VAR .wq), \
.readers = LIST_HEAD_INIT(VAR .readers), \
.mutex = __MUTEX_INITIALIZER(VAR .mutex), \
.w_off = 0, \
.head = 0, \
.size = SIZE, \
};
static int __init create_log(char *log_name, int size)
{
int ret = 0;
struct logger_log *log;
unsigned char *buffer;

DEFINE_LOGGER_DEVICE(log_main, LOGGER_LOG_MAIN, 256*1024)
DEFINE_LOGGER_DEVICE(log_events, LOGGER_LOG_EVENTS, 256*1024)
DEFINE_LOGGER_DEVICE(log_radio, LOGGER_LOG_RADIO, 256*1024)
DEFINE_LOGGER_DEVICE(log_system, LOGGER_LOG_SYSTEM, 256*1024)
buffer = vmalloc(size);
if (buffer == NULL)
return -ENOMEM;

static struct logger_log *get_log_from_minor(int minor)
{
if (log_main.misc.minor == minor)
return &log_main;
if (log_events.misc.minor == minor)
return &log_events;
if (log_radio.misc.minor == minor)
return &log_radio;
if (log_system.misc.minor == minor)
return &log_system;
return NULL;
}
log = kzalloc(sizeof(struct logger_log), GFP_KERNEL);
if (log == NULL) {
ret = -ENOMEM;
goto out_free_buffer;
}
log->buffer = buffer;

static int __init init_log(struct logger_log *log)
{
int ret;
log->misc.minor = MISC_DYNAMIC_MINOR;
log->misc.name = kstrdup(log_name, GFP_KERNEL);
if (log->misc.name == NULL) {
ret = -ENOMEM;
goto out_free_log;
}

log->misc.fops = &logger_fops;
log->misc.parent = NULL;

init_waitqueue_head(&log->wq);
INIT_LIST_HEAD(&log->readers);
mutex_init(&log->mutex);
log->w_off = 0;
log->head = 0;
log->size = size;

INIT_LIST_HEAD(&log->logs);
list_add_tail(&log->logs, &log_list);

/* finally, initialize the misc device for this log */
ret = misc_register(&log->misc);
if (unlikely(ret)) {
printk(KERN_ERR "logger: failed to register misc "
"device for log '%s'!\n", log->misc.name);
return ret;
goto out_free_log;
}

printk(KERN_INFO "logger: created %luK log '%s'\n",
(unsigned long) log->size >> 10, log->misc.name);

return 0;

out_free_log:
kfree(log);

out_free_buffer:
vfree(buffer);
return ret;
}

static int __init logger_init(void)
{
int ret;

ret = init_log(&log_main);
ret = create_log(LOGGER_LOG_MAIN, 256*1024);
if (unlikely(ret))
goto out;

ret = init_log(&log_events);
ret = create_log(LOGGER_LOG_EVENTS, 256*1024);
if (unlikely(ret))
goto out;

ret = init_log(&log_radio);
ret = create_log(LOGGER_LOG_RADIO, 256*1024);
if (unlikely(ret))
goto out;

ret = init_log(&log_system);
ret = create_log(LOGGER_LOG_SYSTEM, 256*1024);
if (unlikely(ret))
goto out;

Expand Down

0 comments on commit 10b2419

Please sign in to comment.