Home | History | Annotate | Line # | Download | only in ptyfs
ptyfs_subr.c revision 1.23.12.3
      1  1.23.12.2       tls /*	$NetBSD: ptyfs_subr.c,v 1.23.12.3 2017/12/03 11:38:43 jdolecek Exp $	*/
      2        1.1  jdolecek 
      3        1.1  jdolecek /*
      4        1.1  jdolecek  * Copyright (c) 1993
      5        1.1  jdolecek  *	The Regents of the University of California.  All rights reserved.
      6        1.1  jdolecek  *
      7        1.1  jdolecek  * This code is derived from software contributed to Berkeley by
      8        1.1  jdolecek  * Jan-Simon Pendry.
      9        1.1  jdolecek  *
     10        1.1  jdolecek  * Redistribution and use in source and binary forms, with or without
     11        1.1  jdolecek  * modification, are permitted provided that the following conditions
     12        1.1  jdolecek  * are met:
     13        1.1  jdolecek  * 1. Redistributions of source code must retain the above copyright
     14        1.1  jdolecek  *    notice, this list of conditions and the following disclaimer.
     15        1.1  jdolecek  * 2. Redistributions in binary form must reproduce the above copyright
     16        1.1  jdolecek  *    notice, this list of conditions and the following disclaimer in the
     17        1.1  jdolecek  *    documentation and/or other materials provided with the distribution.
     18        1.1  jdolecek  * 3. Neither the name of the University nor the names of its contributors
     19        1.1  jdolecek  *    may be used to endorse or promote products derived from this software
     20        1.1  jdolecek  *    without specific prior written permission.
     21        1.1  jdolecek  *
     22        1.1  jdolecek  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     23        1.1  jdolecek  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     24        1.1  jdolecek  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     25        1.1  jdolecek  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     26        1.1  jdolecek  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     27        1.1  jdolecek  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     28        1.1  jdolecek  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     29        1.1  jdolecek  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     30        1.1  jdolecek  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     31        1.1  jdolecek  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     32        1.1  jdolecek  * SUCH DAMAGE.
     33        1.1  jdolecek  *
     34        1.1  jdolecek  *	@(#)ptyfs_subr.c	8.6 (Berkeley) 5/14/95
     35        1.1  jdolecek  */
     36        1.1  jdolecek 
     37        1.1  jdolecek /*
     38        1.1  jdolecek  * Copyright (c) 1994 Christopher G. Demetriou.  All rights reserved.
     39        1.1  jdolecek  * Copyright (c) 1993 Jan-Simon Pendry
     40        1.1  jdolecek  *
     41        1.1  jdolecek  * This code is derived from software contributed to Berkeley by
     42        1.1  jdolecek  * Jan-Simon Pendry.
     43        1.1  jdolecek  *
     44        1.1  jdolecek  * Redistribution and use in source and binary forms, with or without
     45        1.1  jdolecek  * modification, are permitted provided that the following conditions
     46        1.1  jdolecek  * are met:
     47        1.1  jdolecek  * 1. Redistributions of source code must retain the above copyright
     48        1.1  jdolecek  *    notice, this list of conditions and the following disclaimer.
     49        1.1  jdolecek  * 2. Redistributions in binary form must reproduce the above copyright
     50        1.1  jdolecek  *    notice, this list of conditions and the following disclaimer in the
     51        1.1  jdolecek  *    documentation and/or other materials provided with the distribution.
     52        1.1  jdolecek  * 3. All advertising materials mentioning features or use of this software
     53        1.1  jdolecek  *    must display the following acknowledgement:
     54        1.1  jdolecek  *	This product includes software developed by the University of
     55        1.1  jdolecek  *	California, Berkeley and its contributors.
     56        1.1  jdolecek  * 4. Neither the name of the University nor the names of its contributors
     57        1.1  jdolecek  *    may be used to endorse or promote products derived from this software
     58        1.1  jdolecek  *    without specific prior written permission.
     59        1.1  jdolecek  *
     60        1.1  jdolecek  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     61        1.1  jdolecek  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     62        1.1  jdolecek  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     63        1.1  jdolecek  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     64        1.1  jdolecek  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     65        1.1  jdolecek  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     66        1.1  jdolecek  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     67        1.1  jdolecek  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     68        1.1  jdolecek  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     69        1.1  jdolecek  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     70        1.1  jdolecek  * SUCH DAMAGE.
     71        1.1  jdolecek  *
     72        1.1  jdolecek  *	@(#)procfs_subr.c	8.6 (Berkeley) 5/14/95
     73        1.1  jdolecek  */
     74        1.1  jdolecek 
     75        1.1  jdolecek #include <sys/cdefs.h>
     76  1.23.12.2       tls __KERNEL_RCSID(0, "$NetBSD: ptyfs_subr.c,v 1.23.12.3 2017/12/03 11:38:43 jdolecek Exp $");
     77        1.1  jdolecek 
     78        1.1  jdolecek #include <sys/param.h>
     79        1.1  jdolecek #include <sys/systm.h>
     80        1.1  jdolecek #include <sys/time.h>
     81        1.1  jdolecek #include <sys/kernel.h>
     82        1.1  jdolecek #include <sys/vnode.h>
     83       1.16        ad #include <sys/stat.h>
     84        1.1  jdolecek #include <sys/malloc.h>
     85        1.1  jdolecek #include <sys/file.h>
     86        1.1  jdolecek #include <sys/namei.h>
     87        1.1  jdolecek #include <sys/filedesc.h>
     88        1.1  jdolecek #include <sys/select.h>
     89        1.1  jdolecek #include <sys/tty.h>
     90        1.1  jdolecek #include <sys/pty.h>
     91        1.7      elad #include <sys/kauth.h>
     92        1.8        ad #include <sys/lwp.h>
     93        1.1  jdolecek 
     94        1.2  jdolecek #include <fs/ptyfs/ptyfs.h>
     95        1.1  jdolecek 
     96       1.14        ad static kmutex_t ptyfs_hashlock;
     97        1.1  jdolecek 
     98  1.23.12.3  jdolecek static SLIST_HEAD(ptyfs_hashhead, ptyfsnode) *ptyfs_node_tbl;
     99  1.23.12.3  jdolecek static u_long ptyfs_node_mask; /* size of hash table - 1 */
    100        1.1  jdolecek 
    101        1.1  jdolecek /*
    102  1.23.12.3  jdolecek  * allocate a ptyfsnode/vnode pair.  the vnode is referenced.
    103        1.1  jdolecek  *
    104  1.23.12.2       tls  * the pty, ptyfs_type, and mount point uniquely
    105        1.1  jdolecek  * identify a ptyfsnode.  the mount point is needed
    106        1.1  jdolecek  * because someone might mount this filesystem
    107        1.1  jdolecek  * twice.
    108        1.1  jdolecek  */
    109        1.1  jdolecek int
    110  1.23.12.3  jdolecek ptyfs_allocvp(struct mount *mp, struct vnode **vpp, ptyfstype type, int pty)
    111        1.1  jdolecek {
    112  1.23.12.3  jdolecek 	struct ptyfskey key;
    113        1.1  jdolecek 
    114  1.23.12.3  jdolecek 	memset(&key, 0, sizeof(key));
    115  1.23.12.3  jdolecek 	key.ptk_pty = pty;
    116  1.23.12.3  jdolecek 	key.ptk_type = type;
    117  1.23.12.3  jdolecek 	return vcache_get(mp, &key, sizeof(key), vpp);
    118        1.1  jdolecek }
    119        1.1  jdolecek 
    120        1.1  jdolecek /*
    121        1.1  jdolecek  * Initialize ptyfsnode hash table.
    122        1.1  jdolecek  */
    123        1.1  jdolecek void
    124        1.1  jdolecek ptyfs_hashinit(void)
    125        1.1  jdolecek {
    126        1.1  jdolecek 
    127  1.23.12.3  jdolecek 	ptyfs_node_tbl = hashinit(16, HASH_SLIST, true, &ptyfs_node_mask);
    128  1.23.12.3  jdolecek 	mutex_init(&ptyfs_hashlock, MUTEX_DEFAULT, IPL_NONE);
    129        1.1  jdolecek }
    130        1.1  jdolecek 
    131        1.1  jdolecek /*
    132        1.1  jdolecek  * Free ptyfsnode hash table.
    133        1.1  jdolecek  */
    134        1.1  jdolecek void
    135        1.1  jdolecek ptyfs_hashdone(void)
    136        1.1  jdolecek {
    137       1.18      haad 
    138       1.18      haad 	mutex_destroy(&ptyfs_hashlock);
    139  1.23.12.3  jdolecek 	hashdone(ptyfs_node_tbl, HASH_SLIST, ptyfs_node_mask);
    140        1.1  jdolecek }
    141        1.1  jdolecek 
    142        1.1  jdolecek /*
    143  1.23.12.3  jdolecek  * Get a ptyfsnode from the hash table, or allocate one.
    144        1.1  jdolecek  */
    145        1.1  jdolecek struct ptyfsnode *
    146  1.23.12.3  jdolecek ptyfs_get_node(ptyfstype type, int pty)
    147        1.1  jdolecek {
    148        1.1  jdolecek 	struct ptyfs_hashhead *ppp;
    149        1.1  jdolecek 	struct ptyfsnode *pp;
    150        1.1  jdolecek 
    151  1.23.12.3  jdolecek 	ppp = &ptyfs_node_tbl[PTYFS_FILENO(type, pty) & ptyfs_node_mask];
    152  1.23.12.3  jdolecek 
    153  1.23.12.3  jdolecek 	mutex_enter(&ptyfs_hashlock);
    154  1.23.12.3  jdolecek 	SLIST_FOREACH(pp, ppp, ptyfs_hash) {
    155        1.1  jdolecek 		if (pty == pp->ptyfs_pty && pp->ptyfs_type == type) {
    156  1.23.12.3  jdolecek 			mutex_exit(&ptyfs_hashlock);
    157        1.1  jdolecek 			return pp;
    158        1.1  jdolecek 		}
    159        1.1  jdolecek 	}
    160  1.23.12.3  jdolecek 	mutex_exit(&ptyfs_hashlock);
    161        1.1  jdolecek 
    162       1.17    cegger 	pp = malloc(sizeof(struct ptyfsnode), M_TEMP, M_WAITOK);
    163        1.1  jdolecek 	pp->ptyfs_pty = pty;
    164        1.1  jdolecek 	pp->ptyfs_type = type;
    165        1.1  jdolecek 	pp->ptyfs_fileno = PTYFS_FILENO(pty, type);
    166  1.23.12.3  jdolecek 	if (pp->ptyfs_type == PTYFSroot)
    167  1.23.12.3  jdolecek 		pp->ptyfs_mode = S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|
    168  1.23.12.3  jdolecek 		    S_IROTH|S_IXOTH;
    169  1.23.12.3  jdolecek 	else
    170  1.23.12.3  jdolecek 		pp->ptyfs_mode = S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|
    171  1.23.12.3  jdolecek 		    S_IROTH|S_IWOTH;
    172  1.23.12.3  jdolecek 
    173  1.23.12.3  jdolecek 	pp->ptyfs_uid = pp->ptyfs_gid = 0;
    174  1.23.12.3  jdolecek 	pp->ptyfs_status = PTYFS_CHANGE;
    175  1.23.12.3  jdolecek 	PTYFS_ITIMES(pp, NULL, NULL, NULL);
    176  1.23.12.3  jdolecek 	pp->ptyfs_birthtime = pp->ptyfs_mtime =
    177  1.23.12.3  jdolecek 	    pp->ptyfs_atime = pp->ptyfs_ctime;
    178  1.23.12.3  jdolecek 	pp->ptyfs_flags = 0;
    179  1.23.12.3  jdolecek 	mutex_enter(&ptyfs_hashlock);
    180  1.23.12.3  jdolecek 	/*
    181  1.23.12.3  jdolecek 	 * XXX We have minimum race condition when opening master side
    182  1.23.12.3  jdolecek 	 * first time, if other threads through other mount points, trying
    183  1.23.12.3  jdolecek 	 * opening the same device. As follow we have little chance have
    184  1.23.12.3  jdolecek 	 * unused list entries.
    185  1.23.12.3  jdolecek 	 */
    186  1.23.12.3  jdolecek 	SLIST_INSERT_HEAD(ppp, pp, ptyfs_hash);
    187  1.23.12.3  jdolecek 	mutex_exit(&ptyfs_hashlock);
    188        1.1  jdolecek 	return pp;
    189        1.1  jdolecek }
    190        1.1  jdolecek 
    191  1.23.12.3  jdolecek /*
    192  1.23.12.3  jdolecek  * Mark this controlling pty as active.
    193  1.23.12.3  jdolecek  */
    194  1.23.12.3  jdolecek void
    195  1.23.12.3  jdolecek ptyfs_set_active(struct mount *mp, int pty)
    196        1.1  jdolecek {
    197  1.23.12.3  jdolecek 	struct ptyfsmount *pmnt = VFSTOPTY(mp);
    198        1.1  jdolecek 
    199  1.23.12.3  jdolecek 	KASSERT(pty >= 0);
    200  1.23.12.3  jdolecek 	/* Reallocate map if needed. */
    201  1.23.12.3  jdolecek 	if (pty >= pmnt->pmnt_bitmap_size * NBBY) {
    202  1.23.12.3  jdolecek 		int osize, nsize;
    203  1.23.12.3  jdolecek 		uint8_t *obitmap, *nbitmap;
    204  1.23.12.3  jdolecek 
    205  1.23.12.3  jdolecek 		nsize = roundup(howmany(pty + 1, NBBY), 64);
    206  1.23.12.3  jdolecek 		nbitmap = kmem_alloc(nsize, KM_SLEEP);
    207  1.23.12.3  jdolecek 		mutex_enter(&pmnt->pmnt_lock);
    208  1.23.12.3  jdolecek 		if (pty < pmnt->pmnt_bitmap_size * NBBY) {
    209  1.23.12.3  jdolecek 			mutex_exit(&pmnt->pmnt_lock);
    210  1.23.12.3  jdolecek 			kmem_free(nbitmap, nsize);
    211  1.23.12.3  jdolecek 		} else {
    212  1.23.12.3  jdolecek 			osize = pmnt->pmnt_bitmap_size;
    213  1.23.12.3  jdolecek 			obitmap = pmnt->pmnt_bitmap;
    214  1.23.12.3  jdolecek 			pmnt->pmnt_bitmap_size = nsize;
    215  1.23.12.3  jdolecek 			pmnt->pmnt_bitmap = nbitmap;
    216  1.23.12.3  jdolecek 			if (osize > 0)
    217  1.23.12.3  jdolecek 				memcpy(pmnt->pmnt_bitmap, obitmap, osize);
    218  1.23.12.3  jdolecek 			memset(pmnt->pmnt_bitmap + osize, 0, nsize - osize);
    219  1.23.12.3  jdolecek 			mutex_exit(&pmnt->pmnt_lock);
    220  1.23.12.3  jdolecek 			if (osize > 0)
    221  1.23.12.3  jdolecek 				kmem_free(obitmap, osize);
    222        1.1  jdolecek 		}
    223        1.1  jdolecek 	}
    224  1.23.12.3  jdolecek 
    225  1.23.12.3  jdolecek 	mutex_enter(&pmnt->pmnt_lock);
    226  1.23.12.3  jdolecek 	setbit(pmnt->pmnt_bitmap, pty);
    227  1.23.12.3  jdolecek 	mutex_exit(&pmnt->pmnt_lock);
    228        1.1  jdolecek }
    229        1.1  jdolecek 
    230        1.1  jdolecek /*
    231  1.23.12.3  jdolecek  * Mark this controlling pty as inactive.
    232        1.1  jdolecek  */
    233  1.23.12.3  jdolecek void
    234  1.23.12.3  jdolecek ptyfs_clr_active(struct mount *mp, int pty)
    235        1.1  jdolecek {
    236  1.23.12.3  jdolecek 	struct ptyfsmount *pmnt = VFSTOPTY(mp);
    237        1.1  jdolecek 
    238  1.23.12.3  jdolecek 	KASSERT(pty >= 0);
    239  1.23.12.3  jdolecek 	mutex_enter(&pmnt->pmnt_lock);
    240  1.23.12.3  jdolecek 	if (pty >= 0 && pty < pmnt->pmnt_bitmap_size * NBBY)
    241  1.23.12.3  jdolecek 		clrbit(pmnt->pmnt_bitmap, pty);
    242  1.23.12.3  jdolecek 	mutex_exit(&pmnt->pmnt_lock);
    243        1.1  jdolecek }
    244        1.1  jdolecek 
    245        1.1  jdolecek /*
    246  1.23.12.3  jdolecek  * Lookup the next active controlling pty greater or equal "pty".
    247  1.23.12.3  jdolecek  * Return -1 if not found.
    248        1.1  jdolecek  */
    249  1.23.12.3  jdolecek int
    250  1.23.12.3  jdolecek ptyfs_next_active(struct mount *mp, int pty)
    251        1.1  jdolecek {
    252  1.23.12.3  jdolecek 	struct ptyfsmount *pmnt = VFSTOPTY(mp);
    253        1.1  jdolecek 
    254  1.23.12.3  jdolecek 	KASSERT(pty >= 0);
    255  1.23.12.3  jdolecek 	mutex_enter(&pmnt->pmnt_lock);
    256  1.23.12.3  jdolecek 	while (pty < pmnt->pmnt_bitmap_size * NBBY) {
    257  1.23.12.3  jdolecek 		if (isset(pmnt->pmnt_bitmap, pty)) {
    258  1.23.12.3  jdolecek 			mutex_exit(&pmnt->pmnt_lock);
    259  1.23.12.3  jdolecek 			return pty;
    260  1.23.12.3  jdolecek 		}
    261  1.23.12.3  jdolecek 		pty++;
    262  1.23.12.3  jdolecek 	}
    263  1.23.12.3  jdolecek 	mutex_exit(&pmnt->pmnt_lock);
    264  1.23.12.3  jdolecek 	return -1;
    265        1.1  jdolecek }
    266