devfs_vnops.c revision 140196
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 140196 2005-01-13 18:59:48Z 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 = fp->f_flag & (O_NONBLOCK | O_DIRECT);
923	if (ioflag & O_DIRECT)
924		ioflag |= IO_DIRECT;
925
926	if ((flags & FOF_OFFSET) == 0)
927		uio->uio_offset = fp->f_offset;
928
929	if (dsw->d_flags & D_NEEDGIANT)
930		mtx_lock(&Giant);
931	error = dsw->d_read(dev, uio, ioflag);
932	if (dsw->d_flags & D_NEEDGIANT)
933		mtx_unlock(&Giant);
934	dev_relthread(dev);
935	if (uio->uio_resid != resid || (error == 0 && resid != 0))
936		vfs_timestamp(&dev->si_atime);
937
938	if ((flags & FOF_OFFSET) == 0)
939		fp->f_offset = uio->uio_offset;
940	fp->f_nextoff = uio->uio_offset;
941	return (error);
942}
943
944static int
945devfs_readdir(ap)
946	struct vop_readdir_args /* {
947		struct vnode *a_vp;
948		struct uio *a_uio;
949		struct ucred *a_cred;
950		int *a_eofflag;
951		int *a_ncookies;
952		u_long **a_cookies;
953	} */ *ap;
954{
955	int error;
956	struct uio *uio;
957	struct dirent *dp;
958	struct devfs_dirent *dd;
959	struct devfs_dirent *de;
960	struct devfs_mount *dmp;
961	off_t off, oldoff;
962	int ncookies = 0;
963	u_long *cookiebuf, *cookiep;
964	struct dirent *dps, *dpe;
965
966	if (ap->a_vp->v_type != VDIR)
967		return (ENOTDIR);
968
969	uio = ap->a_uio;
970	if (uio->uio_offset < 0)
971		return (EINVAL);
972
973	dmp = VFSTODEVFS(ap->a_vp->v_mount);
974	lockmgr(&dmp->dm_lock, LK_SHARED, 0, curthread);
975	devfs_populate(dmp);
976	error = 0;
977	de = ap->a_vp->v_data;
978	off = 0;
979	oldoff = uio->uio_offset;
980	TAILQ_FOREACH(dd, &de->de_dlist, de_list) {
981		if (dd->de_flags & DE_WHITEOUT)
982			continue;
983		if (dd->de_dirent->d_type == DT_DIR)
984			de = dd->de_dir;
985		else
986			de = dd;
987		dp = dd->de_dirent;
988		if (dp->d_reclen > uio->uio_resid)
989			break;
990		dp->d_fileno = de->de_inode;
991		if (off >= uio->uio_offset) {
992			ncookies++;
993			error = uiomove(dp, dp->d_reclen, uio);
994			if (error)
995				break;
996		}
997		off += dp->d_reclen;
998	}
999	if( !error && ap->a_ncookies != NULL && ap->a_cookies != NULL ) {
1000		MALLOC(cookiebuf, u_long *, ncookies * sizeof(u_long),
1001		       M_TEMP, M_WAITOK);
1002		cookiep = cookiebuf;
1003		dps = (struct dirent *)((char *)uio->uio_iov->iov_base -
1004		    (uio->uio_offset - oldoff));
1005		dpe = (struct dirent *) uio->uio_iov->iov_base;
1006		for( dp = dps;
1007			dp < dpe;
1008			dp = (struct dirent *)((caddr_t) dp + dp->d_reclen)) {
1009				oldoff += dp->d_reclen;
1010				*cookiep++ = (u_long) oldoff;
1011		}
1012		*ap->a_ncookies = ncookies;
1013		*ap->a_cookies = cookiebuf;
1014	}
1015	lockmgr(&dmp->dm_lock, LK_RELEASE, 0, curthread);
1016	uio->uio_offset = off;
1017	return (error);
1018}
1019
1020static int
1021devfs_readlink(ap)
1022	struct vop_readlink_args /* {
1023		struct vnode *a_vp;
1024		struct uio *a_uio;
1025		struct ucred *a_cead;
1026	} */ *ap;
1027{
1028	int error;
1029	struct devfs_dirent *de;
1030
1031	de = ap->a_vp->v_data;
1032	error = uiomove(de->de_symlink, strlen(de->de_symlink), ap->a_uio);
1033	return (error);
1034}
1035
1036static int
1037devfs_reclaim(ap)
1038	struct vop_reclaim_args /* {
1039		struct vnode *a_vp;
1040	} */ *ap;
1041{
1042	struct vnode *vp = ap->a_vp;
1043	struct devfs_dirent *de;
1044	int i;
1045
1046	de = vp->v_data;
1047	if (de != NULL)
1048		de->de_vnode = NULL;
1049	vp->v_data = NULL;
1050	if (vp->v_rdev != NULL) {
1051		i = vcount(vp);
1052		if ((vp->v_rdev->si_flags & SI_CHEAPCLONE) && i == 0 &&
1053		    (vp->v_rdev->si_flags & SI_NAMED))
1054			destroy_dev(vp->v_rdev);
1055	}
1056	return (0);
1057}
1058
1059static int
1060devfs_remove(ap)
1061	struct vop_remove_args /* {
1062		struct vnode *a_dvp;
1063		struct vnode *a_vp;
1064		struct componentname *a_cnp;
1065	} */ *ap;
1066{
1067	struct vnode *vp = ap->a_vp;
1068	struct devfs_dirent *dd;
1069	struct devfs_dirent *de;
1070	struct devfs_mount *dmp = VFSTODEVFS(vp->v_mount);
1071
1072	lockmgr(&dmp->dm_lock, LK_EXCLUSIVE, 0, curthread);
1073	dd = ap->a_dvp->v_data;
1074	de = vp->v_data;
1075	if (de->de_dirent->d_type == DT_LNK) {
1076		TAILQ_REMOVE(&dd->de_dlist, de, de_list);
1077		if (de->de_vnode)
1078			de->de_vnode->v_data = NULL;
1079#ifdef MAC
1080		mac_destroy_devfsdirent(de);
1081#endif
1082		FREE(de, M_DEVFS);
1083	} else {
1084		de->de_flags |= DE_WHITEOUT;
1085	}
1086	lockmgr(&dmp->dm_lock, LK_RELEASE, 0, curthread);
1087	return (0);
1088}
1089
1090/*
1091 * Revoke is called on a tty when a terminal session ends.  The vnode
1092 * is orphaned by setting v_op to deadfs so we need to let go of it
1093 * as well so that we create a new one next time around.
1094 */
1095static int
1096devfs_revoke(ap)
1097	struct vop_revoke_args /* {
1098		struct vnode *a_vp;
1099		int a_flags;
1100	} */ *ap;
1101{
1102	struct vnode *vp = ap->a_vp;
1103	struct vnode *vq;
1104	struct devfs_dirent *de;
1105	struct cdev *dev;
1106
1107	KASSERT((ap->a_flags & REVOKEALL) != 0, ("devfs_revoke !REVOKEALL"));
1108	de = vp->v_data;
1109	de->de_vnode = NULL;
1110
1111	VI_LOCK(vp);
1112	/*
1113	 * If a vgone (or vclean) is already in progress,
1114	 * wait until it is done and return.
1115	 */
1116	if (vp->v_iflag & VI_XLOCK) {
1117		vp->v_iflag |= VI_XWANT;
1118		msleep(vp, VI_MTX(vp), PINOD | PDROP, "vop_revokeall", 0);
1119		return (0);
1120	}
1121	VI_UNLOCK(vp);
1122	dev = vp->v_rdev;
1123	for (;;) {
1124		dev_lock();
1125		vq = SLIST_FIRST(&dev->si_hlist);
1126		dev_unlock();
1127		if (vq == NULL)
1128			break;
1129		vgone(vq);
1130	}
1131	return (0);
1132}
1133
1134static int
1135devfs_rioctl(ap)
1136	struct vop_ioctl_args /* {
1137		struct vnode *a_vp;
1138		u_long  a_command;
1139		caddr_t  a_data;
1140		int  a_fflag;
1141		struct ucred *a_cred;
1142		struct thread *a_td;
1143	} */ *ap;
1144{
1145	int error;
1146	struct devfs_mount *dmp;
1147
1148	dmp = VFSTODEVFS(ap->a_vp->v_mount);
1149	lockmgr(&dmp->dm_lock, LK_SHARED, 0, curthread);
1150	devfs_populate(dmp);
1151	lockmgr(&dmp->dm_lock, LK_RELEASE, 0, curthread);
1152	error = devfs_rules_ioctl(ap->a_vp->v_mount, ap->a_command, ap->a_data,
1153	    ap->a_td);
1154	return (error);
1155}
1156
1157static int
1158devfs_rread(ap)
1159	struct vop_read_args /* {
1160		struct vnode *a_vp;
1161		struct uio *a_uio;
1162		int a_ioflag;
1163		struct ucred *a_cred;
1164	} */ *ap;
1165{
1166
1167	if (ap->a_vp->v_type != VDIR)
1168		return (EINVAL);
1169	return (VOP_READDIR(ap->a_vp, ap->a_uio, ap->a_cred, NULL, NULL, NULL));
1170}
1171
1172static int
1173devfs_setattr(ap)
1174	struct vop_setattr_args /* {
1175		struct vnode *a_vp;
1176		struct vattr *a_vap;
1177		struct ucred *a_cred;
1178		struct proc *a_p;
1179	} */ *ap;
1180{
1181	struct devfs_dirent *de;
1182	struct vattr *vap;
1183	struct vnode *vp;
1184	int c, error;
1185	uid_t uid;
1186	gid_t gid;
1187
1188	vap = ap->a_vap;
1189	vp = ap->a_vp;
1190	if ((vap->va_type != VNON) ||
1191	    (vap->va_nlink != VNOVAL) ||
1192	    (vap->va_fsid != VNOVAL) ||
1193	    (vap->va_fileid != VNOVAL) ||
1194	    (vap->va_blocksize != VNOVAL) ||
1195	    (vap->va_flags != VNOVAL && vap->va_flags != 0) ||
1196	    (vap->va_rdev != VNOVAL) ||
1197	    ((int)vap->va_bytes != VNOVAL) ||
1198	    (vap->va_gen != VNOVAL)) {
1199		return (EINVAL);
1200	}
1201
1202	de = vp->v_data;
1203	if (vp->v_type == VDIR)
1204		de = de->de_dir;
1205
1206	error = c = 0;
1207	if (vap->va_uid == (uid_t)VNOVAL)
1208		uid = de->de_uid;
1209	else
1210		uid = vap->va_uid;
1211	if (vap->va_gid == (gid_t)VNOVAL)
1212		gid = de->de_gid;
1213	else
1214		gid = vap->va_gid;
1215	if (uid != de->de_uid || gid != de->de_gid) {
1216		if (((ap->a_cred->cr_uid != de->de_uid) || uid != de->de_uid ||
1217		    (gid != de->de_gid && !groupmember(gid, ap->a_cred))) &&
1218		    (error = suser_cred(ap->a_td->td_ucred, SUSER_ALLOWJAIL)) != 0)
1219			return (error);
1220		de->de_uid = uid;
1221		de->de_gid = gid;
1222		c = 1;
1223	}
1224
1225	if (vap->va_mode != (mode_t)VNOVAL) {
1226		if ((ap->a_cred->cr_uid != de->de_uid) &&
1227		    (error = suser_cred(ap->a_td->td_ucred, SUSER_ALLOWJAIL)))
1228			return (error);
1229		de->de_mode = vap->va_mode;
1230		c = 1;
1231	}
1232
1233	if (vap->va_atime.tv_sec != VNOVAL || vap->va_mtime.tv_sec != VNOVAL) {
1234		/* See the comment in ufs_vnops::ufs_setattr(). */
1235		if ((error = VOP_ACCESS(vp, VADMIN, ap->a_cred, ap->a_td)) &&
1236		    ((vap->va_vaflags & VA_UTIMES_NULL) == 0 ||
1237		    (error = VOP_ACCESS(vp, VWRITE, ap->a_cred, ap->a_td))))
1238			return (error);
1239		if (vap->va_atime.tv_sec != VNOVAL) {
1240			if (vp->v_type == VCHR)
1241				vp->v_rdev->si_atime = vap->va_atime;
1242			else
1243				de->de_atime = vap->va_atime;
1244		}
1245		if (vap->va_mtime.tv_sec != VNOVAL) {
1246			if (vp->v_type == VCHR)
1247				vp->v_rdev->si_mtime = vap->va_mtime;
1248			else
1249				de->de_mtime = vap->va_mtime;
1250		}
1251		c = 1;
1252	}
1253
1254	if (c) {
1255		if (vp->v_type == VCHR)
1256			vfs_timestamp(&vp->v_rdev->si_ctime);
1257		else
1258			vfs_timestamp(&de->de_mtime);
1259	}
1260	return (0);
1261}
1262
1263#ifdef MAC
1264static int
1265devfs_setlabel(ap)
1266	struct vop_setlabel_args /* {
1267		struct vnode *a_vp;
1268		struct mac *a_label;
1269		struct ucred *a_cred;
1270		struct thread *a_td;
1271	} */ *ap;
1272{
1273	struct vnode *vp;
1274	struct devfs_dirent *de;
1275
1276	vp = ap->a_vp;
1277	de = vp->v_data;
1278
1279	mac_relabel_vnode(ap->a_cred, vp, ap->a_label);
1280	mac_update_devfsdirent(vp->v_mount, de, vp);
1281
1282	return (0);
1283}
1284#endif
1285
1286static int
1287devfs_stat_f(struct file *fp, struct stat *sb, struct ucred *cred, struct thread *td)
1288{
1289
1290	return (vnops.fo_stat(fp, sb, cred, td));
1291}
1292
1293static int
1294devfs_symlink(ap)
1295	struct vop_symlink_args /* {
1296		struct vnode *a_dvp;
1297		struct vnode **a_vpp;
1298		struct componentname *a_cnp;
1299		struct vattr *a_vap;
1300		char *a_target;
1301	} */ *ap;
1302{
1303	int i, error;
1304	struct devfs_dirent *dd;
1305	struct devfs_dirent *de;
1306	struct devfs_mount *dmp;
1307	struct thread *td;
1308
1309	td = ap->a_cnp->cn_thread;
1310	KASSERT(td == curthread, ("devfs_symlink: td != curthread"));
1311	error = suser(td);
1312	if (error)
1313		return(error);
1314	dmp = VFSTODEVFS(ap->a_dvp->v_mount);
1315	dd = ap->a_dvp->v_data;
1316	de = devfs_newdirent(ap->a_cnp->cn_nameptr, ap->a_cnp->cn_namelen);
1317	de->de_uid = 0;
1318	de->de_gid = 0;
1319	de->de_mode = 0755;
1320	de->de_inode = dmp->dm_inode++;
1321	de->de_dirent->d_type = DT_LNK;
1322	i = strlen(ap->a_target) + 1;
1323	MALLOC(de->de_symlink, char *, i, M_DEVFS, M_WAITOK);
1324	bcopy(ap->a_target, de->de_symlink, i);
1325	lockmgr(&dmp->dm_lock, LK_EXCLUSIVE, 0, td);
1326#ifdef MAC
1327	mac_create_devfs_symlink(ap->a_cnp->cn_cred, dmp->dm_mount, dd, de);
1328#endif
1329	TAILQ_INSERT_TAIL(&dd->de_dlist, de, de_list);
1330	devfs_allocv(de, ap->a_dvp->v_mount, ap->a_vpp, td);
1331	lockmgr(&dmp->dm_lock, LK_RELEASE, 0, td);
1332	return (0);
1333}
1334
1335/*
1336 * Vnode op for write
1337 */
1338/* ARGSUSED */
1339static int
1340devfs_write_f(struct file *fp, struct uio *uio, struct ucred *cred, int flags, struct thread *td)
1341{
1342	struct cdev *dev;
1343	struct vnode *vp;
1344	int error, ioflag, resid;
1345	struct cdevsw *dsw;
1346
1347	error = devfs_fp_check(fp, &dev, &dsw);
1348	if (error)
1349		return (error);
1350	KASSERT(uio->uio_td == td, ("uio_td %p is not td %p", uio->uio_td, td));
1351	vp = fp->f_vnode;
1352	ioflag = fp->f_flag & (O_NONBLOCK | O_DIRECT | O_FSYNC);
1353	if (ioflag & O_DIRECT)
1354		ioflag |= IO_DIRECT;
1355	if ((flags & FOF_OFFSET) == 0)
1356		uio->uio_offset = fp->f_offset;
1357
1358	resid = uio->uio_resid;
1359
1360	if (dsw->d_flags & D_NEEDGIANT)
1361		mtx_lock(&Giant);
1362	error = dsw->d_write(dev, uio, ioflag);
1363	if (dsw->d_flags & D_NEEDGIANT)
1364		mtx_unlock(&Giant);
1365	dev_relthread(dev);
1366	if (uio->uio_resid != resid || (error == 0 && resid != 0)) {
1367		vfs_timestamp(&dev->si_ctime);
1368		dev->si_mtime = dev->si_ctime;
1369	}
1370
1371	if ((flags & FOF_OFFSET) == 0)
1372		fp->f_offset = uio->uio_offset;
1373	fp->f_nextoff = uio->uio_offset;
1374	return (error);
1375}
1376
1377static struct vop_vector devfs_vnodeops = {
1378	.vop_default =		&default_vnodeops,
1379
1380	.vop_access =		devfs_access,
1381	.vop_getattr =		devfs_getattr,
1382	.vop_ioctl =		devfs_rioctl,
1383	.vop_lookup =		devfs_lookup,
1384	.vop_mknod =		devfs_mknod,
1385	.vop_pathconf =		devfs_pathconf,
1386	.vop_read =		devfs_rread,
1387	.vop_readdir =		devfs_readdir,
1388	.vop_readlink =		devfs_readlink,
1389	.vop_reclaim =		devfs_reclaim,
1390	.vop_remove =		devfs_remove,
1391	.vop_revoke =		devfs_revoke,
1392	.vop_setattr =		devfs_setattr,
1393#ifdef MAC
1394	.vop_setlabel =		devfs_setlabel,
1395#endif
1396	.vop_symlink =		devfs_symlink,
1397};
1398
1399static struct vop_vector devfs_specops = {
1400	.vop_default =		&default_vnodeops,
1401
1402	.vop_access =		devfs_access,
1403	.vop_advlock =		devfs_advlock,
1404	.vop_bmap =		VOP_PANIC,
1405	.vop_close =		devfs_close,
1406	.vop_create =		VOP_PANIC,
1407	.vop_fsync =		devfs_fsync,
1408	.vop_getattr =		devfs_getattr,
1409	.vop_lease =		VOP_NULL,
1410	.vop_link =		VOP_PANIC,
1411	.vop_mkdir =		VOP_PANIC,
1412	.vop_mknod =		VOP_PANIC,
1413	.vop_open =		devfs_open,
1414	.vop_pathconf =		devfs_pathconf,
1415	.vop_print =		devfs_print,
1416	.vop_read =		VOP_PANIC,
1417	.vop_readdir =		VOP_PANIC,
1418	.vop_readlink =		VOP_PANIC,
1419	.vop_reallocblks =	VOP_PANIC,
1420	.vop_reclaim =		devfs_reclaim,
1421	.vop_remove =		devfs_remove,
1422	.vop_rename =		VOP_PANIC,
1423	.vop_revoke =		devfs_revoke,
1424	.vop_rmdir =		VOP_PANIC,
1425	.vop_setattr =		devfs_setattr,
1426#ifdef MAC
1427	.vop_setlabel =		devfs_setlabel,
1428#endif
1429	.vop_strategy =		VOP_PANIC,
1430	.vop_symlink =		VOP_PANIC,
1431	.vop_write =		VOP_PANIC,
1432};
1433
1434/*
1435 * Our calling convention to the device drivers used to be that we passed
1436 * vnode.h IO_* flags to read()/write(), but we're moving to fcntl.h O_
1437 * flags instead since that's what open(), close() and ioctl() takes and
1438 * we don't really want vnode.h in device drivers.
1439 * We solved the source compatibility by redefining some vnode flags to
1440 * be the same as the fcntl ones and by sending down the bitwise OR of
1441 * the respective fcntl/vnode flags.  These CTASSERTS make sure nobody
1442 * pulls the rug out under this.
1443 */
1444CTASSERT(O_NONBLOCK == IO_NDELAY);
1445CTASSERT(O_FSYNC == IO_SYNC);
1446