devfs_vnops.c revision 139085
1/*
2 * Copyright (c) 2000-2004
3 *	Poul-Henning Kamp.  All rights reserved.
4 * Copyright (c) 1989, 1992-1993, 1995
5 *	The Regents of the University of California.  All rights reserved.
6 *
7 * This code is derived from software donated to Berkeley by
8 * Jan-Simon Pendry.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 *    notice, this list of conditions and the following disclaimer.
15 * 2. Neither the name of the University nor the names of its contributors
16 *    may be used to endorse or promote products derived from this software
17 *    without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 *
31 *	@(#)kernfs_vnops.c	8.15 (Berkeley) 5/21/95
32 * From: FreeBSD: src/sys/miscfs/kernfs/kernfs_vnops.c 1.43
33 *
34 * $FreeBSD: head/sys/fs/devfs/devfs_vnops.c 139085 2004-12-20 21:34:29Z phk $
35 */
36
37/*
38 * TODO:
39 *	remove empty directories
40 *	mknod: hunt down DE_DELETED, compare name, reinstantiate.
41 *	mkdir: want it ?
42 */
43
44#include <opt_devfs.h>
45#include <opt_mac.h>
46
47#include <sys/param.h>
48#include <sys/systm.h>
49#include <sys/conf.h>
50#include <sys/dirent.h>
51#include <sys/fcntl.h>
52#include <sys/file.h>
53#include <sys/filedesc.h>
54#include <sys/filio.h>
55#include <sys/kernel.h>
56#include <sys/lock.h>
57#include <sys/mac.h>
58#include <sys/malloc.h>
59#include <sys/mount.h>
60#include <sys/namei.h>
61#include <sys/proc.h>
62#include <sys/stat.h>
63#include <sys/sx.h>
64#include <sys/time.h>
65#include <sys/ttycom.h>
66#include <sys/unistd.h>
67#include <sys/vnode.h>
68
69#include <fs/devfs/devfs.h>
70
71static fo_rdwr_t	devfs_read_f;
72static fo_rdwr_t	devfs_write_f;
73static fo_ioctl_t	devfs_ioctl_f;
74static fo_poll_t	devfs_poll_f;
75static fo_kqfilter_t	devfs_kqfilter_f;
76static fo_stat_t	devfs_stat_f;
77static fo_close_t	devfs_close_f;
78
79struct fileops devfs_ops_f = {
80	.fo_read =	devfs_read_f,
81	.fo_write =	devfs_write_f,
82	.fo_ioctl =	devfs_ioctl_f,
83	.fo_poll =	devfs_poll_f,
84	.fo_kqfilter =	devfs_kqfilter_f,
85	.fo_stat =	devfs_stat_f,
86	.fo_close =	devfs_close_f,
87	.fo_flags =	DFLAG_PASSABLE | DFLAG_SEEKABLE
88};
89
90static vop_access_t	devfs_access;
91static vop_advlock_t	devfs_advlock;
92static vop_close_t	devfs_close;
93static vop_fsync_t	devfs_fsync;
94static vop_getattr_t	devfs_getattr;
95static vop_lookup_t	devfs_lookupx;
96static vop_mknod_t	devfs_mknod;
97static vop_open_t	devfs_open;
98static vop_pathconf_t	devfs_pathconf;
99static vop_print_t	devfs_print;
100static vop_readdir_t	devfs_readdir;
101static vop_readlink_t	devfs_readlink;
102static vop_reclaim_t	devfs_reclaim;
103static vop_remove_t	devfs_remove;
104static vop_revoke_t	devfs_revoke;
105static vop_ioctl_t	devfs_rioctl;
106static vop_read_t	devfs_rread;
107static vop_setattr_t	devfs_setattr;
108#ifdef MAC
109static vop_setlabel_t	devfs_setlabel;
110#endif
111static vop_symlink_t	devfs_symlink;
112
113extern struct vop_vector devfs_vnodeops;
114extern struct vop_vector devfs_specops;
115
116static int
117devfs_fp_check(struct file *fp, struct cdev **devp, struct cdevsw **dswp)
118{
119
120	*devp = fp->f_vnode->v_rdev;
121	if (*devp != fp->f_data)
122		return (ENXIO);
123	KASSERT((*devp)->si_refcount > 0,
124	    ("devfs: un-referenced struct cdev *(%s)", devtoname(*devp)));
125	*dswp = dev_refthread(*devp);
126	if (*dswp == NULL)
127		return (ENXIO);
128	return (0);
129}
130
131/*
132 * Construct the fully qualified path name relative to the mountpoint
133 */
134static char *
135devfs_fqpn(char *buf, struct vnode *dvp, struct componentname *cnp)
136{
137	int i;
138	struct devfs_dirent *de, *dd;
139	struct devfs_mount *dmp;
140
141	dmp = VFSTODEVFS(dvp->v_mount);
142	dd = dvp->v_data;
143	i = SPECNAMELEN;
144	buf[i] = '\0';
145	i -= cnp->cn_namelen;
146	if (i < 0)
147		 return (NULL);
148	bcopy(cnp->cn_nameptr, buf + i, cnp->cn_namelen);
149	de = dd;
150	while (de != dmp->dm_basedir) {
151		i--;
152		if (i < 0)
153			 return (NULL);
154		buf[i] = '/';
155		i -= de->de_dirent->d_namlen;
156		if (i < 0)
157			 return (NULL);
158		bcopy(de->de_dirent->d_name, buf + i,
159		    de->de_dirent->d_namlen);
160		de = TAILQ_FIRST(&de->de_dlist);	/* "." */
161		de = TAILQ_NEXT(de, de_list);		/* ".." */
162		de = de->de_dir;
163	}
164	return (buf + i);
165}
166
167int
168devfs_allocv(struct devfs_dirent *de, struct mount *mp, struct vnode **vpp, struct thread *td)
169{
170	int error;
171	struct vnode *vp;
172	struct cdev *dev;
173
174	KASSERT(td == curthread, ("devfs_allocv: td != curthread"));
175loop:
176	vp = de->de_vnode;
177	if (vp != NULL) {
178		if (vget(vp, LK_EXCLUSIVE, td))
179			goto loop;
180		*vpp = vp;
181		return (0);
182	}
183	if (de->de_dirent->d_type == DT_CHR) {
184		dev = *devfs_itod(de->de_inode);
185		if (dev == NULL)
186			return (ENOENT);
187	} else {
188		dev = NULL;
189	}
190	error = getnewvnode("devfs", mp, &devfs_vnodeops, &vp);
191	if (error != 0) {
192		printf("devfs_allocv: failed to allocate new vnode\n");
193		return (error);
194	}
195
196	if (de->de_dirent->d_type == DT_CHR) {
197		vp->v_type = VCHR;
198		VI_LOCK(vp);
199		dev_lock();
200		dev->si_refcount++;
201		vp->v_rdev = dev;
202		SLIST_INSERT_HEAD(&dev->si_hlist, vp, v_specnext);
203		dev->si_usecount += vp->v_usecount;
204		dev_unlock();
205		VI_UNLOCK(vp);
206		vp->v_op = &devfs_specops;
207	} else if (de->de_dirent->d_type == DT_DIR) {
208		vp->v_type = VDIR;
209	} else if (de->de_dirent->d_type == DT_LNK) {
210		vp->v_type = VLNK;
211	} else {
212		vp->v_type = VBAD;
213	}
214	vp->v_data = de;
215	de->de_vnode = vp;
216	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
217#ifdef MAC
218	mac_associate_vnode_devfs(mp, de, vp);
219#endif
220	*vpp = vp;
221	return (0);
222}
223
224static int
225devfs_access(ap)
226	struct vop_access_args /* {
227		struct vnode *a_vp;
228		int  a_mode;
229		struct ucred *a_cred;
230		struct thread *a_td;
231	} */ *ap;
232{
233	struct vnode *vp = ap->a_vp;
234	struct devfs_dirent *de;
235	int error;
236
237	de = vp->v_data;
238	if (vp->v_type == VDIR)
239		de = de->de_dir;
240
241	error = vaccess(vp->v_type, de->de_mode, de->de_uid, de->de_gid,
242	    ap->a_mode, ap->a_cred, NULL);
243	if (!error)
244		return (error);
245	if (error != EACCES)
246		return (error);
247	/* We do, however, allow access to the controlling terminal */
248	if (!(ap->a_td->td_proc->p_flag & P_CONTROLT))
249		return (error);
250	if (ap->a_td->td_proc->p_session->s_ttyvp == de->de_vnode)
251		return (0);
252	return (error);
253}
254
255/*
256 * Special device advisory byte-level locks.
257 */
258/* ARGSUSED */
259static int
260devfs_advlock(ap)
261	struct vop_advlock_args /* {
262		struct vnode *a_vp;
263		caddr_t  a_id;
264		int  a_op;
265		struct flock *a_fl;
266		int  a_flags;
267	} */ *ap;
268{
269
270	return (ap->a_flags & F_FLOCK ? EOPNOTSUPP : EINVAL);
271}
272
273/*
274 * Device close routine
275 */
276/* ARGSUSED */
277static int
278devfs_close(ap)
279	struct vop_close_args /* {
280		struct vnode *a_vp;
281		int  a_fflag;
282		struct ucred *a_cred;
283		struct thread *a_td;
284	} */ *ap;
285{
286	struct vnode *vp = ap->a_vp, *oldvp;
287	struct thread *td = ap->a_td;
288	struct cdev *dev = vp->v_rdev;
289	struct cdevsw *dsw;
290	int error;
291
292	/*
293	 * Hack: a tty device that is a controlling terminal
294	 * has a reference from the session structure.
295	 * We cannot easily tell that a character device is
296	 * a controlling terminal, unless it is the closing
297	 * process' controlling terminal.  In that case,
298	 * if the reference count is 2 (this last descriptor
299	 * plus the session), release the reference from the session.
300	 */
301
302	/*
303	 * This needs to be rewritten to take the vp interlock into
304	 * consideration.
305	 */
306
307	oldvp = NULL;
308	sx_xlock(&proctree_lock);
309	if (td && vp == td->td_proc->p_session->s_ttyvp) {
310		SESS_LOCK(td->td_proc->p_session);
311		VI_LOCK(vp);
312		if (count_dev(dev) == 2 && (vp->v_iflag & VI_XLOCK) == 0) {
313			td->td_proc->p_session->s_ttyvp = NULL;
314			oldvp = vp;
315		}
316		VI_UNLOCK(vp);
317		SESS_UNLOCK(td->td_proc->p_session);
318	}
319	sx_xunlock(&proctree_lock);
320	if (oldvp != NULL)
321		vrele(oldvp);
322	/*
323	 * We do not want to really close the device if it
324	 * is still in use unless we are trying to close it
325	 * forcibly. Since every use (buffer, vnode, swap, cmap)
326	 * holds a reference to the vnode, and because we mark
327	 * any other vnodes that alias this device, when the
328	 * sum of the reference counts on all the aliased
329	 * vnodes descends to one, we are on last close.
330	 */
331	dsw = dev_refthread(dev);
332	if (dsw == NULL)
333		return (ENXIO);
334	VI_LOCK(vp);
335	if (vp->v_iflag & VI_XLOCK) {
336		/* Forced close. */
337	} else if (dsw->d_flags & D_TRACKCLOSE) {
338		/* Keep device updated on status. */
339	} else if (count_dev(dev) > 1) {
340		VI_UNLOCK(vp);
341		dev_relthread(dev);
342		return (0);
343	}
344	VI_UNLOCK(vp);
345	KASSERT(dev->si_refcount > 0,
346	    ("devfs_close() on un-referenced struct cdev *(%s)", devtoname(dev)));
347	if (!(dsw->d_flags & D_NEEDGIANT)) {
348		DROP_GIANT();
349		error = dsw->d_close(dev, ap->a_fflag, S_IFCHR, td);
350		PICKUP_GIANT();
351	} else
352		error = dsw->d_close(dev, ap->a_fflag, S_IFCHR, td);
353	dev_relthread(dev);
354	return (error);
355}
356
357static int
358devfs_close_f(struct file *fp, struct thread *td)
359{
360
361	return (vnops.fo_close(fp, td));
362}
363
364/*
365 * Synch buffers associated with a block device
366 */
367/* ARGSUSED */
368static int
369devfs_fsync(ap)
370	struct vop_fsync_args /* {
371		struct vnode *a_vp;
372		struct ucred *a_cred;
373		int  a_waitfor;
374		struct thread *a_td;
375	} */ *ap;
376{
377	if (!vn_isdisk(ap->a_vp, NULL))
378		return (0);
379
380	return (vop_stdfsync(ap));
381}
382
383static int
384devfs_getattr(ap)
385	struct vop_getattr_args /* {
386		struct vnode *a_vp;
387		struct vattr *a_vap;
388		struct ucred *a_cred;
389		struct thread *a_td;
390	} */ *ap;
391{
392	struct vnode *vp = ap->a_vp;
393	struct vattr *vap = ap->a_vap;
394	int error = 0;
395	struct devfs_dirent *de;
396	struct cdev *dev;
397
398	de = vp->v_data;
399	KASSERT(de != NULL, ("Null dirent in devfs_getattr vp=%p", vp));
400	if (vp->v_type == VDIR) {
401		de = de->de_dir;
402		KASSERT(de != NULL,
403		    ("Null dir dirent in devfs_getattr vp=%p", vp));
404	}
405	bzero((caddr_t) vap, sizeof(*vap));
406	vattr_null(vap);
407	vap->va_uid = de->de_uid;
408	vap->va_gid = de->de_gid;
409	vap->va_mode = de->de_mode;
410	if (vp->v_type == VLNK)
411		vap->va_size = strlen(de->de_symlink);
412	else if (vp->v_type == VDIR)
413		vap->va_size = vap->va_bytes = DEV_BSIZE;
414	else
415		vap->va_size = 0;
416	if (vp->v_type != VDIR)
417		vap->va_bytes = 0;
418	vap->va_blocksize = DEV_BSIZE;
419	vap->va_type = vp->v_type;
420
421#define fix(aa)							\
422	do {							\
423		if ((aa).tv_sec == 0) {				\
424			(aa).tv_sec = boottime.tv_sec;		\
425			(aa).tv_nsec = boottime.tv_usec * 1000; \
426		}						\
427	} while (0)
428
429	if (vp->v_type != VCHR)  {
430		fix(de->de_atime);
431		vap->va_atime = de->de_atime;
432		fix(de->de_mtime);
433		vap->va_mtime = de->de_mtime;
434		fix(de->de_ctime);
435		vap->va_ctime = de->de_ctime;
436	} else {
437		dev = vp->v_rdev;
438		fix(dev->si_atime);
439		vap->va_atime = dev->si_atime;
440		fix(dev->si_mtime);
441		vap->va_mtime = dev->si_mtime;
442		fix(dev->si_ctime);
443		vap->va_ctime = dev->si_ctime;
444		vap->va_rdev = dev->si_udev;
445	}
446	vap->va_gen = 0;
447	vap->va_flags = 0;
448	vap->va_nlink = de->de_links;
449	vap->va_fileid = de->de_inode;
450
451	return (error);
452}
453
454/*
455 * Device ioctl operation.
456 */
457/* ARGSUSED */
458static int
459devfs_ioctl_f(struct file *fp, u_long com, void *data, struct ucred *cred, struct thread *td)
460{
461	struct cdev *dev;
462	struct cdevsw *dsw;
463	struct vnode *vp;
464	struct vnode *vpold;
465	int error;
466
467	error = devfs_fp_check(fp, &dev, &dsw);
468	if (error)
469		return (error);
470
471	if (com == FIODTYPE) {
472		*(int *)data = dsw->d_flags & D_TYPEMASK;
473		dev_relthread(dev);
474		return (0);
475	}
476	if (dsw->d_flags & D_NEEDGIANT)
477		mtx_lock(&Giant);
478	error = dsw->d_ioctl(dev, com, data, fp->f_flag, td);
479	if (dsw->d_flags & D_NEEDGIANT)
480		mtx_unlock(&Giant);
481	dev_relthread(dev);
482	if (error == ENOIOCTL)
483		error = ENOTTY;
484	if (error == 0 && com == TIOCSCTTY) {
485		vp = fp->f_vnode;
486
487		/* Do nothing if reassigning same control tty */
488		sx_slock(&proctree_lock);
489		if (td->td_proc->p_session->s_ttyvp == vp) {
490			sx_sunlock(&proctree_lock);
491			return (0);
492		}
493
494		mtx_lock(&Giant);
495
496		vpold = td->td_proc->p_session->s_ttyvp;
497		VREF(vp);
498		SESS_LOCK(td->td_proc->p_session);
499		td->td_proc->p_session->s_ttyvp = vp;
500		SESS_UNLOCK(td->td_proc->p_session);
501
502		sx_sunlock(&proctree_lock);
503
504		/* Get rid of reference to old control tty */
505		if (vpold)
506			vrele(vpold);
507		mtx_unlock(&Giant);
508	}
509	return (error);
510}
511
512
513/* ARGSUSED */
514static int
515devfs_kqfilter_f(struct file *fp, struct knote *kn)
516{
517	struct cdev *dev;
518	struct cdevsw *dsw;
519	int error;
520
521	error = devfs_fp_check(fp, &dev, &dsw);
522	if (error)
523		return (error);
524	if (dsw->d_flags & D_NEEDGIANT)
525		mtx_lock(&Giant);
526	error = dsw->d_kqfilter(dev, kn);
527	if (dsw->d_flags & D_NEEDGIANT)
528		mtx_unlock(&Giant);
529	dev_relthread(dev);
530	return (error);
531}
532
533static int
534devfs_lookupx(ap)
535	struct vop_lookup_args /* {
536		struct vnode * a_dvp;
537		struct vnode ** a_vpp;
538		struct componentname * a_cnp;
539	} */ *ap;
540{
541	struct componentname *cnp;
542	struct vnode *dvp, **vpp;
543	struct thread *td;
544	struct devfs_dirent *de, *dd;
545	struct devfs_dirent **dde;
546	struct devfs_mount *dmp;
547	struct cdev *cdev;
548	int error, flags, nameiop;
549	char specname[SPECNAMELEN + 1], *pname;
550
551	cnp = ap->a_cnp;
552	vpp = ap->a_vpp;
553	dvp = ap->a_dvp;
554	pname = cnp->cn_nameptr;
555	td = cnp->cn_thread;
556	flags = cnp->cn_flags;
557	nameiop = cnp->cn_nameiop;
558	dmp = VFSTODEVFS(dvp->v_mount);
559	dd = dvp->v_data;
560
561	*vpp = NULLVP;
562	cnp->cn_flags &= ~PDIRUNLOCK;
563
564	if ((flags & ISLASTCN) && nameiop == RENAME)
565		return (EOPNOTSUPP);
566
567	if (dvp->v_type != VDIR)
568		return (ENOTDIR);
569
570	if ((flags & ISDOTDOT) && (dvp->v_vflag & VV_ROOT))
571		return (EIO);
572
573	error = VOP_ACCESS(dvp, VEXEC, cnp->cn_cred, td);
574	if (error)
575		return (error);
576
577	if (cnp->cn_namelen == 1 && *pname == '.') {
578		if ((flags & ISLASTCN) && nameiop != LOOKUP)
579			return (EINVAL);
580		*vpp = dvp;
581		VREF(dvp);
582		return (0);
583	}
584
585	if (flags & ISDOTDOT) {
586		if ((flags & ISLASTCN) && nameiop != LOOKUP)
587			return (EINVAL);
588		VOP_UNLOCK(dvp, 0, td);
589		cnp->cn_flags |= PDIRUNLOCK;
590		de = TAILQ_FIRST(&dd->de_dlist);	/* "." */
591		de = TAILQ_NEXT(de, de_list);		/* ".." */
592		de = de->de_dir;
593		error = devfs_allocv(de, dvp->v_mount, vpp, td);
594		if (error || ((flags & LOCKPARENT) && (flags & ISLASTCN))) {
595			vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY, td);
596			cnp->cn_flags &= ~PDIRUNLOCK;
597		}
598		return (error);
599	}
600
601	devfs_populate(dmp);
602	dd = dvp->v_data;
603	TAILQ_FOREACH(de, &dd->de_dlist, de_list) {
604		if (cnp->cn_namelen != de->de_dirent->d_namlen)
605			continue;
606		if (bcmp(cnp->cn_nameptr, de->de_dirent->d_name,
607		    de->de_dirent->d_namlen) != 0)
608			continue;
609		if (de->de_flags & DE_WHITEOUT)
610			goto notfound;
611		goto found;
612	}
613
614	if (nameiop == DELETE)
615		goto notfound;
616
617	/*
618	 * OK, we didn't have an entry for the name we were asked for
619	 * so we try to see if anybody can create it on demand.
620	 */
621	pname = devfs_fqpn(specname, dvp, cnp);
622	if (pname == NULL)
623		goto notfound;
624
625	cdev = NULL;
626	EVENTHANDLER_INVOKE(dev_clone, pname, strlen(pname), &cdev);
627	if (cdev == NULL)
628		goto notfound;
629
630	devfs_populate(dmp);
631
632	dde = devfs_itode(dmp, cdev->si_inode);
633
634	if (dde == NULL || *dde == NULL || *dde == DE_DELETED)
635		goto notfound;
636
637	if ((*dde)->de_flags & DE_WHITEOUT)
638		goto notfound;
639
640	de = *dde;
641	goto found;
642
643notfound:
644
645	if ((nameiop == CREATE || nameiop == RENAME) &&
646	    (flags & (LOCKPARENT | WANTPARENT)) && (flags & ISLASTCN)) {
647		cnp->cn_flags |= SAVENAME;
648		if (!(flags & LOCKPARENT)) {
649			VOP_UNLOCK(dvp, 0, td);
650			cnp->cn_flags |= PDIRUNLOCK;
651		}
652		return (EJUSTRETURN);
653	}
654	return (ENOENT);
655
656
657found:
658
659	if ((cnp->cn_nameiop == DELETE) && (flags & ISLASTCN)) {
660		error = VOP_ACCESS(dvp, VWRITE, cnp->cn_cred, td);
661		if (error)
662			return (error);
663		if (*vpp == dvp) {
664			VREF(dvp);
665			*vpp = dvp;
666			return (0);
667		}
668		error = devfs_allocv(de, dvp->v_mount, vpp, td);
669		if (error)
670			return (error);
671		if (!(flags & LOCKPARENT)) {
672			VOP_UNLOCK(dvp, 0, td);
673			cnp->cn_flags |= PDIRUNLOCK;
674		}
675		return (0);
676	}
677	error = devfs_allocv(de, dvp->v_mount, vpp, td);
678	if (error)
679		return (error);
680	if (!(flags & LOCKPARENT) || !(flags & ISLASTCN)) {
681		VOP_UNLOCK(dvp, 0, td);
682		cnp->cn_flags |= PDIRUNLOCK;
683	}
684	return (0);
685}
686
687static int
688devfs_lookup(struct vop_lookup_args *ap)
689{
690	int j;
691	struct devfs_mount *dmp;
692
693	dmp = VFSTODEVFS(ap->a_dvp->v_mount);
694	lockmgr(&dmp->dm_lock, LK_SHARED, 0, curthread);
695	j = devfs_lookupx(ap);
696	lockmgr(&dmp->dm_lock, LK_RELEASE, 0, curthread);
697	return (j);
698}
699
700static int
701devfs_mknod(struct vop_mknod_args *ap)
702	/*
703	struct vop_mknod_args {
704		struct vnodeop_desc *a_desc;
705		struct vnode *a_dvp;
706		struct vnode **a_vpp;
707		struct componentname *a_cnp;
708		struct vattr *a_vap;
709	}; */
710{
711	struct componentname *cnp;
712	struct vnode *dvp, **vpp;
713	struct thread *td;
714	struct devfs_dirent *dd, *de;
715	struct devfs_mount *dmp;
716	int error;
717
718	dvp = ap->a_dvp;
719	dmp = VFSTODEVFS(dvp->v_mount);
720	lockmgr(&dmp->dm_lock, LK_EXCLUSIVE, 0, curthread);
721
722	cnp = ap->a_cnp;
723	vpp = ap->a_vpp;
724	td = cnp->cn_thread;
725	dd = dvp->v_data;
726
727	error = ENOENT;
728	TAILQ_FOREACH(de, &dd->de_dlist, de_list) {
729		if (cnp->cn_namelen != de->de_dirent->d_namlen)
730			continue;
731		if (bcmp(cnp->cn_nameptr, de->de_dirent->d_name,
732		    de->de_dirent->d_namlen) != 0)
733			continue;
734		if (de->de_flags & DE_WHITEOUT)
735			break;
736		goto notfound;
737	}
738	if (de == NULL)
739		goto notfound;
740	de->de_flags &= ~DE_WHITEOUT;
741	error = devfs_allocv(de, dvp->v_mount, vpp, td);
742notfound:
743	lockmgr(&dmp->dm_lock, LK_RELEASE, 0, curthread);
744	return (error);
745}
746
747/*
748 * Open a special file.
749 */
750/* ARGSUSED */
751static int
752devfs_open(ap)
753	struct vop_open_args /* {
754		struct vnode *a_vp;
755		int  a_mode;
756		struct ucred *a_cred;
757		struct thread *a_td;
758		int a_fdidx;
759	} */ *ap;
760{
761	struct thread *td = ap->a_td;
762	struct vnode *vp = ap->a_vp;
763	struct cdev *dev = vp->v_rdev;
764	struct file *fp;
765	int error;
766	struct cdevsw *dsw;
767
768	if (vp->v_type == VBLK)
769		return (ENXIO);
770
771	if (dev == NULL)
772		return (ENXIO);
773
774	/* Make this field valid before any I/O in d_open. */
775	if (dev->si_iosize_max == 0)
776		dev->si_iosize_max = DFLTPHYS;
777
778	if (vn_isdisk(vp, NULL) &&
779	    ap->a_cred != FSCRED && (ap->a_mode & FWRITE)) {
780		/*
781		* When running in very secure mode, do not allow
782		* opens for writing of any disks.
783		* XXX: should be in geom_dev.c, but we lack the cred there.
784		*/
785		error = securelevel_ge(td->td_ucred, 2);
786		if (error)
787			return (error);
788	}
789
790	dsw = dev_refthread(dev);
791	if (dsw == NULL)
792		return (ENXIO);
793
794	/* XXX: Special casing of ttys for deadfs.  Probably redundant. */
795	if (dsw->d_flags & D_TTY)
796		vp->v_vflag |= VV_ISTTY;
797
798	VOP_UNLOCK(vp, 0, td);
799
800	if(!(dsw->d_flags & D_NEEDGIANT)) {
801		DROP_GIANT();
802		if (dsw->d_fdopen != NULL)
803			error = dsw->d_fdopen(dev, ap->a_mode, td, ap->a_fdidx);
804		else
805			error = dsw->d_open(dev, ap->a_mode, S_IFCHR, td);
806		PICKUP_GIANT();
807	} else if (dsw->d_fdopen != NULL)
808		error = dsw->d_fdopen(dev, ap->a_mode, td, ap->a_fdidx);
809	else
810		error = dsw->d_open(dev, ap->a_mode, S_IFCHR, td);
811
812	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
813
814	dev_relthread(dev);
815
816	if (error)
817		return (error);
818
819#if 0	/* /dev/console */
820	KASSERT(ap->a_fdidx >= 0,
821	     ("Could not vnode bypass device on fd %d", ap->a_fdidx));
822#else
823	if(ap->a_fdidx < 0)
824		return (error);
825#endif
826	/*
827	 * This is a pretty disgustingly long chain, but I am not
828	 * sure there is any better way.  Passing the fdidx into
829	 * VOP_OPEN() offers us more information than just passing
830	 * the file *.
831	 */
832	fp = ap->a_td->td_proc->p_fd->fd_ofiles[ap->a_fdidx];
833	KASSERT(fp->f_ops == &badfileops,
834	     ("Could not vnode bypass device on fdops %p", fp->f_ops));
835	fp->f_ops = &devfs_ops_f;
836	fp->f_data = dev;
837	return (error);
838}
839
840static int
841devfs_pathconf(ap)
842	struct vop_pathconf_args /* {
843		struct vnode *a_vp;
844		int a_name;
845		int *a_retval;
846	} */ *ap;
847{
848
849	switch (ap->a_name) {
850	case _PC_NAME_MAX:
851		*ap->a_retval = NAME_MAX;
852		return (0);
853	case _PC_PATH_MAX:
854		*ap->a_retval = PATH_MAX;
855		return (0);
856	case _PC_MAC_PRESENT:
857#ifdef MAC
858		/*
859		 * If MAC is enabled, devfs automatically supports
860		 * trivial non-persistant label storage.
861		 */
862		*ap->a_retval = 1;
863#else
864		*ap->a_retval = 0;
865#endif
866		return (0);
867	default:
868		return (vop_stdpathconf(ap));
869	}
870	/* NOTREACHED */
871}
872
873/* ARGSUSED */
874static int
875devfs_poll_f(struct file *fp, int events, struct ucred *cred, struct thread *td)
876{
877	struct cdev *dev;
878	struct cdevsw *dsw;
879	int error;
880
881	error = devfs_fp_check(fp, &dev, &dsw);
882	if (error)
883		return (error);
884	if (dsw->d_flags & D_NEEDGIANT)
885		mtx_lock(&Giant);
886	error = dsw->d_poll(dev, events, td);
887	if (dsw->d_flags & D_NEEDGIANT)
888		mtx_unlock(&Giant);
889	dev_relthread(dev);
890	return(error);
891}
892
893/*
894 * Print out the contents of a special device vnode.
895 */
896static int
897devfs_print(ap)
898	struct vop_print_args /* {
899		struct vnode *a_vp;
900	} */ *ap;
901{
902
903	printf("\tdev %s\n", devtoname(ap->a_vp->v_rdev));
904	return (0);
905}
906
907/*
908 * Vnode op for read
909 */
910/* ARGSUSED */
911static int
912devfs_read_f(struct file *fp, struct uio *uio, struct ucred *cred, int flags, struct thread *td)
913{
914	struct cdev *dev;
915	int ioflag, error, resid;
916	struct cdevsw *dsw;
917
918	error = devfs_fp_check(fp, &dev, &dsw);
919	if (error)
920		return (error);
921	resid = uio->uio_resid;
922	ioflag = 0;
923	if (fp->f_flag & O_NONBLOCK)
924		ioflag |= IO_NDELAY;
925	if (fp->f_flag & O_DIRECT)
926		ioflag |= IO_DIRECT;
927
928	if ((flags & FOF_OFFSET) == 0)
929		uio->uio_offset = fp->f_offset;
930
931	if (dsw->d_flags & D_NEEDGIANT)
932		mtx_lock(&Giant);
933	error = dsw->d_read(dev, uio, ioflag);
934	if (dsw->d_flags & D_NEEDGIANT)
935		mtx_unlock(&Giant);
936	dev_relthread(dev);
937	if (uio->uio_resid != resid || (error == 0 && resid != 0))
938		vfs_timestamp(&dev->si_atime);
939
940	if ((flags & FOF_OFFSET) == 0)
941		fp->f_offset = uio->uio_offset;
942	fp->f_nextoff = uio->uio_offset;
943	return (error);
944}
945
946static int
947devfs_readdir(ap)
948	struct vop_readdir_args /* {
949		struct vnode *a_vp;
950		struct uio *a_uio;
951		struct ucred *a_cred;
952		int *a_eofflag;
953		int *a_ncookies;
954		u_long **a_cookies;
955	} */ *ap;
956{
957	int error;
958	struct uio *uio;
959	struct dirent *dp;
960	struct devfs_dirent *dd;
961	struct devfs_dirent *de;
962	struct devfs_mount *dmp;
963	off_t off, oldoff;
964	int ncookies = 0;
965	u_long *cookiebuf, *cookiep;
966	struct dirent *dps, *dpe;
967
968	if (ap->a_vp->v_type != VDIR)
969		return (ENOTDIR);
970
971	uio = ap->a_uio;
972	if (uio->uio_offset < 0)
973		return (EINVAL);
974
975	dmp = VFSTODEVFS(ap->a_vp->v_mount);
976	lockmgr(&dmp->dm_lock, LK_SHARED, 0, curthread);
977	devfs_populate(dmp);
978	error = 0;
979	de = ap->a_vp->v_data;
980	off = 0;
981	oldoff = uio->uio_offset;
982	TAILQ_FOREACH(dd, &de->de_dlist, de_list) {
983		if (dd->de_flags & DE_WHITEOUT)
984			continue;
985		if (dd->de_dirent->d_type == DT_DIR)
986			de = dd->de_dir;
987		else
988			de = dd;
989		dp = dd->de_dirent;
990		if (dp->d_reclen > uio->uio_resid)
991			break;
992		dp->d_fileno = de->de_inode;
993		if (off >= uio->uio_offset) {
994			ncookies++;
995			error = uiomove(dp, dp->d_reclen, uio);
996			if (error)
997				break;
998		}
999		off += dp->d_reclen;
1000	}
1001	if( !error && ap->a_ncookies != NULL && ap->a_cookies != NULL ) {
1002		MALLOC(cookiebuf, u_long *, ncookies * sizeof(u_long),
1003		       M_TEMP, M_WAITOK);
1004		cookiep = cookiebuf;
1005		dps = (struct dirent *)((char *)uio->uio_iov->iov_base -
1006		    (uio->uio_offset - oldoff));
1007		dpe = (struct dirent *) uio->uio_iov->iov_base;
1008		for( dp = dps;
1009			dp < dpe;
1010			dp = (struct dirent *)((caddr_t) dp + dp->d_reclen)) {
1011				oldoff += dp->d_reclen;
1012				*cookiep++ = (u_long) oldoff;
1013		}
1014		*ap->a_ncookies = ncookies;
1015		*ap->a_cookies = cookiebuf;
1016	}
1017	lockmgr(&dmp->dm_lock, LK_RELEASE, 0, curthread);
1018	uio->uio_offset = off;
1019	return (error);
1020}
1021
1022static int
1023devfs_readlink(ap)
1024	struct vop_readlink_args /* {
1025		struct vnode *a_vp;
1026		struct uio *a_uio;
1027		struct ucred *a_cead;
1028	} */ *ap;
1029{
1030	int error;
1031	struct devfs_dirent *de;
1032
1033	de = ap->a_vp->v_data;
1034	error = uiomove(de->de_symlink, strlen(de->de_symlink), ap->a_uio);
1035	return (error);
1036}
1037
1038static int
1039devfs_reclaim(ap)
1040	struct vop_reclaim_args /* {
1041		struct vnode *a_vp;
1042	} */ *ap;
1043{
1044	struct vnode *vp = ap->a_vp;
1045	struct devfs_dirent *de;
1046	int i;
1047
1048	de = vp->v_data;
1049	if (de != NULL)
1050		de->de_vnode = NULL;
1051	vp->v_data = NULL;
1052	if (vp->v_rdev != NULL) {
1053		i = vcount(vp);
1054		if ((vp->v_rdev->si_flags & SI_CHEAPCLONE) && i == 0 &&
1055		    (vp->v_rdev->si_flags & SI_NAMED))
1056			destroy_dev(vp->v_rdev);
1057	}
1058	return (0);
1059}
1060
1061static int
1062devfs_remove(ap)
1063	struct vop_remove_args /* {
1064		struct vnode *a_dvp;
1065		struct vnode *a_vp;
1066		struct componentname *a_cnp;
1067	} */ *ap;
1068{
1069	struct vnode *vp = ap->a_vp;
1070	struct devfs_dirent *dd;
1071	struct devfs_dirent *de;
1072	struct devfs_mount *dmp = VFSTODEVFS(vp->v_mount);
1073
1074	lockmgr(&dmp->dm_lock, LK_EXCLUSIVE, 0, curthread);
1075	dd = ap->a_dvp->v_data;
1076	de = vp->v_data;
1077	if (de->de_dirent->d_type == DT_LNK) {
1078		TAILQ_REMOVE(&dd->de_dlist, de, de_list);
1079		if (de->de_vnode)
1080			de->de_vnode->v_data = NULL;
1081#ifdef MAC
1082		mac_destroy_devfsdirent(de);
1083#endif
1084		FREE(de, M_DEVFS);
1085	} else {
1086		de->de_flags |= DE_WHITEOUT;
1087	}
1088	lockmgr(&dmp->dm_lock, LK_RELEASE, 0, curthread);
1089	return (0);
1090}
1091
1092/*
1093 * Revoke is called on a tty when a terminal session ends.  The vnode
1094 * is orphaned by setting v_op to deadfs so we need to let go of it
1095 * as well so that we create a new one next time around.
1096 */
1097static int
1098devfs_revoke(ap)
1099	struct vop_revoke_args /* {
1100		struct vnode *a_vp;
1101		int a_flags;
1102	} */ *ap;
1103{
1104	struct vnode *vp = ap->a_vp;
1105	struct vnode *vq;
1106	struct devfs_dirent *de;
1107	struct cdev *dev;
1108
1109	KASSERT((ap->a_flags & REVOKEALL) != 0, ("devfs_revoke !REVOKEALL"));
1110	de = vp->v_data;
1111	de->de_vnode = NULL;
1112
1113	VI_LOCK(vp);
1114	/*
1115	 * If a vgone (or vclean) is already in progress,
1116	 * wait until it is done and return.
1117	 */
1118	if (vp->v_iflag & VI_XLOCK) {
1119		vp->v_iflag |= VI_XWANT;
1120		msleep(vp, VI_MTX(vp), PINOD | PDROP, "vop_revokeall", 0);
1121		return (0);
1122	}
1123	VI_UNLOCK(vp);
1124	dev = vp->v_rdev;
1125	for (;;) {
1126		dev_lock();
1127		vq = SLIST_FIRST(&dev->si_hlist);
1128		dev_unlock();
1129		if (vq == NULL)
1130			break;
1131		vgone(vq);
1132	}
1133	return (0);
1134}
1135
1136static int
1137devfs_rioctl(ap)
1138	struct vop_ioctl_args /* {
1139		struct vnode *a_vp;
1140		u_long  a_command;
1141		caddr_t  a_data;
1142		int  a_fflag;
1143		struct ucred *a_cred;
1144		struct thread *a_td;
1145	} */ *ap;
1146{
1147	int error;
1148	struct devfs_mount *dmp;
1149
1150	dmp = VFSTODEVFS(ap->a_vp->v_mount);
1151	lockmgr(&dmp->dm_lock, LK_SHARED, 0, curthread);
1152	devfs_populate(dmp);
1153	lockmgr(&dmp->dm_lock, LK_RELEASE, 0, curthread);
1154	error = devfs_rules_ioctl(ap->a_vp->v_mount, ap->a_command, ap->a_data,
1155	    ap->a_td);
1156	return (error);
1157}
1158
1159static int
1160devfs_rread(ap)
1161	struct vop_read_args /* {
1162		struct vnode *a_vp;
1163		struct uio *a_uio;
1164		int a_ioflag;
1165		struct ucred *a_cred;
1166	} */ *ap;
1167{
1168
1169	if (ap->a_vp->v_type != VDIR)
1170		return (EINVAL);
1171	return (VOP_READDIR(ap->a_vp, ap->a_uio, ap->a_cred, NULL, NULL, NULL));
1172}
1173
1174static int
1175devfs_setattr(ap)
1176	struct vop_setattr_args /* {
1177		struct vnode *a_vp;
1178		struct vattr *a_vap;
1179		struct ucred *a_cred;
1180		struct proc *a_p;
1181	} */ *ap;
1182{
1183	struct devfs_dirent *de;
1184	struct vattr *vap;
1185	struct vnode *vp;
1186	int c, error;
1187	uid_t uid;
1188	gid_t gid;
1189
1190	vap = ap->a_vap;
1191	vp = ap->a_vp;
1192	if ((vap->va_type != VNON) ||
1193	    (vap->va_nlink != VNOVAL) ||
1194	    (vap->va_fsid != VNOVAL) ||
1195	    (vap->va_fileid != VNOVAL) ||
1196	    (vap->va_blocksize != VNOVAL) ||
1197	    (vap->va_flags != VNOVAL && vap->va_flags != 0) ||
1198	    (vap->va_rdev != VNOVAL) ||
1199	    ((int)vap->va_bytes != VNOVAL) ||
1200	    (vap->va_gen != VNOVAL)) {
1201		return (EINVAL);
1202	}
1203
1204	de = vp->v_data;
1205	if (vp->v_type == VDIR)
1206		de = de->de_dir;
1207
1208	error = c = 0;
1209	if (vap->va_uid == (uid_t)VNOVAL)
1210		uid = de->de_uid;
1211	else
1212		uid = vap->va_uid;
1213	if (vap->va_gid == (gid_t)VNOVAL)
1214		gid = de->de_gid;
1215	else
1216		gid = vap->va_gid;
1217	if (uid != de->de_uid || gid != de->de_gid) {
1218		if (((ap->a_cred->cr_uid != de->de_uid) || uid != de->de_uid ||
1219		    (gid != de->de_gid && !groupmember(gid, ap->a_cred))) &&
1220		    (error = suser_cred(ap->a_td->td_ucred, SUSER_ALLOWJAIL)) != 0)
1221			return (error);
1222		de->de_uid = uid;
1223		de->de_gid = gid;
1224		c = 1;
1225	}
1226
1227	if (vap->va_mode != (mode_t)VNOVAL) {
1228		if ((ap->a_cred->cr_uid != de->de_uid) &&
1229		    (error = suser_cred(ap->a_td->td_ucred, SUSER_ALLOWJAIL)))
1230			return (error);
1231		de->de_mode = vap->va_mode;
1232		c = 1;
1233	}
1234
1235	if (vap->va_atime.tv_sec != VNOVAL || vap->va_mtime.tv_sec != VNOVAL) {
1236		/* See the comment in ufs_vnops::ufs_setattr(). */
1237		if ((error = VOP_ACCESS(vp, VADMIN, ap->a_cred, ap->a_td)) &&
1238		    ((vap->va_vaflags & VA_UTIMES_NULL) == 0 ||
1239		    (error = VOP_ACCESS(vp, VWRITE, ap->a_cred, ap->a_td))))
1240			return (error);
1241		if (vap->va_atime.tv_sec != VNOVAL) {
1242			if (vp->v_type == VCHR)
1243				vp->v_rdev->si_atime = vap->va_atime;
1244			else
1245				de->de_atime = vap->va_atime;
1246		}
1247		if (vap->va_mtime.tv_sec != VNOVAL) {
1248			if (vp->v_type == VCHR)
1249				vp->v_rdev->si_mtime = vap->va_mtime;
1250			else
1251				de->de_mtime = vap->va_mtime;
1252		}
1253		c = 1;
1254	}
1255
1256	if (c) {
1257		if (vp->v_type == VCHR)
1258			vfs_timestamp(&vp->v_rdev->si_ctime);
1259		else
1260			vfs_timestamp(&de->de_mtime);
1261	}
1262	return (0);
1263}
1264
1265#ifdef MAC
1266static int
1267devfs_setlabel(ap)
1268	struct vop_setlabel_args /* {
1269		struct vnode *a_vp;
1270		struct mac *a_label;
1271		struct ucred *a_cred;
1272		struct thread *a_td;
1273	} */ *ap;
1274{
1275	struct vnode *vp;
1276	struct devfs_dirent *de;
1277
1278	vp = ap->a_vp;
1279	de = vp->v_data;
1280
1281	mac_relabel_vnode(ap->a_cred, vp, ap->a_label);
1282	mac_update_devfsdirent(vp->v_mount, de, vp);
1283
1284	return (0);
1285}
1286#endif
1287
1288static int
1289devfs_stat_f(struct file *fp, struct stat *sb, struct ucred *cred, struct thread *td)
1290{
1291
1292	return (vnops.fo_stat(fp, sb, cred, td));
1293}
1294
1295static int
1296devfs_symlink(ap)
1297	struct vop_symlink_args /* {
1298		struct vnode *a_dvp;
1299		struct vnode **a_vpp;
1300		struct componentname *a_cnp;
1301		struct vattr *a_vap;
1302		char *a_target;
1303	} */ *ap;
1304{
1305	int i, error;
1306	struct devfs_dirent *dd;
1307	struct devfs_dirent *de;
1308	struct devfs_mount *dmp;
1309	struct thread *td;
1310
1311	td = ap->a_cnp->cn_thread;
1312	KASSERT(td == curthread, ("devfs_symlink: td != curthread"));
1313	error = suser(td);
1314	if (error)
1315		return(error);
1316	dmp = VFSTODEVFS(ap->a_dvp->v_mount);
1317	dd = ap->a_dvp->v_data;
1318	de = devfs_newdirent(ap->a_cnp->cn_nameptr, ap->a_cnp->cn_namelen);
1319	de->de_uid = 0;
1320	de->de_gid = 0;
1321	de->de_mode = 0755;
1322	de->de_inode = dmp->dm_inode++;
1323	de->de_dirent->d_type = DT_LNK;
1324	i = strlen(ap->a_target) + 1;
1325	MALLOC(de->de_symlink, char *, i, M_DEVFS, M_WAITOK);
1326	bcopy(ap->a_target, de->de_symlink, i);
1327	lockmgr(&dmp->dm_lock, LK_EXCLUSIVE, 0, td);
1328#ifdef MAC
1329	mac_create_devfs_symlink(ap->a_cnp->cn_cred, dmp->dm_mount, dd, de);
1330#endif
1331	TAILQ_INSERT_TAIL(&dd->de_dlist, de, de_list);
1332	devfs_allocv(de, ap->a_dvp->v_mount, ap->a_vpp, td);
1333	lockmgr(&dmp->dm_lock, LK_RELEASE, 0, td);
1334	return (0);
1335}
1336
1337/*
1338 * Vnode op for write
1339 */
1340/* ARGSUSED */
1341static int
1342devfs_write_f(struct file *fp, struct uio *uio, struct ucred *cred, int flags, struct thread *td)
1343{
1344	struct cdev *dev;
1345	struct vnode *vp;
1346	int error, ioflag, resid;
1347	struct cdevsw *dsw;
1348
1349	error = devfs_fp_check(fp, &dev, &dsw);
1350	if (error)
1351		return (error);
1352	KASSERT(uio->uio_td == td, ("uio_td %p is not td %p", uio->uio_td, td));
1353	vp = fp->f_vnode;
1354	ioflag = 0;
1355	if (fp->f_flag & O_NONBLOCK)
1356		ioflag |= IO_NDELAY;
1357	if (fp->f_flag & O_DIRECT)
1358		ioflag |= IO_DIRECT;
1359	if ((fp->f_flag & O_FSYNC) ||
1360	    (vp->v_mount && (vp->v_mount->mnt_flag & MNT_SYNCHRONOUS)))
1361		ioflag |= IO_SYNC;
1362	if ((flags & FOF_OFFSET) == 0)
1363		uio->uio_offset = fp->f_offset;
1364
1365	resid = uio->uio_resid;
1366
1367	if (dsw->d_flags & D_NEEDGIANT)
1368		mtx_lock(&Giant);
1369	error = dsw->d_write(dev, uio, ioflag);
1370	if (dsw->d_flags & D_NEEDGIANT)
1371		mtx_unlock(&Giant);
1372	dev_relthread(dev);
1373	if (uio->uio_resid != resid || (error == 0 && resid != 0)) {
1374		vfs_timestamp(&dev->si_ctime);
1375		dev->si_mtime = dev->si_ctime;
1376	}
1377
1378	if ((flags & FOF_OFFSET) == 0)
1379		fp->f_offset = uio->uio_offset;
1380	fp->f_nextoff = uio->uio_offset;
1381	return (error);
1382}
1383
1384static struct vop_vector devfs_vnodeops = {
1385	.vop_default =		&default_vnodeops,
1386	.vop_access =		devfs_access,
1387	.vop_getattr =		devfs_getattr,
1388	.vop_ioctl =		devfs_rioctl,
1389	.vop_lookup =		devfs_lookup,
1390	.vop_mknod =		devfs_mknod,
1391	.vop_pathconf =		devfs_pathconf,
1392	.vop_read =		devfs_rread,
1393	.vop_readdir =		devfs_readdir,
1394	.vop_readlink =		devfs_readlink,
1395	.vop_reclaim =		devfs_reclaim,
1396	.vop_remove =		devfs_remove,
1397	.vop_revoke =		devfs_revoke,
1398	.vop_setattr =		devfs_setattr,
1399#ifdef MAC
1400	.vop_setlabel =		devfs_setlabel,
1401#endif
1402	.vop_symlink =		devfs_symlink,
1403};
1404
1405static struct vop_vector devfs_specops = {
1406	.vop_default =		&default_vnodeops,
1407	.vop_access =		devfs_access,
1408	.vop_advlock =		devfs_advlock,
1409	.vop_bmap =		VOP_PANIC,
1410	.vop_close =		devfs_close,
1411	.vop_create =		VOP_PANIC,
1412	.vop_fsync =		devfs_fsync,
1413	.vop_getattr =		devfs_getattr,
1414	.vop_lease =		VOP_NULL,
1415	.vop_link =		VOP_PANIC,
1416	.vop_mkdir =		VOP_PANIC,
1417	.vop_mknod =		VOP_PANIC,
1418	.vop_open =		devfs_open,
1419	.vop_pathconf =		devfs_pathconf,
1420	.vop_print =		devfs_print,
1421	.vop_read =		VOP_PANIC,
1422	.vop_readdir =		VOP_PANIC,
1423	.vop_readlink =		VOP_PANIC,
1424	.vop_reallocblks =	VOP_PANIC,
1425	.vop_reclaim =		devfs_reclaim,
1426	.vop_remove =		devfs_remove,
1427	.vop_rename =		VOP_PANIC,
1428	.vop_revoke =		devfs_revoke,
1429	.vop_rmdir =		VOP_PANIC,
1430	.vop_setattr =		devfs_setattr,
1431#ifdef MAC
1432	.vop_setlabel =		devfs_setlabel,
1433#endif
1434	.vop_strategy =		VOP_PANIC,
1435	.vop_symlink =		VOP_PANIC,
1436	.vop_write =		VOP_PANIC,
1437};
1438