13f54a085SPoul-Henning Kamp /* 29d960907SPoul-Henning Kamp * Copyright (c) 2000,2004 33f54a085SPoul-Henning Kamp * Poul-Henning Kamp. All rights reserved. 43f54a085SPoul-Henning Kamp * 53f54a085SPoul-Henning Kamp * Redistribution and use in source and binary forms, with or without 63f54a085SPoul-Henning Kamp * modification, are permitted provided that the following conditions 73f54a085SPoul-Henning Kamp * are met: 83f54a085SPoul-Henning Kamp * 1. Redistributions of source code must retain the above copyright 93f54a085SPoul-Henning Kamp * notice, this list of conditions and the following disclaimer. 103f54a085SPoul-Henning Kamp * 2. Neither the name of the University nor the names of its contributors 113f54a085SPoul-Henning Kamp * may be used to endorse or promote products derived from this software 123f54a085SPoul-Henning Kamp * without specific prior written permission. 133f54a085SPoul-Henning Kamp * 143f54a085SPoul-Henning Kamp * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 153f54a085SPoul-Henning Kamp * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 163f54a085SPoul-Henning Kamp * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 173f54a085SPoul-Henning Kamp * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 183f54a085SPoul-Henning Kamp * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 193f54a085SPoul-Henning Kamp * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 203f54a085SPoul-Henning Kamp * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 213f54a085SPoul-Henning Kamp * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 223f54a085SPoul-Henning Kamp * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 233f54a085SPoul-Henning Kamp * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 243f54a085SPoul-Henning Kamp * SUCH DAMAGE. 253f54a085SPoul-Henning Kamp * 263f54a085SPoul-Henning Kamp * From: FreeBSD: src/sys/miscfs/kernfs/kernfs_vfsops.c 1.36 273f54a085SPoul-Henning Kamp * 283f54a085SPoul-Henning Kamp * $FreeBSD$ 293f54a085SPoul-Henning Kamp */ 303f54a085SPoul-Henning Kamp 3193bcdfe2SPoul-Henning Kamp #include "opt_devfs.h" 326742f328SRobert Watson #include "opt_mac.h" 3393bcdfe2SPoul-Henning Kamp 343f54a085SPoul-Henning Kamp #include <sys/param.h> 353f54a085SPoul-Henning Kamp #include <sys/systm.h> 363f54a085SPoul-Henning Kamp #include <sys/conf.h> 37fb919e4dSMark Murray #include <sys/dirent.h> 3893bcdfe2SPoul-Henning Kamp #include <sys/kernel.h> 3993bcdfe2SPoul-Henning Kamp #include <sys/lock.h> 406742f328SRobert Watson #include <sys/mac.h> 41fb919e4dSMark Murray #include <sys/malloc.h> 42fb919e4dSMark Murray #include <sys/proc.h> 43fb919e4dSMark Murray #include <sys/sysctl.h> 44fb919e4dSMark Murray #include <sys/vnode.h> 453f54a085SPoul-Henning Kamp 4693bcdfe2SPoul-Henning Kamp #include <machine/atomic.h> 4793bcdfe2SPoul-Henning Kamp 483f54a085SPoul-Henning Kamp #include <fs/devfs/devfs.h> 493f54a085SPoul-Henning Kamp 5089c9c53dSPoul-Henning Kamp static struct cdev *devfs_inot[NDEVFSINO]; 5189c9c53dSPoul-Henning Kamp static struct cdev **devfs_overflow; 5293bcdfe2SPoul-Henning Kamp static int devfs_ref[NDEVFSINO]; 5393bcdfe2SPoul-Henning Kamp static int *devfs_refoverflow; 5493bcdfe2SPoul-Henning Kamp static int devfs_nextino = 3; 5593bcdfe2SPoul-Henning Kamp static int devfs_numino; 5693bcdfe2SPoul-Henning Kamp static int devfs_topino; 5793bcdfe2SPoul-Henning Kamp static int devfs_noverflowwant = NDEVFSOVERFLOW; 5893bcdfe2SPoul-Henning Kamp static int devfs_noverflow; 5993bcdfe2SPoul-Henning Kamp static unsigned devfs_generation; 6093bcdfe2SPoul-Henning Kamp 612a043678SPoul-Henning Kamp static struct devfs_dirent *devfs_find (struct devfs_dirent *dd, const char *name, int namelen); 622a043678SPoul-Henning Kamp 6393bcdfe2SPoul-Henning Kamp SYSCTL_NODE(_vfs, OID_AUTO, devfs, CTLFLAG_RW, 0, "DEVFS filesystem"); 6493bcdfe2SPoul-Henning Kamp SYSCTL_UINT(_vfs_devfs, OID_AUTO, noverflow, CTLFLAG_RW, 6593bcdfe2SPoul-Henning Kamp &devfs_noverflowwant, 0, "Size of DEVFS overflow table"); 6693bcdfe2SPoul-Henning Kamp SYSCTL_UINT(_vfs_devfs, OID_AUTO, generation, CTLFLAG_RD, 6793bcdfe2SPoul-Henning Kamp &devfs_generation, 0, "DEVFS generation number"); 6893bcdfe2SPoul-Henning Kamp SYSCTL_UINT(_vfs_devfs, OID_AUTO, inodes, CTLFLAG_RD, 6993bcdfe2SPoul-Henning Kamp &devfs_numino, 0, "DEVFS inodes"); 7093bcdfe2SPoul-Henning Kamp SYSCTL_UINT(_vfs_devfs, OID_AUTO, topinode, CTLFLAG_RD, 7193bcdfe2SPoul-Henning Kamp &devfs_topino, 0, "DEVFS highest inode#"); 7293bcdfe2SPoul-Henning Kamp 7393bcdfe2SPoul-Henning Kamp static int * 7493bcdfe2SPoul-Henning Kamp devfs_itor(int inode) 7593bcdfe2SPoul-Henning Kamp { 7693bcdfe2SPoul-Henning Kamp if (inode < NDEVFSINO) 7793bcdfe2SPoul-Henning Kamp return (&devfs_ref[inode]); 7893bcdfe2SPoul-Henning Kamp else if (inode < NDEVFSINO + devfs_noverflow) 7993bcdfe2SPoul-Henning Kamp return (&devfs_refoverflow[inode - NDEVFSINO]); 8093bcdfe2SPoul-Henning Kamp else 8193bcdfe2SPoul-Henning Kamp panic ("YRK!"); 8293bcdfe2SPoul-Henning Kamp } 8393bcdfe2SPoul-Henning Kamp 8493bcdfe2SPoul-Henning Kamp static void 8593bcdfe2SPoul-Henning Kamp devfs_dropref(int inode) 8693bcdfe2SPoul-Henning Kamp { 8793bcdfe2SPoul-Henning Kamp int *ip; 8893bcdfe2SPoul-Henning Kamp 8993bcdfe2SPoul-Henning Kamp ip = devfs_itor(inode); 9093bcdfe2SPoul-Henning Kamp atomic_add_int(ip, -1); 9193bcdfe2SPoul-Henning Kamp } 9293bcdfe2SPoul-Henning Kamp 9393bcdfe2SPoul-Henning Kamp static int 9493bcdfe2SPoul-Henning Kamp devfs_getref(int inode) 9593bcdfe2SPoul-Henning Kamp { 9693bcdfe2SPoul-Henning Kamp int *ip, i, j; 9789c9c53dSPoul-Henning Kamp struct cdev **dp; 9893bcdfe2SPoul-Henning Kamp 9993bcdfe2SPoul-Henning Kamp ip = devfs_itor(inode); 10093bcdfe2SPoul-Henning Kamp dp = devfs_itod(inode); 10193bcdfe2SPoul-Henning Kamp for (;;) { 10293bcdfe2SPoul-Henning Kamp i = *ip; 10393bcdfe2SPoul-Henning Kamp j = i + 1; 10493bcdfe2SPoul-Henning Kamp if (!atomic_cmpset_int(ip, i, j)) 10593bcdfe2SPoul-Henning Kamp continue; 10693bcdfe2SPoul-Henning Kamp if (*dp != NULL) 10793bcdfe2SPoul-Henning Kamp return (1); 10893bcdfe2SPoul-Henning Kamp atomic_add_int(ip, -1); 10993bcdfe2SPoul-Henning Kamp return(0); 11093bcdfe2SPoul-Henning Kamp } 11193bcdfe2SPoul-Henning Kamp } 11293bcdfe2SPoul-Henning Kamp 11393bcdfe2SPoul-Henning Kamp struct devfs_dirent ** 11493bcdfe2SPoul-Henning Kamp devfs_itode (struct devfs_mount *dm, int inode) 11593bcdfe2SPoul-Henning Kamp { 11693bcdfe2SPoul-Henning Kamp 11793bcdfe2SPoul-Henning Kamp if (inode < NDEVFSINO) 11893bcdfe2SPoul-Henning Kamp return (&dm->dm_dirent[inode]); 11993bcdfe2SPoul-Henning Kamp if (devfs_overflow == NULL) 12093bcdfe2SPoul-Henning Kamp return (NULL); 12193bcdfe2SPoul-Henning Kamp if (inode < NDEVFSINO + devfs_noverflow) 12293bcdfe2SPoul-Henning Kamp return (&dm->dm_overflow[inode - NDEVFSINO]); 12393bcdfe2SPoul-Henning Kamp return (NULL); 12493bcdfe2SPoul-Henning Kamp } 12593bcdfe2SPoul-Henning Kamp 12689c9c53dSPoul-Henning Kamp struct cdev ** 12793bcdfe2SPoul-Henning Kamp devfs_itod (int inode) 12893bcdfe2SPoul-Henning Kamp { 12993bcdfe2SPoul-Henning Kamp 13093bcdfe2SPoul-Henning Kamp if (inode < NDEVFSINO) 13193bcdfe2SPoul-Henning Kamp return (&devfs_inot[inode]); 13293bcdfe2SPoul-Henning Kamp if (devfs_overflow == NULL) 13393bcdfe2SPoul-Henning Kamp return (NULL); 13493bcdfe2SPoul-Henning Kamp if (inode < NDEVFSINO + devfs_noverflow) 13593bcdfe2SPoul-Henning Kamp return (&devfs_overflow[inode - NDEVFSINO]); 13693bcdfe2SPoul-Henning Kamp return (NULL); 13793bcdfe2SPoul-Henning Kamp } 13893bcdfe2SPoul-Henning Kamp 1392a043678SPoul-Henning Kamp static struct devfs_dirent * 140c32d0a1dSPoul-Henning Kamp devfs_find(struct devfs_dirent *dd, const char *name, int namelen) 141c32d0a1dSPoul-Henning Kamp { 142c32d0a1dSPoul-Henning Kamp struct devfs_dirent *de; 143c32d0a1dSPoul-Henning Kamp 144c32d0a1dSPoul-Henning Kamp TAILQ_FOREACH(de, &dd->de_dlist, de_list) { 145c32d0a1dSPoul-Henning Kamp if (namelen != de->de_dirent->d_namlen) 146c32d0a1dSPoul-Henning Kamp continue; 147c32d0a1dSPoul-Henning Kamp if (bcmp(name, de->de_dirent->d_name, namelen) != 0) 148c32d0a1dSPoul-Henning Kamp continue; 149c32d0a1dSPoul-Henning Kamp break; 150c32d0a1dSPoul-Henning Kamp } 151c32d0a1dSPoul-Henning Kamp return (de); 152c32d0a1dSPoul-Henning Kamp } 153c32d0a1dSPoul-Henning Kamp 154c32d0a1dSPoul-Henning Kamp struct devfs_dirent * 1553f54a085SPoul-Henning Kamp devfs_newdirent(char *name, int namelen) 1563f54a085SPoul-Henning Kamp { 1573f54a085SPoul-Henning Kamp int i; 1583f54a085SPoul-Henning Kamp struct devfs_dirent *de; 1593f54a085SPoul-Henning Kamp struct dirent d; 1603f54a085SPoul-Henning Kamp 1613f54a085SPoul-Henning Kamp d.d_namlen = namelen; 1623f54a085SPoul-Henning Kamp i = sizeof (*de) + GENERIC_DIRSIZ(&d); 163a163d034SWarner Losh MALLOC(de, struct devfs_dirent *, i, M_DEVFS, M_WAITOK | M_ZERO); 1643f54a085SPoul-Henning Kamp de->de_dirent = (struct dirent *)(de + 1); 1653f54a085SPoul-Henning Kamp de->de_dirent->d_namlen = namelen; 1663f54a085SPoul-Henning Kamp de->de_dirent->d_reclen = GENERIC_DIRSIZ(&d); 167aadf2655SPoul-Henning Kamp bcopy(name, de->de_dirent->d_name, namelen); 168aadf2655SPoul-Henning Kamp de->de_dirent->d_name[namelen] = '\0'; 16993432a92SPoul-Henning Kamp vfs_timestamp(&de->de_ctime); 170a481b90bSPoul-Henning Kamp de->de_mtime = de->de_atime = de->de_ctime; 171a481b90bSPoul-Henning Kamp de->de_links = 1; 1726742f328SRobert Watson #ifdef MAC 1736742f328SRobert Watson mac_init_devfsdirent(de); 1746742f328SRobert Watson #endif 1753f54a085SPoul-Henning Kamp return (de); 1763f54a085SPoul-Henning Kamp } 1773f54a085SPoul-Henning Kamp 178a481b90bSPoul-Henning Kamp struct devfs_dirent * 179a481b90bSPoul-Henning Kamp devfs_vmkdir(char *name, int namelen, struct devfs_dirent *dotdot) 1803f54a085SPoul-Henning Kamp { 181a481b90bSPoul-Henning Kamp struct devfs_dirent *dd; 1823f54a085SPoul-Henning Kamp struct devfs_dirent *de; 1833f54a085SPoul-Henning Kamp 184a481b90bSPoul-Henning Kamp dd = devfs_newdirent(name, namelen); 185a481b90bSPoul-Henning Kamp 186a481b90bSPoul-Henning Kamp TAILQ_INIT(&dd->de_dlist); 187a481b90bSPoul-Henning Kamp 188a481b90bSPoul-Henning Kamp dd->de_dirent->d_type = DT_DIR; 18993432a92SPoul-Henning Kamp dd->de_mode = 0555; 190a481b90bSPoul-Henning Kamp dd->de_links = 2; 191a481b90bSPoul-Henning Kamp dd->de_dir = dd; 1923f54a085SPoul-Henning Kamp 1933f54a085SPoul-Henning Kamp de = devfs_newdirent(".", 1); 1943f54a085SPoul-Henning Kamp de->de_dirent->d_type = DT_DIR; 195a481b90bSPoul-Henning Kamp de->de_dir = dd; 196a481b90bSPoul-Henning Kamp de->de_flags |= DE_DOT; 197a481b90bSPoul-Henning Kamp TAILQ_INSERT_TAIL(&dd->de_dlist, de, de_list); 198a481b90bSPoul-Henning Kamp 199a481b90bSPoul-Henning Kamp de = devfs_newdirent("..", 2); 200a481b90bSPoul-Henning Kamp de->de_dirent->d_type = DT_DIR; 201a481b90bSPoul-Henning Kamp if (dotdot == NULL) 202a481b90bSPoul-Henning Kamp de->de_dir = dd; 203a481b90bSPoul-Henning Kamp else 204a481b90bSPoul-Henning Kamp de->de_dir = dotdot; 205a481b90bSPoul-Henning Kamp de->de_flags |= DE_DOTDOT; 206a481b90bSPoul-Henning Kamp TAILQ_INSERT_TAIL(&dd->de_dlist, de, de_list); 207a481b90bSPoul-Henning Kamp 2083f54a085SPoul-Henning Kamp return (dd); 2093f54a085SPoul-Henning Kamp } 2103f54a085SPoul-Henning Kamp 211a481b90bSPoul-Henning Kamp static void 212a481b90bSPoul-Henning Kamp devfs_delete(struct devfs_dirent *dd, struct devfs_dirent *de) 2133f54a085SPoul-Henning Kamp { 2143f54a085SPoul-Henning Kamp 2153f54a085SPoul-Henning Kamp if (de->de_symlink) { 2163f54a085SPoul-Henning Kamp FREE(de->de_symlink, M_DEVFS); 2173f54a085SPoul-Henning Kamp de->de_symlink = NULL; 2183f54a085SPoul-Henning Kamp } 2198abea41dSPoul-Henning Kamp if (de->de_vnode) 2203f54a085SPoul-Henning Kamp de->de_vnode->v_data = NULL; 221a481b90bSPoul-Henning Kamp TAILQ_REMOVE(&dd->de_dlist, de, de_list); 2226742f328SRobert Watson #ifdef MAC 2236742f328SRobert Watson mac_destroy_devfsdirent(de); 2246742f328SRobert Watson #endif 2253f54a085SPoul-Henning Kamp FREE(de, M_DEVFS); 2263f54a085SPoul-Henning Kamp } 2273f54a085SPoul-Henning Kamp 2283f54a085SPoul-Henning Kamp void 229a481b90bSPoul-Henning Kamp devfs_purge(struct devfs_dirent *dd) 2303f54a085SPoul-Henning Kamp { 2313f54a085SPoul-Henning Kamp struct devfs_dirent *de; 2323f54a085SPoul-Henning Kamp 2333f54a085SPoul-Henning Kamp for (;;) { 234a481b90bSPoul-Henning Kamp de = TAILQ_FIRST(&dd->de_dlist); 2353f54a085SPoul-Henning Kamp if (de == NULL) 2363f54a085SPoul-Henning Kamp break; 2373f54a085SPoul-Henning Kamp devfs_delete(dd, de); 2383f54a085SPoul-Henning Kamp } 2393f54a085SPoul-Henning Kamp FREE(dd, M_DEVFS); 2403f54a085SPoul-Henning Kamp } 2413f54a085SPoul-Henning Kamp 2423f54a085SPoul-Henning Kamp 2433f54a085SPoul-Henning Kamp int 2443f54a085SPoul-Henning Kamp devfs_populate(struct devfs_mount *dm) 2453f54a085SPoul-Henning Kamp { 2463f54a085SPoul-Henning Kamp int i, j; 24789c9c53dSPoul-Henning Kamp struct cdev *dev, *pdev; 248a481b90bSPoul-Henning Kamp struct devfs_dirent *dd; 24993bcdfe2SPoul-Henning Kamp struct devfs_dirent *de, **dep; 2503f54a085SPoul-Henning Kamp char *q, *s; 2513f54a085SPoul-Henning Kamp 25293bcdfe2SPoul-Henning Kamp if (dm->dm_generation == devfs_generation) 25393bcdfe2SPoul-Henning Kamp return (0); 254b40ce416SJulian Elischer lockmgr(&dm->dm_lock, LK_UPGRADE, 0, curthread); 25593bcdfe2SPoul-Henning Kamp if (devfs_noverflow && dm->dm_overflow == NULL) { 25693bcdfe2SPoul-Henning Kamp i = devfs_noverflow * sizeof (struct devfs_dirent *); 25793bcdfe2SPoul-Henning Kamp MALLOC(dm->dm_overflow, struct devfs_dirent **, i, 258a163d034SWarner Losh M_DEVFS, M_WAITOK | M_ZERO); 25993bcdfe2SPoul-Henning Kamp } 2603f54a085SPoul-Henning Kamp while (dm->dm_generation != devfs_generation) { 2613f54a085SPoul-Henning Kamp dm->dm_generation = devfs_generation; 26293bcdfe2SPoul-Henning Kamp for (i = 0; i <= devfs_topino; i++) { 26393bcdfe2SPoul-Henning Kamp dev = *devfs_itod(i); 26493bcdfe2SPoul-Henning Kamp dep = devfs_itode(dm, i); 26593bcdfe2SPoul-Henning Kamp de = *dep; 266a481b90bSPoul-Henning Kamp if (dev == NULL && de == DE_DELETED) { 26793bcdfe2SPoul-Henning Kamp *dep = NULL; 268a481b90bSPoul-Henning Kamp continue; 269a481b90bSPoul-Henning Kamp } 2703f54a085SPoul-Henning Kamp if (dev == NULL && de != NULL) { 2713f54a085SPoul-Henning Kamp dd = de->de_dir; 27293bcdfe2SPoul-Henning Kamp *dep = NULL; 273a481b90bSPoul-Henning Kamp TAILQ_REMOVE(&dd->de_dlist, de, de_list); 2748abea41dSPoul-Henning Kamp if (de->de_vnode) 2753f54a085SPoul-Henning Kamp de->de_vnode->v_data = NULL; 2763f54a085SPoul-Henning Kamp FREE(de, M_DEVFS); 27793bcdfe2SPoul-Henning Kamp devfs_dropref(i); 2783f54a085SPoul-Henning Kamp continue; 2793f54a085SPoul-Henning Kamp } 2803f54a085SPoul-Henning Kamp if (dev == NULL) 2813f54a085SPoul-Henning Kamp continue; 2823f54a085SPoul-Henning Kamp if (de != NULL) 2833f54a085SPoul-Henning Kamp continue; 28493bcdfe2SPoul-Henning Kamp if (!devfs_getref(i)) 28593bcdfe2SPoul-Henning Kamp continue; 2863f54a085SPoul-Henning Kamp dd = dm->dm_basedir; 2873f54a085SPoul-Henning Kamp s = dev->si_name; 288c32d0a1dSPoul-Henning Kamp for (;;) { 2893f54a085SPoul-Henning Kamp for (q = s; *q != '/' && *q != '\0'; q++) 2903f54a085SPoul-Henning Kamp continue; 291c32d0a1dSPoul-Henning Kamp if (*q != '/') 292c32d0a1dSPoul-Henning Kamp break; 293c32d0a1dSPoul-Henning Kamp de = devfs_find(dd, s, q - s); 294c32d0a1dSPoul-Henning Kamp if (de == NULL) { 295a481b90bSPoul-Henning Kamp de = devfs_vmkdir(s, q - s, dd); 2966742f328SRobert Watson #ifdef MAC 297990b4b2dSRobert Watson mac_create_devfs_directory( 298990b4b2dSRobert Watson dm->dm_mount, s, q - s, de); 2996742f328SRobert Watson #endif 300a481b90bSPoul-Henning Kamp de->de_inode = dm->dm_inode++; 301a481b90bSPoul-Henning Kamp TAILQ_INSERT_TAIL(&dd->de_dlist, de, de_list); 302a481b90bSPoul-Henning Kamp dd->de_links++; 303c32d0a1dSPoul-Henning Kamp } 304a481b90bSPoul-Henning Kamp s = q + 1; 305a481b90bSPoul-Henning Kamp dd = de; 3063f54a085SPoul-Henning Kamp } 3073f54a085SPoul-Henning Kamp de = devfs_newdirent(s, q - s); 3083f54a085SPoul-Henning Kamp if (dev->si_flags & SI_ALIAS) { 3093f54a085SPoul-Henning Kamp de->de_inode = dm->dm_inode++; 3103f54a085SPoul-Henning Kamp de->de_uid = 0; 3113f54a085SPoul-Henning Kamp de->de_gid = 0; 31293432a92SPoul-Henning Kamp de->de_mode = 0755; 3133f54a085SPoul-Henning Kamp de->de_dirent->d_type = DT_LNK; 3143344c5a1SPoul-Henning Kamp pdev = dev->si_parent; 3153f54a085SPoul-Henning Kamp j = strlen(pdev->si_name) + 1; 316a163d034SWarner Losh MALLOC(de->de_symlink, char *, j, M_DEVFS, M_WAITOK); 3173f54a085SPoul-Henning Kamp bcopy(pdev->si_name, de->de_symlink, j); 3183f54a085SPoul-Henning Kamp } else { 3193f54a085SPoul-Henning Kamp de->de_inode = i; 3203f54a085SPoul-Henning Kamp de->de_uid = dev->si_uid; 3213f54a085SPoul-Henning Kamp de->de_gid = dev->si_gid; 3223f54a085SPoul-Henning Kamp de->de_mode = dev->si_mode; 3233f54a085SPoul-Henning Kamp de->de_dirent->d_type = DT_CHR; 3243f54a085SPoul-Henning Kamp } 3256742f328SRobert Watson #ifdef MAC 326990b4b2dSRobert Watson mac_create_devfs_device(dm->dm_mount, dev, de); 3276742f328SRobert Watson #endif 32893bcdfe2SPoul-Henning Kamp *dep = de; 329c32d0a1dSPoul-Henning Kamp de->de_dir = dd; 330a1dc2096SDima Dorfman devfs_rules_apply(dm, de); 331a481b90bSPoul-Henning Kamp TAILQ_INSERT_TAIL(&dd->de_dlist, de, de_list); 3323f54a085SPoul-Henning Kamp } 3333f54a085SPoul-Henning Kamp } 334b40ce416SJulian Elischer lockmgr(&dm->dm_lock, LK_DOWNGRADE, 0, curthread); 3353f54a085SPoul-Henning Kamp return (0); 3363f54a085SPoul-Henning Kamp } 3373f54a085SPoul-Henning Kamp 3389d960907SPoul-Henning Kamp /* 3399d960907SPoul-Henning Kamp * devfs_create() and devfs_destroy() are called from kern_conf.c and 3409d960907SPoul-Henning Kamp * in both cases the devlock() mutex is held, so no further locking 3419d960907SPoul-Henning Kamp * is necesary and no sleeping allowed. 3429d960907SPoul-Henning Kamp */ 3439d960907SPoul-Henning Kamp 3449285a87eSPoul-Henning Kamp void 34589c9c53dSPoul-Henning Kamp devfs_create(struct cdev *dev) 3463f54a085SPoul-Henning Kamp { 34793bcdfe2SPoul-Henning Kamp int ino, i, *ip; 34889c9c53dSPoul-Henning Kamp struct cdev **dp; 3499d960907SPoul-Henning Kamp struct cdev **ot; 3509d960907SPoul-Henning Kamp int *or; 3519d960907SPoul-Henning Kamp int n; 35293bcdfe2SPoul-Henning Kamp 35393bcdfe2SPoul-Henning Kamp for (;;) { 35493bcdfe2SPoul-Henning Kamp /* Grab the next inode number */ 35593bcdfe2SPoul-Henning Kamp ino = devfs_nextino; 35693bcdfe2SPoul-Henning Kamp i = ino + 1; 35793bcdfe2SPoul-Henning Kamp /* wrap around when we reach the end */ 35893bcdfe2SPoul-Henning Kamp if (i >= NDEVFSINO + devfs_noverflow) 35993bcdfe2SPoul-Henning Kamp i = 3; 3609d960907SPoul-Henning Kamp devfs_nextino = i; 36193bcdfe2SPoul-Henning Kamp 36293bcdfe2SPoul-Henning Kamp /* see if it was occupied */ 36393bcdfe2SPoul-Henning Kamp dp = devfs_itod(ino); 3649d960907SPoul-Henning Kamp KASSERT(dp != NULL, ("DEVFS: No devptr inode %d", ino)); 36593bcdfe2SPoul-Henning Kamp if (*dp != NULL) 36693bcdfe2SPoul-Henning Kamp continue; 36793bcdfe2SPoul-Henning Kamp ip = devfs_itor(ino); 3689d960907SPoul-Henning Kamp KASSERT(ip != NULL, ("DEVFS: No iptr inode %d", ino)); 36993bcdfe2SPoul-Henning Kamp if (*ip != 0) 37093bcdfe2SPoul-Henning Kamp continue; 3719d960907SPoul-Henning Kamp break; 3729d960907SPoul-Henning Kamp } 37393bcdfe2SPoul-Henning Kamp 3749d960907SPoul-Henning Kamp *dp = dev; 37593bcdfe2SPoul-Henning Kamp dev->si_inode = ino; 3769d960907SPoul-Henning Kamp if (i > devfs_topino) 3779d960907SPoul-Henning Kamp devfs_topino = i; 37893bcdfe2SPoul-Henning Kamp 3799d960907SPoul-Henning Kamp devfs_numino++; 3809d960907SPoul-Henning Kamp devfs_generation++; 3819d960907SPoul-Henning Kamp 3829d960907SPoul-Henning Kamp if (devfs_overflow != NULL || devfs_numino + 100 < NDEVFSINO) 3839d960907SPoul-Henning Kamp return; 3849d960907SPoul-Henning Kamp 3859d960907SPoul-Henning Kamp /* 3869d960907SPoul-Henning Kamp * Try to allocate overflow table 3879d960907SPoul-Henning Kamp * XXX: we can probably be less panicy these days and a linked 3889d960907SPoul-Henning Kamp * XXX: list of PAGESIZE/PTRSIZE entries might be a better idea. 3899d960907SPoul-Henning Kamp * 3909d960907SPoul-Henning Kamp * XXX: we may be into witness unlove here. 3919d960907SPoul-Henning Kamp */ 3929d960907SPoul-Henning Kamp n = devfs_noverflowwant; 3939d960907SPoul-Henning Kamp ot = malloc(sizeof(*ot) * n, M_DEVFS, M_NOWAIT | M_ZERO); 3949d960907SPoul-Henning Kamp if (ot == NULL) 3959d960907SPoul-Henning Kamp return; 3969d960907SPoul-Henning Kamp or = malloc(sizeof(*or) * n, M_DEVFS, M_NOWAIT | M_ZERO); 3979d960907SPoul-Henning Kamp if (or == NULL) { 3989d960907SPoul-Henning Kamp free(ot, M_DEVFS); 3999d960907SPoul-Henning Kamp return; 4009d960907SPoul-Henning Kamp } 4019d960907SPoul-Henning Kamp devfs_overflow = ot; 4029d960907SPoul-Henning Kamp devfs_refoverflow = or; 4039d960907SPoul-Henning Kamp devfs_noverflow = n; 4049d960907SPoul-Henning Kamp printf("DEVFS Overflow table with %d entries allocated\n", n); 4059d960907SPoul-Henning Kamp return; 4063f54a085SPoul-Henning Kamp } 4073f54a085SPoul-Henning Kamp 4089285a87eSPoul-Henning Kamp void 40989c9c53dSPoul-Henning Kamp devfs_destroy(struct cdev *dev) 4103f54a085SPoul-Henning Kamp { 4119d960907SPoul-Henning Kamp int ino; 4129d960907SPoul-Henning Kamp struct cdev **dp; 41393bcdfe2SPoul-Henning Kamp 41493bcdfe2SPoul-Henning Kamp ino = dev->si_inode; 41593bcdfe2SPoul-Henning Kamp dev->si_inode = 0; 41693bcdfe2SPoul-Henning Kamp if (ino == 0) 41793bcdfe2SPoul-Henning Kamp return; 4189d960907SPoul-Henning Kamp dp = devfs_itod(ino); 4199d960907SPoul-Henning Kamp KASSERT(*dp == dev, 4209d960907SPoul-Henning Kamp ("DEVFS: destroying wrong cdev ino %d", ino)); 4219d960907SPoul-Henning Kamp *dp = NULL; 4229d960907SPoul-Henning Kamp devfs_numino--; 4239d960907SPoul-Henning Kamp devfs_generation++; 4249d960907SPoul-Henning Kamp if (ino < devfs_nextino) 4259d960907SPoul-Henning Kamp devfs_nextino = ino; 4263f54a085SPoul-Henning Kamp } 427