at v3.16-rc7 854 lines 21 kB view raw
1/* 2 * drivers/misc/logger.c 3 * 4 * A Logging Subsystem 5 * 6 * Copyright (C) 2007-2008 Google, Inc. 7 * 8 * Robert Love <rlove@google.com> 9 * 10 * This software is licensed under the terms of the GNU General Public 11 * License version 2, as published by the Free Software Foundation, and 12 * may be copied, distributed, and modified under those terms. 13 * 14 * This program is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 * GNU General Public License for more details. 18 */ 19 20#define pr_fmt(fmt) "logger: " fmt 21 22#include <linux/sched.h> 23#include <linux/module.h> 24#include <linux/fs.h> 25#include <linux/miscdevice.h> 26#include <linux/uaccess.h> 27#include <linux/poll.h> 28#include <linux/slab.h> 29#include <linux/time.h> 30#include <linux/vmalloc.h> 31#include <linux/aio.h> 32#include "logger.h" 33 34#include <asm/ioctls.h> 35 36/** 37 * struct logger_log - represents a specific log, such as 'main' or 'radio' 38 * @buffer: The actual ring buffer 39 * @misc: The "misc" device representing the log 40 * @wq: The wait queue for @readers 41 * @readers: This log's readers 42 * @mutex: The mutex that protects the @buffer 43 * @w_off: The current write head offset 44 * @head: The head, or location that readers start reading at. 45 * @size: The size of the log 46 * @logs: The list of log channels 47 * 48 * This structure lives from module insertion until module removal, so it does 49 * not need additional reference counting. The structure is protected by the 50 * mutex 'mutex'. 51 */ 52struct logger_log { 53 unsigned char *buffer; 54 struct miscdevice misc; 55 wait_queue_head_t wq; 56 struct list_head readers; 57 struct mutex mutex; 58 size_t w_off; 59 size_t head; 60 size_t size; 61 struct list_head logs; 62}; 63 64static LIST_HEAD(log_list); 65 66 67/** 68 * struct logger_reader - a logging device open for reading 69 * @log: The associated log 70 * @list: The associated entry in @logger_log's list 71 * @r_off: The current read head offset. 72 * @r_all: Reader can read all entries 73 * @r_ver: Reader ABI version 74 * 75 * This object lives from open to release, so we don't need additional 76 * reference counting. The structure is protected by log->mutex. 77 */ 78struct logger_reader { 79 struct logger_log *log; 80 struct list_head list; 81 size_t r_off; 82 bool r_all; 83 int r_ver; 84}; 85 86/* logger_offset - returns index 'n' into the log via (optimized) modulus */ 87static size_t logger_offset(struct logger_log *log, size_t n) 88{ 89 return n & (log->size - 1); 90} 91 92 93/* 94 * file_get_log - Given a file structure, return the associated log 95 * 96 * This isn't aesthetic. We have several goals: 97 * 98 * 1) Need to quickly obtain the associated log during an I/O operation 99 * 2) Readers need to maintain state (logger_reader) 100 * 3) Writers need to be very fast (open() should be a near no-op) 101 * 102 * In the reader case, we can trivially go file->logger_reader->logger_log. 103 * For a writer, we don't want to maintain a logger_reader, so we just go 104 * file->logger_log. Thus what file->private_data points at depends on whether 105 * or not the file was opened for reading. This function hides that dirtiness. 106 */ 107static inline struct logger_log *file_get_log(struct file *file) 108{ 109 if (file->f_mode & FMODE_READ) { 110 struct logger_reader *reader = file->private_data; 111 112 return reader->log; 113 } else 114 return file->private_data; 115} 116 117/* 118 * get_entry_header - returns a pointer to the logger_entry header within 119 * 'log' starting at offset 'off'. A temporary logger_entry 'scratch' must 120 * be provided. Typically the return value will be a pointer within 121 * 'logger->buf'. However, a pointer to 'scratch' may be returned if 122 * the log entry spans the end and beginning of the circular buffer. 123 */ 124static struct logger_entry *get_entry_header(struct logger_log *log, 125 size_t off, struct logger_entry *scratch) 126{ 127 size_t len = min(sizeof(struct logger_entry), log->size - off); 128 129 if (len != sizeof(struct logger_entry)) { 130 memcpy(((void *) scratch), log->buffer + off, len); 131 memcpy(((void *) scratch) + len, log->buffer, 132 sizeof(struct logger_entry) - len); 133 return scratch; 134 } 135 136 return (struct logger_entry *) (log->buffer + off); 137} 138 139/* 140 * get_entry_msg_len - Grabs the length of the message of the entry 141 * starting from from 'off'. 142 * 143 * An entry length is 2 bytes (16 bits) in host endian order. 144 * In the log, the length does not include the size of the log entry structure. 145 * This function returns the size including the log entry structure. 146 * 147 * Caller needs to hold log->mutex. 148 */ 149static __u32 get_entry_msg_len(struct logger_log *log, size_t off) 150{ 151 struct logger_entry scratch; 152 struct logger_entry *entry; 153 154 entry = get_entry_header(log, off, &scratch); 155 return entry->len; 156} 157 158static size_t get_user_hdr_len(int ver) 159{ 160 if (ver < 2) 161 return sizeof(struct user_logger_entry_compat); 162 else 163 return sizeof(struct logger_entry); 164} 165 166static ssize_t copy_header_to_user(int ver, struct logger_entry *entry, 167 char __user *buf) 168{ 169 void *hdr; 170 size_t hdr_len; 171 struct user_logger_entry_compat v1; 172 173 if (ver < 2) { 174 v1.len = entry->len; 175 v1.__pad = 0; 176 v1.pid = entry->pid; 177 v1.tid = entry->tid; 178 v1.sec = entry->sec; 179 v1.nsec = entry->nsec; 180 hdr = &v1; 181 hdr_len = sizeof(struct user_logger_entry_compat); 182 } else { 183 hdr = entry; 184 hdr_len = sizeof(struct logger_entry); 185 } 186 187 return copy_to_user(buf, hdr, hdr_len); 188} 189 190/* 191 * do_read_log_to_user - reads exactly 'count' bytes from 'log' into the 192 * user-space buffer 'buf'. Returns 'count' on success. 193 * 194 * Caller must hold log->mutex. 195 */ 196static ssize_t do_read_log_to_user(struct logger_log *log, 197 struct logger_reader *reader, 198 char __user *buf, 199 size_t count) 200{ 201 struct logger_entry scratch; 202 struct logger_entry *entry; 203 size_t len; 204 size_t msg_start; 205 206 /* 207 * First, copy the header to userspace, using the version of 208 * the header requested 209 */ 210 entry = get_entry_header(log, reader->r_off, &scratch); 211 if (copy_header_to_user(reader->r_ver, entry, buf)) 212 return -EFAULT; 213 214 count -= get_user_hdr_len(reader->r_ver); 215 buf += get_user_hdr_len(reader->r_ver); 216 msg_start = logger_offset(log, 217 reader->r_off + sizeof(struct logger_entry)); 218 219 /* 220 * We read from the msg in two disjoint operations. First, we read from 221 * the current msg head offset up to 'count' bytes or to the end of 222 * the log, whichever comes first. 223 */ 224 len = min(count, log->size - msg_start); 225 if (copy_to_user(buf, log->buffer + msg_start, len)) 226 return -EFAULT; 227 228 /* 229 * Second, we read any remaining bytes, starting back at the head of 230 * the log. 231 */ 232 if (count != len) 233 if (copy_to_user(buf + len, log->buffer, count - len)) 234 return -EFAULT; 235 236 reader->r_off = logger_offset(log, reader->r_off + 237 sizeof(struct logger_entry) + count); 238 239 return count + get_user_hdr_len(reader->r_ver); 240} 241 242/* 243 * get_next_entry_by_uid - Starting at 'off', returns an offset into 244 * 'log->buffer' which contains the first entry readable by 'euid' 245 */ 246static size_t get_next_entry_by_uid(struct logger_log *log, 247 size_t off, kuid_t euid) 248{ 249 while (off != log->w_off) { 250 struct logger_entry *entry; 251 struct logger_entry scratch; 252 size_t next_len; 253 254 entry = get_entry_header(log, off, &scratch); 255 256 if (uid_eq(entry->euid, euid)) 257 return off; 258 259 next_len = sizeof(struct logger_entry) + entry->len; 260 off = logger_offset(log, off + next_len); 261 } 262 263 return off; 264} 265 266/* 267 * logger_read - our log's read() method 268 * 269 * Behavior: 270 * 271 * - O_NONBLOCK works 272 * - If there are no log entries to read, blocks until log is written to 273 * - Atomically reads exactly one log entry 274 * 275 * Will set errno to EINVAL if read 276 * buffer is insufficient to hold next entry. 277 */ 278static ssize_t logger_read(struct file *file, char __user *buf, 279 size_t count, loff_t *pos) 280{ 281 struct logger_reader *reader = file->private_data; 282 struct logger_log *log = reader->log; 283 ssize_t ret; 284 DEFINE_WAIT(wait); 285 286start: 287 while (1) { 288 mutex_lock(&log->mutex); 289 290 prepare_to_wait(&log->wq, &wait, TASK_INTERRUPTIBLE); 291 292 ret = (log->w_off == reader->r_off); 293 mutex_unlock(&log->mutex); 294 if (!ret) 295 break; 296 297 if (file->f_flags & O_NONBLOCK) { 298 ret = -EAGAIN; 299 break; 300 } 301 302 if (signal_pending(current)) { 303 ret = -EINTR; 304 break; 305 } 306 307 schedule(); 308 } 309 310 finish_wait(&log->wq, &wait); 311 if (ret) 312 return ret; 313 314 mutex_lock(&log->mutex); 315 316 if (!reader->r_all) 317 reader->r_off = get_next_entry_by_uid(log, 318 reader->r_off, current_euid()); 319 320 /* is there still something to read or did we race? */ 321 if (unlikely(log->w_off == reader->r_off)) { 322 mutex_unlock(&log->mutex); 323 goto start; 324 } 325 326 /* get the size of the next entry */ 327 ret = get_user_hdr_len(reader->r_ver) + 328 get_entry_msg_len(log, reader->r_off); 329 if (count < ret) { 330 ret = -EINVAL; 331 goto out; 332 } 333 334 /* get exactly one entry from the log */ 335 ret = do_read_log_to_user(log, reader, buf, ret); 336 337out: 338 mutex_unlock(&log->mutex); 339 340 return ret; 341} 342 343/* 344 * get_next_entry - return the offset of the first valid entry at least 'len' 345 * bytes after 'off'. 346 * 347 * Caller must hold log->mutex. 348 */ 349static size_t get_next_entry(struct logger_log *log, size_t off, size_t len) 350{ 351 size_t count = 0; 352 353 do { 354 size_t nr = sizeof(struct logger_entry) + 355 get_entry_msg_len(log, off); 356 off = logger_offset(log, off + nr); 357 count += nr; 358 } while (count < len); 359 360 return off; 361} 362 363/* 364 * is_between - is a < c < b, accounting for wrapping of a, b, and c 365 * positions in the buffer 366 * 367 * That is, if a<b, check for c between a and b 368 * and if a>b, check for c outside (not between) a and b 369 * 370 * |------- a xxxxxxxx b --------| 371 * c^ 372 * 373 * |xxxxx b --------- a xxxxxxxxx| 374 * c^ 375 * or c^ 376 */ 377static inline int is_between(size_t a, size_t b, size_t c) 378{ 379 if (a < b) { 380 /* is c between a and b? */ 381 if (a < c && c <= b) 382 return 1; 383 } else { 384 /* is c outside of b through a? */ 385 if (c <= b || a < c) 386 return 1; 387 } 388 389 return 0; 390} 391 392/* 393 * fix_up_readers - walk the list of all readers and "fix up" any who were 394 * lapped by the writer; also do the same for the default "start head". 395 * We do this by "pulling forward" the readers and start head to the first 396 * entry after the new write head. 397 * 398 * The caller needs to hold log->mutex. 399 */ 400static void fix_up_readers(struct logger_log *log, size_t len) 401{ 402 size_t old = log->w_off; 403 size_t new = logger_offset(log, old + len); 404 struct logger_reader *reader; 405 406 if (is_between(old, new, log->head)) 407 log->head = get_next_entry(log, log->head, len); 408 409 list_for_each_entry(reader, &log->readers, list) 410 if (is_between(old, new, reader->r_off)) 411 reader->r_off = get_next_entry(log, reader->r_off, len); 412} 413 414/* 415 * do_write_log - writes 'len' bytes from 'buf' to 'log' 416 * 417 * The caller needs to hold log->mutex. 418 */ 419static void do_write_log(struct logger_log *log, const void *buf, size_t count) 420{ 421 size_t len; 422 423 len = min(count, log->size - log->w_off); 424 memcpy(log->buffer + log->w_off, buf, len); 425 426 if (count != len) 427 memcpy(log->buffer, buf + len, count - len); 428 429 log->w_off = logger_offset(log, log->w_off + count); 430 431} 432 433/* 434 * do_write_log_user - writes 'len' bytes from the user-space buffer 'buf' to 435 * the log 'log' 436 * 437 * The caller needs to hold log->mutex. 438 * 439 * Returns 'count' on success, negative error code on failure. 440 */ 441static ssize_t do_write_log_from_user(struct logger_log *log, 442 const void __user *buf, size_t count) 443{ 444 size_t len; 445 446 len = min(count, log->size - log->w_off); 447 if (len && copy_from_user(log->buffer + log->w_off, buf, len)) 448 return -EFAULT; 449 450 if (count != len) 451 if (copy_from_user(log->buffer, buf + len, count - len)) 452 /* 453 * Note that by not updating w_off, this abandons the 454 * portion of the new entry that *was* successfully 455 * copied, just above. This is intentional to avoid 456 * message corruption from missing fragments. 457 */ 458 return -EFAULT; 459 460 log->w_off = logger_offset(log, log->w_off + count); 461 462 return count; 463} 464 465/* 466 * logger_aio_write - our write method, implementing support for write(), 467 * writev(), and aio_write(). Writes are our fast path, and we try to optimize 468 * them above all else. 469 */ 470static ssize_t logger_aio_write(struct kiocb *iocb, const struct iovec *iov, 471 unsigned long nr_segs, loff_t ppos) 472{ 473 struct logger_log *log = file_get_log(iocb->ki_filp); 474 size_t orig; 475 struct logger_entry header; 476 struct timespec now; 477 ssize_t ret = 0; 478 479 now = current_kernel_time(); 480 481 header.pid = current->tgid; 482 header.tid = current->pid; 483 header.sec = now.tv_sec; 484 header.nsec = now.tv_nsec; 485 header.euid = current_euid(); 486 header.len = min_t(size_t, iocb->ki_nbytes, LOGGER_ENTRY_MAX_PAYLOAD); 487 header.hdr_size = sizeof(struct logger_entry); 488 489 /* null writes succeed, return zero */ 490 if (unlikely(!header.len)) 491 return 0; 492 493 mutex_lock(&log->mutex); 494 495 orig = log->w_off; 496 497 /* 498 * Fix up any readers, pulling them forward to the first readable 499 * entry after (what will be) the new write offset. We do this now 500 * because if we partially fail, we can end up with clobbered log 501 * entries that encroach on readable buffer. 502 */ 503 fix_up_readers(log, sizeof(struct logger_entry) + header.len); 504 505 do_write_log(log, &header, sizeof(struct logger_entry)); 506 507 while (nr_segs-- > 0) { 508 size_t len; 509 ssize_t nr; 510 511 /* figure out how much of this vector we can keep */ 512 len = min_t(size_t, iov->iov_len, header.len - ret); 513 514 /* write out this segment's payload */ 515 nr = do_write_log_from_user(log, iov->iov_base, len); 516 if (unlikely(nr < 0)) { 517 log->w_off = orig; 518 mutex_unlock(&log->mutex); 519 return nr; 520 } 521 522 iov++; 523 ret += nr; 524 } 525 526 mutex_unlock(&log->mutex); 527 528 /* wake up any blocked readers */ 529 wake_up_interruptible(&log->wq); 530 531 return ret; 532} 533 534static struct logger_log *get_log_from_minor(int minor) 535{ 536 struct logger_log *log; 537 538 list_for_each_entry(log, &log_list, logs) 539 if (log->misc.minor == minor) 540 return log; 541 return NULL; 542} 543 544/* 545 * logger_open - the log's open() file operation 546 * 547 * Note how near a no-op this is in the write-only case. Keep it that way! 548 */ 549static int logger_open(struct inode *inode, struct file *file) 550{ 551 struct logger_log *log; 552 int ret; 553 554 ret = nonseekable_open(inode, file); 555 if (ret) 556 return ret; 557 558 log = get_log_from_minor(MINOR(inode->i_rdev)); 559 if (!log) 560 return -ENODEV; 561 562 if (file->f_mode & FMODE_READ) { 563 struct logger_reader *reader; 564 565 reader = kmalloc(sizeof(struct logger_reader), GFP_KERNEL); 566 if (!reader) 567 return -ENOMEM; 568 569 reader->log = log; 570 reader->r_ver = 1; 571 reader->r_all = in_egroup_p(inode->i_gid) || 572 capable(CAP_SYSLOG); 573 574 INIT_LIST_HEAD(&reader->list); 575 576 mutex_lock(&log->mutex); 577 reader->r_off = log->head; 578 list_add_tail(&reader->list, &log->readers); 579 mutex_unlock(&log->mutex); 580 581 file->private_data = reader; 582 } else 583 file->private_data = log; 584 585 return 0; 586} 587 588/* 589 * logger_release - the log's release file operation 590 * 591 * Note this is a total no-op in the write-only case. Keep it that way! 592 */ 593static int logger_release(struct inode *ignored, struct file *file) 594{ 595 if (file->f_mode & FMODE_READ) { 596 struct logger_reader *reader = file->private_data; 597 struct logger_log *log = reader->log; 598 599 mutex_lock(&log->mutex); 600 list_del(&reader->list); 601 mutex_unlock(&log->mutex); 602 603 kfree(reader); 604 } 605 606 return 0; 607} 608 609/* 610 * logger_poll - the log's poll file operation, for poll/select/epoll 611 * 612 * Note we always return POLLOUT, because you can always write() to the log. 613 * Note also that, strictly speaking, a return value of POLLIN does not 614 * guarantee that the log is readable without blocking, as there is a small 615 * chance that the writer can lap the reader in the interim between poll() 616 * returning and the read() request. 617 */ 618static unsigned int logger_poll(struct file *file, poll_table *wait) 619{ 620 struct logger_reader *reader; 621 struct logger_log *log; 622 unsigned int ret = POLLOUT | POLLWRNORM; 623 624 if (!(file->f_mode & FMODE_READ)) 625 return ret; 626 627 reader = file->private_data; 628 log = reader->log; 629 630 poll_wait(file, &log->wq, wait); 631 632 mutex_lock(&log->mutex); 633 if (!reader->r_all) 634 reader->r_off = get_next_entry_by_uid(log, 635 reader->r_off, current_euid()); 636 637 if (log->w_off != reader->r_off) 638 ret |= POLLIN | POLLRDNORM; 639 mutex_unlock(&log->mutex); 640 641 return ret; 642} 643 644static long logger_set_version(struct logger_reader *reader, void __user *arg) 645{ 646 int version; 647 648 if (copy_from_user(&version, arg, sizeof(int))) 649 return -EFAULT; 650 651 if ((version < 1) || (version > 2)) 652 return -EINVAL; 653 654 reader->r_ver = version; 655 return 0; 656} 657 658static long logger_ioctl(struct file *file, unsigned int cmd, unsigned long arg) 659{ 660 struct logger_log *log = file_get_log(file); 661 struct logger_reader *reader; 662 long ret = -EINVAL; 663 void __user *argp = (void __user *) arg; 664 665 mutex_lock(&log->mutex); 666 667 switch (cmd) { 668 case LOGGER_GET_LOG_BUF_SIZE: 669 ret = log->size; 670 break; 671 case LOGGER_GET_LOG_LEN: 672 if (!(file->f_mode & FMODE_READ)) { 673 ret = -EBADF; 674 break; 675 } 676 reader = file->private_data; 677 if (log->w_off >= reader->r_off) 678 ret = log->w_off - reader->r_off; 679 else 680 ret = (log->size - reader->r_off) + log->w_off; 681 break; 682 case LOGGER_GET_NEXT_ENTRY_LEN: 683 if (!(file->f_mode & FMODE_READ)) { 684 ret = -EBADF; 685 break; 686 } 687 reader = file->private_data; 688 689 if (!reader->r_all) 690 reader->r_off = get_next_entry_by_uid(log, 691 reader->r_off, current_euid()); 692 693 if (log->w_off != reader->r_off) 694 ret = get_user_hdr_len(reader->r_ver) + 695 get_entry_msg_len(log, reader->r_off); 696 else 697 ret = 0; 698 break; 699 case LOGGER_FLUSH_LOG: 700 if (!(file->f_mode & FMODE_WRITE)) { 701 ret = -EBADF; 702 break; 703 } 704 if (!(in_egroup_p(file_inode(file)->i_gid) || 705 capable(CAP_SYSLOG))) { 706 ret = -EPERM; 707 break; 708 } 709 list_for_each_entry(reader, &log->readers, list) 710 reader->r_off = log->w_off; 711 log->head = log->w_off; 712 ret = 0; 713 break; 714 case LOGGER_GET_VERSION: 715 if (!(file->f_mode & FMODE_READ)) { 716 ret = -EBADF; 717 break; 718 } 719 reader = file->private_data; 720 ret = reader->r_ver; 721 break; 722 case LOGGER_SET_VERSION: 723 if (!(file->f_mode & FMODE_READ)) { 724 ret = -EBADF; 725 break; 726 } 727 reader = file->private_data; 728 ret = logger_set_version(reader, argp); 729 break; 730 } 731 732 mutex_unlock(&log->mutex); 733 734 return ret; 735} 736 737static const struct file_operations logger_fops = { 738 .owner = THIS_MODULE, 739 .read = logger_read, 740 .aio_write = logger_aio_write, 741 .poll = logger_poll, 742 .unlocked_ioctl = logger_ioctl, 743 .compat_ioctl = logger_ioctl, 744 .open = logger_open, 745 .release = logger_release, 746}; 747 748/* 749 * Log size must must be a power of two, and greater than 750 * (LOGGER_ENTRY_MAX_PAYLOAD + sizeof(struct logger_entry)). 751 */ 752static int __init create_log(char *log_name, int size) 753{ 754 int ret = 0; 755 struct logger_log *log; 756 unsigned char *buffer; 757 758 buffer = vmalloc(size); 759 if (buffer == NULL) 760 return -ENOMEM; 761 762 log = kzalloc(sizeof(struct logger_log), GFP_KERNEL); 763 if (log == NULL) { 764 ret = -ENOMEM; 765 goto out_free_buffer; 766 } 767 log->buffer = buffer; 768 769 log->misc.minor = MISC_DYNAMIC_MINOR; 770 log->misc.name = kstrdup(log_name, GFP_KERNEL); 771 if (log->misc.name == NULL) { 772 ret = -ENOMEM; 773 goto out_free_log; 774 } 775 776 log->misc.fops = &logger_fops; 777 log->misc.parent = NULL; 778 779 init_waitqueue_head(&log->wq); 780 INIT_LIST_HEAD(&log->readers); 781 mutex_init(&log->mutex); 782 log->w_off = 0; 783 log->head = 0; 784 log->size = size; 785 786 INIT_LIST_HEAD(&log->logs); 787 list_add_tail(&log->logs, &log_list); 788 789 /* finally, initialize the misc device for this log */ 790 ret = misc_register(&log->misc); 791 if (unlikely(ret)) { 792 pr_err("failed to register misc device for log '%s'!\n", 793 log->misc.name); 794 goto out_free_log; 795 } 796 797 pr_info("created %luK log '%s'\n", 798 (unsigned long) log->size >> 10, log->misc.name); 799 800 return 0; 801 802out_free_log: 803 kfree(log); 804 805out_free_buffer: 806 vfree(buffer); 807 return ret; 808} 809 810static int __init logger_init(void) 811{ 812 int ret; 813 814 ret = create_log(LOGGER_LOG_MAIN, 256*1024); 815 if (unlikely(ret)) 816 goto out; 817 818 ret = create_log(LOGGER_LOG_EVENTS, 256*1024); 819 if (unlikely(ret)) 820 goto out; 821 822 ret = create_log(LOGGER_LOG_RADIO, 256*1024); 823 if (unlikely(ret)) 824 goto out; 825 826 ret = create_log(LOGGER_LOG_SYSTEM, 256*1024); 827 if (unlikely(ret)) 828 goto out; 829 830out: 831 return ret; 832} 833 834static void __exit logger_exit(void) 835{ 836 struct logger_log *current_log, *next_log; 837 838 list_for_each_entry_safe(current_log, next_log, &log_list, logs) { 839 /* we have to delete all the entry inside log_list */ 840 misc_deregister(&current_log->misc); 841 vfree(current_log->buffer); 842 kfree(current_log->misc.name); 843 list_del(&current_log->logs); 844 kfree(current_log); 845 } 846} 847 848 849device_initcall(logger_init); 850module_exit(logger_exit); 851 852MODULE_LICENSE("GPL"); 853MODULE_AUTHOR("Robert Love, <rlove@google.com>"); 854MODULE_DESCRIPTION("Android Logger");