Revert "constty(4): Make MP-safe."
Something is still busted and this is interfering with the releng amd64 testbed.
This commit is contained in:
parent
73f2698769
commit
35c7b9ba47
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
114
sys/kern/tty.c
114
sys/kern/tty.c
|
@ -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);
|
||||
|
||||
|
|
|
@ -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 *);
|
||||
|
|
Loading…
Reference in New Issue