xref: /csrg-svn/sys/miscfs/specfs/spec_vnops.c (revision 53597)
137486Smckusick /*
237486Smckusick  * Copyright (c) 1989 The Regents of the University of California.
337486Smckusick  * All rights reserved.
437486Smckusick  *
544443Sbostic  * %sccs.include.redist.c%
637486Smckusick  *
7*53597Sheideman  *	@(#)spec_vnops.c	7.44 (Berkeley) 05/15/92
837486Smckusick  */
937486Smckusick 
1051457Sbostic #include <sys/param.h>
1151457Sbostic #include <sys/proc.h>
1251457Sbostic #include <sys/systm.h>
1351457Sbostic #include <sys/kernel.h>
1451457Sbostic #include <sys/conf.h>
1551457Sbostic #include <sys/buf.h>
1651457Sbostic #include <sys/mount.h>
1751457Sbostic #include <sys/namei.h>
1851457Sbostic #include <sys/vnode.h>
1951457Sbostic #include <sys/specdev.h>
2051457Sbostic #include <sys/stat.h>
2151457Sbostic #include <sys/errno.h>
2251457Sbostic #include <sys/ioctl.h>
2351457Sbostic #include <sys/file.h>
2451457Sbostic #include <sys/disklabel.h>
2537486Smckusick 
2640707Skarels /* symbolic sleep message strings for devices */
2740707Skarels char	devopn[] = "devopn";
2840707Skarels char	devio[] = "devio";
2940707Skarels char	devwait[] = "devwait";
3040707Skarels char	devin[] = "devin";
3140707Skarels char	devout[] = "devout";
3240707Skarels char	devioc[] = "devioc";
3340707Skarels char	devcls[] = "devcls";
3440707Skarels 
3553542Sheideman int (**spec_vnodeop_p)();
3653542Sheideman struct vnodeopv_entry_desc spec_vnodeop_entries[] = {
3753542Sheideman 	{ &vop_default_desc, vn_default_error },
3853542Sheideman 	{ &vop_lookup_desc, spec_lookup },		/* lookup */
3953542Sheideman 	{ &vop_create_desc, spec_create },		/* create */
4053542Sheideman 	{ &vop_mknod_desc, spec_mknod },		/* mknod */
4153542Sheideman 	{ &vop_open_desc, spec_open },		/* open */
4253542Sheideman 	{ &vop_close_desc, spec_close },		/* close */
4353542Sheideman 	{ &vop_access_desc, spec_access },		/* access */
4453542Sheideman 	{ &vop_getattr_desc, spec_getattr },		/* getattr */
4553542Sheideman 	{ &vop_setattr_desc, spec_setattr },		/* setattr */
4653542Sheideman 	{ &vop_read_desc, spec_read },		/* read */
4753542Sheideman 	{ &vop_write_desc, spec_write },		/* write */
4853542Sheideman 	{ &vop_ioctl_desc, spec_ioctl },		/* ioctl */
4953542Sheideman 	{ &vop_select_desc, spec_select },		/* select */
5053542Sheideman 	{ &vop_mmap_desc, spec_mmap },		/* mmap */
5153542Sheideman 	{ &vop_fsync_desc, spec_fsync },		/* fsync */
5253542Sheideman 	{ &vop_seek_desc, spec_seek },		/* seek */
5353542Sheideman 	{ &vop_remove_desc, spec_remove },		/* remove */
5453542Sheideman 	{ &vop_link_desc, spec_link },		/* link */
5553542Sheideman 	{ &vop_rename_desc, spec_rename },		/* rename */
5653542Sheideman 	{ &vop_mkdir_desc, spec_mkdir },		/* mkdir */
5753542Sheideman 	{ &vop_rmdir_desc, spec_rmdir },		/* rmdir */
5853542Sheideman 	{ &vop_symlink_desc, spec_symlink },		/* symlink */
5953542Sheideman 	{ &vop_readdir_desc, spec_readdir },		/* readdir */
6053542Sheideman 	{ &vop_readlink_desc, spec_readlink },		/* readlink */
6153542Sheideman 	{ &vop_abortop_desc, spec_abortop },		/* abortop */
6253542Sheideman 	{ &vop_inactive_desc, spec_inactive },		/* inactive */
6353542Sheideman 	{ &vop_reclaim_desc, spec_reclaim },		/* reclaim */
6453542Sheideman 	{ &vop_lock_desc, spec_lock },		/* lock */
6553542Sheideman 	{ &vop_unlock_desc, spec_unlock },		/* unlock */
6653542Sheideman 	{ &vop_bmap_desc, spec_bmap },		/* bmap */
6753542Sheideman 	{ &vop_strategy_desc, spec_strategy },		/* strategy */
6853542Sheideman 	{ &vop_print_desc, spec_print },		/* print */
6953542Sheideman 	{ &vop_islocked_desc, spec_islocked },		/* islocked */
7053542Sheideman 	{ &vop_advlock_desc, spec_advlock },		/* advlock */
7153542Sheideman 	{ &vop_blkatoff_desc, spec_blkatoff },		/* blkatoff */
7253542Sheideman 	{ &vop_vget_desc, spec_vget },		/* vget */
7353542Sheideman 	{ &vop_valloc_desc, spec_valloc },		/* valloc */
7453542Sheideman 	{ &vop_vfree_desc, spec_vfree },		/* vfree */
7553542Sheideman 	{ &vop_truncate_desc, spec_truncate },		/* truncate */
7653542Sheideman 	{ &vop_update_desc, spec_update },		/* update */
7753542Sheideman 	{ &vop_bwrite_desc, spec_bwrite },		/* bwrite */
7853542Sheideman 	{ (struct vnodeop_desc*)NULL, (int(*)())NULL }
7937486Smckusick };
8053542Sheideman struct vnodeopv_desc spec_vnodeop_opv_desc =
8153542Sheideman 	{ &spec_vnodeop_p, spec_vnodeop_entries };
8237486Smckusick 
8337486Smckusick /*
8439292Smckusick  * Trivial lookup routine that always fails.
8539292Smckusick  */
8652320Sheideman int
8753542Sheideman spec_lookup (ap)
8853542Sheideman 	struct vop_lookup_args *ap;
8939292Smckusick {
9039292Smckusick 
91*53597Sheideman 	*ap->a_vpp = NULL;
9239292Smckusick 	return (ENOTDIR);
9339292Smckusick }
9439292Smckusick 
9539292Smckusick /*
9649273Skarels  * Open a special file: Don't allow open if fs is mounted -nodev,
9749273Skarels  * and don't allow opens of block devices that are currently mounted.
9849273Skarels  * Otherwise, call device driver open function.
9937486Smckusick  */
10037725Smckusick /* ARGSUSED */
10153542Sheideman spec_open (ap)
10253542Sheideman 	struct vop_open_args *ap;
10337486Smckusick {
10453542Sheideman 	USES_VOP_LOCK;
10553542Sheideman 	USES_VOP_UNLOCK;
106*53597Sheideman 	dev_t dev = (dev_t)ap->a_vp->v_rdev;
10737486Smckusick 	register int maj = major(dev);
10840375Smckusick 	int error;
10937486Smckusick 
110*53597Sheideman 	if (ap->a_vp->v_mount && (ap->a_vp->v_mount->mnt_flag & MNT_NODEV))
11139365Smckusick 		return (ENXIO);
11239365Smckusick 
113*53597Sheideman 	switch (ap->a_vp->v_type) {
11437486Smckusick 
11537486Smckusick 	case VCHR:
11637486Smckusick 		if ((u_int)maj >= nchrdev)
11737486Smckusick 			return (ENXIO);
118*53597Sheideman 		VOP_UNLOCK(ap->a_vp);
119*53597Sheideman 		error = (*cdevsw[maj].d_open)(dev, ap->a_mode, S_IFCHR, ap->a_p);
120*53597Sheideman 		VOP_LOCK(ap->a_vp);
12149944Smckusick 		return (error);
12237486Smckusick 
12337486Smckusick 	case VBLK:
12437486Smckusick 		if ((u_int)maj >= nblkdev)
12537486Smckusick 			return (ENXIO);
126*53597Sheideman 		if (error = ufs_mountedon(ap->a_vp))
12740375Smckusick 			return (error);
128*53597Sheideman 		return ((*bdevsw[maj].d_open)(dev, ap->a_mode, S_IFBLK, ap->a_p));
12937486Smckusick 	}
13037486Smckusick 	return (0);
13137486Smckusick }
13237486Smckusick 
13337486Smckusick /*
13437486Smckusick  * Vnode op for read
13537486Smckusick  */
13641961Smckusick /* ARGSUSED */
13753542Sheideman spec_read (ap)
13853542Sheideman 	struct vop_read_args *ap;
13937486Smckusick {
14053542Sheideman 	USES_VOP_LOCK;
14153542Sheideman 	USES_VOP_UNLOCK;
142*53597Sheideman 	struct proc *p = ap->a_uio->uio_procp;
14339614Smckusick 	struct buf *bp;
14452321Smckusick 	daddr_t bn, nextbn;
14539614Smckusick 	long bsize, bscale;
14639614Smckusick 	struct partinfo dpart;
14739614Smckusick 	register int n, on;
14839614Smckusick 	int error = 0;
14937486Smckusick 
15048015Smckusick #ifdef DIAGNOSTIC
151*53597Sheideman 	if (ap->a_uio->uio_rw != UIO_READ)
15239588Smckusick 		panic("spec_read mode");
153*53597Sheideman 	if (ap->a_uio->uio_segflg == UIO_USERSPACE && ap->a_uio->uio_procp != curproc)
15448015Smckusick 		panic("spec_read proc");
15548015Smckusick #endif
156*53597Sheideman 	if (ap->a_uio->uio_resid == 0)
15739588Smckusick 		return (0);
15839588Smckusick 
159*53597Sheideman 	switch (ap->a_vp->v_type) {
16039588Smckusick 
16139588Smckusick 	case VCHR:
162*53597Sheideman 		VOP_UNLOCK(ap->a_vp);
163*53597Sheideman 		error = (*cdevsw[major(ap->a_vp->v_rdev)].d_read)
164*53597Sheideman 			(ap->a_vp->v_rdev, ap->a_uio, ap->a_ioflag);
165*53597Sheideman 		VOP_LOCK(ap->a_vp);
16639588Smckusick 		return (error);
16739588Smckusick 
16839588Smckusick 	case VBLK:
169*53597Sheideman 		if (ap->a_uio->uio_offset < 0)
17039588Smckusick 			return (EINVAL);
17139614Smckusick 		bsize = BLKDEV_IOSIZE;
172*53597Sheideman 		if ((*bdevsw[major(ap->a_vp->v_rdev)].d_ioctl)(ap->a_vp->v_rdev, DIOCGPART,
17347540Skarels 		    (caddr_t)&dpart, FREAD, p) == 0) {
17439614Smckusick 			if (dpart.part->p_fstype == FS_BSDFFS &&
17539614Smckusick 			    dpart.part->p_frag != 0 && dpart.part->p_fsize != 0)
17639614Smckusick 				bsize = dpart.part->p_frag *
17739614Smckusick 				    dpart.part->p_fsize;
17839614Smckusick 		}
17939614Smckusick 		bscale = bsize / DEV_BSIZE;
18039614Smckusick 		do {
181*53597Sheideman 			bn = (ap->a_uio->uio_offset / DEV_BSIZE) &~ (bscale - 1);
182*53597Sheideman 			on = ap->a_uio->uio_offset % bsize;
183*53597Sheideman 			n = MIN((unsigned)(bsize - on), ap->a_uio->uio_resid);
184*53597Sheideman 			if (ap->a_vp->v_lastr + bscale == bn) {
18552321Smckusick 				nextbn = bn + bscale;
186*53597Sheideman 				error = breadn(ap->a_vp, bn, (int)bsize, &nextbn,
18752321Smckusick 					(int *)&bsize, 1, NOCRED, &bp);
18852321Smckusick 			} else
189*53597Sheideman 				error = bread(ap->a_vp, bn, (int)bsize, NOCRED, &bp);
190*53597Sheideman 			ap->a_vp->v_lastr = bn;
19139614Smckusick 			n = MIN(n, bsize - bp->b_resid);
19239614Smckusick 			if (error) {
19339614Smckusick 				brelse(bp);
19439614Smckusick 				return (error);
19539614Smckusick 			}
196*53597Sheideman 			error = uiomove(bp->b_un.b_addr + on, n, ap->a_uio);
19739614Smckusick 			if (n + on == bsize)
19839614Smckusick 				bp->b_flags |= B_AGE;
19939614Smckusick 			brelse(bp);
200*53597Sheideman 		} while (error == 0 && ap->a_uio->uio_resid > 0 && n != 0);
20139614Smckusick 		return (error);
20239588Smckusick 
20339588Smckusick 	default:
20439588Smckusick 		panic("spec_read type");
20539588Smckusick 	}
20639588Smckusick 	/* NOTREACHED */
20737486Smckusick }
20837486Smckusick 
20937486Smckusick /*
21037486Smckusick  * Vnode op for write
21137486Smckusick  */
21241961Smckusick /* ARGSUSED */
21353542Sheideman spec_write (ap)
21453542Sheideman 	struct vop_write_args *ap;
21537486Smckusick {
21653542Sheideman 	USES_VOP_LOCK;
21753542Sheideman 	USES_VOP_UNLOCK;
218*53597Sheideman 	struct proc *p = ap->a_uio->uio_procp;
21939614Smckusick 	struct buf *bp;
22039614Smckusick 	daddr_t bn;
22139614Smckusick 	int bsize, blkmask;
22239614Smckusick 	struct partinfo dpart;
22345731Smckusick 	register int n, on;
22445731Smckusick 	int error = 0;
22537486Smckusick 
22648015Smckusick #ifdef DIAGNOSTIC
227*53597Sheideman 	if (ap->a_uio->uio_rw != UIO_WRITE)
22839588Smckusick 		panic("spec_write mode");
229*53597Sheideman 	if (ap->a_uio->uio_segflg == UIO_USERSPACE && ap->a_uio->uio_procp != curproc)
23048015Smckusick 		panic("spec_write proc");
23148015Smckusick #endif
23239588Smckusick 
233*53597Sheideman 	switch (ap->a_vp->v_type) {
23439588Smckusick 
23539588Smckusick 	case VCHR:
236*53597Sheideman 		VOP_UNLOCK(ap->a_vp);
237*53597Sheideman 		error = (*cdevsw[major(ap->a_vp->v_rdev)].d_write)
238*53597Sheideman 			(ap->a_vp->v_rdev, ap->a_uio, ap->a_ioflag);
239*53597Sheideman 		VOP_LOCK(ap->a_vp);
24039588Smckusick 		return (error);
24139588Smckusick 
24239588Smckusick 	case VBLK:
243*53597Sheideman 		if (ap->a_uio->uio_resid == 0)
24439588Smckusick 			return (0);
245*53597Sheideman 		if (ap->a_uio->uio_offset < 0)
24639588Smckusick 			return (EINVAL);
24739614Smckusick 		bsize = BLKDEV_IOSIZE;
248*53597Sheideman 		if ((*bdevsw[major(ap->a_vp->v_rdev)].d_ioctl)(ap->a_vp->v_rdev, DIOCGPART,
24947540Skarels 		    (caddr_t)&dpart, FREAD, p) == 0) {
25039614Smckusick 			if (dpart.part->p_fstype == FS_BSDFFS &&
25139614Smckusick 			    dpart.part->p_frag != 0 && dpart.part->p_fsize != 0)
25239614Smckusick 				bsize = dpart.part->p_frag *
25339614Smckusick 				    dpart.part->p_fsize;
25439614Smckusick 		}
25539614Smckusick 		blkmask = (bsize / DEV_BSIZE) - 1;
25639614Smckusick 		do {
257*53597Sheideman 			bn = (ap->a_uio->uio_offset / DEV_BSIZE) &~ blkmask;
258*53597Sheideman 			on = ap->a_uio->uio_offset % bsize;
259*53597Sheideman 			n = MIN((unsigned)(bsize - on), ap->a_uio->uio_resid);
26039614Smckusick 			if (n == bsize)
261*53597Sheideman 				bp = getblk(ap->a_vp, bn, bsize);
26239614Smckusick 			else
263*53597Sheideman 				error = bread(ap->a_vp, bn, bsize, NOCRED, &bp);
26439614Smckusick 			n = MIN(n, bsize - bp->b_resid);
26539614Smckusick 			if (error) {
26639614Smckusick 				brelse(bp);
26739614Smckusick 				return (error);
26839614Smckusick 			}
269*53597Sheideman 			error = uiomove(bp->b_un.b_addr + on, n, ap->a_uio);
27039614Smckusick 			if (n + on == bsize) {
27139614Smckusick 				bp->b_flags |= B_AGE;
27239614Smckusick 				bawrite(bp);
27339614Smckusick 			} else
27439614Smckusick 				bdwrite(bp);
275*53597Sheideman 		} while (error == 0 && ap->a_uio->uio_resid > 0 && n != 0);
27639614Smckusick 		return (error);
27739588Smckusick 
27839588Smckusick 	default:
27939588Smckusick 		panic("spec_write type");
28039588Smckusick 	}
28139588Smckusick 	/* NOTREACHED */
28237486Smckusick }
28337486Smckusick 
28437486Smckusick /*
28537486Smckusick  * Device ioctl operation.
28637486Smckusick  */
28737725Smckusick /* ARGSUSED */
28853542Sheideman spec_ioctl (ap)
28953542Sheideman 	struct vop_ioctl_args *ap;
29037486Smckusick {
291*53597Sheideman 	dev_t dev = ap->a_vp->v_rdev;
29237486Smckusick 
293*53597Sheideman 	switch (ap->a_vp->v_type) {
29437486Smckusick 
29537486Smckusick 	case VCHR:
296*53597Sheideman 		return ((*cdevsw[major(dev)].d_ioctl)(dev, ap->a_command, ap->a_data,
297*53597Sheideman 		    ap->a_fflag, ap->a_p));
29837486Smckusick 
29937486Smckusick 	case VBLK:
300*53597Sheideman 		if (ap->a_command == 0 && (int)ap->a_data == B_TAPE)
30139666Smckusick 			if (bdevsw[major(dev)].d_flags & B_TAPE)
30239666Smckusick 				return (0);
30339666Smckusick 			else
30439666Smckusick 				return (1);
305*53597Sheideman 		return ((*bdevsw[major(dev)].d_ioctl)(dev, ap->a_command, ap->a_data,
306*53597Sheideman 		   ap->a_fflag, ap->a_p));
30737486Smckusick 
30837486Smckusick 	default:
30939446Smckusick 		panic("spec_ioctl");
31037486Smckusick 		/* NOTREACHED */
31137486Smckusick 	}
31237486Smckusick }
31337486Smckusick 
31437725Smckusick /* ARGSUSED */
31553542Sheideman spec_select (ap)
31653542Sheideman 	struct vop_select_args *ap;
31737486Smckusick {
31837486Smckusick 	register dev_t dev;
31937486Smckusick 
320*53597Sheideman 	switch (ap->a_vp->v_type) {
32137486Smckusick 
32237486Smckusick 	default:
32337486Smckusick 		return (1);		/* XXX */
32437486Smckusick 
32537486Smckusick 	case VCHR:
326*53597Sheideman 		dev = ap->a_vp->v_rdev;
327*53597Sheideman 		return (*cdevsw[major(dev)].d_select)(dev, ap->a_which, ap->a_p);
32837486Smckusick 	}
32937486Smckusick }
33037486Smckusick 
33137486Smckusick /*
33237486Smckusick  * Just call the device strategy routine
33337486Smckusick  */
33453542Sheideman spec_strategy (ap)
33553542Sheideman 	struct vop_strategy_args *ap;
33637486Smckusick {
33739666Smckusick 
338*53597Sheideman 	(*bdevsw[major(ap->a_bp->b_dev)].d_strategy)(ap->a_bp);
33937486Smckusick 	return (0);
34037486Smckusick }
34137486Smckusick 
34239432Smckusick /*
34339666Smckusick  * This is a noop, simply returning what one has been given.
34439666Smckusick  */
34553542Sheideman spec_bmap (ap)
34653542Sheideman 	struct vop_bmap_args *ap;
34739666Smckusick {
34839666Smckusick 
349*53597Sheideman 	if (ap->a_vpp != NULL)
350*53597Sheideman 		*ap->a_vpp = ap->a_vp;
351*53597Sheideman 	if (ap->a_bnp != NULL)
352*53597Sheideman 		*ap->a_bnp = ap->a_bn;
35339666Smckusick 	return (0);
35439666Smckusick }
35539666Smckusick 
35639666Smckusick /*
35739432Smckusick  * At the moment we do not do any locking.
35839432Smckusick  */
35939489Smckusick /* ARGSUSED */
36053542Sheideman spec_lock (ap)
36153542Sheideman 	struct vop_lock_args *ap;
36237486Smckusick {
36337486Smckusick 
36437486Smckusick 	return (0);
36537486Smckusick }
36637486Smckusick 
36739489Smckusick /* ARGSUSED */
36853542Sheideman spec_unlock (ap)
36953542Sheideman 	struct vop_unlock_args *ap;
37037486Smckusick {
37137486Smckusick 
37237486Smckusick 	return (0);
37337486Smckusick }
37437486Smckusick 
37537486Smckusick /*
37637486Smckusick  * Device close routine
37737486Smckusick  */
37837725Smckusick /* ARGSUSED */
37953542Sheideman spec_close (ap)
38053542Sheideman 	struct vop_close_args *ap;
38137486Smckusick {
382*53597Sheideman 	dev_t dev = ap->a_vp->v_rdev;
38349273Skarels 	int (*devclose) __P((dev_t, int, int, struct proc *));
38440707Skarels 	int mode;
38537486Smckusick 
386*53597Sheideman 	switch (ap->a_vp->v_type) {
38737725Smckusick 
38837725Smckusick 	case VCHR:
38939485Smckusick 		/*
39039485Smckusick 		 * If the vnode is locked, then we are in the midst
39139485Smckusick 		 * of forcably closing the device, otherwise we only
39239485Smckusick 		 * close on last reference.
39339485Smckusick 		 */
394*53597Sheideman 		if (vcount(ap->a_vp) > 1 && (ap->a_vp->v_flag & VXLOCK) == 0)
39537725Smckusick 			return (0);
39649273Skarels 		devclose = cdevsw[major(dev)].d_close;
39739432Smckusick 		mode = S_IFCHR;
39837725Smckusick 		break;
39937725Smckusick 
40037725Smckusick 	case VBLK:
40137725Smckusick 		/*
40237725Smckusick 		 * On last close of a block device (that isn't mounted)
40337725Smckusick 		 * we must invalidate any in core blocks, so that
40437725Smckusick 		 * we can, for instance, change floppy disks.
40537725Smckusick 		 */
406*53597Sheideman 		vflushbuf(ap->a_vp, 0);
407*53597Sheideman 		if (vinvalbuf(ap->a_vp, 1))
40838613Smckusick 			return (0);
40937725Smckusick 		/*
41039485Smckusick 		 * We do not want to really close the device if it
41139485Smckusick 		 * is still in use unless we are trying to close it
41239485Smckusick 		 * forcibly. Since every use (buffer, vnode, swap, cmap)
41339630Smckusick 		 * holds a reference to the vnode, and because we mark
41439630Smckusick 		 * any other vnodes that alias this device, when the
41539630Smckusick 		 * sum of the reference counts on all the aliased
41639630Smckusick 		 * vnodes descends to one, we are on last close.
41737725Smckusick 		 */
418*53597Sheideman 		if (vcount(ap->a_vp) > 1 && (ap->a_vp->v_flag & VXLOCK) == 0)
41937725Smckusick 			return (0);
42049273Skarels 		devclose = bdevsw[major(dev)].d_close;
42139432Smckusick 		mode = S_IFBLK;
42237725Smckusick 		break;
42337725Smckusick 
42437725Smckusick 	default:
42539446Smckusick 		panic("spec_close: not special");
42637725Smckusick 	}
42737725Smckusick 
428*53597Sheideman 	return ((*devclose)(dev, ap->a_fflag, mode, ap->a_p));
42937486Smckusick }
43037486Smckusick 
43137486Smckusick /*
43239666Smckusick  * Print out the contents of a special device vnode.
43339666Smckusick  */
43453542Sheideman spec_print (ap)
43553542Sheideman 	struct vop_print_args *ap;
43639666Smckusick {
43739666Smckusick 
438*53597Sheideman 	printf("tag VT_NON, dev %d, %d\n", major(ap->a_vp->v_rdev),
439*53597Sheideman 		minor(ap->a_vp->v_rdev));
44039666Smckusick }
44139666Smckusick 
44239666Smckusick /*
44346196Smckusick  * Special device advisory byte-level locks.
44446196Smckusick  */
44548015Smckusick /* ARGSUSED */
44653542Sheideman spec_advlock (ap)
44753542Sheideman 	struct vop_advlock_args *ap;
44846196Smckusick {
44946196Smckusick 
45046196Smckusick 	return (EOPNOTSUPP);
45146196Smckusick }
45246196Smckusick 
45346196Smckusick /*
45439507Smckusick  * Special device failed operation
45537486Smckusick  */
45639507Smckusick spec_ebadf()
45739507Smckusick {
45839507Smckusick 
45939507Smckusick 	return (EBADF);
46039507Smckusick }
46139507Smckusick 
46239507Smckusick /*
46339507Smckusick  * Special device bad operation
46439507Smckusick  */
46539446Smckusick spec_badop()
46637486Smckusick {
46737486Smckusick 
46839446Smckusick 	panic("spec_badop called");
46939292Smckusick 	/* NOTREACHED */
47037486Smckusick }
471