Module Name: src
Committed By: riz
Date: Sun Aug 17 03:34:02 UTC 2014
Modified Files:
src/sbin/mount_ptyfs [netbsd-7]: mount_ptyfs.8
src/sys/fs/ptyfs [netbsd-7]: ptyfs.h ptyfs_subr.c ptyfs_vfsops.c
ptyfs_vnops.c
Log Message:
Pull up following revision(s) (requested by hannken in ticket #29):
sbin/mount_ptyfs/mount_ptyfs.8: revision 1.14
sys/fs/ptyfs/ptyfs_vnops.c: revision 1.48
sys/fs/ptyfs/ptyfs_vnops.c: revision 1.49
sys/fs/ptyfs/ptyfs_subr.c: revision 1.30
sys/fs/ptyfs/ptyfs_subr.c: revision 1.31
sys/fs/ptyfs/ptyfs_vfsops.c: revision 1.51
sys/fs/ptyfs/ptyfs_subr.c: revision 1.32
sys/fs/ptyfs/ptyfs_vfsops.c: revision 1.52
sys/fs/ptyfs/ptyfs_vfsops.c: revision 1.53
sys/fs/ptyfs/ptyfs.h: revision 1.13
sys/fs/ptyfs/ptyfs.h: revision 1.14
Needs HASH_SLIST, not HASH_LIST.
Change ptyfs to vcache.
- Use (type, minor) as key.
- Change ptyfs_allocvp to return a referenced vnode and lock where needed.
- Remove unneeded vnode backpointer ptyfs_vnode.
- Keep a single hashlist for pty nodes to make their attributes persistent.
OK: Christos Zoulas
Overflow if *data_len == OSIZE and args->version >= PTYFS_ARGSVERSION.
Sent on tech-kern@, ok christos@
Adapt to reality -- already open BSD style nodes do not appear on
ptyfs mounts (this changed some months ago).
- 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.13 -r1.13.4.1 src/sbin/mount_ptyfs/mount_ptyfs.8
cvs rdiff -u -r1.12 -r1.12.4.1 src/sys/fs/ptyfs/ptyfs.h
cvs rdiff -u -r1.29 -r1.29.4.1 src/sys/fs/ptyfs/ptyfs_subr.c
cvs rdiff -u -r1.50 -r1.50.2.1 src/sys/fs/ptyfs/ptyfs_vfsops.c
cvs rdiff -u -r1.47 -r1.47.2.1 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/sbin/mount_ptyfs/mount_ptyfs.8
diff -u src/sbin/mount_ptyfs/mount_ptyfs.8:1.13 src/sbin/mount_ptyfs/mount_ptyfs.8:1.13.4.1
--- src/sbin/mount_ptyfs/mount_ptyfs.8:1.13 Fri Apr 4 21:19:35 2014
+++ src/sbin/mount_ptyfs/mount_ptyfs.8 Sun Aug 17 03:34:02 2014
@@ -1,4 +1,4 @@
-.\" $NetBSD: mount_ptyfs.8,v 1.13 2014/04/04 21:19:35 christos Exp $
+.\" $NetBSD: mount_ptyfs.8,v 1.13.4.1 2014/08/17 03:34:02 riz Exp $
.\"
.\"
.\" Copyright (c) 2004, 2014 The NetBSD Foundation, Inc.
@@ -28,7 +28,7 @@
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
-.Dd April 4, 2014
+.Dd August 13, 2014
.Dt MOUNT_PTYFS 8
.Os
.Sh NAME
@@ -57,8 +57,7 @@ at boot time.
.Pp
The filesystem contains pseudo-terminal slave device nodes which are
allocated dynamically via
-.Xr ptm 4 ,
-or they are already open via traditional BSD style ptys.
+.Xr ptm 4 .
.Pp
The options are as follows:
.Bl -tag -width indent
Index: src/sys/fs/ptyfs/ptyfs.h
diff -u src/sys/fs/ptyfs/ptyfs.h:1.12 src/sys/fs/ptyfs/ptyfs.h:1.12.4.1
--- src/sys/fs/ptyfs/ptyfs.h:1.12 Fri Apr 4 18:10:29 2014
+++ src/sys/fs/ptyfs/ptyfs.h Sun Aug 17 03:34:02 2014
@@ -1,4 +1,4 @@
-/* $NetBSD: ptyfs.h,v 1.12 2014/04/04 18:10:29 christos Exp $ */
+/* $NetBSD: ptyfs.h,v 1.12.4.1 2014/08/17 03:34:02 riz Exp $ */
/*
* Copyright (c) 1993
@@ -87,11 +87,15 @@ typedef enum {
/*
* control data for the proc file system.
*/
+struct ptyfskey {
+ ptyfstype ptk_type; /* type of ptyfs node */
+ int ptk_pty; /* the pty index */
+};
struct ptyfsnode {
- LIST_ENTRY(ptyfsnode) ptyfs_hash; /* hash chain */
- struct vnode *ptyfs_vnode; /* vnode associated with this ptyfsnode */
- ptyfstype ptyfs_type; /* type of ptyfs node */
- int ptyfs_pty; /* the pty index */
+ SLIST_ENTRY(ptyfsnode) ptyfs_hash; /* hash chain */
+ struct ptyfskey ptyfs_key;
+#define ptyfs_type ptyfs_key.ptk_type
+#define ptyfs_pty ptyfs_key.ptk_pty
u_long ptyfs_fileno; /* unique file id */
int ptyfs_status; /* status flag for times */
#define PTYFS_ACCESS 1
@@ -106,11 +110,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)
@@ -147,15 +154,14 @@ struct ptyfs_args {
* Convert between ptyfsnode vnode
*/
#define VTOPTYFS(vp) ((struct ptyfsnode *)(vp)->v_data)
-#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);
+struct ptyfsnode *ptyfs_get_node(ptyfstype, int);
void ptyfs_itimes(struct ptyfsnode *, const struct timespec *,
const struct timespec *, const struct timespec *);
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.29.4.1
--- src/sys/fs/ptyfs/ptyfs_subr.c:1.29 Thu Mar 27 17:31:56 2014
+++ src/sys/fs/ptyfs/ptyfs_subr.c Sun Aug 17 03:34:02 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.29.4.1 2014/08/17 03:34:02 riz 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.29.4.1 2014/08/17 03:34:02 riz Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -92,180 +92,29 @@ __KERNEL_RCSID(0, "$NetBSD: ptyfs_subr.c
#include <sys/lwp.h>
#include <fs/ptyfs/ptyfs.h>
-#include <miscfs/specfs/specdev.h>
static kmutex_t ptyfs_hashlock;
-static LIST_HEAD(ptyfs_hashhead, ptyfsnode) *ptyfs_used_tbl, *ptyfs_free_tbl;
-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 void ptyfs_rehash(kmutex_t *, struct ptyfs_hashhead **,
- u_long *);
-
-#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;
-}
-
+static SLIST_HEAD(ptyfs_hashhead, ptyfsnode) *ptyfs_node_tbl;
+static u_long ptyfs_node_mask; /* size of hash table - 1 */
/*
- * allocate a ptyfsnode/vnode pair. the vnode is
- * referenced, and locked.
+ * allocate a ptyfsnode/vnode pair. the vnode is referenced.
*
* the pty, ptyfs_type, and mount point uniquely
* identify a ptyfsnode. the mount point is needed
* because someone might mount this filesystem
* twice.
- *
- * all ptyfsnodes are maintained on a singly-linked
- * list. new nodes are only allocated when they cannot
- * be found on this list. entries on the list are
- * removed when the vfs reclaim entry is called.
- *
- * a single lock is kept for the entire list. this is
- * needed because the getnewvnode() function can block
- * waiting for a vnode to become free, in which case there
- * may be more than one ptyess trying to get the same
- * vnode. this lock is only taken if we are going to
- * call getnewvnode, since the kernel itself is single-threaded.
- *
- * if an entry is found on the list, then call vget() to
- * take a reference. this is done because there may be
- * zero references to it and so it needs to removed from
- * the vnode free list.
*/
int
-ptyfs_allocvp(struct mount *mp, struct vnode **vpp, ptyfstype type, int pty,
- struct lwp *l)
-{
- struct ptyfsnode *ptyfs;
- struct vnode *vp;
- int error;
-
- retry:
- if ((*vpp = ptyfs_used_get(type, pty, mp, LK_EXCLUSIVE)) != NULL)
- return 0;
-
- error = getnewvnode(VT_PTYFS, mp, ptyfs_vnodeop_p, NULL, &vp);
- if (error) {
- *vpp = NULL;
- return error;
- }
-
- mutex_enter(&ptyfs_hashlock);
- if (ptyfs_used_get(type, pty, mp, 0) != NULL) {
- mutex_exit(&ptyfs_hashlock);
- ungetnewvnode(vp);
- goto retry;
- }
-
- vp->v_data = ptyfs = ptyfs_free_get(type, pty, l);
- ptyfs->ptyfs_vnode = vp;
-
- switch (type) {
- case PTYFSroot: /* /pts = dr-xr-xr-x */
- vp->v_type = VDIR;
- vp->v_vflag = VV_ROOT;
- break;
-
- case PTYFSpts: /* /pts/N = cxxxxxxxxx */
- case PTYFSptc: /* controlling side = cxxxxxxxxx */
- vp->v_type = VCHR;
- spec_node_init(vp, PTYFS_MAKEDEV(ptyfs));
- break;
- default:
- panic("ptyfs_allocvp");
- }
-
- ptyfs_hashins(ptyfs);
- uvm_vnp_setsize(vp, 0);
- mutex_exit(&ptyfs_hashlock);
-
- *vpp = vp;
- return 0;
-}
-
-int
-ptyfs_freevp(struct vnode *vp)
+ptyfs_allocvp(struct mount *mp, struct vnode **vpp, ptyfstype type, int pty)
{
- struct ptyfsnode *ptyfs = VTOPTYFS(vp);
+ struct ptyfskey key;
- ptyfs_hashrem(ptyfs);
- vp->v_data = NULL;
- return 0;
+ memset(&key, 0, sizeof(key));
+ key.ptk_pty = pty;
+ key.ptk_type = type;
+ return vcache_get(mp, &key, sizeof(key), vpp);
}
/*
@@ -274,47 +123,9 @@ ptyfs_freevp(struct vnode *vp)
void
ptyfs_hashinit(void)
{
- ptyfs_used_tbl = hashinit(desiredvnodes / 4, HASH_LIST, true,
- &ptyfs_used_mask);
- ptyfs_free_tbl = hashinit(desiredvnodes / 4, HASH_LIST, true,
- &ptyfs_free_mask);
- mutex_init(&ptyfs_hashlock, MUTEX_DEFAULT, IPL_NONE);
- mutex_init(&ptyfs_used_slock, MUTEX_DEFAULT, IPL_NONE);
- mutex_init(&ptyfs_free_slock, MUTEX_DEFAULT, IPL_NONE);
-}
-
-void
-ptyfs_hashreinit(void)
-{
- ptyfs_rehash(&ptyfs_used_slock, &ptyfs_used_tbl, &ptyfs_used_mask);
- ptyfs_rehash(&ptyfs_free_slock, &ptyfs_free_tbl, &ptyfs_free_mask);
-}
-
-static void
-ptyfs_rehash(kmutex_t *hlock, struct ptyfs_hashhead **hhead,
- u_long *hmask)
-{
- struct ptyfsnode *pp;
- struct ptyfs_hashhead *oldhash, *hash;
- u_long i, oldmask, mask, val;
- hash = hashinit(desiredvnodes / 4, HASH_LIST, true, &mask);
-
- mutex_enter(hlock);
- oldhash = *hhead;
- oldmask = *hmask;
- *hhead = hash;
- *hmask = mask;
- for (i = 0; i <= oldmask; i++) {
- while ((pp = LIST_FIRST(&oldhash[i])) != NULL) {
- LIST_REMOVE(pp, ptyfs_hash);
- val = PTYHASH(pp->ptyfs_type, pp->ptyfs_pty,
- ptyfs_used_mask);
- LIST_INSERT_HEAD(&hash[val], pp, ptyfs_hash);
- }
- }
- mutex_exit(hlock);
- hashdone(oldhash, HASH_LIST, oldmask);
+ ptyfs_node_tbl = hashinit(16, HASH_SLIST, true, &ptyfs_node_mask);
+ mutex_init(&ptyfs_hashlock, MUTEX_DEFAULT, IPL_NONE);
}
/*
@@ -325,105 +136,124 @@ ptyfs_hashdone(void)
{
mutex_destroy(&ptyfs_hashlock);
- mutex_destroy(&ptyfs_used_slock);
- mutex_destroy(&ptyfs_free_slock);
- hashdone(ptyfs_used_tbl, HASH_LIST, ptyfs_used_mask);
- hashdone(ptyfs_free_tbl, HASH_LIST, ptyfs_free_mask);
+ hashdone(ptyfs_node_tbl, HASH_SLIST, ptyfs_node_mask);
}
/*
- * Get a ptyfsnode from the free table, or allocate one.
- * Removes the node from the free table.
+ * Get a ptyfsnode from the hash table, or allocate one.
*/
struct ptyfsnode *
-ptyfs_free_get(ptyfstype type, int pty, struct lwp *l)
+ptyfs_get_node(ptyfstype type, int pty)
{
struct ptyfs_hashhead *ppp;
struct ptyfsnode *pp;
- mutex_enter(&ptyfs_free_slock);
- ppp = &ptyfs_free_tbl[PTYHASH(type, pty, ptyfs_free_mask)];
- LIST_FOREACH(pp, ppp, ptyfs_hash) {
+ ppp = &ptyfs_node_tbl[PTYFS_FILENO(type, pty) & ptyfs_node_mask];
+
+ mutex_enter(&ptyfs_hashlock);
+ SLIST_FOREACH(pp, ppp, ptyfs_hash) {
if (pty == pp->ptyfs_pty && pp->ptyfs_type == type) {
- LIST_REMOVE(pp, ptyfs_hash);
- mutex_exit(&ptyfs_free_slock);
+ mutex_exit(&ptyfs_hashlock);
return pp;
}
}
- mutex_exit(&ptyfs_free_slock);
+ mutex_exit(&ptyfs_hashlock);
pp = malloc(sizeof(struct ptyfsnode), M_TEMP, M_WAITOK);
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;
+ mutex_enter(&ptyfs_hashlock);
+ SLIST_INSERT_HEAD(ppp, pp, ptyfs_hash);
+ mutex_exit(&ptyfs_hashlock);
return pp;
}
-struct vnode *
-ptyfs_used_get(ptyfstype type, int pty, struct mount *mp, int flags)
+/*
+ * Mark this controlling pty as active.
+ */
+void
+ptyfs_set_active(struct mount *mp, int pty)
{
- struct ptyfs_hashhead *ppp;
- struct ptyfsnode *pp;
- struct vnode *vp;
+ struct ptyfsmount *pmnt = VFSTOPTY(mp);
-loop:
- mutex_enter(&ptyfs_used_slock);
- ppp = &ptyfs_used_tbl[PTYHASH(type, pty, ptyfs_used_mask)];
- LIST_FOREACH(pp, ppp, ptyfs_hash) {
- vp = PTYFSTOV(pp);
- if (pty == pp->ptyfs_pty && pp->ptyfs_type == type &&
- vp->v_mount == mp) {
- if (flags == 0) {
- mutex_exit(&ptyfs_used_slock);
- } else {
- mutex_enter(vp->v_interlock);
- mutex_exit(&ptyfs_used_slock);
- if (vget(vp, flags))
- goto loop;
- }
- return vp;
+ 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_exit(&ptyfs_used_slock);
- return NULL;
+
+ mutex_enter(&pmnt->pmnt_lock);
+ setbit(pmnt->pmnt_bitmap, pty);
+ mutex_exit(&pmnt->pmnt_lock);
}
/*
- * Insert the ptyfsnode into the used table and lock it.
+ * Mark this controlling pty as inactive.
*/
-static void
-ptyfs_hashins(struct ptyfsnode *pp)
+void
+ptyfs_clr_active(struct mount *mp, int pty)
{
- struct ptyfs_hashhead *ppp;
- int error __diagused;
+ struct ptyfsmount *pmnt = VFSTOPTY(mp);
- /* lock the ptyfsnode, then put it on the appropriate hash list */
- error = VOP_LOCK(PTYFSTOV(pp), LK_EXCLUSIVE);
- KASSERT(error == 0);
-
- mutex_enter(&ptyfs_used_slock);
- ppp = &ptyfs_used_tbl[PTYHASH(pp->ptyfs_type, pp->ptyfs_pty,
- ptyfs_used_mask)];
- LIST_INSERT_HEAD(ppp, pp, ptyfs_hash);
- mutex_exit(&ptyfs_used_slock);
+ 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);
}
/*
- * Remove the ptyfsnode from the used table, and add it to the free table
+ * Lookup the next active controlling pty greater or equal "pty".
+ * Return -1 if not found.
*/
-static void
-ptyfs_hashrem(struct ptyfsnode *pp)
+int
+ptyfs_next_active(struct mount *mp, int pty)
{
- struct ptyfs_hashhead *ppp;
+ struct ptyfsmount *pmnt = VFSTOPTY(mp);
- mutex_enter(&ptyfs_used_slock);
- LIST_REMOVE(pp, ptyfs_hash);
- mutex_exit(&ptyfs_used_slock);
-
- mutex_enter(&ptyfs_free_slock);
- ppp = &ptyfs_free_tbl[PTYHASH(pp->ptyfs_type, pp->ptyfs_pty,
- ptyfs_free_mask)];
- LIST_INSERT_HEAD(ppp, pp, ptyfs_hash);
- mutex_exit(&ptyfs_free_slock);
+ 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.50.2.1
--- src/sys/fs/ptyfs/ptyfs_vfsops.c:1.50 Wed Apr 16 18:55:18 2014
+++ src/sys/fs/ptyfs/ptyfs_vfsops.c Sun Aug 17 03:34:02 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.50.2.1 2014/08/17 03:34:02 riz 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.50.2.1 2014/08/17 03:34:02 riz 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,18 @@ 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)
+ return error;
+ error = vn_lock(*vpp, LK_EXCLUSIVE);
+ if (error) {
+ vrele(*vpp);
+ *vpp = NULL;
+ return error;
+ }
+ if (type == PTYFSptc)
+ ptyfs_set_active(mp, minor(dev));
+ return 0;
}
@@ -235,7 +248,7 @@ ptyfs_init(void)
void
ptyfs_reinit(void)
{
- ptyfs_hashreinit();
+
}
void
@@ -261,8 +274,10 @@ ptyfs_mount(struct mount *mp, const char
if (args == NULL)
return EINVAL;
- if (*data_len != sizeof *args && *data_len != OSIZE)
- return EINVAL;
+ if (*data_len != sizeof *args) {
+ if (*data_len != OSIZE || args->version >= PTYFS_ARGSVERSION)
+ return EINVAL;
+ }
if (UIO_MX & (UIO_MX - 1)) {
log(LOG_ERR, "ptyfs: invalid directory entry size");
@@ -299,12 +314,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 +378,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;
@@ -369,8 +390,19 @@ ptyfs_unmount(struct mount *mp, int mntf
int
ptyfs_root(struct mount *mp, struct vnode **vpp)
{
+ int error;
+
/* setup "." */
- return ptyfs_allocvp(mp, vpp, PTYFSroot, 0, NULL);
+ error = ptyfs_allocvp(mp, vpp, PTYFSroot, 0);
+ if (error)
+ return error;
+ error = vn_lock(*vpp, LK_EXCLUSIVE);
+ if (error) {
+ vrele(*vpp);
+ *vpp = NULL;
+ return error;
+ }
+ return 0;
}
/*ARGSUSED*/
@@ -382,6 +414,46 @@ ptyfs_sync(struct mount *mp, int waitfor
}
/*
+ * Initialize this vnode / ptynode pair.
+ * Caller assures no other thread will try to load this node.
+ */
+int
+ptyfs_loadvnode(struct mount *mp, struct vnode *vp,
+ const void *key, size_t key_len, const void **new_key)
+{
+ struct ptyfskey pkey;
+ struct ptyfsnode *ptyfs;
+
+ KASSERT(key_len == sizeof(pkey));
+ memcpy(&pkey, key, key_len);
+
+ ptyfs = ptyfs_get_node(pkey.ptk_type, pkey.ptk_pty);
+ KASSERT(memcmp(&ptyfs->ptyfs_key, &pkey, sizeof(pkey)) == 0);
+
+ switch (pkey.ptk_type) {
+ case PTYFSroot: /* /pts = dr-xr-xr-x */
+ vp->v_type = VDIR;
+ vp->v_vflag = VV_ROOT;
+ break;
+
+ case PTYFSpts: /* /pts/N = cxxxxxxxxx */
+ case PTYFSptc: /* controlling side = cxxxxxxxxx */
+ vp->v_type = VCHR;
+ spec_node_init(vp, PTYFS_MAKEDEV(ptyfs));
+ break;
+ default:
+ panic("ptyfs_loadvnode");
+ }
+
+ vp->v_tag = VT_PTYFS;
+ vp->v_op = ptyfs_vnodeop_p;
+ vp->v_data = ptyfs;
+ uvm_vnp_setsize(vp, 0);
+ *new_key = &ptyfs->ptyfs_key;
+ return 0;
+}
+
+/*
* Kernfs flat namespace lookup.
* Currently unsupported.
*/
@@ -411,6 +483,7 @@ struct vfsops ptyfs_vfsops = {
.vfs_statvfs = genfs_statvfs,
.vfs_sync = ptyfs_sync,
.vfs_vget = ptyfs_vget,
+ .vfs_loadvnode = ptyfs_loadvnode,
.vfs_fhtovp = (void *)eopnotsupp,
.vfs_vptofh = (void *)eopnotsupp,
.vfs_init = ptyfs_init,
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.47.2.1
--- src/sys/fs/ptyfs/ptyfs_vnops.c:1.47 Fri Jul 25 08:20:52 2014
+++ src/sys/fs/ptyfs/ptyfs_vnops.c Sun Aug 17 03:34:02 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.47.2.1 2014/08/17 03:34:02 riz 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.47.2.1 2014/08/17 03:34:02 riz Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -213,10 +213,7 @@ const struct vnodeopv_desc ptyfs_vnodeop
{ &ptyfs_vnodeop_p, ptyfs_vnodeop_entries };
/*
- * _reclaim is called when getnewvnode()
- * wants to make use of an entry on the vnode
- * free list. at this time the filesystem needs
- * to free any private data and remove the node
+ * free any private data and remove the node
* from any private lists.
*/
int
@@ -225,7 +222,12 @@ ptyfs_reclaim(void *v)
struct vop_reclaim_args /* {
struct vnode *a_vp;
} */ *ap = v;
- return ptyfs_freevp(ap->a_vp);
+ struct vnode *vp = ap->a_vp;
+ struct ptyfsnode *ptyfs = VTOPTYFS(vp);
+
+ vcache_remove(vp->v_mount, &ptyfs->ptyfs_key, sizeof(ptyfs->ptyfs_key));
+ vp->v_data = NULL;
+ return 0;
}
int
@@ -238,15 +240,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,16 +635,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;
- VOP_UNLOCK(*vpp);
+ if (ptyfs_next_active(dvp->v_mount, pty) != pty) {
+ vrele(*vpp);
+ *vpp = NULL;
+ return ENOENT;
+ }
return 0;
default:
@@ -690,7 +685,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 +730,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++;
}