Subject: kern/5155: Kernel messages may be way too verbose for some apps.
To: None <gnats-bugs@gnats.netbsd.org>
From: None <cgd@NetBSD.ORG>
List: netbsd-bugs
Date: 03/12/1998 13:40:17
>Number: 5155
>Category: kern
>Synopsis: Kernel messages may be way too verbose for some apps.
>Confidential: no
>Severity: non-critical
>Priority: low
>Responsible: kern-bug-people (Kernel Bug People)
>State: open
>Class: change-request
>Submitter-Id: net
>Arrival-Date: Thu Mar 12 13:50:02 1998
>Last-Modified:
>Originator: Chris G. Demetriou
>Organization:
Kernel Hackers 'r' Us
>Release: All versions of NetBSD, ever, up to and including today's.
>Environment:
System: NetBSD brick.int.demetriou.com 1.3E NetBSD 1.3E (BRICK) #39: Thu Mar 12 11:55:53 PST 1998 cgd@brick.int.demetriou.com:/usr/src/sys/arch/i386/compile/BRICK i386
But that's really irrelevant.
>Description:
Kernel messages may be way too verbose for some applications.
For some applications, NetBSD is used as an embedded operating
system. Users observing such systems boot don't need to know
much, if anything, about what's going on, except in the case
where something's failed and somebody needs to debug it.
The same is true for messages from, for instance, /etc/rc.
There are simple, inelegant ways to implement this. An example
of one is below. It's not intended to be something that should
be committed to the source tree, but instead should be looked
at as an example of what i'm talking about. (It has a lot of
known problems, which aren't particularly easy to fix cleanly.
However, it served its purpose, it's a concrete example of
the minimum type of functionality i'm talking about, etc.)
There are also more elegant ways to do something like this,
e.g. assign a priority ("highest == always" > "error" >
"informational" > "debugging") to all messages, and only
print those messages which have a priority greater than or
equal to the currently "enabled" level. (Note that in all
cases, the messages should go the to the message buffer. Note
also that, in my opinion at least, most kernel printfs
should probably be logged with levels, whereas now they're
not.)
Examples of particular types of messages:
Always:
boot-time copyright notice announcements, and probably
some announcement that you're running NetBSD.
post-shutdown messages (i.e. "hit any key to reboot")
Error:
panic (maybe this should be "always", but maybe not
to avoid scaring naive users... it'll be in msgbuf
anyway, so if you had to dump the kernel you're fine.)
serious device errors/driver problems (bad block,
terminal on fire, etc. maybe things like "device out
of paper", though that's not really so serious.)
Info:
That autoconfiguration output we all know and love.
Stuff about syncing disks on reboot.
(Should still be kept to a minimum, e.g. no more verboes
than what printf is normally used for now.)
Debugging:
"As verbose as you want to be."
Other useful features it'd be nice to have and/or notes that
should be mentioned:
* It'd be nice to be able to compile the system so that _none_ of
the printfs below a given level is included. (Not necessarily
a good idea, but if you really need to squeeze for space you
should be able to do so.)
* Debugging printfs should still be compiled in via driver/module
#defines, and made conditional on driver/module-specific flags.
Just because you've turned on debugging output to the console
doesn't mean you should get flooded, and don't forget that it's
going to the message buffer anyway.
Note that I'm not suggesting that NetBSD ship with most messages
disabled by default (at least on most systems), but it should
be possible for people to configure their systems so that this
is the default (and have the message-printing level be
configurable via boot arguments or some similar/more permanent
configuration mechanism). I'd say that the default should
probably be "all compiled in, info and higher go to the console."
>How-To-Repeat:
Boot NetBSD. Note that it spews much text.
>Fix:
"See above." Some diffs that show an example implementation
of an inelegant way of doing something like this is below.
(DO NOT SUGGEST THAT IT SHOULD BE COMMITTED, OR FLAME ME FOR
IT! 8-)
Index: sys/kern/init_main.c
===================================================================
RCS file: /cvsroot/src/sys/kern/init_main.c,v
retrieving revision 1.118
diff -c -r1.118 init_main.c
*** init_main.c 1998/03/01 02:22:27 1.118
--- init_main.c 1998/03/12 19:48:07
***************
*** 139,144 ****
--- 139,147 ----
extern char *syscallnames[];
#endif
+ /* boot quietly */
+ static int quiet;
+
struct emul emul_netbsd = {
"netbsd",
NULL,
***************
*** 190,196 ****
--- 193,207 ----
* in case of early panic or other messages.
*/
consinit();
+ /*
+ * Print the copyright message even if we're booting quietly.
+ */
+ quiet = boothowto & RB_QUIET;
+ boothowto &= ~quiet;
printf(copyright);
+ if (quiet)
+ printf("System Starting... ");
+ boothowto |= quiet;
#if defined(UVM)
uvm_init();
***************
*** 354,359 ****
--- 365,371 ----
/* Mount the root file system. */
do {
domountroothook();
+ /* XXX quiet lossage */
if ((error = vfs_mountroot())) {
printf("cannot mount root, error = %d\n", error);
boothowto |= RB_ASKNAME;
***************
*** 393,398 ****
--- 405,419 ----
/* Initialize signal state for process 0. */
siginit(p);
+ /*
+ * Now that all the "nerd junk" has been emitted, enable
+ * kernel printfs if they were disabled by RB_QUIET.
+ */
+ if (quiet) {
+ boothowto &= ~RB_QUIET;
+ printf(" \n");
+ }
+
/* Create process 1 (init(8)). */
if (fork1(p, 0, NULL, &p2))
panic("fork init");
***************
*** 455,461 ****
} */ args;
int options, i, error;
register_t retval[2];
! char flags[4], *flagsp;
char **pathp, *path, *ucp, **uap, *arg0, *arg1 = NULL;
/*
--- 476,482 ----
} */ args;
int options, i, error;
register_t retval[2];
! char flags[5], *flagsp;
char **pathp, *path, *ucp, **uap, *arg0, *arg1 = NULL;
/*
***************
*** 510,515 ****
--- 531,540 ----
options = 1;
}
#endif
+ if (quiet) {
+ *flagsp++ = 'q';
+ options = 1;
+ }
/*
* Move out the flags (arg 1), if necessary.
Index: sys/kern/subr_prf.c
===================================================================
RCS file: /cvsroot/src/sys/kern/subr_prf.c,v
retrieving revision 1.48
diff -c -r1.48 subr_prf.c
*** subr_prf.c 1998/03/01 02:22:31 1.48
--- subr_prf.c 1998/03/12 19:48:07
***************
*** 155,160 ****
--- 155,164 ----
int bootopt;
va_list ap;
+ /*
+ * Force kernel printfs on, regardless of quiet booting
+ */
+ boothowto &= ~RB_QUIET;
bootopt = RB_AUTOBOOT | RB_DUMP;
if (panicstr)
bootopt |= RB_NOSYNC;
***************
*** 318,325 ****
}
}
}
! if ((flags & TOCONS) && constty == NULL && c != '\0')
! (*v_putc)(c);
#ifdef DDB
if (flags & TODDB)
db_putchar(c);
--- 322,336 ----
}
}
}
! if ((flags & TOCONS) && constty == NULL && c != '\0') {
! if ((boothowto & RB_QUIET) == 0)
! (*v_putc)(c);
! else if (c == '\n') {
! (*v_putc)("|/-\\"[twiddlestate++]);
! (*v_putc)('\b');
! twiddlestate %= 4;
! }
! }
#ifdef DDB
if (flags & TODDB)
db_putchar(c);
Index: sys/sys/reboot.h
===================================================================
RCS file: /cvsroot/src/sys/sys/reboot.h,v
retrieving revision 1.14
diff -c -r1.14 reboot.h
*** reboot.h 1998/03/01 02:24:14 1.14
--- reboot.h 1998/03/12 19:48:07
***************
*** 55,60 ****
--- 55,61 ----
#define RB_DUMP 0x100 /* dump kernel memory before reboot */
#define RB_MINIROOT 0x200 /* mini-root present in memory at boot time */
#define RB_STRING 0x400 /* use provided bootstr */
+ #define RB_QUIET 0x800 /* boot quietly (twiddle) */
/*
* Constants for converting boot-style device number to type,
Index: sbin/init/init.c
===================================================================
RCS file: /src/kona.cvs/netbsd/sbin/init/init.c,v
retrieving revision 1.1.1.2
retrieving revision 1.2
diff -c -r1.1.1.2 -r1.2
*** 1.1.1.2 1997/12/09 01:26:04
--- 1.2 1997/12/24 00:02:30
***************
*** 168,173 ****
--- 168,176 ----
int getsecuritylevel __P((void));
int setupargv __P((session_t *, struct ttyent *));
int clang;
+ #ifndef LETS_GET_SMALL
+ int quiet;
+ #endif
void clear_session_logs __P((session_t *));
***************
*** 237,243 ****
* This code assumes that we always get arguments through flags,
* never through bits set in some random machine register.
*/
! while ((c = getopt(argc, argv, "sf")) != -1)
switch (c) {
case 's':
requested_transition = single_user;
--- 240,246 ----
* This code assumes that we always get arguments through flags,
* never through bits set in some random machine register.
*/
! while ((c = getopt(argc, argv, "sfq")) != -1)
switch (c) {
case 's':
requested_transition = single_user;
***************
*** 245,252 ****
case 'f':
runcom_mode = FASTBOOT;
break;
default:
! warning("unrecognized flag '-%c'", c);
break;
}
--- 248,258 ----
case 'f':
runcom_mode = FASTBOOT;
break;
+ case 'q':
+ quiet = 1;
+ break;
default:
! warning("unrecognized flag '-%c'", optopt);
break;
}
***************
*** 531,538 ****
transition(s)
state_t s;
{
! for (;;)
s = (state_t) (*s)();
}
/*
--- 537,548 ----
transition(s)
state_t s;
{
! for (;;) {
s = (state_t) (*s)();
+ #ifndef LETS_GET_SMALL
+ quiet = 0;
+ #endif
+ }
}
/*
***************
*** 729,735 ****
{
pid_t pid, wpid;
int status;
! char *argv[4];
struct sigaction sa;
if ((pid = fork()) == 0) {
--- 739,745 ----
{
pid_t pid, wpid;
int status;
! char *argv[5], **ap;
struct sigaction sa;
if ((pid = fork()) == 0) {
***************
*** 741,750 ****
setctty(_PATH_CONSOLE);
! argv[0] = "sh";
! argv[1] = _PATH_RUNCOM;
! argv[2] = runcom_mode == AUTOBOOT ? "autoboot" : 0;
! argv[3] = 0;
sigprocmask(SIG_SETMASK, &sa.sa_mask, (sigset_t *) 0);
--- 751,764 ----
setctty(_PATH_CONSOLE);
! ap = argv;
! *ap++ = "sh"; /* 1 */
! *ap++ = _PATH_RUNCOM; /* 2 */
! if (quiet)
! *ap++ = "-q"; /* 3 */
! if (runcom_mode == AUTOBOOT)
! *ap++ = "autoboot"; /* 4 */
! *ap++ = 0; /* 5 */
sigprocmask(SIG_SETMASK, &sa.sa_mask, (sigset_t *) 0);
Index: etc/rc
*** etc/rc Thu Jan 15 17:44:56 1998
--- etc/rc Fri Feb 6 15:37:00 1998
***************
*** 16,21 ****
--- 16,29 ----
export HOME=/
export PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/X11R6/bin
+ # XXX check rc.conf variable?
+ if [ "$1x" = -qx ]
+ then
+ shift
+ exec > /dev/null
+ echo Starting OS Utilities 1>&2
+ fi
+
# Configure ccd devices.
if [ -f /etc/ccd.conf ]; then
ccdconfig -C
***************
*** 37,53 ****
exit 1
;;
4)
! echo "Rebooting..."
reboot
! echo "Reboot failed; help!"
exit 1
;;
8)
! echo "Automatic file system check failed; help!"
exit 1
;;
12)
! echo "Boot interrupted."
exit 1
;;
130)
--- 45,61 ----
exit 1
;;
4)
! echo "Rebooting..." 1>&2
reboot
! echo "Reboot failed; help!" 1>&2
exit 1
;;
8)
! echo "Automatic file system check failed; help!" 1>&2
exit 1
;;
12)
! echo "Boot interrupted." 1>&2
exit 1
;;
130)
***************
*** 55,67 ****
exit 1
;;
*)
! echo "Unknown error; help!"
exit 1
;;
esac
fi
! trap "echo 'Boot interrupted.'; exit 1" 3
umount -a >/dev/null 2>&1
mount /
--- 63,75 ----
exit 1
;;
*)
! echo "Unknown error; help!" 1>&2
exit 1
;;
esac
fi
! trap "echo 'Boot interrupted.' 1>&2; exit 1" 3
umount -a >/dev/null 2>&1
mount /
***************
*** 70,76 ****
if [ -f /etc/rc.subr ]; then
. /etc/rc.subr
else
! echo "Can't read /etc/rc.subr; aborting."
exit 1;
fi
--- 78,84 ----
if [ -f /etc/rc.subr ]; then
. /etc/rc.subr
else
! echo "Can't read /etc/rc.subr; aborting." 1>&2
exit 1;
fi
***************
*** 79,85 ****
fi
if [ "$rc_configured" != YES ]; then
! echo "/etc/rc.conf is not configured. Multiuser boot aborted."
exit 1
fi
--- 87,93 ----
fi
if [ "$rc_configured" != YES ]; then
! echo "/etc/rc.conf is not configured. Multiuser boot aborted." 1>&2
exit 1
fi
***************
*** 97,102 ****
--- 105,126 ----
fi
fi
+ # If a network interface is already up and running, then we must have
+ # been booted over the network. In this case, delay starting the
+ # DHCP client untill later. If we can't mount /usr, then delay as well.
+
+ if checkyesno dhclient; then
+ dhcstarted=""
+ nets="`ifconfig -a`"
+ if ! expr "$nets" : '.*inet.*' >/dev/null 2>&1; then
+ mount /usr >/dev/null 2>&1
+ if [ -r /etc/dhclient.conf ] && [ -x /usr/sbin/dhclient ]; then
+ /usr/sbin/dhclient $dhclient_flags
+ dhcstarted=1
+ fi
+ fi
+ fi
+
# set hostname, turn on network
echo 'starting network'
sh /etc/netstart
***************
*** 126,135 ****
# Check for no swap, and warn about it unless that is desired.
if [ "$no_swap" != YES ]; then
swapctl -s | grep 'no swap devices configured' > /dev/null && \
! echo "WARNING: no swap space configured!"
fi
# clean up left-over files
rm -f /etc/nologin
rm -f /var/spool/lock/LCK.*
rm -f /var/spool/uucp/STST/*
--- 150,162 ----
# Check for no swap, and warn about it unless that is desired.
if [ "$no_swap" != YES ]; then
swapctl -s | grep 'no swap devices configured' > /dev/null && \
! echo "WARNING: no swap space configured!" 1>&2
fi
# clean up left-over files
+ if [ -f /etc/rc.var-setup ]; then # set up /var
+ . /etc/rc.var-setup
+ fi
rm -f /etc/nologin
rm -f /var/spool/lock/LCK.*
rm -f /var/spool/uucp/STST/*
***************
*** 145,150 ****
--- 172,185 ----
syslogd $syslogd_flags
fi
+ # If we didn't start the DHCP client earlier, do it now.
+ if checkyesno dhclient; then
+ if [ ! "$dhcstarted" ] && [ -r /etc/dhclient.conf ] && \
+ [ -x /usr/sbin/dhclient ]; then
+ /usr/sbin/dhclient $dhclient_flags $dhclient_net_flags
+ fi
+ fi
+
# Enable ipmon (only useful if ipfilter is running)
# NOTE: requires the IPFILTER_LOG kernel option.
if checkyesno ipmon; then
***************
*** 469,473 ****
. /etc/rc.local
! date
exit 0
--- 504,508 ----
. /etc/rc.local
! date 1>&2
exit 0
>Audit-Trail:
>Unformatted: