svn commit: r271773 - in stable/10/sys: kern sys
Peter Grehan
grehan at FreeBSD.org
Thu Sep 18 14:44:48 UTC 2014
Author: grehan
Date: Thu Sep 18 14:44:47 2014
New Revision: 271773
URL: http://svnweb.freebsd.org/changeset/base/271773
Log:
MFC tty fixes, r259549 and r259663
Keep tty_makedev as a function to preserve the KBI on 10-stable
(it is a macro in CURRENT). The changes for this are direct
commits to 10-stable.
r259549 (glebius):
- Rename tty_makedev() into tty_makedevf() and make it capable
to fail and return error.
- Use make_dev_p() in tty_makedevf() instead of make_dev_cred().
- Always pass MAKEDEV_CHECKNAME flag.
- Optionally pass MAKEDEV_REF flag.
- Provide macro for compatibility with old API.
This fixes races with simultaneous creation and desctruction of
ttys, and makes it possible to call tty_makedevf() from device
cloners.
A race in tty_watermarks() still exist, since the latter drops
lock for M_WAITOK allocation. This will be addressed in separate
commit.
r259663 (glebius):
Move list of ttys handling from the allocating procedures, to the
device creation stage. A device creation can fail, and in that case
an entry already on the list will be freed.
KBI issue pointed out by: kib
Reviewed by: kib (KBI addition)
Approved by: re (kib)
Modified:
stable/10/sys/kern/tty.c
stable/10/sys/sys/tty.h
Directory Properties:
stable/10/ (props changed)
Modified: stable/10/sys/kern/tty.c
==============================================================================
--- stable/10/sys/kern/tty.c Thu Sep 18 14:43:23 2014 (r271772)
+++ stable/10/sys/kern/tty.c Thu Sep 18 14:44:47 2014 (r271773)
@@ -289,7 +289,7 @@ ttydev_open(struct cdev *dev, int oflags
goto done;
ttydisc_open(tp);
- tty_watermarks(tp);
+ tty_watermarks(tp); /* XXXGL: drops lock */
}
/* Wait for Carrier Detect. */
@@ -1007,11 +1007,6 @@ tty_alloc_mutex(struct ttydevsw *tsw, vo
knlist_init_mtx(&tp->t_inpoll.si_note, tp->t_mtx);
knlist_init_mtx(&tp->t_outpoll.si_note, tp->t_mtx);
- sx_xlock(&tty_list_sx);
- TAILQ_INSERT_TAIL(&tty_list, tp, t_list);
- tty_list_count++;
- sx_xunlock(&tty_list_sx);
-
return (tp);
}
@@ -1020,11 +1015,6 @@ tty_dealloc(void *arg)
{
struct tty *tp = arg;
- sx_xlock(&tty_list_sx);
- TAILQ_REMOVE(&tty_list, tp, t_list);
- tty_list_count--;
- sx_xunlock(&tty_list_sx);
-
/* Make sure we haven't leaked buffers. */
MPASS(ttyinq_getsize(&tp->t_inq) == 0);
MPASS(ttyoutq_getsize(&tp->t_outq) == 0);
@@ -1065,6 +1055,11 @@ tty_rel_free(struct tty *tp)
tp->t_dev = NULL;
tty_unlock(tp);
+ sx_xlock(&tty_list_sx);
+ TAILQ_REMOVE(&tty_list, tp, t_list);
+ tty_list_count--;
+ sx_xunlock(&tty_list_sx);
+
if (dev != NULL)
destroy_dev_sched_cb(dev, tty_dealloc, tp);
}
@@ -1174,24 +1169,23 @@ SYSCTL_PROC(_kern, OID_AUTO, ttys, CTLTY
* the user.
*/
-void
-tty_makedev(struct tty *tp, struct ucred *cred, const char *fmt, ...)
+static int
+tty_vmakedevf(struct tty *tp, struct ucred *cred, int flags,
+ const char *fmt, va_list ap)
{
- va_list ap;
- struct cdev *dev;
+ struct cdev *dev, *init, *lock, *cua, *cinit, *clock;
const char *prefix = "tty";
char name[SPECNAMELEN - 3]; /* for "tty" and "cua". */
uid_t uid;
gid_t gid;
mode_t mode;
+ int error;
/* Remove "tty" prefix from devices like PTY's. */
if (tp->t_flags & TF_NOPREFIX)
prefix = "";
- va_start(ap, fmt);
vsnrprintf(name, sizeof name, 32, fmt, ap);
- va_end(ap);
if (cred == NULL) {
/* System device. */
@@ -1205,57 +1199,121 @@ tty_makedev(struct tty *tp, struct ucred
mode = S_IRUSR|S_IWUSR|S_IWGRP;
}
+ flags = flags & TTYMK_CLONING ? MAKEDEV_REF : 0;
+ flags |= MAKEDEV_CHECKNAME;
+
/* Master call-in device. */
- dev = make_dev_cred(&ttydev_cdevsw, 0, cred,
- uid, gid, mode, "%s%s", prefix, name);
+ error = make_dev_p(flags, &dev, &ttydev_cdevsw, cred, uid, gid, mode,
+ "%s%s", prefix, name);
+ if (error)
+ return (error);
dev->si_drv1 = tp;
wakeup(&dev->si_drv1);
tp->t_dev = dev;
+ init = lock = cua = cinit = clock = NULL;
+
/* Slave call-in devices. */
if (tp->t_flags & TF_INITLOCK) {
- dev = make_dev_cred(&ttyil_cdevsw, TTYUNIT_INIT, cred,
- uid, gid, mode, "%s%s.init", prefix, name);
- dev_depends(tp->t_dev, dev);
- dev->si_drv1 = tp;
- wakeup(&dev->si_drv1);
- dev->si_drv2 = &tp->t_termios_init_in;
-
- dev = make_dev_cred(&ttyil_cdevsw, TTYUNIT_LOCK, cred,
- uid, gid, mode, "%s%s.lock", prefix, name);
- dev_depends(tp->t_dev, dev);
- dev->si_drv1 = tp;
- wakeup(&dev->si_drv1);
- dev->si_drv2 = &tp->t_termios_lock_in;
+ error = make_dev_p(flags, &init, &ttyil_cdevsw, cred, uid,
+ gid, mode, "%s%s.init", prefix, name);
+ if (error)
+ goto fail;
+ dev_depends(dev, init);
+ dev2unit(init) = TTYUNIT_INIT;
+ init->si_drv1 = tp;
+ wakeup(&init->si_drv1);
+ init->si_drv2 = &tp->t_termios_init_in;
+
+ error = make_dev_p(flags, &lock, &ttyil_cdevsw, cred, uid,
+ gid, mode, "%s%s.lock", prefix, name);
+ if (error)
+ goto fail;
+ dev_depends(dev, lock);
+ dev2unit(lock) = TTYUNIT_LOCK;
+ lock->si_drv1 = tp;
+ wakeup(&lock->si_drv1);
+ lock->si_drv2 = &tp->t_termios_lock_in;
}
/* Call-out devices. */
if (tp->t_flags & TF_CALLOUT) {
- dev = make_dev_cred(&ttydev_cdevsw, TTYUNIT_CALLOUT, cred,
+ error = make_dev_p(flags, &cua, &ttydev_cdevsw, cred,
UID_UUCP, GID_DIALER, 0660, "cua%s", name);
- dev_depends(tp->t_dev, dev);
- dev->si_drv1 = tp;
- wakeup(&dev->si_drv1);
+ if (error)
+ goto fail;
+ dev_depends(dev, cua);
+ dev2unit(cua) = TTYUNIT_CALLOUT;
+ cua->si_drv1 = tp;
+ wakeup(&cua->si_drv1);
/* Slave call-out devices. */
if (tp->t_flags & TF_INITLOCK) {
- dev = make_dev_cred(&ttyil_cdevsw,
- TTYUNIT_CALLOUT | TTYUNIT_INIT, cred,
+ error = make_dev_p(flags, &cinit, &ttyil_cdevsw, cred,
UID_UUCP, GID_DIALER, 0660, "cua%s.init", name);
- dev_depends(tp->t_dev, dev);
- dev->si_drv1 = tp;
- wakeup(&dev->si_drv1);
- dev->si_drv2 = &tp->t_termios_init_out;
+ if (error)
+ goto fail;
+ dev_depends(dev, cinit);
+ dev2unit(cinit) = TTYUNIT_CALLOUT | TTYUNIT_INIT;
+ cinit->si_drv1 = tp;
+ wakeup(&cinit->si_drv1);
+ cinit->si_drv2 = &tp->t_termios_init_out;
- dev = make_dev_cred(&ttyil_cdevsw,
- TTYUNIT_CALLOUT | TTYUNIT_LOCK, cred,
+ error = make_dev_p(flags, &clock, &ttyil_cdevsw, cred,
UID_UUCP, GID_DIALER, 0660, "cua%s.lock", name);
- dev_depends(tp->t_dev, dev);
- dev->si_drv1 = tp;
- wakeup(&dev->si_drv1);
- dev->si_drv2 = &tp->t_termios_lock_out;
+ if (error)
+ goto fail;
+ dev_depends(dev, clock);
+ dev2unit(clock) = TTYUNIT_CALLOUT | TTYUNIT_LOCK;
+ clock->si_drv1 = tp;
+ wakeup(&clock->si_drv1);
+ clock->si_drv2 = &tp->t_termios_lock_out;
}
}
+
+ sx_xlock(&tty_list_sx);
+ TAILQ_INSERT_TAIL(&tty_list, tp, t_list);
+ tty_list_count++;
+ sx_xunlock(&tty_list_sx);
+
+ return (0);
+
+fail:
+ destroy_dev(dev);
+ if (init)
+ destroy_dev(init);
+ if (lock)
+ destroy_dev(lock);
+ if (cinit)
+ destroy_dev(cinit);
+ if (clock)
+ destroy_dev(clock);
+
+ return (error);
+}
+
+int
+tty_makedevf(struct tty *tp, struct ucred *cred, int flags,
+ const char *fmt, ...)
+{
+ va_list ap;
+ int error;
+
+ va_start(ap, fmt);
+ error = tty_vmakedevf(tp, cred, flags, fmt, ap);
+ va_end(ap);
+
+ return (error);
+}
+
+void
+tty_makedev(struct tty *tp, struct ucred *cred, const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ (void) tty_vmakedevf(tp, cred, 0, fmt, ap);
+ va_end(ap);
}
/*
Modified: stable/10/sys/sys/tty.h
==============================================================================
--- stable/10/sys/sys/tty.h Thu Sep 18 14:43:23 2014 (r271772)
+++ stable/10/sys/sys/tty.h Thu Sep 18 14:44:47 2014 (r271773)
@@ -173,6 +173,9 @@ void tty_rel_gone(struct tty *tp);
/* Device node creation. */
void tty_makedev(struct tty *tp, struct ucred *cred, const char *fmt, ...)
__printflike(3, 4);
+int tty_makedevf(struct tty *tp, struct ucred *cred, int flags,
+ const char *fmt, ...) __printflike(4, 5);
+#define TTYMK_CLONING 0x1
#define tty_makealias(tp,fmt,...) \
make_dev_alias((tp)->t_dev, fmt, ## __VA_ARGS__)
More information about the svn-src-stable-10
mailing list