summaryrefslogtreecommitdiffstats
path: root/sys/kern/tty_pts.c
diff options
context:
space:
mode:
authorkib <kib@FreeBSD.org>2007-07-03 17:44:59 +0000
committerkib <kib@FreeBSD.org>2007-07-03 17:44:59 +0000
commit3f255f64e400627dc96df33d3935bd065e91e621 (patch)
treeeb7b8593249294af9581328bc798dad8f4e72ea4 /sys/kern/tty_pts.c
parentb6f22ce3857da5dbc90fc2eaffa30d773b4e569f (diff)
downloadFreeBSD-src-3f255f64e400627dc96df33d3935bd065e91e621.zip
FreeBSD-src-3f255f64e400627dc96df33d3935bd065e91e621.tar.gz
Use make_dev_credf(MAKEDEV_REF) instead of make_dev() from the clone handler.
Lock Giant in the clone handler. Use destroy_dev_sched() explicitely from pty_maybecleanup() and postpone pty_release() until both master and slave cdevs are destroyed by setting it as callback for destroy_dev_sched(). Debugging help and testing by: Peter Holm Approved by: re (kensmith)
Diffstat (limited to 'sys/kern/tty_pts.c')
-rw-r--r--sys/kern/tty_pts.c26
1 files changed, 16 insertions, 10 deletions
diff --git a/sys/kern/tty_pts.c b/sys/kern/tty_pts.c
index 658d307..d010ddb 100644
--- a/sys/kern/tty_pts.c
+++ b/sys/kern/tty_pts.c
@@ -217,14 +217,15 @@ static void
pty_release(struct pt_desc *pt)
{
+ mtx_lock(&pt_mtx);
KASSERT(pt->pt_ptc_open == 0 && pt->pt_pts_open == 0,
("pty_release: pts/%d freed while open\n", pt->pt_num));
KASSERT(pt->pt_devs == NULL && pt->pt_devc == NULL,
("pty_release: pts/%d freed whith non-null struct cdev\n", pt->pt_num));
- mtx_assert(&pt_mtx, MA_OWNED);
nb_allocated--;
LIST_REMOVE(pt, pt_list);
LIST_INSERT_HEAD(&pt_free_list, pt, pt_list);
+ mtx_unlock(&pt_mtx);
}
/*
@@ -235,6 +236,7 @@ pty_release(struct pt_desc *pt)
static void
pty_maybecleanup(struct pt_desc *pt)
{
+ struct cdev *pt_devs, *pt_devc;
if (pt->pt_ptc_open || pt->pt_pts_open)
return;
@@ -245,16 +247,15 @@ pty_maybecleanup(struct pt_desc *pt)
if (bootverbose)
printf("destroying pty %d\n", pt->pt_num);
- destroy_dev(pt->pt_devs);
- destroy_dev(pt->pt_devc);
+ pt_devs = pt->pt_devs;
+ pt_devc = pt->pt_devc;
pt->pt_devs = pt->pt_devc = NULL;
pt->pt_tty->t_dev = NULL;
+ pt_devc->si_drv1 = NULL;
ttyrel(pt->pt_tty);
pt->pt_tty = NULL;
-
- mtx_lock(&pt_mtx);
- pty_release(pt);
- mtx_unlock(&pt_mtx);
+ destroy_dev_sched(pt_devs);
+ destroy_dev_sched_cb(pt_devc, pty_release, pt);
}
/*ARGSUSED*/
@@ -391,6 +392,8 @@ ptcopen(struct cdev *dev, int flag, int devtype, struct thread *td)
struct cdev *devs;
pt = dev->si_drv1;
+ if (pt == NULL)
+ return (EIO);
/*
* In case we have destroyed the struct tty at the last connect time,
* we need to recreate it.
@@ -866,9 +869,12 @@ pty_clone(void *arg, struct ucred *cred, char *name, int namelen,
if (strcmp(name, "ptmx") != 0)
return;
+ mtx_lock(&Giant);
pt = pty_new();
- if (pt == NULL)
+ if (pt == NULL) {
+ mtx_unlock(&Giant);
return;
+ }
/*
* XXX: Lack of locking here considered worrying. We expose the
@@ -881,14 +887,14 @@ pty_clone(void *arg, struct ucred *cred, char *name, int namelen,
* opened, or some way to tell devfs that "this had better be for
* an open() or we won't create a device".
*/
- pt->pt_devc = devc = make_dev_cred(&ptc_cdevsw,
+ pt->pt_devc = devc = make_dev_credf(MAKEDEV_REF, &ptc_cdevsw,
NUM_TO_MINOR(pt->pt_num), cred, UID_ROOT, GID_WHEEL, 0666,
"pty/%d", pt->pt_num);
- dev_ref(devc);
devc->si_drv1 = pt;
devc->si_tty = pt->pt_tty;
*dev = devc;
+ mtx_unlock(&Giant);
if (bootverbose)
printf("pty_clone: allocated pty %d to uid %d\n", pt->pt_num,
OpenPOWER on IntegriCloud