Revert "constty(4): Make MP-safe."

Something is still busted and this is interfering with the releng
amd64 testbed.
This commit is contained in:
riastradh 2022-10-07 18:59:37 +00:00
parent 73f2698769
commit 35c7b9ba47
4 changed files with 55 additions and 193 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: cons.c,v 1.89 2022/10/07 18:55:50 riastradh Exp $ */
/* $NetBSD: cons.c,v 1.90 2022/10/07 18:59:37 riastradh Exp $ */
/*
* Copyright (c) 1988 University of Utah.
@ -39,7 +39,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: cons.c,v 1.89 2022/10/07 18:55:50 riastradh Exp $");
__KERNEL_RCSID(0, "$NetBSD: cons.c,v 1.90 2022/10/07 18:59:37 riastradh Exp $");
#include <sys/param.h>
#include <sys/proc.h>
@ -54,8 +54,6 @@ __KERNEL_RCSID(0, "$NetBSD: cons.c,v 1.89 2022/10/07 18:55:50 riastradh Exp $");
#include <sys/kauth.h>
#include <sys/mutex.h>
#include <sys/module.h>
#include <sys/atomic.h>
#include <sys/pserialize.h>
#include <dev/cons.h>
@ -69,8 +67,7 @@ dev_type_ioctl(cnioctl);
dev_type_poll(cnpoll);
dev_type_kqfilter(cnkqfilter);
static bool cn_redirect(dev_t *, int, int *, struct tty **);
static void cn_release(struct tty *);
static bool cn_redirect(dev_t *, int, int *);
const struct cdevsw cons_cdevsw = {
.d_open = cnopen,
@ -89,7 +86,7 @@ const struct cdevsw cons_cdevsw = {
static struct kmutex cn_lock;
struct tty *volatile constty; /* virtual console output device */
struct tty *constty = NULL; /* virtual console output device */
struct consdev *cn_tab; /* physical console device info */
struct vnode *cn_devvp[2]; /* vnode for underlying device. */
@ -202,7 +199,6 @@ out: mutex_exit(&cn_lock);
int
cnread(dev_t dev, struct uio *uio, int flag)
{
struct tty *ctp = NULL;
int error;
/*
@ -212,31 +208,25 @@ cnread(dev_t dev, struct uio *uio, int flag)
* input (except a shell in single-user mode, but then,
* one wouldn't TIOCCONS then).
*/
if (!cn_redirect(&dev, 1, &error, &ctp))
if (!cn_redirect(&dev, 1, &error))
return error;
error = cdev_read(dev, uio, flag);
cn_release(ctp);
return error;
return cdev_read(dev, uio, flag);
}
int
cnwrite(dev_t dev, struct uio *uio, int flag)
{
struct tty *ctp = NULL;
int error;
/* Redirect output, if that's appropriate. */
if (!cn_redirect(&dev, 0, &error, &ctp))
if (!cn_redirect(&dev, 0, &error))
return error;
error = cdev_write(dev, uio, flag);
cn_release(ctp);
return error;
return cdev_write(dev, uio, flag);
}
int
cnioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l)
{
struct tty *ctp = NULL;
int error;
error = 0;
@ -245,41 +235,29 @@ cnioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l)
* Superuser can always use this to wrest control of console
* output from the "virtual" console.
*/
if (cmd == TIOCCONS) {
struct tty *tp;
mutex_enter(&constty_lock);
tp = atomic_load_relaxed(&constty);
if (tp == NULL) {
mutex_exit(&constty_lock);
goto passthrough; /* XXX ??? */
}
if (cmd == TIOCCONS && constty != NULL) {
error = kauth_authorize_device_tty(l->l_cred,
KAUTH_DEVICE_TTY_VIRTUAL, tp);
KAUTH_DEVICE_TTY_VIRTUAL, constty);
if (!error)
atomic_store_relaxed(&constty, NULL);
mutex_exit(&constty_lock);
return error;
constty = NULL;
return (error);
}
passthrough:
/*
* Redirect the ioctl, if that's appropriate.
* Note that strange things can happen, if a program does
* ioctls on /dev/console, then the console is redirected
* out from under it.
*/
if (!cn_redirect(&dev, 0, &error, &ctp))
if (!cn_redirect(&dev, 0, &error))
return error;
error = cdev_ioctl(dev, cmd, data, flag, l);
cn_release(ctp);
return error;
return cdev_ioctl(dev, cmd, data, flag, l);
}
/*ARGSUSED*/
int
cnpoll(dev_t dev, int events, struct lwp *l)
{
struct tty *ctp = NULL;
int error;
/*
@ -287,18 +265,15 @@ cnpoll(dev_t dev, int events, struct lwp *l)
* I don't want to think of the possible side effects
* of console redirection here.
*/
if (!cn_redirect(&dev, 0, &error, &ctp))
if (!cn_redirect(&dev, 0, &error))
return POLLHUP;
error = cdev_poll(dev, events, l);
cn_release(ctp);
return error;
return cdev_poll(dev, events, l);
}
/*ARGSUSED*/
int
cnkqfilter(dev_t dev, struct knote *kn)
{
struct tty *ctp = NULL;
int error;
/*
@ -306,11 +281,9 @@ cnkqfilter(dev_t dev, struct knote *kn)
* I don't want to think of the possible side effects
* of console redirection here.
*/
if (!cn_redirect(&dev, 0, &error, &ctp))
if (!cn_redirect(&dev, 0, &error))
return error;
error = cdev_kqfilter(dev, kn);
cn_release(ctp);
return error;
return cdev_kqfilter(dev, kn);
}
int
@ -456,44 +429,28 @@ cnhalt(void)
/*
* Redirect output, if that's appropriate. If there's no real console,
* return ENXIO.
*
* Call with tty_mutex held.
*/
static bool
cn_redirect(dev_t *devp, int is_read, int *error, struct tty **ctpp)
cn_redirect(dev_t *devp, int is_read, int *error)
{
dev_t dev = *devp;
struct tty *ctp;
int s;
bool ok = false;
*error = ENXIO;
*ctpp = NULL;
s = pserialize_read_enter();
if ((ctp = atomic_load_consume(&constty)) != NULL && minor(dev) == 0 &&
if (constty != NULL && minor(dev) == 0 &&
(cn_tab == NULL || (cn_tab->cn_pri != CN_REMOTE))) {
if (is_read) {
*error = 0;
goto out;
return false;
}
tty_acquire(ctp);
*ctpp = ctp;
dev = ctp->t_dev;
dev = constty->t_dev;
} else if (cn_tab == NULL)
goto out;
return false;
else
dev = cn_tab->cn_dev;
ok = true;
*devp = dev;
out: pserialize_read_exit(s);
return ok;
}
static void
cn_release(struct tty *ctp)
{
if (ctp == NULL)
return;
tty_release(ctp);
return true;
}
MODULE(MODULE_CLASS_DRIVER, cons, NULL);

View File

@ -1,4 +1,4 @@
/* $NetBSD: subr_prf.c,v 1.192 2022/10/06 19:58:41 riastradh Exp $ */
/* $NetBSD: subr_prf.c,v 1.193 2022/10/07 18:59:37 riastradh Exp $ */
/*-
* Copyright (c) 1986, 1988, 1991, 1993
@ -37,7 +37,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: subr_prf.c,v 1.192 2022/10/06 19:58:41 riastradh Exp $");
__KERNEL_RCSID(0, "$NetBSD: subr_prf.c,v 1.193 2022/10/07 18:59:37 riastradh Exp $");
#ifdef _KERNEL_OPT
#include "opt_ddb.h"
@ -103,6 +103,7 @@ static void kprintf_internal(const char *, int, void *, char *, ...);
* globals
*/
extern struct tty *constty; /* pointer to console "window" tty */
extern int log_open; /* subr_log: is /dev/klog open? */
const char *panicstr; /* arg to first call to panic (used as a flag
to indicate that panic has already been called). */
@ -400,35 +401,22 @@ addlog(const char *fmt, ...)
static void
putone(int c, int flags, struct tty *tp)
{
struct tty *ctp;
int s;
/*
* Ensure whatever constty points to can't go away while we're
* trying to use it.
*/
s = pserialize_read_enter();
if (panicstr)
atomic_store_relaxed(&constty, NULL);
constty = NULL;
if ((flags & TOCONS) &&
(ctp = atomic_load_consume(&constty)) != NULL &&
tp == NULL) {
tp = ctp;
if ((flags & TOCONS) && tp == NULL && constty) {
tp = constty;
flags |= TOTTY;
}
if ((flags & TOTTY) && tp &&
tputchar(c, flags, tp) < 0 &&
(flags & TOCONS))
atomic_cas_ptr(&constty, tp, NULL);
(flags & TOCONS) && tp == constty)
constty = NULL;
if ((flags & TOLOG) &&
c != '\0' && c != '\r' && c != 0177)
logputchar(c);
if ((flags & TOCONS) && ctp == NULL && c != '\0')
if ((flags & TOCONS) && constty == NULL && c != '\0')
(*v_putc)(c);
pserialize_read_exit(s);
}
static void

View File

@ -1,4 +1,4 @@
/* $NetBSD: tty.c,v 1.304 2022/10/06 19:58:41 riastradh Exp $ */
/* $NetBSD: tty.c,v 1.305 2022/10/07 18:59:37 riastradh Exp $ */
/*-
* Copyright (c) 2008, 2020 The NetBSD Foundation, Inc.
@ -63,7 +63,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: tty.c,v 1.304 2022/10/06 19:58:41 riastradh Exp $");
__KERNEL_RCSID(0, "$NetBSD: tty.c,v 1.305 2022/10/07 18:59:37 riastradh Exp $");
#ifdef _KERNEL_OPT
#include "opt_compat_netbsd.h"
@ -99,9 +99,6 @@ __KERNEL_RCSID(0, "$NetBSD: tty.c,v 1.304 2022/10/06 19:58:41 riastradh Exp $");
#include <sys/module.h>
#include <sys/bitops.h>
#include <sys/compat_stub.h>
#include <sys/atomic.h>
#include <sys/condvar.h>
#include <sys/pserialize.h>
#ifdef COMPAT_60
#include <compat/sys/ttycom.h>
@ -212,9 +209,6 @@ static void *tty_sigsih;
struct ttylist_head ttylist = TAILQ_HEAD_INITIALIZER(ttylist);
int tty_count;
kmutex_t tty_lock;
kmutex_t constty_lock;
static struct pserialize *constty_psz;
static kcondvar_t ttyref_cv;
struct ptm_pty *ptm = NULL;
@ -448,29 +442,14 @@ ttycancel(struct tty *tp)
int
ttyclose(struct tty *tp)
{
extern struct tty *constty; /* Temporary virtual console. */
struct session *sess;
/*
* Make sure this is not the constty. Without constty_lock it
* is always allowed to transition from nonnull to null.
*/
(void)atomic_cas_ptr(&constty, tp, NULL);
/*
* We don't know if this has _ever_ been the constty: another
* thread may have kicked it out as constty before we started
* to close.
*
* So we wait for all users that might be acquiring references
* to finish doing so -- after that, no more references can be
* made, at which point we can safely flush the tty, wait for
* the existing references to drain, and finally free or reuse
* the tty.
*/
pserialize_perform(constty_psz);
mutex_spin_enter(&tty_lock);
if (constty == tp)
constty = NULL;
ttyflush(tp, FREAD | FWRITE);
tp->t_gen++;
@ -479,9 +458,6 @@ ttyclose(struct tty *tp)
sess = tp->t_session;
tp->t_session = NULL;
while (tp->t_refcnt)
cv_wait(&ttyref_cv, &tty_lock);
mutex_spin_exit(&tty_lock);
if (sess != NULL) {
@ -497,44 +473,6 @@ ttyclose(struct tty *tp)
ndflush(q, (q)->c_cc); \
}
/*
* tty_acquire(tp), tty_release(tp)
*
* Acquire a reference to tp that prevents it from being closed
* until released. Caller must guarantee tp has not yet been
* closed, e.g. by obtaining tp from constty during a pserialize
* read section. Caller must not hold tty_lock.
*/
void
tty_acquire(struct tty *tp)
{
unsigned refcnt __diagused;
refcnt = atomic_inc_uint_nv(&tp->t_refcnt);
KASSERT(refcnt < UINT_MAX);
}
void
tty_release(struct tty *tp)
{
unsigned old, new;
KDASSERT(mutex_ownable(&tty_lock));
do {
old = atomic_load_relaxed(&tp->t_refcnt);
if (old == 1) {
mutex_spin_enter(&tty_lock);
if (atomic_dec_uint_nv(&tp->t_refcnt) == 0)
cv_broadcast(&ttyref_cv);
mutex_spin_exit(&tty_lock);
return;
}
KASSERT(old != 0);
new = old - 1;
} while (atomic_cas_uint(&tp->t_refcnt, old, new) != old);
}
/*
* This macro is used in canonical mode input processing, where a read
* request shall not return unless a 'line delimiter' ('\n') or 'break'
@ -1003,6 +941,7 @@ ttyoutput(int c, struct tty *tp)
int
ttioctl(struct tty *tp, u_long cmd, void *data, int flag, struct lwp *l)
{
extern struct tty *constty; /* Temporary virtual console. */
struct proc *p;
struct linesw *lp;
int s, error;
@ -1105,47 +1044,32 @@ ttioctl(struct tty *tp, u_long cmd, void *data, int flag, struct lwp *l)
mutex_spin_exit(&tty_lock);
break;
}
case TIOCCONS: { /* become virtual console */
struct tty *ctp;
mutex_enter(&constty_lock);
error = 0;
ctp = atomic_load_relaxed(&constty);
case TIOCCONS: /* become virtual console */
if (*(int *)data) {
if (ctp != NULL && ctp != tp &&
ISSET(ctp->t_state, TS_CARR_ON | TS_ISOPEN) ==
(TS_CARR_ON | TS_ISOPEN)) {
error = EBUSY;
goto unlock_constty;
}
if (constty && constty != tp &&
ISSET(constty->t_state, TS_CARR_ON | TS_ISOPEN) ==
(TS_CARR_ON | TS_ISOPEN))
return EBUSY;
pb = pathbuf_create("/dev/console");
if (pb == NULL) {
error = ENOMEM;
goto unlock_constty;
return ENOMEM;
}
NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, pb);
if ((error = namei(&nd)) != 0) {
pathbuf_destroy(pb);
goto unlock_constty;
return error;
}
error = VOP_ACCESS(nd.ni_vp, VREAD, l->l_cred);
vput(nd.ni_vp);
pathbuf_destroy(pb);
if (error)
goto unlock_constty;
return error;
KASSERT(atomic_load_relaxed(&constty) == ctp ||
atomic_load_relaxed(&constty) == NULL);
atomic_store_release(&constty, tp);
} else if (tp == ctp) {
atomic_store_relaxed(&constty, NULL);
}
unlock_constty: mutex_exit(&constty_lock);
if (error)
return error;
constty = tp;
} else if (tp == constty)
constty = NULL;
break;
}
case TIOCDRAIN: /* wait till output drained */
if ((error = ttywait(tp)) != 0)
return (error);
@ -3044,8 +2968,6 @@ tty_init(void)
{
mutex_init(&tty_lock, MUTEX_DEFAULT, IPL_VM);
mutex_init(&constty_lock, MUTEX_DEFAULT, IPL_NONE);
constty_psz = pserialize_create();
tty_sigsih = softint_establish(SOFTINT_CLOCK, ttysigintr, NULL);
KASSERT(tty_sigsih != NULL);

View File

@ -1,4 +1,4 @@
/* $NetBSD: tty.h,v 1.100 2022/10/06 19:58:41 riastradh Exp $ */
/* $NetBSD: tty.h,v 1.101 2022/10/07 18:59:37 riastradh Exp $ */
/*-
* Copyright (c) 2008 The NetBSD Foundation, Inc.
@ -149,7 +149,6 @@ struct tty {
int t_sigcount; /* # pending signals */
TAILQ_ENTRY(tty) t_sigqueue; /* entry on pending signal list */
void *t_softc; /* pointer to driver's softc. */
volatile unsigned t_refcnt; /* reference count for constty */
};
#ifdef TTY_ALLOW_PRIVATE
@ -253,8 +252,6 @@ TAILQ_HEAD(ttylist_head, tty); /* the ttylist is a TAILQ */
#ifdef _KERNEL
extern kmutex_t tty_lock;
extern kmutex_t constty_lock;
extern struct tty *volatile constty;
extern int tty_count; /* number of ttys in global ttylist */
extern struct ttychars ttydefaults;
@ -316,8 +313,6 @@ void tty_free(struct tty *);
u_char *firstc(struct clist *, int *);
bool ttypull(struct tty *);
int tty_unit(dev_t);
void tty_acquire(struct tty *);
void tty_release(struct tty *);
int clalloc(struct clist *, int, int);
void clfree(struct clist *);