xref: /xnu-11215/bsd/miscfs/devfs/devfs_tree.c (revision d0c1fef6)
1 /*
2  * Copyright (c) 2000-2007 Apple Inc. All rights reserved.
3  *
4  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5  *
6  * This file contains Original Code and/or Modifications of Original Code
7  * as defined in and that are subject to the Apple Public Source License
8  * Version 2.0 (the 'License'). You may not use this file except in
9  * compliance with the License. The rights granted to you under the License
10  * may not be used to create, or enable the creation or redistribution of,
11  * unlawful or unlicensed copies of an Apple operating system, or to
12  * circumvent, violate, or enable the circumvention or violation of, any
13  * terms of an Apple operating system software license agreement.
14  *
15  * Please obtain a copy of the License at
16  * http://www.opensource.apple.com/apsl/ and read it before using this file.
17  *
18  * The Original Code and all software distributed under the License are
19  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23  * Please see the License for the specific language governing rights and
24  * limitations under the License.
25  *
26  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27  */
28 
29 /*
30  * Copyright 1997,1998 Julian Elischer.  All rights reserved.
31  * [email protected]
32  *
33  * Redistribution and use in source and binary forms, with or without
34  * modification, are permitted provided that the following conditions are
35  * met:
36  *  1. Redistributions of source code must retain the above copyright
37  *     notice, this list of conditions and the following disclaimer.
38  *  2. Redistributions in binary form must reproduce the above copyright notice,
39  *     this list of conditions and the following disclaimer in the documentation
40  *     and/or other materials provided with the distribution.
41  *
42  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER ``AS IS'' AND ANY EXPRESS
43  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
44  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
45  * DISCLAIMED.  IN NO EVENT SHALL THE HOLDER OR CONTRIBUTORS BE LIABLE FOR
46  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
47  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
48  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
49  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
50  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
51  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
52  * SUCH DAMAGE.
53  *
54  * devfs_tree.c
55  */
56 /*
57  * NOTICE: This file was modified by SPARTA, Inc. in 2005 to introduce
58  * support for mandatory and extensible security protections.  This notice
59  * is included in support of clause 2.2 (b) of the Apple Public License,
60  * Version 2.0.
61  */
62 
63 /*
64  * HISTORY
65  *  Dieter Siegmund ([email protected]) Thu Apr  8 14:08:19 PDT 1999
66  *  - removed mounting of "hidden" mountpoint
67  *  - fixed problem in which devnode->dn_vn pointer was not
68  *    updated with the vnode returned from checkalias()
69  *  - replaced devfs_vntodn() with a macro VTODN()
70  *  - rewrote dev_finddir() to not use recursion
71  *  - added locking to avoid data structure corruption (DEVFS_(UN)LOCK())
72  *  Dieter Siegmund ([email protected]) Wed Jul 14 13:37:59 PDT 1999
73  *  - fixed problem with devfs_dntovn() checking the v_id against the
74  *    value cached in the device node; a union mount on top of us causes
75  *    the v_id to get incremented thus, we would end up returning a new
76  *    vnode instead of the existing one that has the mounted_here
77  *    field filled in; the net effect was that the filesystem mounted
78  *    on top of us would never show up
79  *  - added devfs_stats to store how many data structures are actually
80  *    allocated
81  */
82 
83 /* SPLIT_DEVS means each devfs uses a different devnode for the same device */
84 /* Otherwise the same device always ends up at the same vnode even if  */
85 /* reached througgh a different devfs instance. The practical difference */
86 /* is that with the same vnode, chmods and chowns show up on all instances of */
87 /* a device. (etc) */
88 
89 #define SPLIT_DEVS 1 /* maybe make this an option */
90 /*#define SPLIT_DEVS 1*/
91 
92 #include <sys/param.h>
93 #include <sys/systm.h>
94 #include <sys/kernel.h>
95 #include <sys/conf.h>
96 #include <sys/malloc.h>
97 #include <sys/mount_internal.h>
98 #include <sys/proc.h>
99 #include <sys/vnode_internal.h>
100 #include <stdarg.h>
101 #include <libkern/OSAtomic.h>
102 #define BSD_KERNEL_PRIVATE	1	/* devfs_make_link() prototype */
103 #include "devfs.h"
104 #include "devfsdefs.h"
105 
106 #if CONFIG_MACF
107 #include <security/mac_framework.h>
108 #endif
109 
110 #if FDESC
111 #include "fdesc.h"
112 #endif
113 
114 typedef struct devfs_vnode_event {
115 	vnode_t 		dve_vp;
116 	uint32_t 		dve_vid;
117 	uint32_t		dve_events;
118 } *devfs_vnode_event_t;
119 
120 /*
121  * Size of stack buffer (fast path) for notifications.  If
122  * the number of mounts is small, no need to malloc a buffer.
123  */
124 #define NUM_STACK_ENTRIES 5
125 
126 typedef struct devfs_event_log {
127 	size_t 			del_max;
128 	size_t 			del_used;
129 	devfs_vnode_event_t 	del_entries;
130 } *devfs_event_log_t;
131 
132 
133 static void	dev_free_hier(devdirent_t *);
134 static int	devfs_propogate(devdirent_t *, devdirent_t *, devfs_event_log_t);
135 static int	dev_finddir(const char *, devnode_t *, int, devnode_t **, devfs_event_log_t);
136 static int	dev_dup_entry(devnode_t *, devdirent_t *, devdirent_t **, struct devfsmount *);
137 void		devfs_ref_node(devnode_t *);
138 void 		devfs_rele_node(devnode_t *);
139 static void	devfs_record_event(devfs_event_log_t, devnode_t*, uint32_t);
140 static int 	devfs_init_event_log(devfs_event_log_t, uint32_t, devfs_vnode_event_t);
141 static void	devfs_release_event_log(devfs_event_log_t, int);
142 static void	devfs_bulk_notify(devfs_event_log_t);
143 static devdirent_t *devfs_make_node_internal(dev_t, devfstype_t type, uid_t, gid_t, int,
144 			int (*clone)(dev_t dev, int action), const char *fmt, va_list ap);
145 
146 
147 lck_grp_t	* devfs_lck_grp;
148 lck_grp_attr_t	* devfs_lck_grp_attr;
149 lck_attr_t	* devfs_lck_attr;
150 lck_mtx_t  	  devfs_mutex;
151 lck_mtx_t  	  devfs_attr_mutex;
152 
153 devdirent_t *		dev_root = NULL; 	/* root of backing tree */
154 struct devfs_stats	devfs_stats;		/* hold stats */
155 
156 static ino_t		devfs_unique_fileno = 0;
157 
158 #ifdef HIDDEN_MOUNTPOINT
159 static struct mount *devfs_hidden_mount;
160 #endif /* HIDDEN_MOINTPOINT */
161 
162 static int devfs_ready = 0;
163 static uint32_t devfs_nmountplanes = 0; /* The first plane is not used for a mount */
164 
165 #define DEVFS_NOCREATE	FALSE
166 #define DEVFS_CREATE	TRUE
167 
168 /*
169  * Set up the root directory node in the backing plane
170  * This is happenning before the vfs system has been
171  * set up yet, so be careful about what we reference..
172  * Notice that the ops are by indirection.. as they haven't
173  * been set up yet!
174  * DEVFS has a hidden mountpoint that is used as the anchor point
175  * for the internal 'blueprint' version of the dev filesystem tree.
176  */
177 /*proto*/
178 int
179 devfs_sinit(void)
180 {
181     int error;
182 
183     devfs_lck_grp_attr = lck_grp_attr_alloc_init();
184 	devfs_lck_grp = lck_grp_alloc_init("devfs_lock", devfs_lck_grp_attr);
185 
186 	devfs_lck_attr = lck_attr_alloc_init();
187 
188 	lck_mtx_init(&devfs_mutex, devfs_lck_grp, devfs_lck_attr);
189 	lck_mtx_init(&devfs_attr_mutex, devfs_lck_grp, devfs_lck_attr);
190 
191 	DEVFS_LOCK();
192         error = dev_add_entry("root", NULL, DEV_DIR, NULL, NULL, NULL, &dev_root);
193 	DEVFS_UNLOCK();
194 
195 	if (error) {
196 	    printf("devfs_sinit: dev_add_entry failed ");
197 	    return (ENOTSUP);
198 	}
199 #ifdef HIDDEN_MOUNTPOINT
200 	MALLOC(devfs_hidden_mount, struct mount *, sizeof(struct mount),
201 	       M_MOUNT, M_WAITOK);
202 	bzero(devfs_hidden_mount,sizeof(struct mount));
203 	mount_lock_init(devfs_hidden_mount);
204 	TAILQ_INIT(&devfs_hidden_mount->mnt_vnodelist);
205 	TAILQ_INIT(&devfs_hidden_mount->mnt_workerqueue);
206 	TAILQ_INIT(&devfs_hidden_mount->mnt_newvnodes);
207 #if CONFIG_MACF
208 	mac_mount_label_init(devfs_hidden_mount);
209 	mac_mount_label_associate(vfs_context_kernel(), devfs_hidden_mount);
210 #endif
211 
212 	/* Initialize the default IO constraints */
213 	mp->mnt_maxreadcnt = mp->mnt_maxwritecnt = MAXPHYS;
214 	mp->mnt_segreadcnt = mp->mnt_segwritecnt = 32;
215 	mp->mnt_ioflags = 0;
216 	mp->mnt_realrootvp = NULLVP;
217 	mp->mnt_authcache_ttl = CACHED_LOOKUP_RIGHT_TTL;
218 
219 	devfs_mount(devfs_hidden_mount,"dummy",NULL,NULL,NULL);
220 	dev_root->de_dnp->dn_dvm
221 	    = (struct devfsmount *)devfs_hidden_mount->mnt_data;
222 #endif /* HIDDEN_MOUNTPOINT */
223 #if CONFIG_MACF
224 	mac_devfs_label_associate_directory("/", strlen("/"),
225 	    dev_root->de_dnp, "/");
226 #endif
227 	devfs_ready = 1;
228 	return (0);
229 }
230 
231 /***********************************************************************\
232 *************************************************************************
233 *	Routines used to find our way to a point in the tree		*
234 *************************************************************************
235 \***********************************************************************/
236 
237 
238 
239 /***************************************************************
240  * Search down the linked list off a dir to find "name"
241  * return the devnode_t * for that node.
242  *
243  * called with DEVFS_LOCK held
244  ***************************************************************/
245 devdirent_t *
246 dev_findname(devnode_t * dir, const char *name)
247 {
248 	devdirent_t * newfp;
249 	if (dir->dn_type != DEV_DIR) return 0;/*XXX*/ /* printf?*/
250 
251 	if (name[0] == '.')
252 	{
253 		if(name[1] == 0)
254 		{
255 			return dir->dn_typeinfo.Dir.myname;
256 		}
257 		if((name[1] == '.') && (name[2] == 0))
258 		{
259 			/* for root, .. == . */
260 			return dir->dn_typeinfo.Dir.parent->dn_typeinfo.Dir.myname;
261 		}
262 	}
263 	newfp = dir->dn_typeinfo.Dir.dirlist;
264 
265 	while(newfp)
266 	{
267 		if(!(strncmp(name, newfp->de_name, sizeof(newfp->de_name))))
268 			return newfp;
269 		newfp = newfp->de_next;
270 	}
271 	return NULL;
272 }
273 
274 /***********************************************************************
275  * Given a starting node (0 for root) and a pathname, return the node
276  * for the end item on the path. It MUST BE A DIRECTORY. If the 'DEVFS_CREATE'
277  * option is true, then create any missing nodes in the path and create
278  * and return the final node as well.
279  * This is used to set up a directory, before making nodes in it..
280  *
281  * called with DEVFS_LOCK held
282  ***********************************************************************/
283 static int
284 dev_finddir(const char * path,
285 	    devnode_t * dirnode,
286 	    int create,
287 	    devnode_t * * dn_pp,
288 	    devfs_event_log_t delp)
289 {
290 	devnode_t *	dnp = NULL;
291 	int		error = 0;
292 	const char *		scan;
293 #if CONFIG_MACF
294 	char            fullpath[DEVMAXPATHSIZE];
295 #endif
296 
297 
298 	if (!dirnode) /* dirnode == NULL means start at root */
299 	    dirnode = dev_root->de_dnp;
300 
301 	if (dirnode->dn_type != DEV_DIR)
302 	    return ENOTDIR;
303 
304 	if (strlen(path) > (DEVMAXPATHSIZE - 1))
305 	    return ENAMETOOLONG;
306 
307 #if CONFIG_MACF
308 	strlcpy (fullpath, path, DEVMAXPATHSIZE);
309 #endif
310 	scan = path;
311 
312 	while (*scan == '/')
313 	    scan++;
314 
315 	*dn_pp = NULL;
316 
317 	while (1) {
318 	    char		component[DEVMAXPATHSIZE];
319 	    devdirent_t *	dirent_p;
320 	    const char * 	start;
321 
322 	    if (*scan == 0) {
323 		/* we hit the end of the string, we're done */
324 		*dn_pp = dirnode;
325 		break;
326 	    }
327 	    start = scan;
328 	    while (*scan != '/' && *scan)
329 		scan++;
330 
331 	    strlcpy(component, start, scan - start);
332 	    if (*scan == '/')
333 		scan++;
334 
335 	    dirent_p = dev_findname(dirnode, component);
336 	    if (dirent_p) {
337 		dnp = dirent_p->de_dnp;
338 		if (dnp->dn_type != DEV_DIR) {
339 		    error = ENOTDIR;
340 		    break;
341 		}
342 	    }
343 	    else {
344 		if (!create) {
345 		    error = ENOENT;
346 		    break;
347 		}
348 		error = dev_add_entry(component, dirnode,
349 				       DEV_DIR, NULL, NULL, NULL, &dirent_p);
350 		if (error)
351 		    break;
352 		dnp = dirent_p->de_dnp;
353 #if CONFIG_MACF
354 		mac_devfs_label_associate_directory(
355 		    dirnode->dn_typeinfo.Dir.myname->de_name,
356 		    strlen(dirnode->dn_typeinfo.Dir.myname->de_name),
357 		    dnp, fullpath);
358 #endif
359 		devfs_propogate(dirnode->dn_typeinfo.Dir.myname, dirent_p, delp);
360 	    }
361 	    dirnode = dnp; /* continue relative to this directory */
362 	}
363 	return (error);
364 }
365 
366 
367 /***********************************************************************
368  * Add a new NAME element to the devfs
369  * If we're creating a root node, then dirname is NULL
370  * Basically this creates a new namespace entry for the device node
371  *
372  * Creates a name node, and links it to the supplied node
373  *
374  * called with DEVFS_LOCK held
375  ***********************************************************************/
376 int
377 dev_add_name(const char * name, devnode_t * dirnode, __unused devdirent_t * back,
378     devnode_t * dnp, devdirent_t * *dirent_pp)
379 {
380 	devdirent_t * 	dirent_p = NULL;
381 
382 	if(dirnode != NULL ) {
383 		if(dirnode->dn_type != DEV_DIR) return(ENOTDIR);
384 
385 		if( dev_findname(dirnode,name))
386 			return(EEXIST);
387 	}
388 	/*
389 	 * make sure the name is legal
390 	 * slightly misleading in the case of NULL
391 	 */
392 	if (!name || (strlen(name) > (DEVMAXNAMESIZE - 1)))
393 	    return (ENAMETOOLONG);
394 
395 	/*
396 	 * Allocate and fill out a new directory entry
397 	 */
398 	MALLOC(dirent_p, devdirent_t *, sizeof(devdirent_t),
399 	       M_DEVFSNAME, M_WAITOK);
400 	if (!dirent_p) {
401 	    return ENOMEM;
402 	}
403 	bzero(dirent_p,sizeof(devdirent_t));
404 
405 	/* inherrit our parent's mount info */ /*XXX*/
406 	/* a kludge but.... */
407 	if(dirnode && ( dnp->dn_dvm == NULL)) {
408 		dnp->dn_dvm = dirnode->dn_dvm;
409 		/* if(!dnp->dn_dvm) printf("parent had null dvm "); */
410 	}
411 
412 	/*
413 	 * Link the two together
414 	 * include the implicit link in the count of links to the devnode..
415 	 * this stops it from being accidentally freed later.
416 	 */
417 	dirent_p->de_dnp = dnp;
418 	dnp->dn_links++ ; /* implicit from our own name-node */
419 
420 	/*
421 	 * Make sure that we can find all the links that reference a node
422 	 * so that we can get them all if we need to zap the node.
423 	 */
424 	if(dnp->dn_linklist) {
425 		dirent_p->de_nextlink = dnp->dn_linklist;
426 		dirent_p->de_prevlinkp = dirent_p->de_nextlink->de_prevlinkp;
427 		dirent_p->de_nextlink->de_prevlinkp = &(dirent_p->de_nextlink);
428 		*dirent_p->de_prevlinkp = dirent_p;
429 	} else {
430 		dirent_p->de_nextlink = dirent_p;
431 		dirent_p->de_prevlinkp = &(dirent_p->de_nextlink);
432 	}
433 	dnp->dn_linklist = dirent_p;
434 
435 	/*
436 	 * If the node is a directory, then we need to handle the
437 	 * creation of the .. link.
438 	 * A NULL dirnode indicates a root node, so point to ourself.
439 	 */
440 	if(dnp->dn_type == DEV_DIR) {
441 		dnp->dn_typeinfo.Dir.myname = dirent_p;
442 		/*
443 		 * If we are unlinking from an old dir, decrement its links
444 		 * as we point our '..' elsewhere
445 		 * Note: it's up to the calling code to remove the
446 		 * us from the original directory's list
447 		 */
448 		if(dnp->dn_typeinfo.Dir.parent) {
449 			dnp->dn_typeinfo.Dir.parent->dn_links--;
450 		}
451 	 	if(dirnode) {
452 			dnp->dn_typeinfo.Dir.parent = dirnode;
453 		} else {
454 			dnp->dn_typeinfo.Dir.parent = dnp;
455 		}
456 		dnp->dn_typeinfo.Dir.parent->dn_links++; /* account for the new '..' */
457 	}
458 
459 	/*
460 	 * put the name into the directory entry.
461 	 */
462 	strlcpy(dirent_p->de_name, name, DEVMAXNAMESIZE);
463 
464 
465 	/*
466 	 * Check if we are not making a root node..
467 	 * (i.e. have parent)
468 	 */
469 	if(dirnode) {
470 		/*
471 	 	 * Put it on the END of the linked list of directory entries
472 	 	 */
473 		dirent_p->de_parent = dirnode; /* null for root */
474 		dirent_p->de_prevp = dirnode->dn_typeinfo.Dir.dirlast;
475 		dirent_p->de_next = *(dirent_p->de_prevp); /* should be NULL */
476 							/*right?*/
477 		*(dirent_p->de_prevp) = dirent_p;
478 		dirnode->dn_typeinfo.Dir.dirlast = &(dirent_p->de_next);
479 		dirnode->dn_typeinfo.Dir.entrycount++;
480 		dirnode->dn_len += strlen(name) + 8;/*ok, ok?*/
481 	}
482 
483 	*dirent_pp = dirent_p;
484 	DEVFS_INCR_ENTRIES();
485 	return 0 ;
486 }
487 
488 
489 /***********************************************************************
490  * Add a new element to the devfs plane.
491  *
492  * Creates a new dev_node to go with it if the prototype should not be
493  * reused. (Is a DIR, or we select SPLIT_DEVS at compile time)
494  * typeinfo gives us info to make our node if we don't have a prototype.
495  * If typeinfo is null and proto exists, then the typeinfo field of
496  * the proto is used intead in the DEVFS_CREATE case.
497  * note the 'links' count is 0 (except if a dir)
498  * but it is only cleared on a transition
499  * so this is ok till we link it to something
500  * Even in SPLIT_DEVS mode,
501  * if the node already exists on the wanted plane, just return it
502  *
503  * called with DEVFS_LOCK held
504 ***********************************************************************/
505 int
506 dev_add_node(int entrytype, devnode_type_t * typeinfo, devnode_t * proto,
507 	     devnode_t * *dn_pp, struct devfsmount *dvm)
508 {
509 	devnode_t *	dnp = NULL;
510 
511 #if defined SPLIT_DEVS
512 	/*
513 	 * If we have a prototype, then check if there is already a sibling
514 	 * on the mount plane we are looking at, if so, just return it.
515 	 */
516 	if (proto) {
517 		dnp = proto->dn_nextsibling;
518 		while( dnp != proto) {
519 			if (dnp->dn_dvm == dvm) {
520 				*dn_pp = dnp;
521 				return (0);
522 			}
523 			dnp = dnp->dn_nextsibling;
524 		}
525 		if (typeinfo == NULL)
526 			typeinfo = &(proto->dn_typeinfo);
527 	}
528 #else	/* SPLIT_DEVS */
529 	if ( proto ) {
530 		switch (proto->type) {
531 			case DEV_BDEV:
532 			case DEV_CDEV:
533 				*dn_pp = proto;
534 				return 0;
535 		}
536 	}
537 #endif	/* SPLIT_DEVS */
538 	MALLOC(dnp, devnode_t *, sizeof(devnode_t), M_DEVFSNODE, M_WAITOK);
539 	if (!dnp) {
540 	    return ENOMEM;
541 	}
542 
543 	/*
544 	 * If we have a proto, that means that we are duplicating some
545 	 * other device, which can only happen if we are not at the back plane
546 	 */
547 	if (proto) {
548 		bcopy(proto, dnp, sizeof(devnode_t));
549 		dnp->dn_links = 0;
550 		dnp->dn_linklist = NULL;
551 		dnp->dn_vn = NULL;
552 		dnp->dn_len = 0;
553 		/* add to END of siblings list */
554 		dnp->dn_prevsiblingp = proto->dn_prevsiblingp;
555 		*(dnp->dn_prevsiblingp) = dnp;
556 		dnp->dn_nextsibling = proto;
557 		proto->dn_prevsiblingp = &(dnp->dn_nextsibling);
558 #if CONFIG_MACF
559 		mac_devfs_label_init(dnp);
560 		mac_devfs_label_copy(proto->dn_label, dnp->dn_label);
561 #endif
562 	} else {
563 	        struct timeval tv;
564 
565 		/*
566 		 * We have no prototype, so start off with a clean slate
567 		 */
568 		microtime(&tv);
569 		bzero(dnp, sizeof(devnode_t));
570 		dnp->dn_type = entrytype;
571 		dnp->dn_nextsibling = dnp;
572 		dnp->dn_prevsiblingp = &(dnp->dn_nextsibling);
573 		dnp->dn_atime.tv_sec = tv.tv_sec;
574 		dnp->dn_mtime.tv_sec = tv.tv_sec;
575 		dnp->dn_ctime.tv_sec = tv.tv_sec;
576 #if CONFIG_MACF
577 		mac_devfs_label_init(dnp);
578 #endif
579 	}
580 	dnp->dn_dvm = dvm;
581 	dnp->dn_refcount = 0;
582 	dnp->dn_ino = devfs_unique_fileno;
583 	devfs_unique_fileno++;
584 
585 	/*
586 	 * fill out the dev node according to type
587 	 */
588 	switch(entrytype) {
589 	case DEV_DIR:
590 		/*
591 		 * As it's a directory, make sure
592 		 * it has a null entries list
593 		 */
594 		dnp->dn_typeinfo.Dir.dirlast = &(dnp->dn_typeinfo.Dir.dirlist);
595 		dnp->dn_typeinfo.Dir.dirlist = (devdirent_t *)0;
596 		dnp->dn_typeinfo.Dir.entrycount = 0;
597 		/*  until we know better, it has a null parent pointer*/
598 		dnp->dn_typeinfo.Dir.parent = NULL;
599 		dnp->dn_links++; /* for .*/
600 		dnp->dn_typeinfo.Dir.myname = NULL;
601 		/*
602 		 * make sure that the ops associated with it are the ops
603 		 * that we use (by default) for directories
604 		 */
605 		dnp->dn_ops = &devfs_vnodeop_p;
606 		dnp->dn_mode |= 0555;	/* default perms */
607 		break;
608 	case DEV_SLNK:
609 		/*
610 		 * As it's a symlink allocate and store the link info
611 		 * Symlinks should only ever be created by the user,
612 		 * so they are not on the back plane and should not be
613 		 * propogated forward.. a bit like directories in that way..
614 		 * A symlink only exists on one plane and has its own
615 		 * node.. therefore we might be on any random plane.
616 		 */
617 	    	MALLOC(dnp->dn_typeinfo.Slnk.name, char *,
618 		       typeinfo->Slnk.namelen+1,
619 		       M_DEVFSNODE, M_WAITOK);
620 		if (!dnp->dn_typeinfo.Slnk.name) {
621 		    	FREE(dnp,M_DEVFSNODE);
622 			return ENOMEM;
623 		}
624 		strlcpy(dnp->dn_typeinfo.Slnk.name, typeinfo->Slnk.name,
625 			typeinfo->Slnk.namelen + 1);
626 		dnp->dn_typeinfo.Slnk.namelen = typeinfo->Slnk.namelen;
627 		DEVFS_INCR_STRINGSPACE(dnp->dn_typeinfo.Slnk.namelen + 1);
628 		dnp->dn_ops = &devfs_vnodeop_p;
629 		dnp->dn_mode |= 0555;	/* default perms */
630 		break;
631 	case DEV_CDEV:
632 	case DEV_BDEV:
633 		/*
634 		 * Make sure it has DEVICE type ops
635 		 * and device specific fields are correct
636 		 */
637 		dnp->dn_ops = &devfs_spec_vnodeop_p;
638 		dnp->dn_typeinfo.dev = typeinfo->dev;
639 		break;
640 
641 	#if FDESC
642 	/* /dev/fd is special */
643 	case DEV_DEVFD:
644 		dnp->dn_ops = &devfs_devfd_vnodeop_p;
645 		dnp->dn_mode |= 0555;	/* default perms */
646 		break;
647 
648 	#endif /* FDESC */
649 	default:
650 		return EINVAL;
651 	}
652 
653 	*dn_pp = dnp;
654 	DEVFS_INCR_NODES();
655 	return 0 ;
656 }
657 
658 
659 /***********************************************************************
660  * called with DEVFS_LOCK held
661  **********************************************************************/
662 void
663 devnode_free(devnode_t * dnp)
664 {
665 #if CONFIG_MACF
666 	mac_devfs_label_destroy(dnp);
667 #endif
668     if (dnp->dn_type == DEV_SLNK) {
669         DEVFS_DECR_STRINGSPACE(dnp->dn_typeinfo.Slnk.namelen + 1);
670 	FREE(dnp->dn_typeinfo.Slnk.name, M_DEVFSNODE);
671     }
672     DEVFS_DECR_NODES();
673     FREE(dnp, M_DEVFSNODE);
674 }
675 
676 
677 /***********************************************************************
678  * called with DEVFS_LOCK held
679  **********************************************************************/
680 static void
681 devfs_dn_free(devnode_t * dnp)
682 {
683 	if(--dnp->dn_links <= 0 ) /* can be -1 for initial free, on error */
684 	{
685 		/*probably need to do other cleanups XXX */
686 		if (dnp->dn_nextsibling != dnp) {
687 			devnode_t * * 	prevp = dnp->dn_prevsiblingp;
688 			*prevp = dnp->dn_nextsibling;
689 			dnp->dn_nextsibling->dn_prevsiblingp = prevp;
690 
691 		}
692 
693 		/* Can only free if there are no references; otherwise, wait for last vnode to be reclaimed */
694 		if (dnp->dn_refcount == 0) {
695 		    devnode_free(dnp);
696 		}
697 		else {
698 		    dnp->dn_lflags |= DN_DELETE;
699 		}
700 	}
701 }
702 
703 /***********************************************************************\
704 *	Front Node Operations						*
705 *	Add or delete a chain of front nodes				*
706 \***********************************************************************/
707 
708 
709 /***********************************************************************
710  * Given a directory backing node, and a child backing node, add the
711  * appropriate front nodes to the front nodes of the directory to
712  * represent the child node to the user
713  *
714  * on failure, front nodes will either be correct or not exist for each
715  * front dir, however dirs completed will not be stripped of completed
716  * frontnodes on failure of a later frontnode
717  *
718  * This allows a new node to be propogated through all mounted planes
719  *
720  * called with DEVFS_LOCK held
721  ***********************************************************************/
722 static int
723 devfs_propogate(devdirent_t * parent,devdirent_t * child, devfs_event_log_t delp)
724 {
725 	int	error;
726 	devdirent_t * newnmp;
727 	devnode_t *	dnp = child->de_dnp;
728 	devnode_t *	pdnp = parent->de_dnp;
729 	devnode_t *	adnp = parent->de_dnp;
730 	int type = child->de_dnp->dn_type;
731 	uint32_t events;
732 
733 	events = (dnp->dn_type == DEV_DIR ? VNODE_EVENT_DIR_CREATED : VNODE_EVENT_FILE_CREATED);
734 	if (delp != NULL) {
735 		devfs_record_event(delp, pdnp, events);
736 	}
737 
738 	/***********************************************
739 	 * Find the other instances of the parent node
740 	 ***********************************************/
741 	for (adnp = pdnp->dn_nextsibling;
742 		adnp != pdnp;
743 		adnp = adnp->dn_nextsibling)
744 	{
745 		/*
746 		 * Make the node, using the original as a prototype)
747 		 * if the node already exists on that plane it won't be
748 		 * re-made..
749 		 */
750 		if ((error = dev_add_entry(child->de_name, adnp, type,
751 					   NULL, dnp, adnp->dn_dvm,
752 					   &newnmp)) != 0) {
753 			printf("duplicating %s failed\n",child->de_name);
754 		} else {
755 			if (delp != NULL) {
756 				devfs_record_event(delp, adnp, events);
757 
758 				/*
759 				 * Slightly subtle.  We're guaranteed that there will
760 				 * only be a vnode hooked into this devnode if we're creating
761 				 * a new link to an existing node; otherwise, the devnode is new
762 				 * and no one can have looked it up yet. If we're making a link,
763 				 * then the buffer is large enough for two nodes in each
764 				 * plane; otherwise, there's no vnode and this call will
765 				 * do nothing.
766 				 */
767 				devfs_record_event(delp, newnmp->de_dnp, VNODE_EVENT_LINK);
768 			}
769 		}
770 	}
771 	return 0;	/* for now always succeed */
772 }
773 
774 static uint32_t
775 remove_notify_count(devnode_t *dnp)
776 {
777 	uint32_t notify_count = 0;
778 	devnode_t *dnp2;
779 
780 	/*
781 	 * Could need to notify for one removed node on each mount and
782 	 * one parent for each such node.
783 	 */
784 	notify_count = devfs_nmountplanes;
785 	notify_count += dnp->dn_links;
786 	for (dnp2 = dnp->dn_nextsibling; dnp2 != dnp; dnp2 = dnp2->dn_nextsibling) {
787 		notify_count += dnp2->dn_links;
788 	}
789 
790 	return notify_count;
791 
792 }
793 
794 /***********************************************************************
795  * remove all instances of this devicename [for backing nodes..]
796  * note.. if there is another link to the node (non dir nodes only)
797  * then the devfs_node will still exist as the ref count will be non-0
798  * removing a directory node will remove all sup-nodes on all planes (ZAP)
799  *
800  * Used by device drivers to remove nodes that are no longer relevant
801  * The argument is the 'cookie' they were given when they created the node
802  * this function is exported.. see devfs.h
803  ***********************************************************************/
804 void
805 devfs_remove(void *dirent_p)
806 {
807 	devnode_t * dnp = ((devdirent_t *)dirent_p)->de_dnp;
808 	devnode_t * dnp2;
809 	boolean_t   lastlink;
810 	struct devfs_event_log event_log;
811 	uint32_t    log_count = 0;
812 	int	    do_notify = 0;
813 	int	    need_free = 0;
814 	struct devfs_vnode_event stackbuf[NUM_STACK_ENTRIES];
815 
816 	DEVFS_LOCK();
817 
818 	if (!devfs_ready) {
819 		printf("devfs_remove: not ready for devices!\n");
820 		goto out;
821 	}
822 
823 	log_count = remove_notify_count(dnp);
824 
825 	if (log_count > NUM_STACK_ENTRIES) {
826 		uint32_t new_count;
827 wrongsize:
828 		DEVFS_UNLOCK();
829 		if (devfs_init_event_log(&event_log, log_count, NULL) == 0) {
830 			do_notify = 1;
831 			need_free = 1;
832 		}
833 		DEVFS_LOCK();
834 
835 		new_count = remove_notify_count(dnp);
836 		if (need_free && (new_count > log_count)) {
837 			devfs_release_event_log(&event_log, 1);
838 			need_free = 0;
839 			do_notify = 0;
840 			log_count = log_count * 2;
841 			goto wrongsize;
842 		}
843 	} else {
844 		if (devfs_init_event_log(&event_log, NUM_STACK_ENTRIES, &stackbuf[0]) == 0) {
845 			do_notify = 1;
846 		}
847 	}
848 
849 	/* This file has been deleted */
850 	if (do_notify != 0) {
851 		devfs_record_event(&event_log, dnp, VNODE_EVENT_DELETE);
852 	}
853 
854 	/* keep removing the next sibling till only we exist. */
855 	while ((dnp2 = dnp->dn_nextsibling) != dnp) {
856 
857 		/*
858 		 * Keep removing the next front node till no more exist
859 		 */
860 		dnp->dn_nextsibling = dnp2->dn_nextsibling;
861 		dnp->dn_nextsibling->dn_prevsiblingp = &(dnp->dn_nextsibling);
862 		dnp2->dn_nextsibling = dnp2;
863 		dnp2->dn_prevsiblingp = &(dnp2->dn_nextsibling);
864 
865 		/* This file has been deleted in this plane */
866 		if (do_notify != 0) {
867 			devfs_record_event(&event_log, dnp2, VNODE_EVENT_DELETE);
868 		}
869 
870 		if (dnp2->dn_linklist) {
871 			do {
872 				lastlink = (1 == dnp2->dn_links);
873 				/* Each parent of a link to this file has lost a child in this plane */
874 				if (do_notify != 0) {
875 					devfs_record_event(&event_log, dnp2->dn_linklist->de_parent, VNODE_EVENT_FILE_REMOVED);
876 				}
877 				dev_free_name(dnp2->dn_linklist);
878 			} while (!lastlink);
879 		}
880 	}
881 
882 	/*
883 	 * then free the main node
884 	 * If we are not running in SPLIT_DEVS mode, then
885 	 * THIS is what gets rid of the propogated nodes.
886 	 */
887 	if (dnp->dn_linklist) {
888 		do {
889 			lastlink = (1 == dnp->dn_links);
890 			/* Each parent of a link to this file has lost a child */
891 			if (do_notify != 0) {
892 				devfs_record_event(&event_log, dnp->dn_linklist->de_parent, VNODE_EVENT_FILE_REMOVED);
893 			}
894 			dev_free_name(dnp->dn_linklist);
895 		} while (!lastlink);
896 	}
897 out:
898 	DEVFS_UNLOCK();
899 	if (do_notify != 0) {
900 		devfs_bulk_notify(&event_log);
901 		devfs_release_event_log(&event_log, need_free);
902 	}
903 
904 	return ;
905 }
906 
907 
908 
909 /***************************************************************
910  * duplicate the backing tree into a tree of nodes hung off the
911  * mount point given as the argument. Do this by
912  * calling dev_dup_entry which recurses all the way
913  * up the tree..
914  *
915  * called with DEVFS_LOCK held
916  **************************************************************/
917 int
918 dev_dup_plane(struct devfsmount *devfs_mp_p)
919 {
920 	devdirent_t *	new;
921 	int		error = 0;
922 
923 	if ((error = dev_dup_entry(NULL, dev_root, &new, devfs_mp_p)))
924 	        return error;
925 	devfs_mp_p->plane_root = new;
926 	devfs_nmountplanes++;
927 	return error;
928 }
929 
930 
931 
932 /***************************************************************
933  * Free a whole plane
934  *
935  * called with DEVFS_LOCK held
936  ***************************************************************/
937 void
938 devfs_free_plane(struct devfsmount *devfs_mp_p)
939 {
940 	devdirent_t * dirent_p;
941 
942 	dirent_p = devfs_mp_p->plane_root;
943 	if (dirent_p) {
944 		dev_free_hier(dirent_p);
945 		dev_free_name(dirent_p);
946 	}
947 	devfs_mp_p->plane_root = NULL;
948 	devfs_nmountplanes--;
949 
950 	if (devfs_nmountplanes > (devfs_nmountplanes+1)) {
951 		panic("plane count wrapped around.\n");
952 	}
953 }
954 
955 
956 /***************************************************************
957  * Create and link in a new front element..
958  * Parent can be 0 for a root node
959  * Not presently usable to make a symlink XXX
960  * (Ok, symlinks don't propogate)
961  * recursively will create subnodes corresponding to equivalent
962  * child nodes in the base level
963  *
964  * called with DEVFS_LOCK held
965  ***************************************************************/
966 static int
967 dev_dup_entry(devnode_t * parent, devdirent_t * back, devdirent_t * *dnm_pp,
968 	      struct devfsmount *dvm)
969 {
970 	devdirent_t *	entry_p;
971 	devdirent_t *	newback;
972 	devdirent_t *	newfront;
973 	int	error;
974 	devnode_t *	dnp = back->de_dnp;
975 	int type = dnp->dn_type;
976 
977 	/*
978 	 * go get the node made (if we need to)
979 	 * use the back one as a prototype
980 	 */
981 	if ((error = dev_add_entry(back->de_name, parent, type,
982 				NULL, dnp,
983 				parent?parent->dn_dvm:dvm, &entry_p)) != 0) {
984 		printf("duplicating %s failed\n",back->de_name);
985 	}
986 
987 	/*
988 	 * If we have just made the root, then insert the pointer to the
989 	 * mount information
990 	 */
991 	if(dvm) {
992 		entry_p->de_dnp->dn_dvm = dvm;
993 	}
994 
995 	/*
996 	 * If it is a directory, then recurse down all the other
997 	 * subnodes in it....
998 	 * note that this time we don't pass on the mount info..
999 	 */
1000 	if (type == DEV_DIR)
1001 	{
1002 		for(newback = back->de_dnp->dn_typeinfo.Dir.dirlist;
1003 				newback; newback = newback->de_next)
1004 		{
1005 			if((error = dev_dup_entry(entry_p->de_dnp,
1006 					    newback, &newfront, NULL)) != 0)
1007 			{
1008 				break; /* back out with an error */
1009 			}
1010 		}
1011 	}
1012 	*dnm_pp = entry_p;
1013 	return error;
1014 }
1015 
1016 
1017 /***************************************************************
1018  * Free a name node
1019  * remember that if there are other names pointing to the
1020  * dev_node then it may not get freed yet
1021  * can handle if there is no dnp
1022  *
1023  * called with DEVFS_LOCK held
1024  ***************************************************************/
1025 
1026 int
1027 dev_free_name(devdirent_t * dirent_p)
1028 {
1029 	devnode_t *	parent = dirent_p->de_parent;
1030 	devnode_t *	dnp = dirent_p->de_dnp;
1031 
1032 	if(dnp) {
1033 		if(dnp->dn_type == DEV_DIR)
1034 		{
1035 		    	devnode_t * p;
1036 
1037 			if(dnp->dn_typeinfo.Dir.dirlist)
1038 				return (ENOTEMPTY);
1039 			p = dnp->dn_typeinfo.Dir.parent;
1040 			devfs_dn_free(dnp); 	/* account for '.' */
1041 			devfs_dn_free(p); 	/* '..' */
1042 		}
1043 		/*
1044 		 * unlink us from the list of links for this node
1045 		 * If we are the only link, it's easy!
1046 		 * if we are a DIR of course there should not be any
1047 		 * other links.
1048 	 	 */
1049 		if(dirent_p->de_nextlink == dirent_p) {
1050 				dnp->dn_linklist = NULL;
1051 		} else {
1052 			if(dnp->dn_linklist == dirent_p) {
1053 				dnp->dn_linklist = dirent_p->de_nextlink;
1054 			}
1055 		}
1056 		devfs_dn_free(dnp);
1057 	}
1058 
1059 	dirent_p->de_nextlink->de_prevlinkp = dirent_p->de_prevlinkp;
1060 	*(dirent_p->de_prevlinkp) = dirent_p->de_nextlink;
1061 
1062 	/*
1063 	 * unlink ourselves from the directory on this plane
1064 	 */
1065 	if(parent) /* if not fs root */
1066 	{
1067 		if( (*dirent_p->de_prevp = dirent_p->de_next) )/* yes, assign */
1068 		{
1069 			dirent_p->de_next->de_prevp = dirent_p->de_prevp;
1070 		}
1071 		else
1072 		{
1073 			parent->dn_typeinfo.Dir.dirlast
1074 				= dirent_p->de_prevp;
1075 		}
1076 		parent->dn_typeinfo.Dir.entrycount--;
1077 		parent->dn_len -= strlen(dirent_p->de_name) + 8;
1078 	}
1079 
1080 	DEVFS_DECR_ENTRIES();
1081 	FREE(dirent_p, M_DEVFSNAME);
1082 	return 0;
1083 }
1084 
1085 
1086 /***************************************************************
1087  * Free a hierarchy starting at a directory node name
1088  * remember that if there are other names pointing to the
1089  * dev_node then it may not get freed yet
1090  * can handle if there is no dnp
1091  * leave the node itself allocated.
1092  *
1093  * called with DEVFS_LOCK held
1094  ***************************************************************/
1095 
1096 static void
1097 dev_free_hier(devdirent_t * dirent_p)
1098 {
1099 	devnode_t *	dnp = dirent_p->de_dnp;
1100 
1101 	if(dnp) {
1102 		if(dnp->dn_type == DEV_DIR)
1103 		{
1104 			while(dnp->dn_typeinfo.Dir.dirlist)
1105 			{
1106 				dev_free_hier(dnp->dn_typeinfo.Dir.dirlist);
1107 				dev_free_name(dnp->dn_typeinfo.Dir.dirlist);
1108 			}
1109 		}
1110 	}
1111 }
1112 
1113 
1114 /***************************************************************
1115  * given a dev_node, find the appropriate vnode if one is already
1116  * associated, or get a new one and associate it with the dev_node
1117  *
1118  * called with DEVFS_LOCK held
1119  *
1120  * If an error is returned, then the dnp may have been freed (we
1121  * raced with a delete and lost).  A devnode should not be accessed
1122  * after devfs_dntovn() fails.
1123  ****************************************************************/
1124 int
1125 devfs_dntovn(devnode_t * dnp, struct vnode **vn_pp, __unused struct proc * p)
1126 {
1127 	struct vnode *vn_p;
1128 	int error = 0;
1129 	struct vnode_fsparam vfsp;
1130 	enum vtype vtype = 0;
1131 	int markroot = 0;
1132 	int n_minor = DEVFS_CLONE_ALLOC; /* new minor number for clone device */
1133 
1134 	/*
1135 	 * We should never come in and find that our devnode has been marked for delete.
1136 	 * The lookup should have held the lock from entry until now; it should not have
1137 	 * been able to find a removed entry. Any other pathway would have just created
1138 	 * the devnode and come here without dropping the devfs lock, so no one would
1139 	 * have a chance to delete.
1140 	 */
1141 	if (dnp->dn_lflags & DN_DELETE) {
1142 		panic("devfs_dntovn: DN_DELETE set on a devnode upon entry.");
1143 	}
1144 
1145 	devfs_ref_node(dnp);
1146 
1147 retry:
1148 	*vn_pp = NULL;
1149 	vn_p = dnp->dn_vn;
1150 
1151 	if (vn_p) { /* already has a vnode */
1152 	        uint32_t vid;
1153 
1154 		vid = vnode_vid(vn_p);
1155 
1156 		DEVFS_UNLOCK();
1157 
1158 	        error = vnode_getwithvid(vn_p, vid);
1159 
1160 	        DEVFS_LOCK();
1161 
1162 		if (dnp->dn_lflags & DN_DELETE) {
1163 		        /*
1164 			 * our BUSY node got marked for
1165 			 * deletion while the DEVFS lock
1166 			 * was dropped...
1167 			 */
1168 		        if (error == 0) {
1169 			        /*
1170 				 * vnode_getwithvid returned a valid ref
1171 				 * which we need to drop
1172 				 */
1173 			        vnode_put(vn_p);
1174 			}
1175 
1176 			/*
1177 			 * This entry is no longer in the namespace.  This is only
1178 			 * possible for lookup: no other path would not find an existing
1179 			 * vnode.  Therefore, ENOENT is a valid result.
1180 			 */
1181 			error = ENOENT;
1182 		}
1183 		if ( !error)
1184 		        *vn_pp = vn_p;
1185 
1186 		goto out;
1187 	}
1188 
1189 	/*
1190 	 * If we get here, then we've beaten any deletes;
1191 	 * if someone sets DN_DELETE during a subsequent drop
1192 	 * of the devfs lock, we'll still vend a vnode.
1193 	 */
1194 
1195 	if (dnp->dn_lflags & DN_CREATE) {
1196 		dnp->dn_lflags |= DN_CREATEWAIT;
1197 		msleep(&dnp->dn_lflags, &devfs_mutex, PRIBIO, 0 , 0);
1198 		goto retry;
1199 	}
1200 
1201 	dnp->dn_lflags |= DN_CREATE;
1202 
1203 	switch (dnp->dn_type) {
1204 		case	DEV_SLNK:
1205 			vtype = VLNK;
1206 			break;
1207 		case	DEV_DIR:
1208 			if (dnp->dn_typeinfo.Dir.parent == dnp) {
1209 				markroot = 1;
1210 			}
1211 			vtype = VDIR;
1212 			break;
1213 		case	DEV_BDEV:
1214 		case	DEV_CDEV:
1215 		    	vtype = (dnp->dn_type == DEV_BDEV) ? VBLK : VCHR;
1216 			break;
1217 #if FDESC
1218 		case 	DEV_DEVFD:
1219 			vtype = VDIR;
1220 			break;
1221 #endif /* FDESC */
1222 	}
1223 	vfsp.vnfs_mp = dnp->dn_dvm->mount;
1224 	vfsp.vnfs_vtype = vtype;
1225 	vfsp.vnfs_str = "devfs";
1226 	vfsp.vnfs_dvp = 0;
1227 	vfsp.vnfs_fsnode = dnp;
1228 	vfsp.vnfs_cnp = 0;
1229 	vfsp.vnfs_vops = *(dnp->dn_ops);
1230 
1231 	if (vtype == VBLK || vtype == VCHR) {
1232 		/*
1233 		 * Ask the clone minor number function for a new minor number
1234 		 * to use for the next device instance.  If an administative
1235 		 * limit has been reached, this function will return -1.
1236 		 */
1237 		if (dnp->dn_clone != NULL) {
1238 			int	n_major = major(dnp->dn_typeinfo.dev);
1239 
1240 			n_minor = (*dnp->dn_clone)(dnp->dn_typeinfo.dev, DEVFS_CLONE_ALLOC);
1241 			if (n_minor == -1) {
1242 				error = ENOMEM;
1243 				goto out;
1244 			}
1245 
1246 			vfsp.vnfs_rdev = makedev(n_major, n_minor);;
1247 		} else {
1248 		vfsp.vnfs_rdev = dnp->dn_typeinfo.dev;
1249 		}
1250 	} else {
1251 		vfsp.vnfs_rdev = 0;
1252 	}
1253 	vfsp.vnfs_filesize = 0;
1254 	vfsp.vnfs_flags = VNFS_NOCACHE | VNFS_CANTCACHE;
1255 	/* Tag system files */
1256 	vfsp.vnfs_marksystem = 0;
1257 	vfsp.vnfs_markroot = markroot;
1258 
1259 	DEVFS_UNLOCK();
1260 
1261 	error = vnode_create(VNCREATE_FLAVOR, VCREATESIZE, &vfsp, &vn_p);
1262 
1263 	/* Do this before grabbing the lock */
1264 	if (error == 0) {
1265 		vnode_setneedinactive(vn_p);
1266 	}
1267 
1268 	DEVFS_LOCK();
1269 
1270 	if (error == 0) {
1271 			vnode_settag(vn_p, VT_DEVFS);
1272 
1273 			if ((dnp->dn_clone != NULL) && (dnp->dn_vn != NULLVP) )
1274 				panic("devfs_dntovn: cloning device with a vnode?\n");
1275 
1276 			*vn_pp = vn_p;
1277 
1278 			/*
1279 			 * Another vnode that has this devnode as its v_data.
1280 			 * This reference, unlike the one taken at the start
1281 			 * of the function, persists until a VNOP_RECLAIM
1282 			 * comes through for this vnode.
1283 			 */
1284 			devfs_ref_node(dnp);
1285 
1286 			/*
1287 			 * A cloned vnode is not hooked into the devnode; every lookup
1288 			 * gets a new vnode.
1289 			 */
1290 			if (dnp->dn_clone == NULL) {
1291 				dnp->dn_vn = vn_p;
1292 			}
1293 	} else if (n_minor != DEVFS_CLONE_ALLOC) {
1294 		/*
1295 		 * If we failed the create, we need to release the cloned minor
1296 		 * back to the free list.  In general, this is only useful if
1297 		 * the clone function results in a state change in the cloned
1298 		 * device for which the minor number was obtained.  If we get
1299 		 * past this point withouth falling into this case, it's
1300 		 * assumed that any state to be released will be released when
1301 		 * the vnode is dropped, instead.
1302 		 */
1303 		 (void)(*dnp->dn_clone)(dnp->dn_typeinfo.dev, DEVFS_CLONE_FREE);
1304 	}
1305 
1306 	dnp->dn_lflags &= ~DN_CREATE;
1307 	if (dnp->dn_lflags & DN_CREATEWAIT) {
1308 		dnp->dn_lflags &= ~DN_CREATEWAIT;
1309 		wakeup(&dnp->dn_lflags);
1310 	}
1311 
1312 out:
1313 	/*
1314 	 * Release the reference we took to prevent deletion while we weren't holding the lock.
1315 	 * If not returning success, then dropping this reference could delete the devnode;
1316 	 * no one should access a devnode after a call to devfs_dntovn fails.
1317 	 */
1318 	devfs_rele_node(dnp);
1319 
1320 	return error;
1321 }
1322 
1323 /*
1324  * Increment refcount on a devnode; prevents free of the node
1325  * while the devfs lock is not held.
1326  */
1327 void
1328 devfs_ref_node(devnode_t *dnp)
1329 {
1330 	dnp->dn_refcount++;
1331 }
1332 
1333 /*
1334  * Release a reference on a devnode.  If the devnode is marked for
1335  * free and the refcount is dropped to zero, do the free.
1336  */
1337 void
1338 devfs_rele_node(devnode_t *dnp)
1339 {
1340 	dnp->dn_refcount--;
1341 	if (dnp->dn_refcount < 0) {
1342 		panic("devfs_rele_node: devnode with a negative refcount!\n");
1343 	} else if ((dnp->dn_refcount == 0) && (dnp->dn_lflags & DN_DELETE))  {
1344 		devnode_free(dnp);
1345 	}
1346 
1347 }
1348 
1349 /***********************************************************************
1350  * add a whole device, with no prototype.. make name element and node
1351  * Used for adding the original device entries
1352  *
1353  * called with DEVFS_LOCK held
1354  ***********************************************************************/
1355 int
1356 dev_add_entry(const char *name, devnode_t * parent, int type, devnode_type_t * typeinfo,
1357 	      devnode_t * proto, struct devfsmount *dvm, devdirent_t * *nm_pp)
1358 {
1359 	devnode_t *	dnp;
1360 	int	error = 0;
1361 
1362 	if ((error = dev_add_node(type, typeinfo, proto, &dnp,
1363 			(parent?parent->dn_dvm:dvm))) != 0)
1364 	{
1365 		printf("devfs: %s: base node allocation failed (Errno=%d)\n",
1366 			name,error);
1367 		return error;
1368 	}
1369 	if ((error = dev_add_name(name ,parent ,NULL, dnp, nm_pp)) != 0)
1370 	{
1371 		devfs_dn_free(dnp); /* 1->0 for dir, 0->(-1) for other */
1372 		printf("devfs: %s: name slot allocation failed (Errno=%d)\n",
1373 		       name,error);
1374 
1375 	}
1376 	return error;
1377 }
1378 
1379 static void
1380 devfs_bulk_notify(devfs_event_log_t delp)
1381 {
1382 	uint32_t i;
1383 	for (i = 0; i < delp->del_used; i++) {
1384 		devfs_vnode_event_t dvep = &delp->del_entries[i];
1385 		if (vnode_getwithvid(dvep->dve_vp, dvep->dve_vid) == 0) {
1386 			vnode_notify(dvep->dve_vp, dvep->dve_events, NULL);
1387 			vnode_put(dvep->dve_vp);
1388 		}
1389 	}
1390 }
1391 
1392 static void
1393 devfs_record_event(devfs_event_log_t delp, devnode_t *dnp, uint32_t events)
1394 {
1395 	if (delp->del_used >= delp->del_max) {
1396 		panic("devfs event log overflowed.\n");
1397 	}
1398 
1399 	/* Can only notify for nodes that have an associated vnode */
1400 	if (dnp->dn_vn != NULLVP && vnode_ismonitored(dnp->dn_vn)) {
1401 		devfs_vnode_event_t dvep = &delp->del_entries[delp->del_used];
1402 		dvep->dve_vp = dnp->dn_vn;
1403 		dvep->dve_vid = vnode_vid(dnp->dn_vn);
1404 		dvep->dve_events = events;
1405 		delp->del_used++;
1406 	}
1407 }
1408 
1409 static int
1410 devfs_init_event_log(devfs_event_log_t delp, uint32_t count, devfs_vnode_event_t buf)
1411 {
1412 	devfs_vnode_event_t dvearr;
1413 
1414 	if (buf == NULL)  {
1415 		MALLOC(dvearr, devfs_vnode_event_t, count * sizeof(struct devfs_vnode_event), M_TEMP, M_WAITOK | M_ZERO);
1416 		if (dvearr == NULL) {
1417 			return ENOMEM;
1418 		}
1419 	} else {
1420 		dvearr = buf;
1421 	}
1422 
1423 	delp->del_max = count;
1424 	delp->del_used = 0;
1425 	delp->del_entries = dvearr;
1426 	return 0;
1427 }
1428 
1429 static void
1430 devfs_release_event_log(devfs_event_log_t delp, int need_free)
1431 {
1432 	if (delp->del_entries == NULL) {
1433 		panic("Free of devfs notify info that has not been intialized.\n");
1434 	}
1435 
1436 	if (need_free) {
1437 		FREE(delp->del_entries, M_TEMP);
1438 	}
1439 
1440 	delp->del_entries = NULL;
1441 }
1442 
1443 /*
1444  * Function: devfs_make_node
1445  *
1446  * Purpose
1447  *   Create a device node with the given pathname in the devfs namespace.
1448  *
1449  * Parameters:
1450  *   dev 	- the dev_t value to associate
1451  *   chrblk	- block or character device (DEVFS_CHAR or DEVFS_BLOCK)
1452  *   uid, gid	- ownership
1453  *   perms	- permissions
1454  *   clone	- minor number cloning function
1455  *   fmt, ...	- path format string with printf args to format the path name
1456  * Returns:
1457  *   A handle to a device node if successful, NULL otherwise.
1458  */
1459 void *
1460 devfs_make_node_clone(dev_t dev, int chrblk, uid_t uid,
1461 		gid_t gid, int perms, int (*clone)(dev_t dev, int action),
1462 		const char *fmt, ...)
1463 {
1464 	devdirent_t *	new_dev = NULL;
1465 	devfstype_t 	type;
1466 	va_list ap;
1467 
1468 	switch (chrblk) {
1469 		case DEVFS_CHAR:
1470 			type = DEV_CDEV;
1471 			break;
1472 		case DEVFS_BLOCK:
1473 			type = DEV_BDEV;
1474 			break;
1475 		default:
1476 			goto out;
1477 	}
1478 
1479 	va_start(ap, fmt);
1480 	new_dev = devfs_make_node_internal(dev, type, uid, gid, perms, clone, fmt, ap);
1481 	va_end(ap);
1482 out:
1483 	return new_dev;
1484 }
1485 
1486 
1487 /*
1488  * Function: devfs_make_node
1489  *
1490  * Purpose
1491  *   Create a device node with the given pathname in the devfs namespace.
1492  *
1493  * Parameters:
1494  *   dev 	- the dev_t value to associate
1495  *   chrblk	- block or character device (DEVFS_CHAR or DEVFS_BLOCK)
1496  *   uid, gid	- ownership
1497  *   perms	- permissions
1498  *   fmt, ...	- path format string with printf args to format the path name
1499  * Returns:
1500  *   A handle to a device node if successful, NULL otherwise.
1501  */
1502 void *
1503 devfs_make_node(dev_t dev, int chrblk, uid_t uid,
1504 		gid_t gid, int perms, const char *fmt, ...)
1505 {
1506 	devdirent_t *	new_dev = NULL;
1507 	devfstype_t type;
1508 	va_list ap;
1509 
1510 	if (chrblk != DEVFS_CHAR && chrblk != DEVFS_BLOCK)
1511 		goto out;
1512 
1513 	type = (chrblk == DEVFS_BLOCK ? DEV_BDEV : DEV_CDEV);
1514 
1515 	va_start(ap, fmt);
1516 	new_dev = devfs_make_node_internal(dev, type, uid, gid, perms, NULL, fmt, ap);
1517 	va_end(ap);
1518 
1519 out:
1520 	return new_dev;
1521 }
1522 
1523 static devdirent_t *
1524 devfs_make_node_internal(dev_t dev, devfstype_t type, uid_t uid,
1525 		gid_t gid, int perms, int (*clone)(dev_t dev, int action), const char *fmt, va_list ap)
1526 {
1527 	devdirent_t *	new_dev = NULL;
1528 	devnode_t * dnp;
1529 	devnode_type_t	typeinfo;
1530 
1531 	char 		*name, buf[256]; /* XXX */
1532 	const char 	*path;
1533 #if CONFIG_MACF
1534 	char buff[sizeof(buf)];
1535 #endif
1536 	int 		i;
1537 	uint32_t 	log_count;
1538 	struct devfs_event_log event_log;
1539 	struct devfs_vnode_event stackbuf[NUM_STACK_ENTRIES];
1540 	int		need_free = 0;
1541 
1542 	vsnprintf(buf, sizeof(buf), fmt, ap);
1543 
1544 #if CONFIG_MACF
1545 	bcopy(buf, buff, sizeof(buff));
1546 	buff[sizeof(buff)-1] = 0;
1547 #endif
1548 	name = NULL;
1549 
1550 	for(i=strlen(buf); i>0; i--)
1551 		if(buf[i] == '/') {
1552 			name=&buf[i];
1553 			buf[i]=0;
1554 			break;
1555 		}
1556 
1557 	if (name) {
1558 		*name++ = '\0';
1559 		path = buf;
1560 	} else {
1561 		name = buf;
1562 		path = "/";
1563 	}
1564 
1565 	log_count = devfs_nmountplanes;
1566 	if (log_count > NUM_STACK_ENTRIES) {
1567 wrongsize:
1568 		need_free = 1;
1569 		if (devfs_init_event_log(&event_log, log_count, NULL) != 0) {
1570 			return NULL;
1571 		}
1572 	} else {
1573 		need_free = 0;
1574 		log_count = NUM_STACK_ENTRIES;
1575 		if (devfs_init_event_log(&event_log, log_count, &stackbuf[0]) != 0) {
1576 			return NULL;
1577 		}
1578 	}
1579 
1580 	DEVFS_LOCK();
1581 	if (log_count < devfs_nmountplanes) {
1582 		DEVFS_UNLOCK();
1583 		devfs_release_event_log(&event_log, need_free);
1584 		log_count = log_count * 2;
1585 		goto wrongsize;
1586 	}
1587 
1588 	if (!devfs_ready) {
1589 		printf("devfs_make_node: not ready for devices!\n");
1590 		goto out;
1591 	}
1592 
1593 	/* find/create directory path ie. mkdir -p */
1594 	if (dev_finddir(path, NULL, DEVFS_CREATE, &dnp, &event_log) == 0) {
1595 	    typeinfo.dev = dev;
1596 	    if (dev_add_entry(name, dnp, type, &typeinfo, NULL, NULL, &new_dev) == 0) {
1597 		new_dev->de_dnp->dn_gid = gid;
1598 		new_dev->de_dnp->dn_uid = uid;
1599 		new_dev->de_dnp->dn_mode |= perms;
1600 		new_dev->de_dnp->dn_clone = clone;
1601 #if CONFIG_MACF
1602 		mac_devfs_label_associate_device(dev, new_dev->de_dnp, buff);
1603 #endif
1604 		devfs_propogate(dnp->dn_typeinfo.Dir.myname, new_dev, &event_log);
1605 	    }
1606 	}
1607 
1608 out:
1609 	DEVFS_UNLOCK();
1610 
1611 	devfs_bulk_notify(&event_log);
1612 	devfs_release_event_log(&event_log, need_free);
1613 	return new_dev;
1614 }
1615 
1616 /*
1617  * Function: devfs_make_link
1618  *
1619  * Purpose:
1620  *   Create a link to a previously created device node.
1621  *
1622  * Returns:
1623  *   0 if successful, -1 if failed
1624  */
1625 int
1626 devfs_make_link(void *original, char *fmt, ...)
1627 {
1628 	devdirent_t *	new_dev = NULL;
1629 	devdirent_t *	orig = (devdirent_t *) original;
1630 	devnode_t *	dirnode;	/* devnode for parent directory */
1631 	struct devfs_event_log event_log;
1632 	uint32_t	log_count;
1633 
1634 	va_list ap;
1635 	char *p, buf[256]; /* XXX */
1636 	int i;
1637 
1638 	DEVFS_LOCK();
1639 
1640 	if (!devfs_ready) {
1641 		DEVFS_UNLOCK();
1642 		printf("devfs_make_link: not ready for devices!\n");
1643 		return -1;
1644 	}
1645 	DEVFS_UNLOCK();
1646 
1647 	va_start(ap, fmt);
1648 	vsnprintf(buf, sizeof(buf), fmt, ap);
1649 	va_end(ap);
1650 
1651 	p = NULL;
1652 
1653 	for(i=strlen(buf); i>0; i--) {
1654 		if(buf[i] == '/') {
1655 				p=&buf[i];
1656 				buf[i]=0;
1657 				break;
1658 		}
1659 	}
1660 
1661 	/*
1662 	 * One slot for each directory, one for each devnode
1663 	 * whose link count changes
1664 	 */
1665 	log_count = devfs_nmountplanes * 2;
1666 wrongsize:
1667 	if (devfs_init_event_log(&event_log, log_count, NULL) != 0) {
1668 		/* No lock held, no allocations done, can just return */
1669 		return -1;
1670 	}
1671 
1672 	DEVFS_LOCK();
1673 
1674 	if (log_count < devfs_nmountplanes) {
1675 		DEVFS_UNLOCK();
1676 		devfs_release_event_log(&event_log, 1);
1677 		log_count = log_count * 2;
1678 		goto wrongsize;
1679 	}
1680 
1681 	if (p) {
1682 	        *p++ = '\0';
1683 
1684 		if (dev_finddir(buf, NULL, DEVFS_CREATE, &dirnode, &event_log)
1685 		    || dev_add_name(p, dirnode, NULL, orig->de_dnp, &new_dev))
1686 		        goto fail;
1687 	} else {
1688 	        if (dev_finddir("", NULL, DEVFS_CREATE, &dirnode, &event_log)
1689 		    || dev_add_name(buf, dirnode, NULL, orig->de_dnp, &new_dev))
1690 		        goto fail;
1691 	}
1692 	devfs_propogate(dirnode->dn_typeinfo.Dir.myname, new_dev, &event_log);
1693 fail:
1694 	DEVFS_UNLOCK();
1695 	devfs_bulk_notify(&event_log);
1696 	devfs_release_event_log(&event_log, 1);
1697 
1698 	return ((new_dev != NULL) ? 0 : -1);
1699 }
1700