diff options
author | Dmitry Kozlov <xeb@mail.ru> | 2010-09-22 22:53:59 +0400 |
---|---|---|
committer | Dmitry Kozlov <xeb@mail.ru> | 2010-09-22 22:53:59 +0400 |
commit | 3e61cb3f8d58f64c8023e95bf74341e6bc61560e (patch) | |
tree | d73a44bf63044e35e8c3b1088598fc29e95a30b9 /accel-pptpd/logs | |
parent | b96fbc3f966b012720d2b74b1dfd2a0ab95086cf (diff) | |
download | accel-ppp-3e61cb3f8d58f64c8023e95bf74341e6bc61560e.tar.gz accel-ppp-3e61cb3f8d58f64c8023e95bf74341e6bc61560e.zip |
log: log_file rewrited to use aio
log: simplified engine
various bug fixes
Diffstat (limited to 'accel-pptpd/logs')
-rw-r--r-- | accel-pptpd/logs/CMakeLists.txt | 2 | ||||
-rw-r--r-- | accel-pptpd/logs/log_file.c | 595 | ||||
-rw-r--r-- | accel-pptpd/logs/log_pgsql.c | 9 |
3 files changed, 364 insertions, 242 deletions
diff --git a/accel-pptpd/logs/CMakeLists.txt b/accel-pptpd/logs/CMakeLists.txt index 4282761b..17ae92d0 100644 --- a/accel-pptpd/logs/CMakeLists.txt +++ b/accel-pptpd/logs/CMakeLists.txt @@ -1,4 +1,4 @@ -ADD_LIBRARY(log_file SHARED log_file.c) +ADD_LIBRARY(log_file SHARED log_file2.c) ADD_LIBRARY(log_pgsql SHARED log_pgsql.c) TARGET_LINK_LIBRARIES(log_pgsql pq) diff --git a/accel-pptpd/logs/log_file.c b/accel-pptpd/logs/log_file.c index f5bded9d..b13f81a4 100644 --- a/accel-pptpd/logs/log_file.c +++ b/accel-pptpd/logs/log_file.c @@ -5,13 +5,19 @@ #include <fcntl.h> #include <unistd.h> #include <limits.h> +#include <aio.h> +#include <sys/signalfd.h> #include "log.h" +#include "events.h" #include "ppp.h" #include "spinlock.h" +#include "mempool.h" #include "memdebug.h" +#define LOG_BUF_SIZE 16*1024 + #define RED_COLOR "\033[1;31m" #define GREEN_COLOR "\033[1;32m" #define YELLOW_COLOR "\033[1;33m" @@ -20,28 +26,29 @@ struct log_file_t { - struct triton_context_t ctx; - struct triton_md_handler_t hnd; + struct list_head entry; struct list_head msgs; - struct log_msg_t *cur_msg; - struct log_chunk_t *cur_chunk; - int cur_pos; spinlock_t lock; - int sleeping:1; int need_free:1; + int queued:1; struct log_file_pd_t *lpd; + + int fd; + off_t offset; }; struct log_file_pd_t { struct ppp_pd_t pd; struct log_file_t lf; + uint64_t tmp; }; 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 const char* level_name[]={" msg", "error", " warn", " info", "debug"}; static const char* level_color[]={NORMAL_COLOR, RED_COLOR, YELLOW_COLOR, GREEN_COLOR, BLUE_COLOR}; @@ -50,175 +57,192 @@ static void *pd_key1; static void *pd_key2; static struct log_file_t *log_file; -static int log_write(struct triton_md_handler_t *h); +static mempool_t lpd_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 uint64_t temp_seq; + +static void send_next_chunk(); -static int log_file_init(struct log_file_t *lf, const char *fname) +static void log_file_init(struct log_file_t *lf) { spinlock_init(&lf->lock); - lf->sleeping = 1; INIT_LIST_HEAD(&lf->msgs); - lf->hnd.write = log_write; + lf->fd = -1; +} - lf->hnd.fd = open(fname, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR); - if (lf->hnd.fd < 0) { +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); + if (lf->fd < 0) { log_emerg("log_file: open '%s': %s\n", fname, strerror(errno)); return -1; } - lseek(lf->hnd.fd, 0, SEEK_END); + lf->offset = lseek(lf->fd, 0, SEEK_END); - if (fcntl(lf->hnd.fd, F_SETFL, O_NONBLOCK)) { - log_emerg("log_file: cann't to set nonblocking mode: %s\n", strerror(errno)); - goto out_err; - } - - if (triton_context_register(&lf->ctx, NULL)) - goto out_err; - triton_md_register_handler(&lf->ctx, &lf->hnd); return 0; - -out_err: - close(lf->hnd.fd); - return -1; } -static void set_hdr(struct log_msg_t *msg, struct ppp_t *ppp) +static void sigio(int num, siginfo_t *si, void *uc) { - struct tm tm; - char timestamp[32]; + struct log_file_t *lf; + int n; - localtime_r(&msg->timestamp.tv_sec, &tm); + lf = (struct log_file_t *)si->si_ptr; - strftime(timestamp, sizeof(timestamp), "%Y-%m-%d %H:%M:%S", &tm); - sprintf(msg->hdr->msg, "%s[%s]: %s: %s%s%s", conf_color ? level_color[msg->level] : "", - timestamp, level_name[msg->level], - ppp ? ppp->ifname : "", - ppp ? ": " : "", - conf_color ? NORMAL_COLOR : ""); - msg->hdr->len = strlen(msg->hdr->msg); + 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 %i %lu\n", n, aiocb.aio_nbytes); + + spin_lock(&lf->lock); + lf->offset += n; + if (list_empty(&lf->msgs) && lf->need_free) { + spin_unlock(&lf->lock); + close(lf->fd); + mempool_free(lf->lpd); + } else + spin_unlock(&lf->lock); + + send_next_chunk(); } -static int write_chunk(int fd, struct log_chunk_t *chunk, int pos) + +static int dequeue_log(struct log_file_t *lf) { - int n; + int n, pos = 0; + struct log_msg_t *msg; + struct log_chunk_t *chunk; while (1) { - n = write(fd, chunk->msg + pos, chunk->len - pos); - if (n < 0) { - if (errno == EINTR) - continue; - if (errno == EAGAIN) - return pos; - log_emerg("log_file: write: %s\n", strerror(errno)); - break; + spin_lock(&lf->lock); + if (list_empty(&lf->msgs)) { + lf->queued = 0; + spin_unlock(&lf->lock); + return pos; } + msg = list_entry(lf->msgs.next, typeof(*msg), entry); + list_del(&msg->entry); + spin_unlock(&lf->lock); + + memcpy(log_buf + pos, msg->hdr->msg, msg->hdr->len); + n = msg->hdr->len; + if (pos + n > LOG_BUF_SIZE) + goto overrun; + + list_for_each_entry(chunk, msg->chunks, entry) { + memcpy(log_buf + pos + n, chunk->msg, chunk->len); + n += chunk->len; + if (pos + n > LOG_BUF_SIZE) + goto overrun; + } + + log_free_msg(msg); pos += n; - if (pos == chunk->len) - return 0; - } - return -1; -} -static int write_msg(struct log_file_t *lf) -{ - if (!lf->cur_chunk) - lf->cur_chunk = lf->cur_msg->hdr; - - if (lf->cur_chunk == lf->cur_msg->hdr) { - lf->cur_pos = write_chunk(lf->hnd.fd, lf->cur_chunk, lf->cur_pos); - if (lf->cur_pos < 0) - goto out; - if (lf->cur_pos) - return -1; - lf->cur_chunk = list_entry(lf->cur_msg->chunks->next, typeof(*lf->cur_chunk), entry); } - while(&lf->cur_chunk->entry != lf->cur_msg->chunks) { - lf->cur_pos = write_chunk(lf->hnd.fd, lf->cur_chunk, lf->cur_pos); - if (lf->cur_pos < 0) - break; - if (lf->cur_pos) - return -1; - lf->cur_chunk = list_entry(lf->cur_chunk->entry.next, typeof(*lf->cur_chunk), entry); - } +overrun: + spin_lock(&lf->lock); + list_add(&msg->entry, &lf->msgs); + spin_unlock(&lf->lock); -out: - log_free_msg(lf->cur_msg); - lf->cur_chunk = NULL; - lf->cur_msg = NULL; - lf->cur_pos = 0; - return 0; + spin_lock(&lf_queue_lock); + list_add_tail(&lf->entry, &lf_queue); + spin_unlock(&lf_queue_lock); + + return pos; } -static int log_write(struct triton_md_handler_t *h) +static void send_next_chunk(void) { - struct log_file_t *lf = container_of(h, typeof(*lf), hnd); + struct log_file_t *lf; - if (lf->cur_msg) - if (write_msg(lf)) - return 0; + 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); - while (1) { - spin_lock(&lf->lock); - if (!list_empty(&lf->msgs)) { - lf->cur_msg = list_entry(lf->msgs.next, typeof(*lf->cur_msg), entry); - list_del(&lf->cur_msg->entry); - spin_unlock(&lf->lock); + 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 (write_msg(lf)) - return 0; - - continue; - } - if (lf->need_free) { - spin_unlock(&lf->lock); - triton_md_unregister_handler(&lf->hnd); - close(lf->hnd.fd); - triton_context_unregister(&lf->ctx); - _free(lf->lpd); - return 1; - } - lf->sleeping = 1; - spin_unlock(&lf->lock); - triton_md_disable_handler(&lf->hnd, MD_MODE_WRITE); - return 0; - } + if (aio_write(&aiocb)) + log_emerg("log_file: aio_write: %s\n", strerror(errno)); } -static void log_wakeup(struct log_file_t *lf) +static void queue_lf(struct log_file_t *lf) { - if (log_write(&lf->hnd)) - return ; + int r; + + spin_lock(&lf_queue_lock); + list_add_tail(&lf->entry, &lf_queue); + r = lf_queue_sleeping; + lf_queue_sleeping = 0; + spin_unlock(&lf_queue_lock); - if (!lf->sleeping) - triton_md_enable_handler(&lf->hnd, MD_MODE_WRITE); + if (r) + send_next_chunk(); } -static void log_queue(struct log_file_t *lf, struct log_msg_t *msg) +static void queue_log(struct log_file_t *lf, struct log_msg_t *msg) { int r; + spin_lock(&lf->lock); list_add_tail(&msg->entry, &lf->msgs); - r = lf->sleeping; - lf->sleeping = 0; + if (lf->fd != -1) { + r = lf->queued; + lf->queued = 1; + } else + r = 1; spin_unlock(&lf->lock); - if (r) - triton_context_call(&lf->ctx, (void (*)(void *))log_wakeup, lf); + if (!r) + queue_lf(lf); } -static void general_log(struct log_msg_t *msg) +static void set_hdr(struct log_msg_t *msg, struct ppp_t *ppp) { - if (!log_file) - return; - set_hdr(msg, NULL); - log_queue(log_file, msg); + struct tm tm; + char timestamp[32]; + + localtime_r(&msg->timestamp.tv_sec, &tm); + + strftime(timestamp, sizeof(timestamp), "%Y-%m-%d %H:%M:%S", &tm); + sprintf(msg->hdr->msg, "%s[%s]: %s: %s%s%s", conf_color ? level_color[msg->level] : "", + timestamp, level_name[msg->level], + ppp ? ppp->ifname : "", + ppp ? ": " : "", + conf_color ? NORMAL_COLOR : ""); + msg->hdr->len = strlen(msg->hdr->msg); } -static void general_session_log(struct ppp_t *ppp, struct log_msg_t *msg) +static void general_log(struct log_msg_t *msg, struct ppp_t *ppp) { - if (!log_file) + if (ppp && !conf_copy) { + log_free_msg(msg); return; + } + set_hdr(msg, ppp); - log_queue(log_file, msg); + queue_log(log_file, msg); } static struct log_file_pd_t *find_pd(struct ppp_t *ppp, void *pd_key) @@ -237,48 +261,200 @@ static struct log_file_pd_t *find_pd(struct ppp_t *ppp, void *pd_key) return NULL; } -static void session_log(struct ppp_t *ppp, struct log_msg_t *msg, void *pd_key) +static void per_user_log(struct log_msg_t *msg, struct ppp_t *ppp) +{ + struct log_file_pd_t *lpd; + + if (!ppp) { + log_free_msg(msg); + return; + } + + lpd = find_pd(ppp, &pd_key1); + + if (!lpd) { + log_free_msg(msg); + return; + } + + set_hdr(msg, ppp); + queue_log(&lpd->lf, msg); +} + +static void per_session_log(struct log_msg_t *msg, struct ppp_t *ppp) { - struct log_file_pd_t *lpd = find_pd(ppp, pd_key); + struct log_file_pd_t *lpd; + + if (!ppp) { + log_free_msg(msg); + return; + } - if (!lpd) + lpd = find_pd(ppp, &pd_key2); + + if (!lpd) { + log_free_msg(msg); return; + } set_hdr(msg, ppp); - log_queue(&lpd->lf, msg); + queue_log(&lpd->lf, msg); } -static void per_user_session_log(struct ppp_t *ppp, struct log_msg_t *msg) +static void free_lpd(struct log_file_pd_t *lpd) { - session_log(ppp, msg, &pd_key1); + struct log_msg_t *msg; + + spin_lock(&lpd->lf.lock); + lpd->lf.need_free = 1; + if (lpd->lf.queued) + spin_unlock(&lpd->lf.lock); + else { + while (!list_empty(&lpd->lf.msgs)) { + msg = list_entry(lpd->lf.msgs.next, typeof(*msg), entry); + list_del(&msg->entry); + log_free_msg(msg); + } + if (lpd->lf.fd != -1) + close(lpd->lf.fd); + spin_unlock(&lpd->lf.lock); + mempool_free(lpd); + } } -static void per_session_log(struct ppp_t *ppp, struct log_msg_t *msg) +static void ev_ctrl_started(struct ppp_t *ppp) { - session_log(ppp, msg, &pd_key2); + struct log_file_pd_t *lpd; + char *fname; + + if (conf_per_user_dir) { + lpd = mempool_alloc(lpd_pool); + if (!lpd) { + log_emerg("log_file: out of memory\n"); + return; + } + memset(lpd, 0, sizeof(*lpd)); + lpd->pd.key = &pd_key1; + log_file_init(&lpd->lf); + lpd->lf.lpd = lpd; + list_add_tail(&lpd->pd.entry, &ppp->pd_list); + } + + if (conf_per_session_dir) { + lpd = mempool_alloc(lpd_pool); + if (!lpd) { + log_emerg("log_file: out of memory\n"); + return; + } + memset(lpd, 0, sizeof(*lpd)); + lpd->pd.key = &pd_key2; + log_file_init(&lpd->lf); + lpd->lf.lpd = lpd; + + fname = _malloc(PATH_MAX); + if (!fname) { + mempool_free(lpd); + log_emerg("log_file: out of memory\n"); + return; + } + + lpd->tmp = __sync_fetch_and_add(&temp_seq, 1); + strcpy(fname, conf_per_session_dir); + strcat(fname, "/tmp"); + sprintf(fname + strlen(fname), "%lu", lpd->tmp); + + if (log_file_open(&lpd->lf, fname)) { + mempool_free(lpd); + _free(fname); + return; + } + + _free(fname); + + list_add_tail(&lpd->pd.entry, &ppp->pd_list); + } } -static void per_user_session_start(struct ppp_t *ppp) +static void ev_ctrl_finished(struct ppp_t *ppp) { struct log_file_pd_t *lpd; char *fname; + + lpd = find_pd(ppp, &pd_key1); + if (lpd) + free_lpd(lpd); + + + lpd = find_pd(ppp, &pd_key2); + if (lpd) { + if (lpd->tmp) { + fname = _malloc(PATH_MAX); + if (fname) { + strcpy(fname, conf_per_session_dir); + strcat(fname, "/tmp"); + sprintf(fname + strlen(fname), "%lu", lpd->tmp); + if (unlink(fname)) + log_emerg("log_file: unlink '%s': %s\n", fname, strerror(errno)); + _free(fname); + } else + log_emerg("log_file: out of memory\n"); + } + free_lpd(lpd); + } +} + +static void ev_ppp_starting(struct ppp_t *ppp) +{ + struct log_file_pd_t *lpd; + char *fname1, *fname2; + + lpd = find_pd(ppp, &pd_key2); + if (!lpd) + return; - fname = _malloc(PATH_MAX + 32); - if (!fname) { + fname1 = _malloc(PATH_MAX); + if (!fname1) { log_emerg("log_file: out of memory\n"); return; } - lpd = _malloc(sizeof(*lpd)); - if (!lpd) { + fname2 = _malloc(PATH_MAX); + if (!fname2) { log_emerg("log_file: out of memory\n"); - goto out_err; + _free(fname1); + return; + } + + strcpy(fname1, conf_per_session_dir); + strcat(fname1, "/tmp"); + sprintf(fname1 + strlen(fname1), "%lu", lpd->tmp); + + strcpy(fname2, conf_per_session_dir); + strcat(fname2, "/"); + strcat(fname2, ppp->sessionid); + strcat(fname2, ".log"); + + if (rename(fname1, fname2)) + log_emerg("log_file: rename '%s' to '%s': %s\n", fname1, fname2, strerror(errno)); + + _free(fname1); + _free(fname2); +} + +static void ev_ppp_authorized(struct ppp_t *ppp) +{ + struct log_file_pd_t *lpd; + char *fname; + + lpd = find_pd(ppp, &pd_key1); + if (!lpd) + return; + + fname = _malloc(PATH_MAX); + if (!fname) { + log_emerg("log_file: out of memory\n"); + return; } - - memset(lpd, 0, sizeof(*lpd)); - lpd->pd.key = &pd_key1; - lpd->lf.hnd.fd = -1; - lpd->lf.lpd = lpd; strcpy(fname, conf_per_user_dir); strcat(fname, "/"); @@ -293,123 +469,71 @@ static void per_user_session_start(struct ppp_t *ppp) } strcat(fname, ".log"); - if (log_file_init(&lpd->lf, fname)) + if (log_file_open(&lpd->lf, fname)) goto out_err; - - list_add_tail(&lpd->pd.entry, &ppp->pd_list); _free(fname); - return; -out_err: - _free(fname); - if (lpd) - _free(lpd); -} -static void per_session_start(struct ppp_t *ppp) -{ - struct log_file_pd_t *lpd; - char *fname; - - fname = _malloc(PATH_MAX + 32); - if (!fname) { - log_emerg("log_file: out of memory\n"); - return; - } - - lpd = _malloc(sizeof(*lpd)); - if (!lpd) { - log_emerg("log_file: out of memory\n"); - goto out_err; + if (!list_empty(&lpd->lf.msgs)) { + lpd->lf.queued = 1; + queue_lf(&lpd->lf); } - - memset(lpd, 0, sizeof(*lpd)); - lpd->pd.key = &pd_key2; - lpd->lf.hnd.fd = -1; - lpd->lf.lpd = lpd; - - strcpy(fname, conf_per_session_dir); - strcat(fname, "/"); - strcat(fname, ppp->sessionid); - strcat(fname, ".log"); - - if (log_file_init(&lpd->lf, fname)) - goto out_err; - - list_add_tail(&lpd->pd.entry, &ppp->pd_list); - _free(fname); return; out_err: _free(fname); - if (lpd) - _free(lpd); -} - -static void session_stop(struct ppp_t *ppp, void *pd_key) -{ - struct log_file_pd_t *lpd = find_pd(ppp, pd_key); - int r; - - spin_lock(&lpd->lf.lock); - r = lpd->lf.sleeping; - lpd->lf.sleeping = 0; - lpd->lf.need_free = 1; - spin_unlock(&lpd->lf.lock); - - if (r) - triton_context_call(&lpd->lf.ctx, (void (*)(void *))log_wakeup, &lpd->lf); + list_del(&lpd->pd.entry); + free_lpd(lpd); } -static void per_user_session_stop(struct ppp_t *ppp) -{ - session_stop(ppp, &pd_key1); -} - -static void per_session_stop(struct ppp_t *ppp) -{ - session_stop(ppp, &pd_key2); -} - -static struct log_target_t target = +static struct log_target_t general_target = { .log = general_log, }; static struct log_target_t per_user_target = { - .session_log = per_user_session_log, - .session_start = per_user_session_start, - .session_stop = per_user_session_stop, + .log = per_user_log, }; static struct log_target_t per_session_target = { - .session_log = per_session_log, - .session_start = per_session_start, - .session_stop = per_session_stop, + .log = per_session_log, }; - static void __init init(void) { char *opt; - - opt = conf_get_opt("log","color"); - if (opt && atoi(opt) > 0) - conf_color = 1; - + struct sigaction sa = { + .sa_sigaction = sigio, + .sa_flags = SA_SIGINFO, + }; + + lpd_pool = mempool_create(sizeof(struct log_file_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) { - log_file = _malloc(sizeof(*log_file)); + log_file = malloc(sizeof(*log_file)); memset(log_file, 0, sizeof(*log_file)); - if (log_file_init(log_file, opt)) { - _free(log_file); - log_file = NULL; + log_file_init(log_file); + if (log_file_open(log_file, opt)) { + free(log_file); + _exit(EXIT_FAILURE); } } + opt = conf_get_opt("log","color"); + if (opt && atoi(opt) > 0) + conf_color = 1; + opt = conf_get_opt("log", "per-user-dir"); if (opt) conf_per_user_dir = opt; @@ -421,17 +545,22 @@ static void __init init(void) opt = conf_get_opt("log", "per-session"); if (opt && atoi(opt) > 0) conf_per_session = 1; + + opt = conf_get_opt("log", "copy"); + if (opt && atoi(opt) > 0) + conf_copy = 1; + log_register_target(&general_target); + if (conf_per_user_dir) log_register_target(&per_user_target); if (conf_per_session_dir) log_register_target(&per_session_target); - - if (log_file) { - if (!conf_per_user_dir && !conf_per_session_dir) - target.session_log = general_session_log; - log_register_target(&target); - } + + triton_event_register_handler(EV_CTRL_STARTED, (triton_event_func)ev_ctrl_started); + triton_event_register_handler(EV_CTRL_FINISHED, (triton_event_func)ev_ctrl_finished); + triton_event_register_handler(EV_PPP_STARTING, (triton_event_func)ev_ppp_starting); + triton_event_register_handler(EV_PPP_AUTHORIZED, (triton_event_func)ev_ppp_authorized); } diff --git a/accel-pptpd/logs/log_pgsql.c b/accel-pptpd/logs/log_pgsql.c index f9cf7ed2..393c3bdc 100644 --- a/accel-pptpd/logs/log_pgsql.c +++ b/accel-pptpd/logs/log_pgsql.c @@ -161,13 +161,7 @@ static void queue_log(struct log_msg_t *msg) } -static void general_log(struct log_msg_t *msg) -{ - set_hdr(msg, NULL); - queue_log(msg); -} - -static void session_log(struct ppp_t *ppp, struct log_msg_t *msg) +static void general_log(struct log_msg_t *msg, struct ppp_t *ppp) { set_hdr(msg, ppp); queue_log(msg); @@ -238,7 +232,6 @@ static void start_connect_timer(struct triton_timer_t *t) static struct log_target_t target = { .log = general_log, - .session_log = session_log, }; static void __init init(void) |