···11+/*22+ * drivers/misc/logger.c33+ *44+ * A Logging Subsystem55+ *66+ * Copyright (C) 2007-2008 Google, Inc.77+ *88+ * Robert Love <rlove@google.com>99+ *1010+ * This software is licensed under the terms of the GNU General Public1111+ * License version 2, as published by the Free Software Foundation, and1212+ * may be copied, distributed, and modified under those terms.1313+ *1414+ * This program is distributed in the hope that it will be useful,1515+ * but WITHOUT ANY WARRANTY; without even the implied warranty of1616+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the1717+ * GNU General Public License for more details.1818+ */1919+2020+#include <linux/module.h>2121+#include <linux/fs.h>2222+#include <linux/miscdevice.h>2323+#include <linux/uaccess.h>2424+#include <linux/poll.h>2525+#include <linux/time.h>2626+#include "logger.h"2727+2828+#include <asm/ioctls.h>2929+3030+/*3131+ * struct logger_log - represents a specific log, such as 'main' or 'radio'3232+ *3333+ * This structure lives from module insertion until module removal, so it does3434+ * not need additional reference counting. The structure is protected by the3535+ * mutex 'mutex'.3636+ */3737+struct logger_log {3838+ unsigned char * buffer; /* the ring buffer itself */3939+ struct miscdevice misc; /* misc device representing the log */4040+ wait_queue_head_t wq; /* wait queue for readers */4141+ struct list_head readers; /* this log's readers */4242+ struct mutex mutex; /* mutex protecting buffer */4343+ size_t w_off; /* current write head offset */4444+ size_t head; /* new readers start here */4545+ size_t size; /* size of the log */4646+};4747+4848+/*4949+ * struct logger_reader - a logging device open for reading5050+ *5151+ * This object lives from open to release, so we don't need additional5252+ * reference counting. The structure is protected by log->mutex.5353+ */5454+struct logger_reader {5555+ struct logger_log * log; /* associated log */5656+ struct list_head list; /* entry in logger_log's list */5757+ size_t r_off; /* current read head offset */5858+};5959+6060+/* logger_offset - returns index 'n' into the log via (optimized) modulus */6161+#define logger_offset(n) ((n) & (log->size - 1))6262+6363+/*6464+ * file_get_log - Given a file structure, return the associated log6565+ *6666+ * This isn't aesthetic. We have several goals:6767+ *6868+ * 1) Need to quickly obtain the associated log during an I/O operation6969+ * 2) Readers need to maintain state (logger_reader)7070+ * 3) Writers need to be very fast (open() should be a near no-op)7171+ *7272+ * In the reader case, we can trivially go file->logger_reader->logger_log.7373+ * For a writer, we don't want to maintain a logger_reader, so we just go7474+ * file->logger_log. Thus what file->private_data points at depends on whether7575+ * or not the file was opened for reading. This function hides that dirtiness.7676+ */7777+static inline struct logger_log * file_get_log(struct file *file)7878+{7979+ if (file->f_mode & FMODE_READ) {8080+ struct logger_reader *reader = file->private_data;8181+ return reader->log;8282+ } else8383+ return file->private_data;8484+}8585+8686+/*8787+ * get_entry_len - Grabs the length of the payload of the next entry starting8888+ * from 'off'.8989+ *9090+ * Caller needs to hold log->mutex.9191+ */9292+static __u32 get_entry_len(struct logger_log *log, size_t off)9393+{9494+ __u16 val;9595+9696+ switch (log->size - off) {9797+ case 1:9898+ memcpy(&val, log->buffer + off, 1);9999+ memcpy(((char *) &val) + 1, log->buffer, 1);100100+ break;101101+ default:102102+ memcpy(&val, log->buffer + off, 2);103103+ }104104+105105+ return sizeof(struct logger_entry) + val;106106+}107107+108108+/*109109+ * do_read_log_to_user - reads exactly 'count' bytes from 'log' into the110110+ * user-space buffer 'buf'. Returns 'count' on success.111111+ *112112+ * Caller must hold log->mutex.113113+ */114114+static ssize_t do_read_log_to_user(struct logger_log *log,115115+ struct logger_reader *reader,116116+ char __user *buf,117117+ size_t count)118118+{119119+ size_t len;120120+121121+ /*122122+ * We read from the log in two disjoint operations. First, we read from123123+ * the current read head offset up to 'count' bytes or to the end of124124+ * the log, whichever comes first.125125+ */126126+ len = min(count, log->size - reader->r_off);127127+ if (copy_to_user(buf, log->buffer + reader->r_off, len))128128+ return -EFAULT;129129+130130+ /*131131+ * Second, we read any remaining bytes, starting back at the head of132132+ * the log.133133+ */134134+ if (count != len)135135+ if (copy_to_user(buf + len, log->buffer, count - len))136136+ return -EFAULT;137137+138138+ reader->r_off = logger_offset(reader->r_off + count);139139+140140+ return count;141141+}142142+143143+/*144144+ * logger_read - our log's read() method145145+ *146146+ * Behavior:147147+ *148148+ * - O_NONBLOCK works149149+ * - If there are no log entries to read, blocks until log is written to150150+ * - Atomically reads exactly one log entry151151+ *152152+ * Optimal read size is LOGGER_ENTRY_MAX_LEN. Will set errno to EINVAL if read153153+ * buffer is insufficient to hold next entry.154154+ */155155+static ssize_t logger_read(struct file *file, char __user *buf,156156+ size_t count, loff_t *pos)157157+{158158+ struct logger_reader *reader = file->private_data;159159+ struct logger_log *log = reader->log;160160+ ssize_t ret;161161+ DEFINE_WAIT(wait);162162+163163+start:164164+ while (1) {165165+ prepare_to_wait(&log->wq, &wait, TASK_INTERRUPTIBLE);166166+167167+ mutex_lock(&log->mutex);168168+ ret = (log->w_off == reader->r_off);169169+ mutex_unlock(&log->mutex);170170+ if (!ret)171171+ break;172172+173173+ if (file->f_flags & O_NONBLOCK) {174174+ ret = -EAGAIN;175175+ break;176176+ }177177+178178+ if (signal_pending(current)) {179179+ ret = -EINTR;180180+ break;181181+ }182182+183183+ schedule();184184+ }185185+186186+ finish_wait(&log->wq, &wait);187187+ if (ret)188188+ return ret;189189+190190+ mutex_lock(&log->mutex);191191+192192+ /* is there still something to read or did we race? */193193+ if (unlikely(log->w_off == reader->r_off)) {194194+ mutex_unlock(&log->mutex);195195+ goto start;196196+ }197197+198198+ /* get the size of the next entry */199199+ ret = get_entry_len(log, reader->r_off);200200+ if (count < ret) {201201+ ret = -EINVAL;202202+ goto out;203203+ }204204+205205+ /* get exactly one entry from the log */206206+ ret = do_read_log_to_user(log, reader, buf, ret);207207+208208+out:209209+ mutex_unlock(&log->mutex);210210+211211+ return ret;212212+}213213+214214+/*215215+ * get_next_entry - return the offset of the first valid entry at least 'len'216216+ * bytes after 'off'.217217+ *218218+ * Caller must hold log->mutex.219219+ */220220+static size_t get_next_entry(struct logger_log *log, size_t off, size_t len)221221+{222222+ size_t count = 0;223223+224224+ do {225225+ size_t nr = get_entry_len(log, off);226226+ off = logger_offset(off + nr);227227+ count += nr;228228+ } while (count < len);229229+230230+ return off;231231+}232232+233233+/*234234+ * clock_interval - is a < c < b in mod-space? Put another way, does the line235235+ * from a to b cross c?236236+ */237237+static inline int clock_interval(size_t a, size_t b, size_t c)238238+{239239+ if (b < a) {240240+ if (a < c || b >= c)241241+ return 1;242242+ } else {243243+ if (a < c && b >= c)244244+ return 1;245245+ }246246+247247+ return 0;248248+}249249+250250+/*251251+ * fix_up_readers - walk the list of all readers and "fix up" any who were252252+ * lapped by the writer; also do the same for the default "start head".253253+ * We do this by "pulling forward" the readers and start head to the first254254+ * entry after the new write head.255255+ *256256+ * The caller needs to hold log->mutex.257257+ */258258+static void fix_up_readers(struct logger_log *log, size_t len)259259+{260260+ size_t old = log->w_off;261261+ size_t new = logger_offset(old + len);262262+ struct logger_reader *reader;263263+264264+ if (clock_interval(old, new, log->head))265265+ log->head = get_next_entry(log, log->head, len);266266+267267+ list_for_each_entry(reader, &log->readers, list)268268+ if (clock_interval(old, new, reader->r_off))269269+ reader->r_off = get_next_entry(log, reader->r_off, len);270270+}271271+272272+/*273273+ * do_write_log - writes 'len' bytes from 'buf' to 'log'274274+ *275275+ * The caller needs to hold log->mutex.276276+ */277277+static void do_write_log(struct logger_log *log, const void *buf, size_t count)278278+{279279+ size_t len;280280+281281+ len = min(count, log->size - log->w_off);282282+ memcpy(log->buffer + log->w_off, buf, len);283283+284284+ if (count != len)285285+ memcpy(log->buffer, buf + len, count - len);286286+287287+ log->w_off = logger_offset(log->w_off + count);288288+289289+}290290+291291+/*292292+ * do_write_log_user - writes 'len' bytes from the user-space buffer 'buf' to293293+ * the log 'log'294294+ *295295+ * The caller needs to hold log->mutex.296296+ *297297+ * Returns 'count' on success, negative error code on failure.298298+ */299299+static ssize_t do_write_log_from_user(struct logger_log *log,300300+ const void __user *buf, size_t count)301301+{302302+ size_t len;303303+304304+ len = min(count, log->size - log->w_off);305305+ if (len && copy_from_user(log->buffer + log->w_off, buf, len))306306+ return -EFAULT;307307+308308+ if (count != len)309309+ if (copy_from_user(log->buffer, buf + len, count - len))310310+ return -EFAULT;311311+312312+ log->w_off = logger_offset(log->w_off + count);313313+314314+ return count;315315+}316316+317317+/*318318+ * logger_aio_write - our write method, implementing support for write(),319319+ * writev(), and aio_write(). Writes are our fast path, and we try to optimize320320+ * them above all else.321321+ */322322+ssize_t logger_aio_write(struct kiocb *iocb, const struct iovec *iov,323323+ unsigned long nr_segs, loff_t ppos)324324+{325325+ struct logger_log *log = file_get_log(iocb->ki_filp);326326+ size_t orig = log->w_off;327327+ struct logger_entry header;328328+ struct timespec now;329329+ ssize_t ret = 0;330330+331331+ now = current_kernel_time();332332+333333+ header.pid = current->tgid;334334+ header.tid = current->pid;335335+ header.sec = now.tv_sec;336336+ header.nsec = now.tv_nsec;337337+ header.len = min_t(size_t, iocb->ki_left, LOGGER_ENTRY_MAX_PAYLOAD);338338+339339+ /* null writes succeed, return zero */340340+ if (unlikely(!header.len))341341+ return 0;342342+343343+ mutex_lock(&log->mutex);344344+345345+ /*346346+ * Fix up any readers, pulling them forward to the first readable347347+ * entry after (what will be) the new write offset. We do this now348348+ * because if we partially fail, we can end up with clobbered log349349+ * entries that encroach on readable buffer.350350+ */351351+ fix_up_readers(log, sizeof(struct logger_entry) + header.len);352352+353353+ do_write_log(log, &header, sizeof(struct logger_entry));354354+355355+ while (nr_segs-- > 0) {356356+ size_t len;357357+ ssize_t nr;358358+359359+ /* figure out how much of this vector we can keep */360360+ len = min_t(size_t, iov->iov_len, header.len - ret);361361+362362+ /* write out this segment's payload */363363+ nr = do_write_log_from_user(log, iov->iov_base, len);364364+ if (unlikely(nr < 0)) {365365+ log->w_off = orig;366366+ mutex_unlock(&log->mutex);367367+ return nr;368368+ }369369+370370+ iov++;371371+ ret += nr;372372+ }373373+374374+ mutex_unlock(&log->mutex);375375+376376+ /* wake up any blocked readers */377377+ wake_up_interruptible(&log->wq);378378+379379+ return ret;380380+}381381+382382+static struct logger_log * get_log_from_minor(int);383383+384384+/*385385+ * logger_open - the log's open() file operation386386+ *387387+ * Note how near a no-op this is in the write-only case. Keep it that way!388388+ */389389+static int logger_open(struct inode *inode, struct file *file)390390+{391391+ struct logger_log *log;392392+ int ret;393393+394394+ ret = nonseekable_open(inode, file);395395+ if (ret)396396+ return ret;397397+398398+ log = get_log_from_minor(MINOR(inode->i_rdev));399399+ if (!log)400400+ return -ENODEV;401401+402402+ if (file->f_mode & FMODE_READ) {403403+ struct logger_reader *reader;404404+405405+ reader = kmalloc(sizeof(struct logger_reader), GFP_KERNEL);406406+ if (!reader)407407+ return -ENOMEM;408408+409409+ reader->log = log;410410+ INIT_LIST_HEAD(&reader->list);411411+412412+ mutex_lock(&log->mutex);413413+ reader->r_off = log->head;414414+ list_add_tail(&reader->list, &log->readers);415415+ mutex_unlock(&log->mutex);416416+417417+ file->private_data = reader;418418+ } else419419+ file->private_data = log;420420+421421+ return 0;422422+}423423+424424+/*425425+ * logger_release - the log's release file operation426426+ *427427+ * Note this is a total no-op in the write-only case. Keep it that way!428428+ */429429+static int logger_release(struct inode *ignored, struct file *file)430430+{431431+ if (file->f_mode & FMODE_READ) {432432+ struct logger_reader *reader = file->private_data;433433+ list_del(&reader->list);434434+ kfree(reader);435435+ }436436+437437+ return 0;438438+}439439+440440+/*441441+ * logger_poll - the log's poll file operation, for poll/select/epoll442442+ *443443+ * Note we always return POLLOUT, because you can always write() to the log.444444+ * Note also that, strictly speaking, a return value of POLLIN does not445445+ * guarantee that the log is readable without blocking, as there is a small446446+ * chance that the writer can lap the reader in the interim between poll()447447+ * returning and the read() request.448448+ */449449+static unsigned int logger_poll(struct file *file, poll_table *wait)450450+{451451+ struct logger_reader *reader;452452+ struct logger_log *log;453453+ unsigned int ret = POLLOUT | POLLWRNORM;454454+455455+ if (!(file->f_mode & FMODE_READ))456456+ return ret;457457+458458+ reader = file->private_data;459459+ log = reader->log;460460+461461+ poll_wait(file, &log->wq, wait);462462+463463+ mutex_lock(&log->mutex);464464+ if (log->w_off != reader->r_off)465465+ ret |= POLLIN | POLLRDNORM;466466+ mutex_unlock(&log->mutex);467467+468468+ return ret;469469+}470470+471471+static long logger_ioctl(struct file *file, unsigned int cmd, unsigned long arg)472472+{473473+ struct logger_log *log = file_get_log(file);474474+ struct logger_reader *reader;475475+ long ret = -ENOTTY;476476+477477+ mutex_lock(&log->mutex);478478+479479+ switch (cmd) {480480+ case LOGGER_GET_LOG_BUF_SIZE:481481+ ret = log->size;482482+ break;483483+ case LOGGER_GET_LOG_LEN:484484+ if (!(file->f_mode & FMODE_READ)) {485485+ ret = -EBADF;486486+ break;487487+ }488488+ reader = file->private_data;489489+ if (log->w_off >= reader->r_off)490490+ ret = log->w_off - reader->r_off;491491+ else492492+ ret = (log->size - reader->r_off) + log->w_off;493493+ break;494494+ case LOGGER_GET_NEXT_ENTRY_LEN:495495+ if (!(file->f_mode & FMODE_READ)) {496496+ ret = -EBADF;497497+ break;498498+ }499499+ reader = file->private_data;500500+ if (log->w_off != reader->r_off)501501+ ret = get_entry_len(log, reader->r_off);502502+ else503503+ ret = 0;504504+ break;505505+ case LOGGER_FLUSH_LOG:506506+ if (!(file->f_mode & FMODE_WRITE)) {507507+ ret = -EBADF;508508+ break;509509+ }510510+ list_for_each_entry(reader, &log->readers, list)511511+ reader->r_off = log->w_off;512512+ log->head = log->w_off;513513+ ret = 0;514514+ break;515515+ }516516+517517+ mutex_unlock(&log->mutex);518518+519519+ return ret;520520+}521521+522522+static struct file_operations logger_fops = {523523+ .owner = THIS_MODULE,524524+ .read = logger_read,525525+ .aio_write = logger_aio_write,526526+ .poll = logger_poll,527527+ .unlocked_ioctl = logger_ioctl,528528+ .compat_ioctl = logger_ioctl,529529+ .open = logger_open,530530+ .release = logger_release,531531+};532532+533533+/*534534+ * Defines a log structure with name 'NAME' and a size of 'SIZE' bytes, which535535+ * must be a power of two, greater than LOGGER_ENTRY_MAX_LEN, and less than536536+ * LONG_MAX minus LOGGER_ENTRY_MAX_LEN.537537+ */538538+#define DEFINE_LOGGER_DEVICE(VAR, NAME, SIZE) \539539+static unsigned char _buf_ ## VAR[SIZE]; \540540+static struct logger_log VAR = { \541541+ .buffer = _buf_ ## VAR, \542542+ .misc = { \543543+ .minor = MISC_DYNAMIC_MINOR, \544544+ .name = NAME, \545545+ .fops = &logger_fops, \546546+ .parent = NULL, \547547+ }, \548548+ .wq = __WAIT_QUEUE_HEAD_INITIALIZER(VAR .wq), \549549+ .readers = LIST_HEAD_INIT(VAR .readers), \550550+ .mutex = __MUTEX_INITIALIZER(VAR .mutex), \551551+ .w_off = 0, \552552+ .head = 0, \553553+ .size = SIZE, \554554+};555555+556556+DEFINE_LOGGER_DEVICE(log_main, LOGGER_LOG_MAIN, 64*1024)557557+DEFINE_LOGGER_DEVICE(log_events, LOGGER_LOG_EVENTS, 256*1024)558558+DEFINE_LOGGER_DEVICE(log_radio, LOGGER_LOG_RADIO, 64*1024)559559+560560+static struct logger_log * get_log_from_minor(int minor)561561+{562562+ if (log_main.misc.minor == minor)563563+ return &log_main;564564+ if (log_events.misc.minor == minor)565565+ return &log_events;566566+ if (log_radio.misc.minor == minor)567567+ return &log_radio;568568+ return NULL;569569+}570570+571571+static int __init init_log(struct logger_log *log)572572+{573573+ int ret;574574+575575+ ret = misc_register(&log->misc);576576+ if (unlikely(ret)) {577577+ printk(KERN_ERR "logger: failed to register misc "578578+ "device for log '%s'!\n", log->misc.name);579579+ return ret;580580+ }581581+582582+ printk(KERN_INFO "logger: created %luK log '%s'\n",583583+ (unsigned long) log->size >> 10, log->misc.name);584584+585585+ return 0;586586+}587587+588588+static int __init logger_init(void)589589+{590590+ int ret;591591+592592+ ret = init_log(&log_main);593593+ if (unlikely(ret))594594+ goto out;595595+596596+ ret = init_log(&log_events);597597+ if (unlikely(ret))598598+ goto out;599599+600600+ ret = init_log(&log_radio);601601+ if (unlikely(ret))602602+ goto out;603603+604604+out:605605+ return ret;606606+}607607+device_initcall(logger_init);
+48
drivers/staging/android/logger.h
···11+/* include/linux/logger.h22+ *33+ * Copyright (C) 2007-2008 Google, Inc.44+ * Author: Robert Love <rlove@android.com>55+ *66+ * This software is licensed under the terms of the GNU General Public77+ * License version 2, as published by the Free Software Foundation, and88+ * may be copied, distributed, and modified under those terms.99+ *1010+ * This program is distributed in the hope that it will be useful,1111+ * but WITHOUT ANY WARRANTY; without even the implied warranty of1212+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the1313+ * GNU General Public License for more details.1414+ *1515+ */1616+1717+#ifndef _LINUX_LOGGER_H1818+#define _LINUX_LOGGER_H1919+2020+#include <linux/types.h>2121+#include <linux/ioctl.h>2222+2323+struct logger_entry {2424+ __u16 len; /* length of the payload */2525+ __u16 __pad; /* no matter what, we get 2 bytes of padding */2626+ __s32 pid; /* generating process's pid */2727+ __s32 tid; /* generating process's tid */2828+ __s32 sec; /* seconds since Epoch */2929+ __s32 nsec; /* nanoseconds */3030+ char msg[0]; /* the entry's payload */3131+};3232+3333+#define LOGGER_LOG_RADIO "log_radio" /* radio-related messages */3434+#define LOGGER_LOG_EVENTS "log_events" /* system/hardware events */3535+#define LOGGER_LOG_MAIN "log_main" /* everything else */3636+3737+#define LOGGER_ENTRY_MAX_LEN (4*1024)3838+#define LOGGER_ENTRY_MAX_PAYLOAD \3939+ (LOGGER_ENTRY_MAX_LEN - sizeof(struct logger_entry))4040+4141+#define __LOGGERIO 0xAE4242+4343+#define LOGGER_GET_LOG_BUF_SIZE _IO(__LOGGERIO, 1) /* size of log */4444+#define LOGGER_GET_LOG_LEN _IO(__LOGGERIO, 2) /* used log len */4545+#define LOGGER_GET_NEXT_ENTRY_LEN _IO(__LOGGERIO, 3) /* next entry len */4646+#define LOGGER_FLUSH_LOG _IO(__LOGGERIO, 4) /* flush log */4747+4848+#endif /* _LINUX_LOGGER_H */