diff options
Diffstat (limited to 'accel-pppd/logs/log_file.c')
-rw-r--r-- | accel-pppd/logs/log_file.c | 272 |
1 files changed, 99 insertions, 173 deletions
diff --git a/accel-pppd/logs/log_file.c b/accel-pppd/logs/log_file.c index 3a618237..cc8c1bc4 100644 --- a/accel-pppd/logs/log_file.c +++ b/accel-pppd/logs/log_file.c @@ -9,6 +9,7 @@ #include <signal.h> #include <sys/stat.h> #include <sys/types.h> +#include <sys/uio.h> #include "log.h" #include "events.h" @@ -26,8 +27,7 @@ #define BLUE_COLOR "\033[1;34m" #define NORMAL_COLOR "\033[0;39m" -struct log_file_t -{ +struct log_file_t { struct list_head entry; struct list_head msgs; spinlock_t lock; @@ -37,30 +37,26 @@ struct log_file_t int fd; int new_fd; - off_t offset; - unsigned long magic; }; -struct log_file_pd_t -{ +struct log_file_pd_t { struct ap_private pd; struct log_file_t lf; unsigned long tmp; }; -struct fail_log_pd_t -{ +struct fail_log_pd_t { struct ap_private pd; struct list_head msgs; }; - static int conf_color; static int conf_per_session; static char *conf_per_user_dir; static char *conf_per_session_dir; static int conf_copy; static int conf_fail_log; +static pthread_t log_thr; static const char* level_name[]={" msg", "error", " warn", " info", " info", "debug"}; static const char* level_color[]={NORMAL_COLOR, RED_COLOR, YELLOW_COLOR, GREEN_COLOR, GREEN_COLOR, BLUE_COLOR}; @@ -74,23 +70,13 @@ static struct log_file_t *fail_log_file; static mempool_t lpd_pool; static mempool_t fpd_pool; -static char *log_buf; - -static struct aiocb aiocb = { - .aio_lio_opcode = LIO_WRITE, - .aio_sigevent.sigev_notify = SIGEV_SIGNAL, - .aio_sigevent.sigev_signo = SIGIO, -}; static LIST_HEAD(lf_queue); -static spinlock_t lf_queue_lock = SPINLOCK_INITIALIZER; -static int lf_queue_sleeping = 1; +static pthread_cond_t cond = PTHREAD_COND_INITIALIZER; +static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; static unsigned long temp_seq; -static void send_next_chunk(); - - static void log_file_init(struct log_file_t *lf) { spinlock_init(&lf->lock); @@ -101,147 +87,84 @@ static void log_file_init(struct log_file_t *lf) static int log_file_open(struct log_file_t *lf, const char *fname) { - lf->fd = open(fname, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR); + lf->fd = open(fname, O_WRONLY | O_CREAT | O_APPEND | O_CLOEXEC, S_IRUSR | S_IWUSR); if (lf->fd < 0) { log_emerg("log_file: open '%s': %s\n", fname, strerror(errno)); return -1; } - fcntl(lf->fd, F_SETFD, fcntl(lf->fd, F_GETFD) | FD_CLOEXEC); - - lf->offset = lseek(lf->fd, 0, SEEK_END); - return 0; } -static void sigio(int num, siginfo_t *si, void *uc) +static void *log_thread(void *unused) { struct log_file_t *lf; - int n; - - if (si->si_signo != SIGIO) - return; - - if (si->si_code != SI_ASYNCIO) { - if (aio_write(&aiocb)) - log_emerg("log_file: aio_write: %s\n", strerror(errno)); - return; - } - - lf = (struct log_file_t *)si->si_ptr; - - n = aio_return(&aiocb); - if (n < 0) - log_emerg("log_file: %s\n", strerror(aio_error(&aiocb))); - else if (n != aiocb.aio_nbytes) - log_emerg("log_file: short write %p %i %lu\n", lf, n, aiocb.aio_nbytes); - - spin_lock(&lf->lock); - lf->offset += n; - if (list_empty(&lf->msgs)) { - if (lf->need_free) { - spin_unlock(&lf->lock); - close(lf->fd); - mempool_free(lf->lpd); - } else { - lf->queued = 0; - spin_unlock(&lf->lock); - } - } else { - spin_unlock(&lf->lock); - - spin_lock(&lf_queue_lock); - list_add_tail(&lf->entry, &lf_queue); - spin_unlock(&lf_queue_lock); - } - - send_next_chunk(); -} - -static int dequeue_log(struct log_file_t *lf) -{ - int n, pos = 0; - struct log_msg_t *msg; + struct iovec iov[IOV_MAX]; struct log_chunk_t *chunk; + struct log_msg_t *msg; + int iov_cnt = 0; while (1) { - spin_lock(&lf->lock); - if (list_empty(&lf->msgs)) { + pthread_mutex_lock(&lock); + if (list_empty(&lf_queue)) + pthread_cond_wait(&cond, &lock); + lf = list_first_entry(&lf_queue, typeof(*lf), entry); + list_del(&lf->entry); + pthread_mutex_unlock(&lock); + + iov_cnt = 0; + + while (1) { + spin_lock(&lf->lock); + if (list_empty(&lf->msgs)) { + lf->queued = 0; + if (lf->need_free) { + spin_unlock(&lf->lock); + close(lf->fd); + if (lf->new_fd != -1) + close(lf->new_fd); + mempool_free(lf->lpd); + } else { + spin_unlock(&lf->lock); + + if (iov_cnt) + writev(lf->fd, iov, iov_cnt); + + if (lf->new_fd != -1) { + close(lf->fd); + lf->fd = lf->new_fd; + lf->new_fd = -1; + } + } + break; + } + + msg = list_first_entry(&lf->msgs, typeof(*msg), entry); + list_del(&msg->entry); spin_unlock(&lf->lock); - return pos; - } - msg = list_entry(lf->msgs.next, typeof(*msg), entry); - list_del(&msg->entry); - spin_unlock(&lf->lock); - - if (pos + msg->hdr->len > LOG_BUF_SIZE) - goto overrun; - memcpy(log_buf + pos, msg->hdr->msg, msg->hdr->len); - n = msg->hdr->len; - - list_for_each_entry(chunk, msg->chunks, entry) { - if (pos + n + chunk->len > LOG_BUF_SIZE) - goto overrun; - memcpy(log_buf + pos + n, chunk->msg, chunk->len); - n += chunk->len; - } - - log_free_msg(msg); - pos += n; - } - -overrun: - spin_lock(&lf->lock); - list_add(&msg->entry, &lf->msgs); - spin_unlock(&lf->lock); - - return pos; -} - -static void send_next_chunk(void) -{ - struct log_file_t *lf; - spin_lock(&lf_queue_lock); - if (list_empty(&lf_queue)) { - lf_queue_sleeping = 1; - spin_unlock(&lf_queue_lock); - return; - } - lf = list_entry(lf_queue.next, typeof(*lf), entry); - - list_del(&lf->entry); - - spin_unlock(&lf_queue_lock); - - if (lf->new_fd != -1) { - close(lf->fd); - lf->fd = lf->new_fd; - lf->new_fd = -1; - lf->offset = 0; + list_for_each_entry(chunk, msg->chunks, entry) { + iov[iov_cnt].iov_base = chunk->msg; + iov[iov_cnt].iov_len = chunk->len; + if (++iov_cnt == IOV_MAX) { + writev(lf->fd, iov, iov_cnt); + iov_cnt = 0; + } + } + + log_free_msg(msg); + } } - aiocb.aio_fildes = lf->fd; - aiocb.aio_offset = lf->offset; - aiocb.aio_sigevent.sigev_value.sival_ptr = lf; - aiocb.aio_nbytes = dequeue_log(lf); - - if (aio_write(&aiocb)) - log_emerg("log_file: aio_write: %s\n", strerror(errno)); + return NULL; } static void queue_lf(struct log_file_t *lf) { - int r; - - spin_lock(&lf_queue_lock); + pthread_mutex_lock(&lock); list_add_tail(&lf->entry, &lf_queue); - r = lf_queue_sleeping; - lf_queue_sleeping = 0; - spin_unlock(&lf_queue_lock); - - if (r) - send_next_chunk(); + pthread_cond_signal(&cond); + pthread_mutex_unlock(&lock); } static void queue_log(struct log_file_t *lf, struct log_msg_t *msg) @@ -264,14 +187,9 @@ static void queue_log(struct log_file_t *lf, struct log_msg_t *msg) static void queue_log_list(struct log_file_t *lf, struct list_head *l) { int r; - struct log_msg_t *msg; spin_lock(&lf->lock); - while (!list_empty(l)) { - msg = list_entry(l->next, typeof(*msg), entry); - list_del(&msg->entry); - list_add_tail(&msg->entry, &lf->msgs); - } + list_splice_init(l, &lf->msgs); if (lf->fd != -1) { r = lf->queued; lf->queued = 1; @@ -407,27 +325,48 @@ static void fail_log(struct log_target_t *t, struct log_msg_t *msg, struct ap_se static void fail_reopen(void) { - char *fname = conf_get_opt("log", "log-fail-file"); - int fd = open(fname, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR); + const char *fname = conf_get_opt("log", "log-fail-file"); + int old_fd = -1; + int fd = open(fname, O_WRONLY | O_CREAT | O_APPEND | O_CLOEXEC, S_IRUSR | S_IWUSR); if (fd < 0) { log_emerg("log_file: open '%s': %s\n", fname, strerror(errno)); return; } - fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC); - fail_log_file->new_fd = fd; -} + + spin_lock(&fail_log_file->lock); + if (fail_log_file->queued) + fail_log_file->new_fd = fd; + else { + old_fd = fail_log_file->fd; + fail_log_file->fd = fd; + } + spin_unlock(&fail_log_file->lock); + if (old_fd != -1) + close(old_fd); +} static void general_reopen(void) { - char *fname = conf_get_opt("log", "log-file"); - int fd = open(fname, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR); + const char *fname = conf_get_opt("log", "log-file"); + int old_fd = -1; + int fd = open(fname, O_WRONLY | O_CREAT | O_APPEND | O_CLOEXEC, S_IRUSR | S_IWUSR); if (fd < 0) { log_emerg("log_file: open '%s': %s\n", fname, strerror(errno)); return; } - fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC); - log_file->new_fd = fd; + + spin_lock(&log_file->lock); + if (log_file->queued) + log_file->new_fd = fd; + else { + old_fd = log_file->fd; + log_file->fd = fd; + } + spin_unlock(&log_file->lock); + + if (old_fd != -1) + close(old_fd); } static void free_lpd(struct log_file_pd_t *lpd) @@ -447,6 +386,8 @@ static void free_lpd(struct log_file_pd_t *lpd) } if (lpd->lf.fd != -1) close(lpd->lf.fd); + if (lpd->lf.new_fd != -1) + close(lpd->lf.fd); spin_unlock(&lpd->lf.lock); mempool_free(lpd); } @@ -682,27 +623,12 @@ static struct log_target_t fail_log_target = static void init(void) { - char *opt; - - sigset_t set; - sigemptyset(&set); - sigaddset(&set, SIGIO); - - struct sigaction sa = { - .sa_sigaction = sigio, - .sa_flags = SA_SIGINFO, - .sa_mask = set, - }; + const char *opt; + pthread_create(&log_thr, NULL, log_thread, NULL); + lpd_pool = mempool_create(sizeof(struct log_file_pd_t)); fpd_pool = mempool_create(sizeof(struct fail_log_pd_t)); - log_buf = malloc(LOG_BUF_SIZE); - aiocb.aio_buf = log_buf; - - if (sigaction(SIGIO, &sa, NULL)) { - log_emerg("log_file: sigaction: %s\n", strerror(errno)); - return; - } opt = conf_get_opt("log", "log-file"); if (opt) { |