Module Name: src Committed By: hannken Date: Wed Aug 13 14:10:00 UTC 2014
Modified Files: src/sys/fs/ptyfs: ptyfs.h ptyfs_subr.c ptyfs_vfsops.c ptyfs_vnops.c Log Message: - Add a map of active controlling ptys per mount and no longer abuse the vnode lifecycle. - No longer set "recycle" on VOP_INACTIVE(). - Make ptyfs_used_get() private to ptyfs_subr.c - Stop copying device attributes from traditional ptys on first allocation. - Remove unneeded argument "lwp" from ptyfs_allocvp() and ptyfs_free_get(). OK: Christos Zoulas To generate a diff of this commit: cvs rdiff -u -r1.12 -r1.13 src/sys/fs/ptyfs/ptyfs.h cvs rdiff -u -r1.29 -r1.30 src/sys/fs/ptyfs/ptyfs_subr.c cvs rdiff -u -r1.50 -r1.51 src/sys/fs/ptyfs/ptyfs_vfsops.c cvs rdiff -u -r1.47 -r1.48 src/sys/fs/ptyfs/ptyfs_vnops.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/fs/ptyfs/ptyfs.h diff -u src/sys/fs/ptyfs/ptyfs.h:1.12 src/sys/fs/ptyfs/ptyfs.h:1.13 --- src/sys/fs/ptyfs/ptyfs.h:1.12 Fri Apr 4 18:10:29 2014 +++ src/sys/fs/ptyfs/ptyfs.h Wed Aug 13 14:10:00 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: ptyfs.h,v 1.12 2014/04/04 18:10:29 christos Exp $ */ +/* $NetBSD: ptyfs.h,v 1.13 2014/08/13 14:10:00 hannken Exp $ */ /* * Copyright (c) 1993 @@ -106,11 +106,14 @@ struct ptyfsnode { }; struct ptyfsmount { + kmutex_t pmnt_lock; TAILQ_ENTRY(ptyfsmount) pmnt_le; struct mount *pmnt_mp; gid_t pmnt_gid; mode_t pmnt_mode; int pmnt_flags; + int pmnt_bitmap_size; + uint8_t *pmnt_bitmap; }; #define VFSTOPTY(mp) ((struct ptyfsmount *)(mp)->mnt_data) @@ -150,9 +153,10 @@ struct ptyfs_args { #define PTYFSTOV(ptyfs) ((ptyfs)->ptyfs_vnode) int ptyfs_freevp(struct vnode *); -struct vnode *ptyfs_used_get(ptyfstype, int, struct mount *, int); -int ptyfs_allocvp(struct mount *, struct vnode **, ptyfstype, int, - struct lwp *); +void ptyfs_set_active(struct mount *, int); +void ptyfs_clr_active(struct mount *, int); +int ptyfs_next_active(struct mount *, int); +int ptyfs_allocvp(struct mount *, struct vnode **, ptyfstype, int); void ptyfs_hashinit(void); void ptyfs_hashreinit(void); void ptyfs_hashdone(void); Index: src/sys/fs/ptyfs/ptyfs_subr.c diff -u src/sys/fs/ptyfs/ptyfs_subr.c:1.29 src/sys/fs/ptyfs/ptyfs_subr.c:1.30 --- src/sys/fs/ptyfs/ptyfs_subr.c:1.29 Thu Mar 27 17:31:56 2014 +++ src/sys/fs/ptyfs/ptyfs_subr.c Wed Aug 13 14:10:00 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: ptyfs_subr.c,v 1.29 2014/03/27 17:31:56 christos Exp $ */ +/* $NetBSD: ptyfs_subr.c,v 1.30 2014/08/13 14:10:00 hannken Exp $ */ /* * Copyright (c) 1993 @@ -73,7 +73,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ptyfs_subr.c,v 1.29 2014/03/27 17:31:56 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ptyfs_subr.c,v 1.30 2014/08/13 14:10:00 hannken Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -100,12 +100,11 @@ static LIST_HEAD(ptyfs_hashhead, ptyfsno static u_long ptyfs_used_mask, ptyfs_free_mask; /* size of hash table - 1 */ static kmutex_t ptyfs_used_slock, ptyfs_free_slock; -static void ptyfs_getinfo(struct ptyfsnode *, struct lwp *); - static void ptyfs_hashins(struct ptyfsnode *); static void ptyfs_hashrem(struct ptyfsnode *); -static struct ptyfsnode *ptyfs_free_get(ptyfstype, int, struct lwp *); +static struct vnode *ptyfs_used_get(ptyfstype, int, struct mount *, int); +static struct ptyfsnode *ptyfs_free_get(ptyfstype, int); static void ptyfs_rehash(kmutex_t *, struct ptyfs_hashhead **, u_long *); @@ -113,74 +112,6 @@ static void ptyfs_rehash(kmutex_t *, str #define PTYHASH(type, pty, mask) (PTYFS_FILENO(type, pty) % (mask + 1)) -static void -ptyfs_getinfo(struct ptyfsnode *ptyfs, struct lwp *l) -{ - extern struct ptm_pty *ptyfs_save_ptm; - - if (ptyfs->ptyfs_type == PTYFSroot) { - ptyfs->ptyfs_mode = S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP| - S_IROTH|S_IXOTH; - goto out; - } else - ptyfs->ptyfs_mode = S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP| - S_IROTH|S_IWOTH; - - if (ptyfs_save_ptm != NULL) { - int error; - struct pathbuf *pb; - struct nameidata nd; - char ttyname[64]; - kauth_cred_t cred; - struct vattr va; - - /* - * We support traditional ptys, so we copy the info - * from the inode - */ - if ((error = (*ptyfs_save_ptm->makename)( - NULL, l, ttyname, sizeof(ttyname), - ptyfs->ptyfs_pty, ptyfs->ptyfs_type == PTYFSpts ? 't' - : 'p')) != 0) - goto out; - pb = pathbuf_create(ttyname); - if (pb == NULL) { - error = ENOMEM; - goto out; - } - NDINIT(&nd, LOOKUP, NOFOLLOW|LOCKLEAF, pb); - if ((error = namei(&nd)) != 0) { - pathbuf_destroy(pb); - goto out; - } - cred = kauth_cred_alloc(); - error = VOP_GETATTR(nd.ni_vp, &va, cred); - kauth_cred_free(cred); - VOP_UNLOCK(nd.ni_vp); - vrele(nd.ni_vp); - pathbuf_destroy(pb); - if (error) - goto out; - ptyfs->ptyfs_uid = va.va_uid; - ptyfs->ptyfs_gid = va.va_gid; - ptyfs->ptyfs_mode = va.va_mode; - ptyfs->ptyfs_flags = va.va_flags; - ptyfs->ptyfs_birthtime = va.va_birthtime; - ptyfs->ptyfs_ctime = va.va_ctime; - ptyfs->ptyfs_mtime = va.va_mtime; - ptyfs->ptyfs_atime = va.va_atime; - return; - } -out: - ptyfs->ptyfs_uid = ptyfs->ptyfs_gid = 0; - ptyfs->ptyfs_status |= PTYFS_CHANGE; - PTYFS_ITIMES(ptyfs, NULL, NULL, NULL); - ptyfs->ptyfs_birthtime = ptyfs->ptyfs_mtime = - ptyfs->ptyfs_atime = ptyfs->ptyfs_ctime; - ptyfs->ptyfs_flags = 0; -} - - /* * allocate a ptyfsnode/vnode pair. the vnode is * referenced, and locked. @@ -208,8 +139,7 @@ out: * the vnode free list. */ int -ptyfs_allocvp(struct mount *mp, struct vnode **vpp, ptyfstype type, int pty, - struct lwp *l) +ptyfs_allocvp(struct mount *mp, struct vnode **vpp, ptyfstype type, int pty) { struct ptyfsnode *ptyfs; struct vnode *vp; @@ -232,7 +162,7 @@ ptyfs_allocvp(struct mount *mp, struct v goto retry; } - vp->v_data = ptyfs = ptyfs_free_get(type, pty, l); + vp->v_data = ptyfs = ptyfs_free_get(type, pty); ptyfs->ptyfs_vnode = vp; switch (type) { @@ -336,7 +266,7 @@ ptyfs_hashdone(void) * Removes the node from the free table. */ struct ptyfsnode * -ptyfs_free_get(ptyfstype type, int pty, struct lwp *l) +ptyfs_free_get(ptyfstype type, int pty) { struct ptyfs_hashhead *ppp; struct ptyfsnode *pp; @@ -356,7 +286,19 @@ ptyfs_free_get(ptyfstype type, int pty, pp->ptyfs_pty = pty; pp->ptyfs_type = type; pp->ptyfs_fileno = PTYFS_FILENO(pty, type); - ptyfs_getinfo(pp, l); + if (pp->ptyfs_type == PTYFSroot) + pp->ptyfs_mode = S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP| + S_IROTH|S_IXOTH; + else + pp->ptyfs_mode = S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP| + S_IROTH|S_IWOTH; + + pp->ptyfs_uid = pp->ptyfs_gid = 0; + pp->ptyfs_status = PTYFS_CHANGE; + PTYFS_ITIMES(pp, NULL, NULL, NULL); + pp->ptyfs_birthtime = pp->ptyfs_mtime = + pp->ptyfs_atime = pp->ptyfs_ctime; + pp->ptyfs_flags = 0; return pp; } @@ -427,3 +369,79 @@ ptyfs_hashrem(struct ptyfsnode *pp) LIST_INSERT_HEAD(ppp, pp, ptyfs_hash); mutex_exit(&ptyfs_free_slock); } + +/* + * Mark this controlling pty as active. + */ +void +ptyfs_set_active(struct mount *mp, int pty) +{ + struct ptyfsmount *pmnt = VFSTOPTY(mp); + + KASSERT(pty >= 0); + /* Reallocate map if needed. */ + if (pty >= pmnt->pmnt_bitmap_size * NBBY) { + int osize, nsize; + uint8_t *obitmap, *nbitmap; + + nsize = roundup(howmany(pty + 1, NBBY), 64); + nbitmap = kmem_alloc(nsize, KM_SLEEP); + mutex_enter(&pmnt->pmnt_lock); + if (pty < pmnt->pmnt_bitmap_size * NBBY) { + mutex_exit(&pmnt->pmnt_lock); + kmem_free(nbitmap, nsize); + } else { + osize = pmnt->pmnt_bitmap_size; + obitmap = pmnt->pmnt_bitmap; + pmnt->pmnt_bitmap_size = nsize; + pmnt->pmnt_bitmap = nbitmap; + if (osize > 0) + memcpy(pmnt->pmnt_bitmap, obitmap, osize); + memset(pmnt->pmnt_bitmap + osize, 0, nsize - osize); + mutex_exit(&pmnt->pmnt_lock); + if (osize > 0) + kmem_free(obitmap, osize); + } + } + + mutex_enter(&pmnt->pmnt_lock); + setbit(pmnt->pmnt_bitmap, pty); + mutex_exit(&pmnt->pmnt_lock); +} + +/* + * Mark this controlling pty as inactive. + */ +void +ptyfs_clr_active(struct mount *mp, int pty) +{ + struct ptyfsmount *pmnt = VFSTOPTY(mp); + + KASSERT(pty >= 0); + mutex_enter(&pmnt->pmnt_lock); + if (pty >= 0 && pty < pmnt->pmnt_bitmap_size * NBBY) + clrbit(pmnt->pmnt_bitmap, pty); + mutex_exit(&pmnt->pmnt_lock); +} + +/* + * Lookup the next active controlling pty greater or equal "pty". + * Return -1 if not found. + */ +int +ptyfs_next_active(struct mount *mp, int pty) +{ + struct ptyfsmount *pmnt = VFSTOPTY(mp); + + KASSERT(pty >= 0); + mutex_enter(&pmnt->pmnt_lock); + while (pty < pmnt->pmnt_bitmap_size * NBBY) { + if (isset(pmnt->pmnt_bitmap, pty)) { + mutex_exit(&pmnt->pmnt_lock); + return pty; + } + pty++; + } + mutex_exit(&pmnt->pmnt_lock); + return -1; +} Index: src/sys/fs/ptyfs/ptyfs_vfsops.c diff -u src/sys/fs/ptyfs/ptyfs_vfsops.c:1.50 src/sys/fs/ptyfs/ptyfs_vfsops.c:1.51 --- src/sys/fs/ptyfs/ptyfs_vfsops.c:1.50 Wed Apr 16 18:55:18 2014 +++ src/sys/fs/ptyfs/ptyfs_vfsops.c Wed Aug 13 14:10:00 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: ptyfs_vfsops.c,v 1.50 2014/04/16 18:55:18 maxv Exp $ */ +/* $NetBSD: ptyfs_vfsops.c,v 1.51 2014/08/13 14:10:00 hannken Exp $ */ /* * Copyright (c) 1992, 1993, 1995 @@ -38,7 +38,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ptyfs_vfsops.c,v 1.50 2014/04/16 18:55:18 maxv Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ptyfs_vfsops.c,v 1.51 2014/08/13 14:10:00 hannken Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -155,6 +155,7 @@ ptyfs__makename(struct mount *mp, struct { size_t len; const char *np; + int pty = minor(dev); switch (ms) { case 'p': @@ -170,7 +171,7 @@ ptyfs__makename(struct mount *mp, struct */ if (l->l_proc->p_cwdi->cwdi_rdir == NULL && ptyfs_save_ptm != NULL - && ptyfs_used_get(PTYFSptc, minor(dev), mp, 0) == NULL) + && ptyfs_next_active(mp, pty) != pty) return (*ptyfs_save_ptm->makename)(mp, l, tbuf, bufsiz, dev, ms); @@ -193,6 +194,7 @@ static int ptyfs__allocvp(struct mount *mp, struct lwp *l, struct vnode **vpp, dev_t dev, char ms) { + int error; ptyfstype type; switch (ms) { @@ -206,7 +208,10 @@ ptyfs__allocvp(struct mount *mp, struct return EINVAL; } - return ptyfs_allocvp(mp, vpp, type, minor(dev), l); + error = ptyfs_allocvp(mp, vpp, type, minor(dev)); + if (error == 0 && type == PTYFSptc) + ptyfs_set_active(mp, minor(dev)); + return error; } @@ -299,12 +304,15 @@ ptyfs_mount(struct mount *mp, const char pmnt = malloc(sizeof(struct ptyfsmount), M_PTYFSMNT, M_WAITOK); mp->mnt_data = pmnt; + mutex_init(&pmnt->pmnt_lock, MUTEX_DEFAULT, IPL_NONE); pmnt->pmnt_gid = args->gid; pmnt->pmnt_mode = args->mode; if (args->version >= PTYFS_ARGSVERSION) pmnt->pmnt_flags = args->flags; else pmnt->pmnt_flags = 0; + pmnt->pmnt_bitmap_size = 0; + pmnt->pmnt_bitmap = NULL; mp->mnt_flag |= MNT_LOCAL; vfs_getnewfsid(mp); @@ -360,6 +368,9 @@ ptyfs_unmount(struct mount *mp, int mntf /* * Finally, throw away the ptyfsmount structure */ + if (pmnt->pmnt_bitmap_size > 0) + kmem_free(pmnt->pmnt_bitmap, pmnt->pmnt_bitmap_size); + mutex_destroy(&pmnt->pmnt_lock); free(mp->mnt_data, M_PTYFSMNT); mp->mnt_data = NULL; @@ -370,7 +381,7 @@ int ptyfs_root(struct mount *mp, struct vnode **vpp) { /* setup "." */ - return ptyfs_allocvp(mp, vpp, PTYFSroot, 0, NULL); + return ptyfs_allocvp(mp, vpp, PTYFSroot, 0); } /*ARGSUSED*/ Index: src/sys/fs/ptyfs/ptyfs_vnops.c diff -u src/sys/fs/ptyfs/ptyfs_vnops.c:1.47 src/sys/fs/ptyfs/ptyfs_vnops.c:1.48 --- src/sys/fs/ptyfs/ptyfs_vnops.c:1.47 Fri Jul 25 08:20:52 2014 +++ src/sys/fs/ptyfs/ptyfs_vnops.c Wed Aug 13 14:10:00 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: ptyfs_vnops.c,v 1.47 2014/07/25 08:20:52 dholland Exp $ */ +/* $NetBSD: ptyfs_vnops.c,v 1.48 2014/08/13 14:10:00 hannken Exp $ */ /* * Copyright (c) 1993, 1995 @@ -76,7 +76,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ptyfs_vnops.c,v 1.47 2014/07/25 08:20:52 dholland Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ptyfs_vnops.c,v 1.48 2014/08/13 14:10:00 hannken Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -238,15 +238,8 @@ ptyfs_inactive(void *v) struct vnode *vp = ap->a_vp; struct ptyfsnode *ptyfs = VTOPTYFS(vp); - switch (ptyfs->ptyfs_type) { - case PTYFSpts: - case PTYFSptc: - /* Emulate file deletion for call reclaim(). */ - *ap->a_recycle = true; - break; - default: - break; - } + if (ptyfs->ptyfs_type == PTYFSptc) + ptyfs_clr_active(vp->v_mount, ptyfs->ptyfs_pty); return spec_inactive(v); } @@ -640,15 +633,16 @@ ptyfs_lookup(void *v) return EIO; pty = atoi(pname, cnp->cn_namelen); - - if (pty < 0 || pty >= npty || pty_isfree(pty, 1) || - ptyfs_used_get(PTYFSptc, pty, dvp->v_mount, 0) == NULL) + if (pty < 0 || ptyfs_next_active(dvp->v_mount, pty) != pty) break; - - error = ptyfs_allocvp(dvp->v_mount, vpp, PTYFSpts, pty, - curlwp); + error = ptyfs_allocvp(dvp->v_mount, vpp, PTYFSpts, pty); if (error) return error; + if (ptyfs_next_active(dvp->v_mount, pty) != pty) { + vput(*vpp); + *vpp = NULL; + return ENOENT; + } VOP_UNLOCK(*vpp); return 0; @@ -690,7 +684,7 @@ ptyfs_readdir(void *v) off_t *cookies = NULL; int ncookies; struct vnode *vp; - int nc = 0; + int n, nc = 0; vp = ap->a_vp; ptyfs = VTOPTYFS(vp); @@ -735,20 +729,20 @@ ptyfs_readdir(void *v) *cookies++ = i + 1; nc++; } - for (; uio->uio_resid >= UIO_MX && i < npty; i++) { + while (uio->uio_resid >= UIO_MX) { /* check for used ptys */ - if (pty_isfree(i - 2, 1) || - ptyfs_used_get(PTYFSptc, i - 2, vp->v_mount, 0) == NULL) - continue; - - dp->d_fileno = PTYFS_FILENO(i - 2, PTYFSpts); + n = ptyfs_next_active(vp->v_mount, i - 2); + if (n < 0) + break; + dp->d_fileno = PTYFS_FILENO(n, PTYFSpts); dp->d_namlen = snprintf(dp->d_name, sizeof(dp->d_name), - "%lld", (long long)(i - 2)); + "%lld", (long long)(n)); dp->d_type = DT_CHR; if ((error = uiomove(dp, UIO_MX, uio)) != 0) goto out; + i = n + 3; if (cookies) - *cookies++ = i + 1; + *cookies++ = i; nc++; }