Page MenuHomeFreeBSD

D59961.diff
No OneTemporary

D59961.diff

diff --git a/sys/kern/kern_cons.c b/sys/kern/kern_cons.c
--- a/sys/kern/kern_cons.c
+++ b/sys/kern/kern_cons.c
@@ -111,6 +111,7 @@
static struct callout conscallout; /* callout for outputting to constty */
struct msgbuf consmsgbuf; /* message buffer for console tty */
static bool console_pausing; /* pause after each line during probe */
+static bool cn_mirror; /* mirror writes to secondary consoles */
static const char console_pausestr[] =
"<pause; press any key to proceed to next line or '.' to end pause mode>";
struct tty *constty; /* pointer to console "window" tty */
@@ -167,6 +168,9 @@
|RB_VERBOSE
|RB_ASKNAME)) == RB_MUTE);
+ /* Mirror non-interactive console writes until a getty claims one. */
+ cn_mirror = (boothowto & RB_MULTIPLE) != 0;
+
/*
* Bring up the kbd layer just in time for cnprobe. Console drivers
* have a dependency on kbd being ready, so this fits nicely between the
@@ -590,6 +594,70 @@
cnputsn(p, strlen(p));
}
+bool
+cn_mirror_active(void)
+{
+
+ return (cn_mirror);
+}
+
+static void
+cnputc_secondary(int c)
+{
+ struct cn_device *cnd, *head;
+ struct consdev *cn;
+
+ if (cn_mute || c == '\0')
+ return;
+
+ head = STAILQ_FIRST(&cn_devlist);
+ STAILQ_FOREACH(cnd, &cn_devlist, cnd_next) {
+ if (cnd == head)
+ continue;
+ cn = cnd->cnd_cn;
+ if (kdb_active && (cn->cn_flags & CN_FLAG_NODEBUG))
+ continue;
+ if (c == '\n')
+ cn->cn_ops->cn_putc(cn, '\r');
+ cn->cn_ops->cn_putc(cn, c);
+ }
+}
+
+/*
+ * Mirror non-interactive console output (e.g. /etc/rc) to every
+ * secondary boot console added via RB_MULTIPLE. Writes go straight to
+ * the raw device, bypassing the tty layer, same as boot-message
+ * fan-out in cnputc(). init(8) clears kern.console_mirror for good
+ * once it starts spawning getty(8) on the individual devices, since
+ * TIOCSCTTY alone can't tell that apart from /etc/rc's own controlling
+ * tty (run_script() sets one up too, for job control).
+ */
+void
+cnputsn_secondary(const char *p, size_t n)
+{
+ size_t i;
+ bool unlock_reqd = false;
+
+ if (!cn_mirror)
+ return;
+
+ if (mtx_initialized(&cnputs_mtx)) {
+ if (mtx_owned(&cnputs_mtx))
+ return;
+ mtx_lock_spin(&cnputs_mtx);
+ unlock_reqd = true;
+ }
+
+ for (i = 0; i < n; i++)
+ cnputc_secondary(p[i]);
+
+ if (unlock_reqd)
+ mtx_unlock_spin(&cnputs_mtx);
+}
+
+SYSCTL_BOOL(_kern, OID_AUTO, console_mirror, CTLFLAG_RWTUN, &cn_mirror, 0,
+ "Mirror non-interactive console writes to secondary boot consoles");
+
static unsigned int consmsgbuf_size = 65536;
SYSCTL_UINT(_kern, OID_AUTO, consmsgbuf_size, CTLFLAG_RWTUN, &consmsgbuf_size,
0, "Console tty buffer size");
diff --git a/sys/kern/tty.c b/sys/kern/tty.c
--- a/sys/kern/tty.c
+++ b/sys/kern/tty.c
@@ -65,6 +65,7 @@
#include <sys/ttydefaults.h>
#undef TTYDEFCHARS
#include <sys/ucred.h>
+#include <sys/uio.h>
#include <sys/vnode.h>
#define EXTERR_CATEGORY EXTERR_CAT_TTY
#include <sys/exterrvar.h>
@@ -2371,9 +2372,24 @@
static int
ttyconsdev_write(struct cdev *dev, struct uio *uio, int ioflag)
{
+ struct uio *couio;
+ char buf[128];
+ int error, n;
log_console(uio);
+ if (cn_mirror_active()) {
+ couio = cloneuio(uio);
+ while (couio->uio_resid > 0) {
+ n = imin(couio->uio_resid, sizeof(buf));
+ error = uiomove(buf, n, couio);
+ if (error != 0)
+ break;
+ cnputsn_secondary(buf, n);
+ }
+ freeuio(couio);
+ }
+
return (ttydev_write(dev, uio, ioflag));
}
diff --git a/sys/sys/cons.h b/sys/sys/cons.h
--- a/sys/sys/cons.h
+++ b/sys/sys/cons.h
@@ -137,6 +137,8 @@
void cnputc(int);
void cnputs(const char *);
void cnputsn(const char *, size_t);
+void cnputsn_secondary(const char *, size_t);
+bool cn_mirror_active(void);
int cnunavailable(void);
int constty_set(struct tty *tp);
int constty_clear(struct tty *tp);

File Metadata

Mime Type
text/plain
Expires
Tue, Oct 6, 6:46 AM (55 m, 52 s)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
40284530
Default Alt Text
D59961.diff (3 KB)

Event Timeline