xref: /openbsd-src/sys/kern/spec_vnops.c (revision 25c4e8bd056e974b28f4a0ffd39d76c190a56013)
1 /*	$OpenBSD: spec_vnops.c,v 1.108 2022/06/26 05:20:42 visa Exp $	*/
2 /*	$NetBSD: spec_vnops.c,v 1.29 1996/04/22 01:42:38 christos Exp $	*/
3 
4 /*
5  * Copyright (c) 1989, 1993
6  *	The Regents of the University of California.  All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. Neither the name of the University nor the names of its contributors
17  *    may be used to endorse or promote products derived from this software
18  *    without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30  * SUCH DAMAGE.
31  *
32  *	@(#)spec_vnops.c	8.8 (Berkeley) 11/21/94
33  */
34 
35 #include <sys/param.h>
36 #include <sys/proc.h>
37 #include <sys/systm.h>
38 #include <sys/kernel.h>
39 #include <sys/conf.h>
40 #include <sys/buf.h>
41 #include <sys/mount.h>
42 #include <sys/namei.h>
43 #include <sys/vnode.h>
44 #include <sys/lock.h>
45 #include <sys/stat.h>
46 #include <sys/errno.h>
47 #include <sys/ioctl.h>
48 #include <sys/fcntl.h>
49 #include <sys/disklabel.h>
50 #include <sys/lockf.h>
51 #include <sys/dkio.h>
52 #include <sys/malloc.h>
53 #include <sys/specdev.h>
54 #include <sys/unistd.h>
55 
56 #include <uvm/uvm_extern.h>
57 
58 #define v_lastr v_specinfo->si_lastr
59 
60 int	spec_open_clone(struct vop_open_args *);
61 
62 struct vnodechain speclisth[SPECHSZ];
63 
64 const struct vops spec_vops = {
65 	.vop_lookup	= vop_generic_lookup,
66 	.vop_create	= vop_generic_badop,
67 	.vop_mknod	= vop_generic_badop,
68 	.vop_open	= spec_open,
69 	.vop_close	= spec_close,
70 	.vop_access	= spec_access,
71 	.vop_getattr	= spec_getattr,
72 	.vop_setattr	= spec_setattr,
73 	.vop_read	= spec_read,
74 	.vop_write	= spec_write,
75 	.vop_ioctl	= spec_ioctl,
76 	.vop_kqfilter	= spec_kqfilter,
77 	.vop_revoke	= vop_generic_revoke,
78 	.vop_fsync	= spec_fsync,
79 	.vop_remove	= vop_generic_badop,
80 	.vop_link	= vop_generic_badop,
81 	.vop_rename	= vop_generic_badop,
82 	.vop_mkdir	= vop_generic_badop,
83 	.vop_rmdir	= vop_generic_badop,
84 	.vop_symlink	= vop_generic_badop,
85 	.vop_readdir	= vop_generic_badop,
86 	.vop_readlink	= vop_generic_badop,
87 	.vop_abortop	= vop_generic_badop,
88 	.vop_inactive	= spec_inactive,
89 	.vop_reclaim	= nullop,
90 	.vop_lock	= nullop,
91 	.vop_unlock	= nullop,
92 	.vop_islocked	= nullop,
93 	.vop_bmap	= vop_generic_bmap,
94 	.vop_strategy	= spec_strategy,
95 	.vop_print	= spec_print,
96 	.vop_pathconf	= spec_pathconf,
97 	.vop_advlock	= spec_advlock,
98 	.vop_bwrite	= vop_generic_bwrite,
99 };
100 
101 /*
102  * Open a special file.
103  */
104 int
105 spec_open(void *v)
106 {
107 	struct vop_open_args *ap = v;
108 	struct proc *p = ap->a_p;
109 	struct vnode *vp = ap->a_vp;
110 	struct vnode *bvp;
111 	dev_t bdev;
112 	dev_t dev = (dev_t)vp->v_rdev;
113 	int maj = major(dev);
114 	int error;
115 
116 	/*
117 	 * Don't allow open if fs is mounted -nodev.
118 	 */
119 	if (vp->v_mount && (vp->v_mount->mnt_flag & MNT_NODEV))
120 		return (ENXIO);
121 
122 	switch (vp->v_type) {
123 
124 	case VCHR:
125 		if ((u_int)maj >= nchrdev)
126 			return (ENXIO);
127 		if (ap->a_cred != FSCRED && (ap->a_mode & FWRITE)) {
128 			/*
129 			 * When running in very secure mode, do not allow
130 			 * opens for writing of any disk character devices.
131 			 */
132 			if (securelevel >= 2 && cdevsw[maj].d_type == D_DISK)
133 				return (EPERM);
134 			/*
135 			 * When running in secure mode, do not allow opens
136 			 * for writing of /dev/mem, /dev/kmem, or character
137 			 * devices whose corresponding block devices are
138 			 * currently mounted.
139 			 */
140 			if (securelevel >= 1) {
141 				if ((bdev = chrtoblk(dev)) != NODEV &&
142 				    vfinddev(bdev, VBLK, &bvp) &&
143 				    bvp->v_usecount > 0 &&
144 				    (error = vfs_mountedon(bvp)))
145 					return (error);
146 				if (iskmemdev(dev))
147 					return (EPERM);
148 			}
149 		}
150 		if (cdevsw[maj].d_type == D_TTY)
151 			vp->v_flag |= VISTTY;
152 		if (cdevsw[maj].d_flags & D_CLONE)
153 			return (spec_open_clone(ap));
154 		VOP_UNLOCK(vp);
155 		error = (*cdevsw[maj].d_open)(dev, ap->a_mode, S_IFCHR, p);
156 		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
157 		return (error);
158 
159 	case VBLK:
160 		if ((u_int)maj >= nblkdev)
161 			return (ENXIO);
162 		/*
163 		 * When running in very secure mode, do not allow
164 		 * opens for writing of any disk block devices.
165 		 */
166 		if (securelevel >= 2 && ap->a_cred != FSCRED &&
167 		    (ap->a_mode & FWRITE) && bdevsw[maj].d_type == D_DISK)
168 			return (EPERM);
169 		/*
170 		 * Do not allow opens of block devices that are
171 		 * currently mounted.
172 		 */
173 		if ((error = vfs_mountedon(vp)) != 0)
174 			return (error);
175 		return ((*bdevsw[maj].d_open)(dev, ap->a_mode, S_IFBLK, p));
176 	case VNON:
177 	case VLNK:
178 	case VDIR:
179 	case VREG:
180 	case VBAD:
181 	case VFIFO:
182 	case VSOCK:
183 		break;
184 	}
185 	return (0);
186 }
187 
188 /*
189  * Vnode op for read
190  */
191 int
192 spec_read(void *v)
193 {
194 	struct vop_read_args *ap = v;
195 	struct vnode *vp = ap->a_vp;
196 	struct uio *uio = ap->a_uio;
197  	struct proc *p = uio->uio_procp;
198 	struct buf *bp;
199 	daddr_t bn, nextbn, bscale;
200 	int bsize;
201 	struct partinfo dpart;
202 	size_t n;
203 	int on, majordev;
204 	int (*ioctl)(dev_t, u_long, caddr_t, int, struct proc *);
205 	int error = 0;
206 
207 #ifdef DIAGNOSTIC
208 	if (uio->uio_rw != UIO_READ)
209 		panic("spec_read mode");
210 	if (uio->uio_segflg == UIO_USERSPACE && uio->uio_procp != curproc)
211 		panic("spec_read proc");
212 #endif
213 	if (uio->uio_resid == 0)
214 		return (0);
215 
216 	switch (vp->v_type) {
217 
218 	case VCHR:
219 		VOP_UNLOCK(vp);
220 		error = (*cdevsw[major(vp->v_rdev)].d_read)
221 			(vp->v_rdev, uio, ap->a_ioflag);
222 		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
223 		return (error);
224 
225 	case VBLK:
226 		if (uio->uio_offset < 0)
227 			return (EINVAL);
228 		bsize = BLKDEV_IOSIZE;
229 		if ((majordev = major(vp->v_rdev)) < nblkdev &&
230 		    (ioctl = bdevsw[majordev].d_ioctl) != NULL &&
231 		    (*ioctl)(vp->v_rdev, DIOCGPART, (caddr_t)&dpart, FREAD, p) == 0) {
232 			u_int32_t frag =
233 			    DISKLABELV1_FFS_FRAG(dpart.part->p_fragblock);
234 			u_int32_t fsize =
235 			    DISKLABELV1_FFS_FSIZE(dpart.part->p_fragblock);
236 			if (dpart.part->p_fstype == FS_BSDFFS && frag != 0 &&
237 			    fsize != 0)
238 				bsize = frag * fsize;
239 		}
240 		bscale = btodb(bsize);
241 		do {
242 			bn = btodb(uio->uio_offset) & ~(bscale - 1);
243 			on = uio->uio_offset % bsize;
244 			n = ulmin((bsize - on), uio->uio_resid);
245 			if (vp->v_lastr + bscale == bn) {
246 				nextbn = bn + bscale;
247 				error = breadn(vp, bn, bsize, &nextbn, &bsize,
248 				    1, &bp);
249 			} else
250 				error = bread(vp, bn, bsize, &bp);
251 			vp->v_lastr = bn;
252 			n = ulmin(n, bsize - bp->b_resid);
253 			if (error) {
254 				brelse(bp);
255 				return (error);
256 			}
257 			error = uiomove((char *)bp->b_data + on, n, uio);
258 			brelse(bp);
259 		} while (error == 0 && uio->uio_resid > 0 && n != 0);
260 		return (error);
261 
262 	default:
263 		panic("spec_read type");
264 	}
265 	/* NOTREACHED */
266 }
267 
268 int
269 spec_inactive(void *v)
270 {
271 	struct vop_inactive_args *ap = v;
272 
273 	VOP_UNLOCK(ap->a_vp);
274 	return (0);
275 }
276 
277 /*
278  * Vnode op for write
279  */
280 int
281 spec_write(void *v)
282 {
283 	struct vop_write_args *ap = v;
284 	struct vnode *vp = ap->a_vp;
285 	struct uio *uio = ap->a_uio;
286 	struct proc *p = uio->uio_procp;
287 	struct buf *bp;
288 	daddr_t bn, bscale;
289 	int bsize;
290 	struct partinfo dpart;
291 	size_t n;
292 	int on, majordev;
293 	int (*ioctl)(dev_t, u_long, caddr_t, int, struct proc *);
294 	int error = 0;
295 
296 #ifdef DIAGNOSTIC
297 	if (uio->uio_rw != UIO_WRITE)
298 		panic("spec_write mode");
299 	if (uio->uio_segflg == UIO_USERSPACE && uio->uio_procp != curproc)
300 		panic("spec_write proc");
301 #endif
302 
303 	switch (vp->v_type) {
304 
305 	case VCHR:
306 		VOP_UNLOCK(vp);
307 		error = (*cdevsw[major(vp->v_rdev)].d_write)
308 			(vp->v_rdev, uio, ap->a_ioflag);
309 		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
310 		return (error);
311 
312 	case VBLK:
313 		if (uio->uio_resid == 0)
314 			return (0);
315 		if (uio->uio_offset < 0)
316 			return (EINVAL);
317 		bsize = BLKDEV_IOSIZE;
318 		if ((majordev = major(vp->v_rdev)) < nblkdev &&
319 		    (ioctl = bdevsw[majordev].d_ioctl) != NULL &&
320 		    (*ioctl)(vp->v_rdev, DIOCGPART, (caddr_t)&dpart, FREAD, p) == 0) {
321 			u_int32_t frag =
322 			    DISKLABELV1_FFS_FRAG(dpart.part->p_fragblock);
323 			u_int32_t fsize =
324 			    DISKLABELV1_FFS_FSIZE(dpart.part->p_fragblock);
325 			if (dpart.part->p_fstype == FS_BSDFFS && frag != 0 &&
326 			    fsize != 0)
327 				bsize = frag * fsize;
328 		}
329 		bscale = btodb(bsize);
330 		do {
331 			bn = btodb(uio->uio_offset) & ~(bscale - 1);
332 			on = uio->uio_offset % bsize;
333 			n = ulmin((bsize - on), uio->uio_resid);
334 			error = bread(vp, bn, bsize, &bp);
335 			n = ulmin(n, bsize - bp->b_resid);
336 			if (error) {
337 				brelse(bp);
338 				return (error);
339 			}
340 			error = uiomove((char *)bp->b_data + on, n, uio);
341 			if (n + on == bsize)
342 				bawrite(bp);
343 			else
344 				bdwrite(bp);
345 		} while (error == 0 && uio->uio_resid > 0 && n != 0);
346 		return (error);
347 
348 	default:
349 		panic("spec_write type");
350 	}
351 	/* NOTREACHED */
352 }
353 
354 /*
355  * Device ioctl operation.
356  */
357 int
358 spec_ioctl(void *v)
359 {
360 	struct vop_ioctl_args *ap = v;
361 	dev_t dev = ap->a_vp->v_rdev;
362 	int maj = major(dev);
363 
364 	switch (ap->a_vp->v_type) {
365 
366 	case VCHR:
367 		return ((*cdevsw[maj].d_ioctl)(dev, ap->a_command, ap->a_data,
368 		    ap->a_fflag, ap->a_p));
369 
370 	case VBLK:
371 		return ((*bdevsw[maj].d_ioctl)(dev, ap->a_command, ap->a_data,
372 		    ap->a_fflag, ap->a_p));
373 
374 	default:
375 		panic("spec_ioctl");
376 		/* NOTREACHED */
377 	}
378 }
379 
380 int
381 spec_kqfilter(void *v)
382 {
383 	struct vop_kqfilter_args *ap = v;
384 	dev_t dev;
385 
386 	dev = ap->a_vp->v_rdev;
387 
388 	switch (ap->a_vp->v_type) {
389 	default:
390 		if (ap->a_kn->kn_flags & (__EV_POLL | __EV_SELECT))
391 			return seltrue_kqfilter(dev, ap->a_kn);
392 		break;
393 	case VCHR:
394 		if (cdevsw[major(dev)].d_kqfilter)
395 			return (*cdevsw[major(dev)].d_kqfilter)(dev, ap->a_kn);
396 	}
397 	return (EOPNOTSUPP);
398 }
399 
400 /*
401  * Synch buffers associated with a block device
402  */
403 int
404 spec_fsync(void *v)
405 {
406 	struct vop_fsync_args *ap = v;
407 	struct vnode *vp = ap->a_vp;
408 	struct buf *bp;
409 	struct buf *nbp;
410 	int s;
411 
412 	if (vp->v_type == VCHR)
413 		return (0);
414 	/*
415 	 * Flush all dirty buffers associated with a block device.
416 	 */
417 loop:
418 	s = splbio();
419 	LIST_FOREACH_SAFE(bp, &vp->v_dirtyblkhd, b_vnbufs, nbp) {
420 		if ((bp->b_flags & B_BUSY))
421 			continue;
422 		if ((bp->b_flags & B_DELWRI) == 0)
423 			panic("spec_fsync: not dirty");
424 		bremfree(bp);
425 		buf_acquire(bp);
426 		splx(s);
427 		bawrite(bp);
428 		goto loop;
429 	}
430 	if (ap->a_waitfor == MNT_WAIT) {
431 		vwaitforio (vp, 0, "spec_fsync", INFSLP);
432 
433 #ifdef DIAGNOSTIC
434 		if (!LIST_EMPTY(&vp->v_dirtyblkhd)) {
435 			splx(s);
436 			vprint("spec_fsync: dirty", vp);
437 			goto loop;
438 		}
439 #endif
440 	}
441 	splx(s);
442 	return (0);
443 }
444 
445 int
446 spec_strategy(void *v)
447 {
448 	struct vop_strategy_args *ap = v;
449 	struct buf *bp = ap->a_bp;
450 	int maj = major(bp->b_dev);
451 
452 	if (LIST_FIRST(&bp->b_dep) != NULL)
453 		buf_start(bp);
454 
455 	(*bdevsw[maj].d_strategy)(bp);
456 	return (0);
457 }
458 
459 /*
460  * Device close routine
461  */
462 int
463 spec_close(void *v)
464 {
465 	struct vop_close_args *ap = v;
466 	struct proc *p = ap->a_p;
467 	struct vnode *vp = ap->a_vp;
468 	dev_t dev = vp->v_rdev;
469 	int (*devclose)(dev_t, int, int, struct proc *);
470 	int mode, relock, xlocked, error;
471 	int clone = 0;
472 
473 	switch (vp->v_type) {
474 
475 	case VCHR:
476 		/*
477 		 * Hack: a tty device that is a controlling terminal
478 		 * has a reference from the session structure.
479 		 * We cannot easily tell that a character device is
480 		 * a controlling terminal, unless it is the closing
481 		 * process' controlling terminal.  In that case,
482 		 * if the reference count is 2 (this last descriptor
483 		 * plus the session), release the reference from the session.
484 		 */
485 		if (vcount(vp) == 2 && p != NULL && p->p_p->ps_pgrp &&
486 		    vp == p->p_p->ps_pgrp->pg_session->s_ttyvp) {
487 			vrele(vp);
488 			p->p_p->ps_pgrp->pg_session->s_ttyvp = NULL;
489 		}
490 		if (cdevsw[major(dev)].d_flags & D_CLONE) {
491 			clone = 1;
492 		} else {
493 			/*
494 			 * If the vnode is locked, then we are in the midst
495 			 * of forcibly closing the device, otherwise we only
496 			 * close on last reference.
497 			 */
498 			mtx_enter(&vnode_mtx);
499 			xlocked = (vp->v_lflag & VXLOCK);
500 			mtx_leave(&vnode_mtx);
501 			if (vcount(vp) > 1 && !xlocked)
502 				return (0);
503 		}
504 		devclose = cdevsw[major(dev)].d_close;
505 		mode = S_IFCHR;
506 		break;
507 
508 	case VBLK:
509 		/*
510 		 * On last close of a block device (that isn't mounted)
511 		 * we must invalidate any in core blocks, so that
512 		 * we can, for instance, change floppy disks. In order to do
513 		 * that, we must lock the vnode. If we are coming from
514 		 * vclean(), the vnode is already locked.
515 		 */
516 		mtx_enter(&vnode_mtx);
517 		xlocked = (vp->v_lflag & VXLOCK);
518 		mtx_leave(&vnode_mtx);
519 		if (!xlocked)
520 			vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
521 		error = vinvalbuf(vp, V_SAVE, ap->a_cred, p, 0, INFSLP);
522 		if (!xlocked)
523 			VOP_UNLOCK(vp);
524 		if (error)
525 			return (error);
526 		/*
527 		 * We do not want to really close the device if it
528 		 * is still in use unless we are trying to close it
529 		 * forcibly. Since every use (buffer, vnode, swap, cmap)
530 		 * holds a reference to the vnode, and because we mark
531 		 * any other vnodes that alias this device, when the
532 		 * sum of the reference counts on all the aliased
533 		 * vnodes descends to one, we are on last close.
534 		 */
535 		mtx_enter(&vnode_mtx);
536 		xlocked = (vp->v_lflag & VXLOCK);
537 		mtx_leave(&vnode_mtx);
538 		if (vcount(vp) > 1 && !xlocked)
539 			return (0);
540 		devclose = bdevsw[major(dev)].d_close;
541 		mode = S_IFBLK;
542 		break;
543 
544 	default:
545 		panic("spec_close: not special");
546 	}
547 
548 	/* release lock if held and this isn't coming from vclean() */
549 	mtx_enter(&vnode_mtx);
550 	xlocked = (vp->v_lflag & VXLOCK);
551 	mtx_leave(&vnode_mtx);
552 	relock = VOP_ISLOCKED(vp) && !xlocked;
553 	if (relock)
554 		VOP_UNLOCK(vp);
555 	error = (*devclose)(dev, ap->a_fflag, mode, p);
556 	if (relock)
557 		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
558 
559 	if (error == 0 && clone) {
560 		struct vnode *pvp;
561 
562 		pvp = vp->v_specparent; /* get parent device */
563 		clrbit(pvp->v_specbitmap, minor(dev) >> CLONE_SHIFT);
564 		vrele(pvp);
565 	}
566 
567 	return (error);
568 }
569 
570 int
571 spec_getattr(void *v)
572 {
573 	struct vop_getattr_args	*ap = v;
574 	struct vnode		*vp = ap->a_vp;
575 	int			 error;
576 
577 	if (!(vp->v_flag & VCLONE))
578 		return (EBADF);
579 
580 	vn_lock(vp->v_specparent, LK_EXCLUSIVE|LK_RETRY);
581 	error = VOP_GETATTR(vp->v_specparent, ap->a_vap, ap->a_cred, ap->a_p);
582 	VOP_UNLOCK(vp->v_specparent);
583 
584 	return (error);
585 }
586 
587 int
588 spec_setattr(void *v)
589 {
590 	struct vop_getattr_args	*ap = v;
591 	struct proc		*p = ap->a_p;
592 	struct vnode		*vp = ap->a_vp;
593 	int			 error;
594 
595 	if (!(vp->v_flag & VCLONE))
596 		return (EBADF);
597 
598 	vn_lock(vp->v_specparent, LK_EXCLUSIVE|LK_RETRY);
599 	error = VOP_SETATTR(vp->v_specparent, ap->a_vap, ap->a_cred, p);
600 	VOP_UNLOCK(vp->v_specparent);
601 
602 	return (error);
603 }
604 
605 int
606 spec_access(void *v)
607 {
608 	struct vop_access_args	*ap = v;
609 	struct vnode		*vp = ap->a_vp;
610 	int			 error;
611 
612 	if (!(vp->v_flag & VCLONE))
613 		return (EBADF);
614 
615 	vn_lock(vp->v_specparent, LK_EXCLUSIVE|LK_RETRY);
616 	error = VOP_ACCESS(vp->v_specparent, ap->a_mode, ap->a_cred, ap->a_p);
617 	VOP_UNLOCK(vp->v_specparent);
618 
619 	return (error);
620 }
621 
622 /*
623  * Print out the contents of a special device vnode.
624  */
625 int
626 spec_print(void *v)
627 {
628 	struct vop_print_args *ap = v;
629 
630 	printf("tag VT_NON, dev %d, %d\n", major(ap->a_vp->v_rdev),
631 		minor(ap->a_vp->v_rdev));
632 	return 0;
633 }
634 
635 /*
636  * Return POSIX pathconf information applicable to special devices.
637  */
638 int
639 spec_pathconf(void *v)
640 {
641 	struct vop_pathconf_args *ap = v;
642 	int error = 0;
643 
644 	switch (ap->a_name) {
645 	case _PC_LINK_MAX:
646 		*ap->a_retval = LINK_MAX;
647 		break;
648 	case _PC_MAX_CANON:
649 		*ap->a_retval = MAX_CANON;
650 		break;
651 	case _PC_MAX_INPUT:
652 		*ap->a_retval = MAX_INPUT;
653 		break;
654 	case _PC_CHOWN_RESTRICTED:
655 		*ap->a_retval = 1;
656 		break;
657 	case _PC_VDISABLE:
658 		*ap->a_retval = _POSIX_VDISABLE;
659 		break;
660 	case _PC_TIMESTAMP_RESOLUTION:
661 		*ap->a_retval = 1;
662 		break;
663 	default:
664 		error = EINVAL;
665 		break;
666 	}
667 
668 	return (error);
669 }
670 
671 /*
672  * Special device advisory byte-level locks.
673  */
674 int
675 spec_advlock(void *v)
676 {
677 	struct vop_advlock_args *ap = v;
678 	struct vnode *vp = ap->a_vp;
679 
680 	return (lf_advlock(&vp->v_speclockf, (off_t)0, ap->a_id,
681 		ap->a_op, ap->a_fl, ap->a_flags));
682 }
683 
684 /*
685  * Copyright (c) 2006 Pedro Martelletto <pedro@ambientworks.net>
686  * Copyright (c) 2006 Thordur Bjornsson <thib@openbsd.org>
687  *
688  * Permission to use, copy, modify, and distribute this software for any
689  * purpose with or without fee is hereby granted, provided that the above
690  * copyright notice and this permission notice appear in all copies.
691  *
692  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
693  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
694  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
695  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
696  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
697  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
698  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
699  */
700 
701 #ifdef	CLONE_DEBUG
702 #define	DNPRINTF(m...)	do { printf(m);  } while (0)
703 #else
704 #define	DNPRINTF(m...)	/* nothing */
705 #endif
706 
707 int
708 spec_open_clone(struct vop_open_args *ap)
709 {
710 	struct vnode *cvp, *vp = ap->a_vp;
711 	struct cloneinfo *cip;
712 	int error, i;
713 
714 	DNPRINTF("cloning vnode\n");
715 
716 	if (minor(vp->v_rdev) >= (1 << CLONE_SHIFT))
717 		return (ENXIO);
718 
719 	for (i = 1; i < CLONE_MAPSZ * NBBY; i++)
720 		if (isclr(vp->v_specbitmap, i)) {
721 			setbit(vp->v_specbitmap, i);
722 			break;
723 		}
724 
725 	if (i == CLONE_MAPSZ * NBBY)
726 		return (EBUSY); /* too many open instances */
727 
728 	error = cdevvp(makedev(major(vp->v_rdev),
729 	    (i << CLONE_SHIFT) | minor(vp->v_rdev)), &cvp);
730 	if (error) {
731 		clrbit(vp->v_specbitmap, i);
732 		return (error); /* out of vnodes */
733 	}
734 
735 	VOP_UNLOCK(vp);
736 
737 	error = cdevsw[major(vp->v_rdev)].d_open(cvp->v_rdev, ap->a_mode,
738 	    S_IFCHR, ap->a_p);
739 
740 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
741 
742 	if (error) {
743 		vput(cvp);
744 		clrbit(vp->v_specbitmap, i);
745 		return (error); /* device open failed */
746 	}
747 
748 	cvp->v_flag |= VCLONE;
749 
750 	cip = malloc(sizeof(struct cloneinfo), M_TEMP, M_WAITOK);
751 	cip->ci_data = vp->v_data;
752 	cip->ci_vp = cvp;
753 
754 	cvp->v_specparent = vp;
755 	vp->v_flag |= VCLONED;
756 	vp->v_data = cip;
757 
758 	DNPRINTF("clone of vnode %p is vnode %p\n", vp, cvp);
759 
760 	return (0); /* device cloned */
761 }
762