Don't leave the console TTY constantly open.

When we leave the console TTY constantly open, we never reset the
termios attributes. This causes output processing, echoing, etc. not to
be reset to the proper values when going into single user mode after the
system has booted. It also causes nl-to-crnl-conversion not to take
place during shutdown, which causes a `staircase effect'.

This patch adds a new TTY flag, TF_OPENED_CONS, which is set when the
TTY is opened through /dev/console. Because the flags are only used by
the kernel and the pstat(8) utility, I've decided to renumber the TTY
flags. This shouldn't be an issue, because the TTY layer is not yet part
of a stable release.

Reported by:	Mark Atkinson <atkin901 yahoo com>
Tested by:	sepotvin
This commit is contained in:
Ed Schouten 2009-02-05 14:21:09 +00:00
parent ca04ba6430
commit c3328b2ab8
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=188147
4 changed files with 80 additions and 67 deletions

View File

@ -291,11 +291,12 @@ ttydev_open(struct cdev *dev, int oflags, int devtype, struct thread *td)
}
}
if (TTY_CALLOUT(tp, dev)) {
if (dev == dev_console)
tp->t_flags |= TF_OPENED_CONS;
else if (TTY_CALLOUT(tp, dev))
tp->t_flags |= TF_OPENED_OUT;
} else {
else
tp->t_flags |= TF_OPENED_IN;
}
done: tp->t_flags &= ~TF_OPENCLOSE;
ttydev_leave(tp);
@ -308,22 +309,28 @@ ttydev_close(struct cdev *dev, int fflag, int devtype, struct thread *td)
{
struct tty *tp = dev->si_drv1;
tty_lock(tp);
/*
* Don't actually close the device if it is being used as the
* console.
*/
if (dev_console_filename != NULL &&
strcmp(dev_console_filename, tty_devname(tp)) == 0)
return (0);
MPASS((tp->t_flags & TF_OPENED) != TF_OPENED);
if (dev == dev_console)
tp->t_flags &= ~TF_OPENED_CONS;
else
tp->t_flags &= ~(TF_OPENED_IN|TF_OPENED_OUT);
tty_lock(tp);
if (tp->t_flags & TF_OPENED) {
tty_unlock(tp);
return (0);
}
/*
* This can only be called once. The callin and the callout
* devices cannot be opened at the same time.
*/
MPASS((tp->t_flags & TF_OPENED) != TF_OPENED);
tp->t_flags &= ~(TF_OPENED|TF_EXCLUDE|TF_STOPPED);
tp->t_flags &= ~(TF_EXCLUDE|TF_STOPPED);
/* Properly wake up threads that are stuck - revoke(). */
tp->t_revokecnt++;
@ -1797,13 +1804,14 @@ ttyconsdev_write(struct cdev *dev, struct uio *uio, int ioflag)
}
/*
* /dev/console is a little different than normal TTY's. Unlike regular
* TTY device nodes, this device node will not revoke the entire TTY
* upon closure and all data written to it will be logged.
* /dev/console is a little different than normal TTY's. When opened,
* it determines which TTY to use. When data gets written to it, it
* will be logged in the kernel message buffer.
*/
static struct cdevsw ttyconsdev_cdevsw = {
.d_version = D_VERSION,
.d_open = ttyconsdev_open,
.d_close = ttydev_close,
.d_read = ttydev_read,
.d_write = ttyconsdev_write,
.d_ioctl = ttydev_ioctl,
@ -1845,33 +1853,34 @@ static struct {
char val;
} ttystates[] = {
#if 0
{ TF_NOPREFIX, 'N' },
{ TF_NOPREFIX, 'N' },
#endif
{ TF_INITLOCK, 'I' },
{ TF_CALLOUT, 'C' },
{ TF_INITLOCK, 'I' },
{ TF_CALLOUT, 'C' },
/* Keep these together -> 'Oi' and 'Oo'. */
{ TF_OPENED, 'O' },
{ TF_OPENED_IN, 'i' },
{ TF_OPENED_OUT,'o' },
{ TF_OPENED, 'O' },
{ TF_OPENED_IN, 'i' },
{ TF_OPENED_OUT, 'o' },
{ TF_OPENED_CONS, 'c' },
{ TF_GONE, 'G' },
{ TF_OPENCLOSE, 'B' },
{ TF_ASYNC, 'Y' },
{ TF_LITERAL, 'L' },
{ TF_GONE, 'G' },
{ TF_OPENCLOSE, 'B' },
{ TF_ASYNC, 'Y' },
{ TF_LITERAL, 'L' },
/* Keep these together -> 'Hi' and 'Ho'. */
{ TF_HIWAT, 'H' },
{ TF_HIWAT_IN, 'i' },
{ TF_HIWAT_OUT, 'o' },
{ TF_HIWAT, 'H' },
{ TF_HIWAT_IN, 'i' },
{ TF_HIWAT_OUT, 'o' },
{ TF_STOPPED, 'S' },
{ TF_EXCLUDE, 'X' },
{ TF_BYPASS, 'l' },
{ TF_ZOMBIE, 'Z' },
{ TF_HOOK, 's' },
{ TF_STOPPED, 'S' },
{ TF_EXCLUDE, 'X' },
{ TF_BYPASS, 'l' },
{ TF_ZOMBIE, 'Z' },
{ TF_HOOK, 's' },
{ 0, '\0' },
{ 0, '\0'},
};
#define TTY_FLAG_BITS \

View File

@ -64,24 +64,25 @@ struct tty {
TAILQ_ENTRY(tty) t_list; /* (l) TTY list entry. */
unsigned int t_flags; /* (t) Terminal option flags. */
/* Keep flags in sync with db_show_tty and pstat(8). */
#define TF_NOPREFIX 0x0001 /* Don't prepend "tty" to device name. */
#define TF_INITLOCK 0x0002 /* Create init/lock state devices. */
#define TF_CALLOUT 0x0004 /* Create "cua" devices. */
#define TF_OPENED_IN 0x0008 /* "tty" node is in use. */
#define TF_OPENED_OUT 0x0010 /* "cua" node is in use. */
#define TF_OPENED (TF_OPENED_IN|TF_OPENED_OUT)
#define TF_GONE 0x0020 /* Device node is gone. */
#define TF_OPENCLOSE 0x0040 /* Device is in open()/close(). */
#define TF_ASYNC 0x0080 /* Asynchronous I/O enabled. */
#define TF_LITERAL 0x0100 /* Accept the next character literally. */
#define TF_HIWAT_IN 0x0200 /* We've reached the input watermark. */
#define TF_HIWAT_OUT 0x0400 /* We've reached the output watermark. */
#define TF_NOPREFIX 0x00001 /* Don't prepend "tty" to device name. */
#define TF_INITLOCK 0x00002 /* Create init/lock state devices. */
#define TF_CALLOUT 0x00004 /* Create "cua" devices. */
#define TF_OPENED_IN 0x00008 /* "tty" node is in use. */
#define TF_OPENED_OUT 0x00010 /* "cua" node is in use. */
#define TF_OPENED_CONS 0x00020 /* Device in use as console. */
#define TF_OPENED (TF_OPENED_IN|TF_OPENED_OUT|TF_OPENED_CONS)
#define TF_GONE 0x00040 /* Device node is gone. */
#define TF_OPENCLOSE 0x00080 /* Device is in open()/close(). */
#define TF_ASYNC 0x00100 /* Asynchronous I/O enabled. */
#define TF_LITERAL 0x00200 /* Accept the next character literally. */
#define TF_HIWAT_IN 0x00400 /* We've reached the input watermark. */
#define TF_HIWAT_OUT 0x00800 /* We've reached the output watermark. */
#define TF_HIWAT (TF_HIWAT_IN|TF_HIWAT_OUT)
#define TF_STOPPED 0x0800 /* Output flow control - stopped. */
#define TF_EXCLUDE 0x1000 /* Exclusive access. */
#define TF_BYPASS 0x2000 /* Optimized input path. */
#define TF_ZOMBIE 0x4000 /* Modem disconnect received. */
#define TF_HOOK 0x8000 /* TTY has hook attached. */
#define TF_STOPPED 0x01000 /* Output flow control - stopped. */
#define TF_EXCLUDE 0x02000 /* Exclusive access. */
#define TF_BYPASS 0x04000 /* Optimized input path. */
#define TF_ZOMBIE 0x08000 /* Modem disconnect received. */
#define TF_HOOK 0x10000 /* TTY has hook attached. */
unsigned int t_revokecnt; /* (t) revoke() count. */
/* Buffering mechanisms. */

View File

@ -183,6 +183,8 @@ init/lock-state device nodes present
callout device nodes present
.It O
opened
.It c
console in use
.It G
gone
.It B

View File

@ -288,33 +288,34 @@ static struct {
char val;
} ttystates[] = {
#if 0
{ TF_NOPREFIX, 'N' },
{ TF_NOPREFIX, 'N' },
#endif
{ TF_INITLOCK, 'I' },
{ TF_CALLOUT, 'C' },
{ TF_INITLOCK, 'I' },
{ TF_CALLOUT, 'C' },
/* Keep these together -> 'Oi' and 'Oo'. */
{ TF_OPENED, 'O' },
{ TF_OPENED_IN, 'i' },
{ TF_OPENED_OUT,'o' },
{ TF_OPENED, 'O' },
{ TF_OPENED_IN, 'i' },
{ TF_OPENED_OUT, 'o' },
{ TF_OPENED_CONS, 'c' },
{ TF_GONE, 'G' },
{ TF_OPENCLOSE, 'B' },
{ TF_ASYNC, 'Y' },
{ TF_LITERAL, 'L' },
{ TF_GONE, 'G' },
{ TF_OPENCLOSE, 'B' },
{ TF_ASYNC, 'Y' },
{ TF_LITERAL, 'L' },
/* Keep these together -> 'Hi' and 'Ho'. */
{ TF_HIWAT, 'H' },
{ TF_HIWAT_IN, 'i' },
{ TF_HIWAT_OUT, 'o' },
{ TF_HIWAT, 'H' },
{ TF_HIWAT_IN, 'i' },
{ TF_HIWAT_OUT, 'o' },
{ TF_STOPPED, 'S' },
{ TF_EXCLUDE, 'X' },
{ TF_BYPASS, 'l' },
{ TF_ZOMBIE, 'Z' },
{ TF_HOOK, 's' },
{ TF_STOPPED, 'S' },
{ TF_EXCLUDE, 'X' },
{ TF_BYPASS, 'l' },
{ TF_ZOMBIE, 'Z' },
{ TF_HOOK, 's' },
{ 0, '\0' },
{ 0, '\0'},
};
static void