Nice, does what it says on the lid: Mar 7 11:42:10 openbsd-build dhcpleased[65929]: adding 10.2.1.48 to vio1 (lease from 10.2.1.11) Mar 7 11:42:10 openbsd-build dhcpleased[65929]: adding nameservers 10.2.1.1 9.9.9.9 8.8.8.8 (lease from 10.2.1.11 on vio1)
On Sun, Mar 07, 2021 at 12:17:18AM +0100, Alexander Bluhm wrote: > Hi > > Early daemons like dhcpleased, slaacd, unwind, resolvd are started > before syslogd. This results in ugly sendsyslog: dropped 1 message > logs and the real message is lost. > > Changing the start order of syslogd and and network daemons is not > feasible. A possible solution is a temporary buffer for log meassges > in kernel. > > ok? > > bluhm > > Index: sys/kern/subr_log.c > =================================================================== > RCS file: /data/mirror/openbsd/cvs/src/sys/kern/subr_log.c,v > retrieving revision 1.72 > diff -u -p -r1.72 subr_log.c > --- sys/kern/subr_log.c 8 Feb 2021 08:18:45 -0000 1.72 > +++ sys/kern/subr_log.c 5 Mar 2021 21:58:50 -0000 > @@ -454,6 +454,146 @@ logioctl(dev_t dev, u_long com, caddr_t > return (0); > } > > +/* > + * If syslogd is not running, temporarily store a limited amount of messages > + * in kernel. After log stash is full, drop messages and count them. When > + * syslogd is available again, next log message will flush the stashed > + * messages and insert a message with drop count. Calls to malloc(9) and > + * copyin(9) may sleep, protect data structures with rwlock. > + */ > + > +#define LOGSTASH_SIZE 100 > +struct logstash_messages { > + char *lgs_buffer; > + size_t lgs_size; > +} logstash_messages[LOGSTASH_SIZE]; > + > +struct logstash_messages *logstash_in = &logstash_messages[0]; > +struct logstash_messages *logstash_out = &logstash_messages[0]; > + > +struct rwlock logstash_rwlock = RWLOCK_INITIALIZER("logstash"); > + > +int logstash_dropped, logstash_error, logstash_pid; > + > +void logstash_insert(const char *, size_t, int, pid_t); > +void logstash_remove(void); > +int logstash_sendsyslog(struct proc *); > + > +static inline int > +logstash_empty(void) > +{ > + rw_assert_anylock(&logstash_rwlock); > + > + return logstash_out->lgs_buffer == NULL; > +} > + > +static inline int > +logstash_full(void) > +{ > + rw_assert_anylock(&logstash_rwlock); > + > + return logstash_out->lgs_buffer != NULL && > + logstash_in == logstash_out; > +} > + > +static inline void > +logstash_increment(struct logstash_messages **msg) > +{ > + rw_assert_wrlock(&logstash_rwlock); > + > + KASSERT((*msg) >= &logstash_messages[0]); > + KASSERT((*msg) < &logstash_messages[LOGSTASH_SIZE]); > + (*msg)++; > + if ((*msg) == &logstash_messages[LOGSTASH_SIZE]) > + (*msg) = &logstash_messages[0]; > +} > + > +void > +logstash_insert(const char *buf, size_t nbyte, int error, pid_t pid) > +{ > + rw_enter_write(&logstash_rwlock); > + > + if (logstash_full()) { > + if (logstash_dropped == 0) { > + logstash_error = error; > + logstash_pid = pid; > + } > + logstash_dropped++; > + > + rw_exit(&logstash_rwlock); > + return; > + } > + > + logstash_in->lgs_buffer = malloc(nbyte, M_LOG, M_WAITOK); > + copyin(buf, logstash_in->lgs_buffer, nbyte); > + logstash_in->lgs_size = nbyte; > + logstash_increment(&logstash_in); > + > + rw_exit(&logstash_rwlock); > +} > + > +void > +logstash_remove(void) > +{ > + rw_assert_wrlock(&logstash_rwlock); > + > + KASSERT(!logstash_empty()); > + free(logstash_out->lgs_buffer, M_LOG, logstash_out->lgs_size); > + logstash_out->lgs_buffer = NULL; > + logstash_increment(&logstash_out); > + > + /* Insert dropped message in sequence where messages were dropped. */ > + if (logstash_dropped) { > + size_t l, nbyte; > + char buf[80]; > + > + l = snprintf(buf, sizeof(buf), > + "<%d>sendsyslog: dropped %d message%s, error %d, pid %d", > + LOG_KERN|LOG_WARNING, logstash_dropped, > + logstash_dropped == 1 ? "" : "s", > + logstash_error, logstash_pid); > + logstash_dropped = 0; > + logstash_error = 0; > + logstash_pid = 0; > + > + /* Cannot fail, we have just freed a slot. */ > + KASSERT(!logstash_full()); > + nbyte = ulmin(l, sizeof(buf) - 1); > + logstash_in->lgs_buffer = malloc(nbyte, M_LOG, M_WAITOK); > + memcpy(logstash_in->lgs_buffer, buf, nbyte); > + logstash_in->lgs_size = nbyte; > + logstash_increment(&logstash_in); > + } > +} > + > +int > +logstash_sendsyslog(struct proc *p) > +{ > + int error; > + > + rw_enter_write(&logstash_rwlock); > + > + while (logstash_out->lgs_buffer != NULL) { > + error = dosendsyslog(p, logstash_out->lgs_buffer, > + logstash_out->lgs_size, 0, UIO_SYSSPACE); > + if (error) { > + rw_exit(&logstash_rwlock); > + return (error); > + } > + logstash_remove(); > + } > + > + rw_exit(&logstash_rwlock); > + return (0); > +} > + > +/* > + * Send syslog(3) message from userland to socketpair(2) created by > syslogd(8). > + * Store message in kernel log stash for later if syslogd(8) is not available > + * or sending fails. Send to console if LOG_CONS is set and syslogd(8) > socket > + * does not exist. > + */ > + > int > sys_sendsyslog(struct proc *p, void *v, register_t *retval) > { > @@ -462,32 +602,18 @@ sys_sendsyslog(struct proc *p, void *v, > syscallarg(size_t) nbyte; > syscallarg(int) flags; > } */ *uap = v; > + size_t nbyte; > int error; > - static int dropped_count, orig_error, orig_pid; > > - if (dropped_count) { > - size_t l; > - char buf[80]; > + nbyte = SCARG(uap, nbyte); > + if (nbyte > LOG_MAXLINE) > + nbyte = LOG_MAXLINE; > > - l = snprintf(buf, sizeof(buf), > - "<%d>sendsyslog: dropped %d message%s, error %d, pid %d", > - LOG_KERN|LOG_WARNING, dropped_count, > - dropped_count == 1 ? "" : "s", orig_error, orig_pid); > - error = dosendsyslog(p, buf, ulmin(l, sizeof(buf) - 1), > - 0, UIO_SYSSPACE); > - if (error == 0) { > - dropped_count = 0; > - orig_error = 0; > - orig_pid = 0; > - } > - } > - error = dosendsyslog(p, SCARG(uap, buf), SCARG(uap, nbyte), > - SCARG(uap, flags), UIO_USERSPACE); > - if (error) { > - dropped_count++; > - orig_error = error; > - orig_pid = p->p_p->ps_pid; > - } > + logstash_sendsyslog(p); > + error = dosendsyslog(p, SCARG(uap, buf), nbyte, SCARG(uap, flags), > + UIO_USERSPACE); > + if (error) > + logstash_insert(SCARG(uap, buf), nbyte, error, p->p_p->ps_pid); > return (error); > } > > @@ -504,9 +630,6 @@ dosendsyslog(struct proc *p, const char > struct uio auio; > size_t i, len; > int error; > - > - if (nbyte > LOG_MAXLINE) > - nbyte = LOG_MAXLINE; > > /* Global variable syslogf may change during sleep, use local copy. */ > fp = syslogf; > Index: sys/sys/malloc.h > =================================================================== > RCS file: /data/mirror/openbsd/cvs/src/sys/sys/malloc.h,v > retrieving revision 1.120 > diff -u -p -r1.120 malloc.h > --- sys/sys/malloc.h 23 Feb 2021 13:50:16 -0000 1.120 > +++ sys/sys/malloc.h 4 Mar 2021 23:11:04 -0000 > @@ -83,7 +83,7 @@ > /* 21 - free */ > #define M_NFSREQ 22 /* NFS request header */ > #define M_NFSMNT 23 /* NFS mount structure */ > -/* 24 - free */ > +#define M_LOG 24 /* Messages in kernel log stash */ > #define M_VNODE 25 /* Dynamically allocated vnodes */ > #define M_CACHE 26 /* Dynamically allocated cache entries > */ > #define M_DQUOT 27 /* UFS quota entries */ > @@ -208,7 +208,7 @@ > NULL, \ > "NFS req", /* 22 M_NFSREQ */ \ > "NFS mount", /* 23 M_NFSMNT */ \ > - NULL, \ > + "log", /* 24 M_LOG */ \ > "vnodes", /* 25 M_VNODE */ \ > "namecache", /* 26 M_CACHE */ \ > "UFS quota", /* 27 M_DQUOT */ \ > Index: lib/libc/sys/sendsyslog.2 > =================================================================== > RCS file: /data/mirror/openbsd/cvs/src/lib/libc/sys/sendsyslog.2,v > retrieving revision 1.12 > diff -u -p -r1.12 sendsyslog.2 > --- lib/libc/sys/sendsyslog.2 5 Nov 2020 16:04:39 -0000 1.12 > +++ lib/libc/sys/sendsyslog.2 5 Mar 2021 19:15:10 -0000 > @@ -51,10 +51,12 @@ This is used internally by > so that messages can be sent during difficult situations. > If sending to > .Xr syslogd 8 > -fails, dropped messages are counted. > +fails, up to 100 messages are stashed in the kernel. > +After that, dropped messages are counted. > When > .Xr syslogd 8 > -works again, a warning with the counter and error number is logged. > +works again, before the next message, stashed messages and possibly > +a warning with the drop counter, error number, and pid is logged. > .Pp > To receive messages from the kernel, > .Xr syslogd 8 > Index: usr.sbin/syslogd/syslogd.c > =================================================================== > RCS file: /data/mirror/openbsd/cvs/src/usr.sbin/syslogd/syslogd.c,v > retrieving revision 1.264 > diff -u -p -r1.264 syslogd.c > --- usr.sbin/syslogd/syslogd.c 14 Sep 2020 20:36:01 -0000 1.264 > +++ usr.sbin/syslogd/syslogd.c 6 Mar 2021 09:27:52 -0000 > @@ -891,6 +891,10 @@ main(int argc, char *argv[]) > if (sigprocmask(SIG_SETMASK, &sigmask, NULL) == -1) > err(1, "sigprocmask unblock"); > > + /* Send message via libc, flushes log stash in kernel. */ > + openlog("syslogd", LOG_PID, LOG_SYSLOG); > + syslog(LOG_DEBUG, "running"); > + > event_dispatch(); > /* NOTREACHED */ > return (0); > -- I'm not entirely sure you are real.