Implement sbuf_prf(), which takes an sbuf and outputs it

to stdout in the non-kernel case and to the console+log
in the kernel case.  For the kernel case it hooks the
putbuf() machinery underneath printf(9) so that the buffer
is written completely atomically and without a copy into
another temporary buffer.  This is useful for fixing
compound console/log messages that become broken and
interleaved when multiple threads are competing for the
console.

Reviewed by:	ken, imp
Sponsored by:	Netflix
This commit is contained in:
Scott Long 2017-02-28 18:25:06 +00:00
parent 6d91604093
commit 388f3ce6c3
2 changed files with 44 additions and 13 deletions

View File

@ -57,7 +57,8 @@
.Nm sbuf_delete ,
.Nm sbuf_start_section ,
.Nm sbuf_end_section ,
.Nm sbuf_hexdump
.Nm sbuf_hexdump ,
.Nm sbuf_putbuf
.Nd safe string composition
.Sh SYNOPSIS
.In sys/types.h
@ -124,6 +125,8 @@
.Fa "const char *hdr"
.Fa "int flags"
.Fc
.Ft void
.Fn sbuf_putbuf "struct sbuf *s"
.In sys/sysctl.h
.Ft struct sbuf *
.Fn sbuf_new_for_sysctl "struct sbuf *s" "char *buf" "int length" "struct sysctl_req *req"
@ -472,6 +475,12 @@ representation of the bytes if possible.
See the
.Xr hexdump 3
man page for more details on the interface.
.Pp
The
.Fn sbuf_putbuf
function printfs the sbuf to stdout if in userland, and to the console
and log if in the kernel.
It does not drain the buffer or update any pointers.
.Sh NOTES
If an operation caused an
.Fa sbuf

View File

@ -410,6 +410,23 @@ vprintf(const char *fmt, va_list ap)
return (retval);
}
static void
prf_putbuf(char *bufr, int flags, int pri)
{
if (flags & TOLOG)
msglogstr(bufr, pri, /*filter_cr*/1);
if (flags & TOCONS) {
if ((panicstr == NULL) && (constty != NULL))
msgbuf_addstr(&consmsgbuf, -1,
bufr, /*filter_cr*/ 0);
if ((constty == NULL) ||(always_console_output))
cnputs(bufr);
}
}
static void
putbuf(int c, struct putchar_arg *ap)
{
@ -431,18 +448,7 @@ putbuf(int c, struct putchar_arg *ap)
/* Check if the buffer needs to be flushed. */
if (ap->remain == 2 || c == '\n') {
if (ap->flags & TOLOG)
msglogstr(ap->p_bufr, ap->pri, /*filter_cr*/1);
if (ap->flags & TOCONS) {
if ((panicstr == NULL) && (constty != NULL))
msgbuf_addstr(&consmsgbuf, -1,
ap->p_bufr, /*filter_cr*/ 0);
if ((constty == NULL) ||(always_console_output))
cnputs(ap->p_bufr);
}
prf_putbuf(ap->p_bufr, ap->flags, ap->pri);
ap->p_next = ap->p_bufr;
ap->remain = ap->n_bufr;
@ -1221,3 +1227,19 @@ counted_warning(unsigned *counter, const char *msg)
}
}
#endif
#ifdef _KERNEL
void
sbuf_putbuf(struct sbuf *sb)
{
prf_putbuf(sbuf_data(sb), TOLOG | TOCONS, -1);
}
#else
void
sbuf_putbuf(struct sbuf *sb)
{
printf("%s", sbuf_data(sb));
}
#endif