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.

Reply via email to