X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/d9a64523371fa019c4575bb400cbbc3a50ac9903..0a7de7458d150b5d4dffc935ba399be265ef0a1a:/bsd/kern/subr_log.c?ds=sidebyside diff --git a/bsd/kern/subr_log.c b/bsd/kern/subr_log.c index ff45d5c8a..46475b683 100644 --- a/bsd/kern/subr_log.c +++ b/bsd/kern/subr_log.c @@ -111,23 +111,23 @@ uint32_t oslog_s_streamed_msgcount = 0; uint32_t oslog_s_dropped_msgcount = 0; extern uint32_t oslog_s_error_count; -#define LOG_RDPRI (PZERO + 1) +#define LOG_RDPRI (PZERO + 1) -#define LOG_NBIO 0x02 -#define LOG_ASYNC 0x04 -#define LOG_RDWAIT 0x08 +#define LOG_NBIO 0x02 +#define LOG_ASYNC 0x04 +#define LOG_RDWAIT 0x08 /* All globals should be accessed under LOG_LOCK() */ static char amsg_bufc[1024]; -static struct msgbuf aslbuf = {MSG_MAGIC, sizeof (amsg_bufc), 0, 0, amsg_bufc}; +static struct msgbuf aslbuf = {MSG_MAGIC, sizeof(amsg_bufc), 0, 0, amsg_bufc}; struct msgbuf *aslbufp __attribute__((used)) = &aslbuf; /* logsoftc only valid while log_open=1 */ struct logsoftc { - int sc_state; /* see above for possibilities */ - struct selinfo sc_selp; /* thread waiting for select */ - int sc_pgid; /* process/group for async I/O */ + int sc_state; /* see above for possibilities */ + struct selinfo sc_selp; /* thread waiting for select */ + int sc_pgid; /* process/group for async I/O */ struct msgbuf *sc_mbp; } logsoftc; @@ -152,35 +152,36 @@ struct msgbuf *oslog_streambufp __attribute__((used)) = &oslog_stream_buf; // List entries for keeping track of the streaming buffer static oslog_stream_buf_entry_t oslog_stream_buf_entries; -#define OSLOG_NUM_STREAM_ENTRIES 64 -#define OSLOG_STREAM_BUF_SIZE 4096 +#define OSLOG_NUM_STREAM_ENTRIES 64 +#define OSLOG_STREAM_BUF_SIZE 4096 -int oslog_open = 0; -int os_log_wakeup = 0; -int oslog_stream_open = 0; -int oslog_stream_buf_size = OSLOG_STREAM_BUF_SIZE; -int oslog_stream_num_entries = OSLOG_NUM_STREAM_ENTRIES; +int oslog_open = 0; +int os_log_wakeup = 0; +int oslog_stream_open = 0; +int oslog_stream_buf_bytesavail = 0; +int oslog_stream_buf_size = OSLOG_STREAM_BUF_SIZE; +int oslog_stream_num_entries = OSLOG_NUM_STREAM_ENTRIES; uint8_t __firehose_buffer_kernel_chunk_count = FIREHOSE_BUFFER_KERNEL_DEFAULT_CHUNK_COUNT; uint8_t __firehose_num_kernel_io_pages = FIREHOSE_BUFFER_KERNEL_DEFAULT_IO_PAGES; /* oslogsoftc only valid while oslog_open=1 */ struct oslogsoftc { - int sc_state; /* see above for possibilities */ - struct selinfo sc_selp; /* thread waiting for select */ - int sc_pgid; /* process/group for async I/O */ + int sc_state; /* see above for possibilities */ + struct selinfo sc_selp; /* thread waiting for select */ + int sc_pgid; /* process/group for async I/O */ } oslogsoftc; struct oslog_streamsoftc { - int sc_state; /* see above for possibilities */ - struct selinfo sc_selp; /* thread waiting for select */ - int sc_pgid; /* process/group for async I/O */ + int sc_state; /* see above for possibilities */ + struct selinfo sc_selp; /* thread waiting for select */ + int sc_pgid; /* process/group for async I/O */ } oslog_streamsoftc; STAILQ_HEAD(, oslog_stream_buf_entry_s) oslog_stream_free_head = - STAILQ_HEAD_INITIALIZER(oslog_stream_free_head); + STAILQ_HEAD_INITIALIZER(oslog_stream_free_head); STAILQ_HEAD(, oslog_stream_buf_entry_s) oslog_stream_buf_head = - STAILQ_HEAD_INITIALIZER(oslog_stream_buf_head); + STAILQ_HEAD_INITIALIZER(oslog_stream_buf_head); /* defined in osfmk/kern/printf.c */ extern void oslog_lock_init(void); @@ -195,6 +196,8 @@ void bsd_log_init(void); * for lock groups. */ decl_lck_spin_data(extern, oslog_stream_lock) +#define stream_lock() lck_spin_lock(&oslog_stream_lock) +#define stream_unlock() lck_spin_unlock(&oslog_stream_lock) /* XXX wants a linker set so these can be static */ extern d_open_t logopen; @@ -219,7 +222,7 @@ extern d_select_t oslog_streamselect; void oslog_init(void); void oslog_setsize(int size); void oslog_streamwrite_locked(firehose_tracepoint_id_u ftid, - uint64_t stamp, const void *pubdata, size_t publen); + uint64_t stamp, const void *pubdata, size_t publen); void oslog_streamwrite_metadata_locked(oslog_stream_buf_entry_t m_entry); static oslog_stream_buf_entry_t oslog_stream_find_free_buf_entry_locked(void); static void oslog_streamwrite_append_bytes(const char *buffer, int buflen); @@ -230,8 +233,8 @@ static void oslog_streamwrite_append_bytes(const char *buffer, int buflen); * at interrupt level must be guarded with a spin lock. */ -#define LOG_LOCK() bsd_log_lock() -#define LOG_UNLOCK() bsd_log_unlock() +#define LOG_LOCK() bsd_log_lock() +#define LOG_UNLOCK() bsd_log_unlock() #if DEBUG #define LOG_SETSIZE_DEBUG(x...) kprintf(x) @@ -240,7 +243,7 @@ static void oslog_streamwrite_append_bytes(const char *buffer, int buflen); #endif static int sysctl_kern_msgbuf(struct sysctl_oid *oidp, - void *arg1, int arg2, struct sysctl_req *req); + void *arg1, int arg2, struct sysctl_req *req); /*ARGSUSED*/ int @@ -249,7 +252,7 @@ logopen(__unused dev_t dev, __unused int flags, __unused int mode, struct proc * LOG_LOCK(); if (log_open) { LOG_UNLOCK(); - return (EBUSY); + return EBUSY; } if (atm_get_diagnostic_config() & ATM_ENABLE_LEGACY_LOGGING) { logsoftc.sc_mbp = msgbufp; @@ -261,12 +264,12 @@ logopen(__unused dev_t dev, __unused int flags, __unused int mode, struct proc * */ logsoftc.sc_mbp = aslbufp; } - logsoftc.sc_pgid = p->p_pid; /* signal process only */ + logsoftc.sc_pgid = p->p_pid; /* signal process only */ log_open = 1; LOG_UNLOCK(); - return (0); + return 0; } /*ARGSUSED*/ @@ -279,7 +282,7 @@ logclose(__unused dev_t dev, __unused int flag, __unused int devtype, __unused s selthreadclear(&logsoftc.sc_selp); log_open = 0; LOG_UNLOCK(); - return (0); + return 0; } @@ -289,13 +292,13 @@ oslogopen(__unused dev_t dev, __unused int flags, __unused int mode, struct proc LOG_LOCK(); if (oslog_open) { LOG_UNLOCK(); - return(EBUSY); + return EBUSY; } - oslogsoftc.sc_pgid = p->p_pid; /* signal process only */ + oslogsoftc.sc_pgid = p->p_pid; /* signal process only */ oslog_open = 1; LOG_UNLOCK(); - return (0); + return 0; } int @@ -307,7 +310,7 @@ oslogclose(__unused dev_t dev, __unused int flag, __unused int devtype, __unused selthreadclear(&oslogsoftc.sc_selp); oslog_open = 0; LOG_UNLOCK(); - return (0); + return 0; } int @@ -316,12 +319,12 @@ oslog_streamopen(__unused dev_t dev, __unused int flags, __unused int mode, stru char *oslog_stream_msg_bufc = NULL; oslog_stream_buf_entry_t entries = NULL; - lck_spin_lock(&oslog_stream_lock); + stream_lock(); if (oslog_stream_open) { - lck_spin_unlock(&oslog_stream_lock); + stream_unlock(); return EBUSY; } - lck_spin_unlock(&oslog_stream_lock); + stream_unlock(); // Allocate the stream buffer oslog_stream_msg_bufc = kalloc(oslog_stream_buf_size); @@ -336,9 +339,9 @@ oslog_streamopen(__unused dev_t dev, __unused int flags, __unused int mode, stru return ENOMEM; } - lck_spin_lock(&oslog_stream_lock); + stream_lock(); if (oslog_stream_open) { - lck_spin_unlock(&oslog_stream_lock); + stream_unlock(); kfree(oslog_stream_msg_bufc, oslog_stream_buf_size); kfree(entries, oslog_stream_num_entries * sizeof(struct oslog_stream_buf_entry_s)); return EBUSY; @@ -370,7 +373,8 @@ oslog_streamopen(__unused dev_t dev, __unused int flags, __unused int mode, stru oslog_streambufp->msg_bufr = 0; oslog_streamsoftc.sc_pgid = p->p_pid; /* signal process only */ oslog_stream_open = 1; - lck_spin_unlock(&oslog_stream_lock); + oslog_stream_buf_bytesavail = oslog_stream_buf_size; + stream_unlock(); return 0; } @@ -382,10 +386,10 @@ oslog_streamclose(__unused dev_t dev, __unused int flag, __unused int devtype, _ char *oslog_stream_msg_bufc = NULL; oslog_stream_buf_entry_t entries = NULL; - lck_spin_lock(&oslog_stream_lock); + stream_lock(); if (oslog_stream_open == 0) { - lck_spin_unlock(&oslog_stream_lock); + stream_unlock(); return EBADF; } @@ -407,7 +411,7 @@ oslog_streamclose(__unused dev_t dev, __unused int flag, __unused int devtype, _ oslog_stream_buf_entries = NULL; oslog_streambufp->msg_size = 0; - lck_spin_unlock(&oslog_stream_lock); + stream_unlock(); // Free the stream buffer kfree(oslog_stream_msg_bufc, oslog_stream_buf_size); @@ -438,14 +442,15 @@ logread(__unused dev_t dev, struct uio *uio, int flag) logsoftc.sc_state |= LOG_RDWAIT; LOG_UNLOCK(); /* - * If the wakeup is missed - * then wait for 5 sec and reevaluate + * If the wakeup is missed + * then wait for 5 sec and reevaluate */ if ((error = tsleep((caddr_t)mbp, LOG_RDPRI | PCATCH, - "klog", 5 * hz)) != 0) { + "klog", 5 * hz)) != 0) { /* if it times out; ignore */ - if (error != EWOULDBLOCK) - return (error); + if (error != EWOULDBLOCK) { + return error; + } } LOG_LOCK(); } @@ -455,25 +460,29 @@ logread(__unused dev_t dev, struct uio *uio, int flag) int readpos; l = mbp->msg_bufx - mbp->msg_bufr; - if (l < 0) + if (l < 0) { l = mbp->msg_size - mbp->msg_bufr; + } l = min(l, uio_resid(uio)); - if (l == 0) + if (l == 0) { break; + } readpos = mbp->msg_bufr; LOG_UNLOCK(); error = uiomove((caddr_t)&mbp->msg_bufc[readpos], l, uio); LOG_LOCK(); - if (error) + if (error) { break; + } mbp->msg_bufr = readpos + l; - if (mbp->msg_bufr >= mbp->msg_size) + if (mbp->msg_bufr >= mbp->msg_size) { mbp->msg_bufr = 0; + } } out: LOG_UNLOCK(); - return (error); + return error; } /*ARGSUSED*/ @@ -484,40 +493,42 @@ oslog_streamread(__unused dev_t dev, struct uio *uio, int flag) int copy_size = 0; static char logline[FIREHOSE_CHUNK_SIZE]; - lck_spin_lock(&oslog_stream_lock); + stream_lock(); if (!oslog_stream_open) { - lck_spin_unlock(&oslog_stream_lock); + stream_unlock(); return EBADF; } while (STAILQ_EMPTY(&oslog_stream_buf_head)) { + assert(oslog_stream_buf_bytesavail == oslog_stream_buf_size); + if (flag & IO_NDELAY || oslog_streamsoftc.sc_state & LOG_NBIO) { - lck_spin_unlock(&oslog_stream_lock); + stream_unlock(); return EWOULDBLOCK; } oslog_streamsoftc.sc_state |= LOG_RDWAIT; wait_result_t wr = assert_wait((event_t)oslog_streambufp, - THREAD_INTERRUPTIBLE); + THREAD_INTERRUPTIBLE); if (wr == THREAD_WAITING) { - lck_spin_unlock(&oslog_stream_lock); + stream_unlock(); wr = thread_block(THREAD_CONTINUE_NULL); - lck_spin_lock(&oslog_stream_lock); + stream_lock(); } switch (wr) { - case THREAD_AWAKENED: - case THREAD_TIMED_OUT: - break; - default: - lck_spin_unlock(&oslog_stream_lock); - return EINTR; + case THREAD_AWAKENED: + case THREAD_TIMED_OUT: + break; + default: + stream_unlock(); + return EINTR; } } if (!oslog_stream_open) { - lck_spin_unlock(&oslog_stream_lock); + stream_unlock(); return EBADF; } @@ -534,60 +545,64 @@ oslog_streamread(__unused dev_t dev, struct uio *uio, int flag) logpos += sizeof(uint64_t); switch (read_entry->type) { - /* Handle metadata messages */ - case oslog_stream_link_type_metadata: - { - memcpy(logline + logpos, - (read_entry->metadata), read_entry->size); - logpos += read_entry->size; + /* Handle metadata messages */ + case oslog_stream_link_type_metadata: + { + memcpy(logline + logpos, + (read_entry->metadata), read_entry->size); + logpos += read_entry->size; - lck_spin_unlock(&oslog_stream_lock); + stream_unlock(); - // Free the list entry - kfree(read_entry, (sizeof(struct oslog_stream_buf_entry_s) + read_entry->size)); - break; - } - /* Handle log messages */ - case oslog_stream_link_type_log: - { - /* ensure that the correct read entry was dequeued */ - assert(read_entry->offset == oslog_streambufp->msg_bufr); - rec_length = read_entry->size; - - // If the next log line is contiguous in the buffer, copy it out. - if(read_entry->offset + rec_length <= oslog_streambufp->msg_size) { - memcpy(logline + logpos, - oslog_streambufp->msg_bufc + read_entry->offset, rec_length); - - oslog_streambufp->msg_bufr += rec_length; - if (oslog_streambufp->msg_bufr == oslog_streambufp->msg_size) { - oslog_streambufp->msg_bufr = 0; - } - logpos += rec_length; - } else { - // Otherwise, copy until the end of the buffer, and - // copy the remaining bytes starting at index 0. - int bytes_left = oslog_streambufp->msg_size - read_entry->offset; - memcpy(logline + logpos, - oslog_streambufp->msg_bufc + read_entry->offset, bytes_left); - logpos += bytes_left; - rec_length -= bytes_left; - - memcpy(logline + logpos, (const void *)oslog_streambufp->msg_bufc, - rec_length); - oslog_streambufp->msg_bufr = rec_length; - logpos += rec_length; - } - assert(oslog_streambufp->msg_bufr < oslog_streambufp->msg_size); - STAILQ_INSERT_TAIL(&oslog_stream_free_head, read_entry, buf_entries); + // Free the list entry + kfree(read_entry, (sizeof(struct oslog_stream_buf_entry_s) + read_entry->size)); + break; + } + /* Handle log messages */ + case oslog_stream_link_type_log: + { + /* ensure that the correct read entry was dequeued */ + assert(read_entry->offset == oslog_streambufp->msg_bufr); + rec_length = read_entry->size; + + // If the next log line is contiguous in the buffer, copy it out. + if (read_entry->offset + rec_length <= oslog_streambufp->msg_size) { + memcpy(logline + logpos, + oslog_streambufp->msg_bufc + read_entry->offset, rec_length); - lck_spin_unlock(&oslog_stream_lock); - break; - } - default: - { - panic("Got unexpected log entry type: %hhu\n", read_entry->type); + oslog_streambufp->msg_bufr += rec_length; + if (oslog_streambufp->msg_bufr == oslog_streambufp->msg_size) { + oslog_streambufp->msg_bufr = 0; + } + logpos += rec_length; + } else { + // Otherwise, copy until the end of the buffer, and + // copy the remaining bytes starting at index 0. + int bytes_left = oslog_streambufp->msg_size - read_entry->offset; + memcpy(logline + logpos, + oslog_streambufp->msg_bufc + read_entry->offset, bytes_left); + logpos += bytes_left; + rec_length -= bytes_left; + + memcpy(logline + logpos, (const void *)oslog_streambufp->msg_bufc, + rec_length); + oslog_streambufp->msg_bufr = rec_length; + logpos += rec_length; } + + oslog_stream_buf_bytesavail += read_entry->size; + assert(oslog_stream_buf_bytesavail <= oslog_stream_buf_size); + + assert(oslog_streambufp->msg_bufr < oslog_streambufp->msg_size); + STAILQ_INSERT_TAIL(&oslog_stream_free_head, read_entry, buf_entries); + + stream_unlock(); + break; + } + default: + { + panic("Got unexpected log entry type: %hhu\n", read_entry->type); + } } copy_size = min(logpos, uio_resid(uio)); @@ -606,36 +621,34 @@ logselect(__unused dev_t dev, int rw, void * wql, struct proc *p) const struct msgbuf *mbp = logsoftc.sc_mbp; switch (rw) { - case FREAD: - LOG_LOCK(); + LOG_LOCK(); if (mbp->msg_bufr != mbp->msg_bufx) { LOG_UNLOCK(); - return (1); + return 1; } selrecord(p, &logsoftc.sc_selp, wql); LOG_UNLOCK(); break; } - return (0); + return 0; } int oslogselect(__unused dev_t dev, int rw, void * wql, struct proc *p) { switch (rw) { - case FREAD: LOG_LOCK(); if (os_log_wakeup) { LOG_UNLOCK(); - return (1); + return 1; } selrecord(p, &oslogsoftc.sc_selp, wql); LOG_UNLOCK(); break; } - return (0); + return 0; } int @@ -643,7 +656,7 @@ oslog_streamselect(__unused dev_t dev, int rw, void * wql, struct proc *p) { int ret = 0; - lck_spin_lock(&oslog_stream_lock); + stream_lock(); switch (rw) { case FREAD: @@ -655,7 +668,7 @@ oslog_streamselect(__unused dev_t dev, int rw, void * wql, struct proc *p) break; } - lck_spin_unlock(&oslog_stream_lock); + stream_unlock(); return ret; } @@ -667,23 +680,26 @@ logwakeup(struct msgbuf *mbp) return; } - LOG_LOCK(); + LOG_LOCK(); if (!log_open) { LOG_UNLOCK(); return; } - if (NULL == mbp) + if (NULL == mbp) { mbp = logsoftc.sc_mbp; - if (mbp != logsoftc.sc_mbp) + } + if (mbp != logsoftc.sc_mbp) { goto out; + } selwakeup(&logsoftc.sc_selp); if (logsoftc.sc_state & LOG_ASYNC) { int pgid = logsoftc.sc_pgid; LOG_UNLOCK(); - if (pgid < 0) - gsignal(-pgid, SIGIO); - else + if (pgid < 0) { + gsignal(-pgid, SIGIO); + } else { proc_signal(pgid, SIGIO); + } LOG_LOCK(); } if (logsoftc.sc_state & LOG_RDWAIT) { @@ -729,9 +745,9 @@ oslog_streamwakeup(void) return; } - lck_spin_lock(&oslog_stream_lock); + stream_lock(); oslog_streamwakeup_locked(); - lck_spin_unlock(&oslog_stream_lock); + stream_unlock(); } /*ARGSUSED*/ @@ -743,27 +759,29 @@ logioctl(__unused dev_t dev, u_long com, caddr_t data, __unused int flag, __unus LOG_LOCK(); switch (com) { - /* return number of characters immediately available */ case FIONREAD: l = mbp->msg_bufx - mbp->msg_bufr; - if (l < 0) + if (l < 0) { l += mbp->msg_size; + } *(off_t *)data = l; break; case FIONBIO: - if (*(int *)data) + if (*(int *)data) { logsoftc.sc_state |= LOG_NBIO; - else + } else { logsoftc.sc_state &= ~LOG_NBIO; + } break; case FIOASYNC: - if (*(int *)data) + if (*(int *)data) { logsoftc.sc_state |= LOG_ASYNC; - else + } else { logsoftc.sc_state &= ~LOG_ASYNC; + } break; case TIOCSPGRP: @@ -776,10 +794,10 @@ logioctl(__unused dev_t dev, u_long com, caddr_t data, __unused int flag, __unus default: LOG_UNLOCK(); - return (-1); + return -1; } LOG_UNLOCK(); - return (0); + return 0; } /*ARGSUSED*/ @@ -794,32 +812,31 @@ oslogioctl(__unused dev_t dev, u_long com, caddr_t data, __unused int flag, __un mach_port_t mem_entry_ptr = MACH_PORT_NULL; switch (com) { - /* return number of characters immediately available */ case LOGBUFFERMAP: kernel_firehose_buffer = (firehose_buffer_t)kernel_firehose_addr; ret = mach_make_memory_entry_64(kernel_map, - &buffer_size, - (mach_vm_offset_t) kernel_firehose_buffer, - ( MAP_MEM_VM_SHARE | VM_PROT_READ ), - &mem_entry_ptr, - MACH_PORT_NULL); + &buffer_size, + (mach_vm_offset_t) kernel_firehose_buffer, + (MAP_MEM_VM_SHARE | VM_PROT_READ), + &mem_entry_ptr, + MACH_PORT_NULL); if (ret == KERN_SUCCESS) { ret = mach_vm_map_kernel(get_task_map(current_task()), - &user_addr, - buffer_size, - 0, /* mask */ - VM_FLAGS_ANYWHERE, - VM_MAP_KERNEL_FLAGS_NONE, - VM_KERN_MEMORY_NONE, - mem_entry_ptr, - 0, /* offset */ - FALSE, /* copy */ - VM_PROT_READ, - VM_PROT_READ, - VM_INHERIT_SHARE); + &user_addr, + buffer_size, + 0, /* mask */ + VM_FLAGS_ANYWHERE, + VM_MAP_KERNEL_FLAGS_NONE, + VM_KERN_MEMORY_NONE, + mem_entry_ptr, + 0, /* offset */ + FALSE, /* copy */ + VM_PROT_READ, + VM_PROT_READ, + VM_INHERIT_SHARE); } if (ret == KERN_SUCCESS) { @@ -835,9 +852,9 @@ oslogioctl(__unused dev_t dev, u_long com, caddr_t data, __unused int flag, __un __firehose_merge_updates(*(firehose_push_reply_t *)(data)); break; default: - return (-1); + return -1; } - return (0); + return 0; } /*ARGSUSED*/ @@ -846,27 +863,29 @@ oslog_streamioctl(__unused dev_t dev, u_long com, caddr_t data, __unused int fla { int err = 0; - lck_spin_lock(&oslog_stream_lock); + stream_lock(); switch (com) { case FIONBIO: - if (data && *(int *)data) + if (data && *(int *)data) { oslog_streamsoftc.sc_state |= LOG_NBIO; - else + } else { oslog_streamsoftc.sc_state &= ~LOG_NBIO; + } break; case FIOASYNC: - if (data && *(int *)data) + if (data && *(int *)data) { oslog_streamsoftc.sc_state |= LOG_ASYNC; - else + } else { oslog_streamsoftc.sc_state &= ~LOG_ASYNC; + } break; default: err = -1; break; } - lck_spin_unlock(&oslog_stream_lock); + stream_unlock(); return err; } @@ -896,8 +915,8 @@ oslog_init(void) oslog_lock_init(); kr = kmem_alloc_flags(kernel_map, &kernel_firehose_addr, - size + (2 * PAGE_SIZE), VM_KERN_MEMORY_LOG, - KMA_GUARD_FIRST | KMA_GUARD_LAST); + size + (2 * PAGE_SIZE), VM_KERN_MEMORY_LOG, + KMA_GUARD_FIRST | KMA_GUARD_LAST); if (kr != KERN_SUCCESS) { panic("Failed to allocate memory for firehose logging buffer"); } @@ -928,8 +947,9 @@ void log_putc_locked(struct msgbuf *mbp, char c) { mbp->msg_bufc[mbp->msg_bufx++] = c; - if (mbp->msg_bufx >= mbp->msg_size) + if (mbp->msg_bufx >= mbp->msg_size) { mbp->msg_bufx = 0; + } } static oslog_stream_buf_entry_t @@ -945,8 +965,7 @@ oslog_stream_find_free_buf_entry_locked(void) buf_entry = STAILQ_FIRST(&oslog_stream_free_head); if (buf_entry) { STAILQ_REMOVE_HEAD(&oslog_stream_free_head, buf_entries); - } - else { + } else { // If no list elements are available in the free-list, // consume the next log line so we can free up its list element oslog_stream_buf_entry_t prev_entry = NULL; @@ -959,8 +978,7 @@ oslog_stream_find_free_buf_entry_locked(void) if (prev_entry == NULL) { STAILQ_REMOVE_HEAD(&oslog_stream_buf_head, buf_entries); - } - else { + } else { STAILQ_REMOVE_AFTER(&oslog_stream_buf_head, prev_entry, buf_entries); } @@ -990,9 +1008,16 @@ oslog_streamwrite_append_bytes(const char *buffer, int buflen) LCK_SPIN_ASSERT(&oslog_stream_lock, LCK_ASSERT_OWNED); + assert(oslog_stream_buf_bytesavail >= buflen); + oslog_stream_buf_bytesavail -= buflen; + assert(oslog_stream_buf_bytesavail >= 0); + mbp = oslog_streambufp; - // Check if we have enough space in the stream buffer to write the data if (mbp->msg_bufx + buflen <= mbp->msg_size) { + /* + * If this will fit without needing to be split across the end + * of the buffer, copy it directly in one go. + */ memcpy((void *)(mbp->msg_bufc + mbp->msg_bufx), buffer, buflen); mbp->msg_bufx += buflen; @@ -1000,7 +1025,10 @@ oslog_streamwrite_append_bytes(const char *buffer, int buflen) mbp->msg_bufx = 0; } } else { - // Copy part of the data until the end of the stream + /* + * Copy up to the end of the stream buffer, and then put what remains + * at the beginning. + */ int bytes_left = mbp->msg_size - mbp->msg_bufx; memcpy((void *)(mbp->msg_bufc + mbp->msg_bufx), buffer, bytes_left); @@ -1014,13 +1042,11 @@ oslog_streamwrite_append_bytes(const char *buffer, int buflen) return; } - void oslog_streamwrite_locked(firehose_tracepoint_id_u ftid, - uint64_t stamp, const void *pubdata, size_t publen) + uint64_t stamp, const void *pubdata, size_t publen) { struct msgbuf *mbp; - int available_space = 0; oslog_stream_buf_entry_t buf_entry = NULL; oslog_stream_buf_entry_t next_entry = NULL; @@ -1040,13 +1066,7 @@ oslog_streamwrite_locked(firehose_tracepoint_id_u ftid, assert(buf_entry != NULL); - // Ensure that we have space in the ring buffer for the current logline - if (mbp->msg_bufr > mbp->msg_bufx) { - available_space = mbp->msg_bufr - mbp->msg_bufx; - } else { - available_space = mbp->msg_size - mbp->msg_bufx + mbp->msg_bufr; - } - while(ft_length > available_space) { + while (ft_length > oslog_stream_buf_bytesavail) { oslog_stream_buf_entry_t prev_entry = NULL; next_entry = STAILQ_FIRST(&oslog_stream_buf_head); @@ -1058,8 +1078,7 @@ oslog_streamwrite_locked(firehose_tracepoint_id_u ftid, if (prev_entry == NULL) { STAILQ_REMOVE_HEAD(&oslog_stream_buf_head, buf_entries); - } - else { + } else { STAILQ_REMOVE_AFTER(&oslog_stream_buf_head, prev_entry, buf_entries); } @@ -1069,12 +1088,13 @@ oslog_streamwrite_locked(firehose_tracepoint_id_u ftid, } oslog_s_dropped_msgcount++; - available_space += next_entry->size; + oslog_stream_buf_bytesavail += next_entry->size; + assert(oslog_stream_buf_bytesavail <= oslog_stream_buf_size); STAILQ_INSERT_TAIL(&oslog_stream_free_head, next_entry, buf_entries); } - assert(ft_length <= available_space); + assert(ft_length <= oslog_stream_buf_bytesavail); // Write the log line and update the list entry for this record buf_entry->offset = mbp->msg_bufx; @@ -1123,10 +1143,12 @@ log_putc(char c) unread_count = msgbufp->msg_bufx - msgbufp->msg_bufr; LOG_UNLOCK(); - if (unread_count < 0) + if (unread_count < 0) { unread_count = 0 - unread_count; - if (c == '\n' || unread_count >= (msgbufp->msg_size / 2)) + } + if (c == '\n' || unread_count >= (msgbufp->msg_size / 2)) { logwakeup(msgbufp); + } } @@ -1149,16 +1171,18 @@ log_setsize(int size) int i, count; char *p, ch; - if (size > MAX_MSG_BSIZE) - return (EINVAL); + if (size > MAX_MSG_BSIZE) { + return EINVAL; + } - if (size <= 0) - return (EINVAL); + if (size <= 0) { + return EINVAL; + } new_logsize = size; if (!(new_logdata = (char*)kalloc(size))) { printf("log_setsize: unable to allocate memory\n"); - return (ENOMEM); + return ENOMEM; } bzero(new_logdata, new_logsize); @@ -1170,7 +1194,7 @@ log_setsize(int size) old_bufx = msgbufp->msg_bufx; LOG_SETSIZE_DEBUG("log_setsize(%d): old_logdata %p old_logsize %d old_bufr %d old_bufx %d\n", - size, old_logdata, old_logsize, old_bufr, old_bufx); + size, old_logdata, old_logsize, old_bufr, old_bufx); /* start "new_logsize" bytes before the write pointer */ if (new_logsize <= old_bufx) { @@ -1185,36 +1209,40 @@ log_setsize(int size) p = old_logdata + old_logsize - (count - old_bufx); } for (i = 0; i < count; i++) { - if (p >= old_logdata + old_logsize) + if (p >= old_logdata + old_logsize) { p = old_logdata; + } ch = *p++; new_logdata[i] = ch; } new_bufx = i; - if (new_bufx >= new_logsize) + if (new_bufx >= new_logsize) { new_bufx = 0; + } msgbufp->msg_bufx = new_bufx; new_bufr = old_bufx - old_bufr; /* how much were we trailing bufx by? */ - if (new_bufr < 0) + if (new_bufr < 0) { new_bufr += old_logsize; + } new_bufr = new_bufx - new_bufr; /* now relative to oldest data in new buffer */ - if (new_bufr < 0) + if (new_bufr < 0) { new_bufr += new_logsize; + } msgbufp->msg_bufr = new_bufr; msgbufp->msg_size = new_logsize; msgbufp->msg_bufc = new_logdata; LOG_SETSIZE_DEBUG("log_setsize(%d): new_logdata %p new_logsize %d new_bufr %d new_bufx %d\n", - size, new_logdata, new_logsize, new_bufr, new_bufx); + size, new_logdata, new_logsize, new_bufr, new_bufx); LOG_UNLOCK(); /* this memory is now dead - clear it so that it compresses better - in case of suspend to disk etc. */ + * in case of suspend to disk etc. */ bzero(old_logdata, old_logsize); if (old_logdata != smsg_bufc) { /* dynamic memory that must be freed */ @@ -1226,7 +1254,8 @@ log_setsize(int size) return 0; } -void oslog_setsize(int size) +void +oslog_setsize(int size) { uint16_t scale = 0; // If the size is less than the default stream buffer @@ -1243,12 +1272,12 @@ void oslog_setsize(int size) } SYSCTL_PROC(_kern, OID_AUTO, msgbuf, - CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_LOCKED, 0, 0, - sysctl_kern_msgbuf, "I", ""); + CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_LOCKED, 0, 0, + sysctl_kern_msgbuf, "I", ""); static int sysctl_kern_msgbuf(struct sysctl_oid *oidp __unused, - void *arg1 __unused, int arg2 __unused, struct sysctl_req *req) + void *arg1 __unused, int arg2 __unused, struct sysctl_req *req) { int old_bufsize, bufsize; int error; @@ -1258,14 +1287,15 @@ sysctl_kern_msgbuf(struct sysctl_oid *oidp __unused, LOG_UNLOCK(); error = sysctl_io_number(req, bufsize, sizeof(bufsize), &bufsize, NULL); - if (error) - return (error); + if (error) { + return error; + } if (bufsize != old_bufsize) { error = log_setsize(bufsize); } - return (error); + return error; } @@ -1289,7 +1319,7 @@ log_dmesg(user_addr_t buffer, uint32_t buffersize, int32_t * retval) /* Allocate a temporary non-circular buffer for copyout */ if (!(localbuff = (char *)kalloc(localbuff_size))) { printf("log_dmesg: unable to allocate memory\n"); - return (ENOMEM); + return ENOMEM; } /* in between here, the log could become bigger, but that's fine */ @@ -1301,21 +1331,24 @@ log_dmesg(user_addr_t buffer, uint32_t buffersize, int32_t * retval) */ p = msgbufp->msg_bufc + msgbufp->msg_bufx; for (i = newl = skip = 0; p != msgbufp->msg_bufc + msgbufp->msg_bufx - 1; ++p) { - if (p >= msgbufp->msg_bufc + msgbufp->msg_size) + if (p >= msgbufp->msg_bufc + msgbufp->msg_size) { p = msgbufp->msg_bufc; + } ch = *p; /* Skip "\n<.*>" syslog sequences. */ if (skip) { - if (ch == '>') + if (ch == '>') { newl = skip = 0; + } continue; } if (newl && ch == '<') { skip = 1; continue; } - if (ch == '\0') + if (ch == '\0') { continue; + } newl = (ch == '\n'); localbuff[i++] = ch; /* The original version of this routine contained a buffer @@ -1323,11 +1356,13 @@ log_dmesg(user_addr_t buffer, uint32_t buffersize, int32_t * retval) * so the change below to check the buffer bounds was made. * TODO: rewrite this needlessly convoluted routine. */ - if (i == (localbuff_size - 2)) + if (i == (localbuff_size - 2)) { break; + } } - if (!newl) + if (!newl) { localbuff[i++] = '\n'; + } localbuff[i++] = 0; if (buffersize >= i) { @@ -1341,11 +1376,12 @@ log_dmesg(user_addr_t buffer, uint32_t buffersize, int32_t * retval) LOG_UNLOCK(); error = copyout(copystart, buffer, copysize); - if (!error) + if (!error) { *retval = copysize; + } kfree(localbuff, localbuff_size); - return (error); + return error; } #ifdef CONFIG_XNUPOST