spec_vnops.c revision 1.22 1 /* $NetBSD: spec_vnops.c,v 1.22 1994/12/14 18:49:38 mycroft Exp $ */
2
3 /*
4 * Copyright (c) 1989, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by the University of
18 * California, Berkeley and its contributors.
19 * 4. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 *
35 * @(#)spec_vnops.c 8.8 (Berkeley) 11/21/94
36 */
37
38 #include <sys/param.h>
39 #include <sys/proc.h>
40 #include <sys/systm.h>
41 #include <sys/kernel.h>
42 #include <sys/conf.h>
43 #include <sys/buf.h>
44 #include <sys/mount.h>
45 #include <sys/namei.h>
46 #include <sys/vnode.h>
47 #include <sys/stat.h>
48 #include <sys/errno.h>
49 #include <sys/ioctl.h>
50 #include <sys/file.h>
51 #include <sys/disklabel.h>
52 #include <miscfs/specfs/specdev.h>
53
54 /* symbolic sleep message strings for devices */
55 char devopn[] = "devopn";
56 char devio[] = "devio";
57 char devwait[] = "devwait";
58 char devin[] = "devin";
59 char devout[] = "devout";
60 char devioc[] = "devioc";
61 char devcls[] = "devcls";
62
63 int (**spec_vnodeop_p)();
64 struct vnodeopv_entry_desc spec_vnodeop_entries[] = {
65 { &vop_default_desc, vn_default_error },
66 { &vop_lookup_desc, spec_lookup }, /* lookup */
67 { &vop_create_desc, spec_create }, /* create */
68 { &vop_mknod_desc, spec_mknod }, /* mknod */
69 { &vop_open_desc, spec_open }, /* open */
70 { &vop_close_desc, spec_close }, /* close */
71 { &vop_access_desc, spec_access }, /* access */
72 { &vop_getattr_desc, spec_getattr }, /* getattr */
73 { &vop_setattr_desc, spec_setattr }, /* setattr */
74 { &vop_read_desc, spec_read }, /* read */
75 { &vop_write_desc, spec_write }, /* write */
76 { &vop_lease_desc, spec_lease_check }, /* lease */
77 { &vop_ioctl_desc, spec_ioctl }, /* ioctl */
78 { &vop_select_desc, spec_select }, /* select */
79 { &vop_mmap_desc, spec_mmap }, /* mmap */
80 { &vop_fsync_desc, spec_fsync }, /* fsync */
81 { &vop_seek_desc, spec_seek }, /* seek */
82 { &vop_remove_desc, spec_remove }, /* remove */
83 { &vop_link_desc, spec_link }, /* link */
84 { &vop_rename_desc, spec_rename }, /* rename */
85 { &vop_mkdir_desc, spec_mkdir }, /* mkdir */
86 { &vop_rmdir_desc, spec_rmdir }, /* rmdir */
87 { &vop_symlink_desc, spec_symlink }, /* symlink */
88 { &vop_readdir_desc, spec_readdir }, /* readdir */
89 { &vop_readlink_desc, spec_readlink }, /* readlink */
90 { &vop_abortop_desc, spec_abortop }, /* abortop */
91 { &vop_inactive_desc, spec_inactive }, /* inactive */
92 { &vop_reclaim_desc, spec_reclaim }, /* reclaim */
93 { &vop_lock_desc, spec_lock }, /* lock */
94 { &vop_unlock_desc, spec_unlock }, /* unlock */
95 { &vop_bmap_desc, spec_bmap }, /* bmap */
96 { &vop_strategy_desc, spec_strategy }, /* strategy */
97 { &vop_print_desc, spec_print }, /* print */
98 { &vop_islocked_desc, spec_islocked }, /* islocked */
99 { &vop_pathconf_desc, spec_pathconf }, /* pathconf */
100 { &vop_advlock_desc, spec_advlock }, /* advlock */
101 { &vop_blkatoff_desc, spec_blkatoff }, /* blkatoff */
102 { &vop_valloc_desc, spec_valloc }, /* valloc */
103 { &vop_vfree_desc, spec_vfree }, /* vfree */
104 { &vop_truncate_desc, spec_truncate }, /* truncate */
105 { &vop_update_desc, spec_update }, /* update */
106 { &vop_bwrite_desc, spec_bwrite }, /* bwrite */
107 { (struct vnodeop_desc*)NULL, (int(*)())NULL }
108 };
109 struct vnodeopv_desc spec_vnodeop_opv_desc =
110 { &spec_vnodeop_p, spec_vnodeop_entries };
111
112 /*
113 * Trivial lookup routine that always fails.
114 */
115 int
116 spec_lookup(ap)
117 struct vop_lookup_args /* {
118 struct vnode *a_dvp;
119 struct vnode **a_vpp;
120 struct componentname *a_cnp;
121 } */ *ap;
122 {
123
124 *ap->a_vpp = NULL;
125 return (ENOTDIR);
126 }
127
128 /*
129 * Open a special file.
130 */
131 /* ARGSUSED */
132 spec_open(ap)
133 struct vop_open_args /* {
134 struct vnode *a_vp;
135 int a_mode;
136 struct ucred *a_cred;
137 struct proc *a_p;
138 } */ *ap;
139 {
140 struct vnode *bvp, *vp = ap->a_vp;
141 dev_t bdev, dev = (dev_t)vp->v_rdev;
142 register int maj = major(dev);
143 int error;
144
145 /*
146 * Don't allow open if fs is mounted -nodev.
147 */
148 if (vp->v_mount && (vp->v_mount->mnt_flag & MNT_NODEV))
149 return (ENXIO);
150
151 switch (vp->v_type) {
152
153 case VCHR:
154 if ((u_int)maj >= nchrdev)
155 return (ENXIO);
156 if (ap->a_cred != FSCRED && (ap->a_mode & FWRITE)) {
157 /*
158 * When running in very secure mode, do not allow
159 * opens for writing of any disk character devices.
160 */
161 if (securelevel >= 2 && isdisk(dev, VCHR))
162 return (EPERM);
163 /*
164 * When running in secure mode, do not allow opens
165 * for writing of /dev/mem, /dev/kmem, or character
166 * devices whose corresponding block devices are
167 * currently mounted.
168 */
169 if (securelevel >= 1) {
170 if ((bdev = chrtoblk(dev)) != NODEV &&
171 vfinddev(bdev, VBLK, &bvp) &&
172 bvp->v_usecount > 0 &&
173 (error = vfs_mountedon(bvp)))
174 return (error);
175 if (iskmemdev(dev))
176 return (EPERM);
177 }
178 }
179 VOP_UNLOCK(vp);
180 error = (*cdevsw[maj].d_open)(dev, ap->a_mode, S_IFCHR, ap->a_p);
181 VOP_LOCK(vp);
182 return (error);
183
184 case VBLK:
185 if ((u_int)maj >= nblkdev)
186 return (ENXIO);
187 /*
188 * When running in very secure mode, do not allow
189 * opens for writing of any disk block devices.
190 */
191 if (securelevel >= 2 && ap->a_cred != FSCRED &&
192 (ap->a_mode & FWRITE) && isdisk(dev, VBLK))
193 return (EPERM);
194 /*
195 * Do not allow opens of block devices that are
196 * currently mounted.
197 */
198 if (error = vfs_mountedon(vp))
199 return (error);
200 return ((*bdevsw[maj].d_open)(dev, ap->a_mode, S_IFBLK, ap->a_p));
201 }
202 return (0);
203 }
204
205 /*
206 * Vnode op for read
207 */
208 /* ARGSUSED */
209 spec_read(ap)
210 struct vop_read_args /* {
211 struct vnode *a_vp;
212 struct uio *a_uio;
213 int a_ioflag;
214 struct ucred *a_cred;
215 } */ *ap;
216 {
217 register struct vnode *vp = ap->a_vp;
218 register struct uio *uio = ap->a_uio;
219 struct proc *p = uio->uio_procp;
220 struct buf *bp;
221 daddr_t bn, nextbn;
222 long bsize, bscale, ssize;
223 struct partinfo dpart;
224 int n, on, majordev, (*ioctl)();
225 int error = 0;
226 dev_t dev;
227
228 #ifdef DIAGNOSTIC
229 if (uio->uio_rw != UIO_READ)
230 panic("spec_read mode");
231 if (uio->uio_segflg == UIO_USERSPACE && uio->uio_procp != curproc)
232 panic("spec_read proc");
233 #endif
234 if (uio->uio_resid == 0)
235 return (0);
236
237 switch (vp->v_type) {
238
239 case VCHR:
240 VOP_UNLOCK(vp);
241 error = (*cdevsw[major(vp->v_rdev)].d_read)
242 (vp->v_rdev, uio, ap->a_ioflag);
243 VOP_LOCK(vp);
244 return (error);
245
246 case VBLK:
247 if (uio->uio_offset < 0)
248 return (EINVAL);
249 bsize = BLKDEV_IOSIZE;
250 ssize = DEV_BSIZE;
251 dev = vp->v_rdev;
252 if ((majordev = major(dev)) < nblkdev &&
253 (ioctl = bdevsw[majordev].d_ioctl) != NULL &&
254 (*ioctl)(dev, DIOCGPART, (caddr_t)&dpart, FREAD, p) == 0) {
255 if (dpart.part->p_fstype == FS_BSDFFS &&
256 dpart.part->p_frag != 0 && dpart.part->p_fsize != 0)
257 bsize = dpart.part->p_frag *
258 dpart.part->p_fsize;
259 if (dpart.disklab->d_secsize != 0)
260 ssize = dpart.disklab->d_secsize;
261 }
262 bscale = bsize / ssize;
263 do {
264 bn = (uio->uio_offset / ssize) &~ (bscale - 1);
265 on = uio->uio_offset % bsize;
266 n = min((unsigned)(bsize - on), uio->uio_resid);
267 if (vp->v_lastr + bscale == bn) {
268 nextbn = bn + bscale;
269 error = breadn(vp, bn, (int)bsize, &nextbn,
270 (int *)&bsize, 1, NOCRED, &bp);
271 } else
272 error = bread(vp, bn, (int)bsize, NOCRED, &bp);
273 vp->v_lastr = bn;
274 n = min(n, bsize - bp->b_resid);
275 if (error) {
276 brelse(bp);
277 return (error);
278 }
279 error = uiomove((char *)bp->b_data + on, n, uio);
280 if (n + on == bsize)
281 bp->b_flags |= B_AGE;
282 brelse(bp);
283 } while (error == 0 && uio->uio_resid > 0 && n != 0);
284 return (error);
285
286 default:
287 panic("spec_read type");
288 }
289 /* NOTREACHED */
290 }
291
292 /*
293 * Vnode op for write
294 */
295 /* ARGSUSED */
296 spec_write(ap)
297 struct vop_write_args /* {
298 struct vnode *a_vp;
299 struct uio *a_uio;
300 int a_ioflag;
301 struct ucred *a_cred;
302 } */ *ap;
303 {
304 register struct vnode *vp = ap->a_vp;
305 register struct uio *uio = ap->a_uio;
306 struct proc *p = uio->uio_procp;
307 struct buf *bp;
308 daddr_t bn;
309 int bsize, blkmask, ssize;
310 struct partinfo dpart;
311 register int n, on;
312 int error = 0;
313
314 #ifdef DIAGNOSTIC
315 if (uio->uio_rw != UIO_WRITE)
316 panic("spec_write mode");
317 if (uio->uio_segflg == UIO_USERSPACE && uio->uio_procp != curproc)
318 panic("spec_write proc");
319 #endif
320
321 switch (vp->v_type) {
322
323 case VCHR:
324 VOP_UNLOCK(vp);
325 error = (*cdevsw[major(vp->v_rdev)].d_write)
326 (vp->v_rdev, uio, ap->a_ioflag);
327 VOP_LOCK(vp);
328 return (error);
329
330 case VBLK:
331 if (uio->uio_resid == 0)
332 return (0);
333 if (uio->uio_offset < 0)
334 return (EINVAL);
335 bsize = BLKDEV_IOSIZE;
336 ssize = DEV_BSIZE;
337 if ((*bdevsw[major(vp->v_rdev)].d_ioctl)(vp->v_rdev, DIOCGPART,
338 (caddr_t)&dpart, FREAD, p) == 0) {
339 if (dpart.part->p_fstype == FS_BSDFFS &&
340 dpart.part->p_frag != 0 && dpart.part->p_fsize != 0)
341 bsize = dpart.part->p_frag *
342 dpart.part->p_fsize;
343 if (dpart.disklab->d_secsize != 0)
344 ssize = dpart.disklab->d_secsize;
345 }
346 blkmask = (bsize / ssize) - 1;
347 do {
348 bn = (uio->uio_offset / ssize) &~ blkmask;
349 on = uio->uio_offset % bsize;
350 n = min((unsigned)(bsize - on), uio->uio_resid);
351 if (n == bsize)
352 bp = getblk(vp, bn, bsize, 0, 0);
353 else
354 error = bread(vp, bn, bsize, NOCRED, &bp);
355 n = min(n, bsize - bp->b_resid);
356 if (error) {
357 brelse(bp);
358 return (error);
359 }
360 error = uiomove((char *)bp->b_data + on, n, uio);
361 if (n + on == bsize) {
362 bp->b_flags |= B_AGE;
363 bawrite(bp);
364 } else
365 bdwrite(bp);
366 } while (error == 0 && uio->uio_resid > 0 && n != 0);
367 return (error);
368
369 default:
370 panic("spec_write type");
371 }
372 /* NOTREACHED */
373 }
374
375 /*
376 * Device ioctl operation.
377 */
378 /* ARGSUSED */
379 spec_ioctl(ap)
380 struct vop_ioctl_args /* {
381 struct vnode *a_vp;
382 u_long a_command;
383 caddr_t a_data;
384 int a_fflag;
385 struct ucred *a_cred;
386 struct proc *a_p;
387 } */ *ap;
388 {
389 dev_t dev = ap->a_vp->v_rdev;
390
391 switch (ap->a_vp->v_type) {
392
393 case VCHR:
394 return ((*cdevsw[major(dev)].d_ioctl)(dev, ap->a_command, ap->a_data,
395 ap->a_fflag, ap->a_p));
396
397 case VBLK:
398 if (ap->a_command == 0 && (long)ap->a_data == B_TAPE)
399 if (bdevsw[major(dev)].d_flags & B_TAPE)
400 return (0);
401 else
402 return (1);
403 return ((*bdevsw[major(dev)].d_ioctl)(dev, ap->a_command, ap->a_data,
404 ap->a_fflag, ap->a_p));
405
406 default:
407 panic("spec_ioctl");
408 /* NOTREACHED */
409 }
410 }
411
412 /* ARGSUSED */
413 spec_select(ap)
414 struct vop_select_args /* {
415 struct vnode *a_vp;
416 int a_which;
417 int a_fflags;
418 struct ucred *a_cred;
419 struct proc *a_p;
420 } */ *ap;
421 {
422 register dev_t dev;
423
424 switch (ap->a_vp->v_type) {
425
426 default:
427 return (1); /* XXX */
428
429 case VCHR:
430 dev = ap->a_vp->v_rdev;
431 return (*cdevsw[major(dev)].d_select)(dev, ap->a_which, ap->a_p);
432 }
433 }
434 /*
435 * Synch buffers associated with a block device
436 */
437 /* ARGSUSED */
438 int
439 spec_fsync(ap)
440 struct vop_fsync_args /* {
441 struct vnode *a_vp;
442 struct ucred *a_cred;
443 int a_waitfor;
444 struct proc *a_p;
445 } */ *ap;
446 {
447 register struct vnode *vp = ap->a_vp;
448 register struct buf *bp;
449 struct buf *nbp;
450 int s;
451
452 if (vp->v_type == VCHR)
453 return (0);
454 /*
455 * Flush all dirty buffers associated with a block device.
456 */
457 loop:
458 s = splbio();
459 for (bp = vp->v_dirtyblkhd.lh_first; bp; bp = nbp) {
460 nbp = bp->b_vnbufs.le_next;
461 if ((bp->b_flags & B_BUSY))
462 continue;
463 if ((bp->b_flags & B_DELWRI) == 0)
464 panic("spec_fsync: not dirty");
465 bremfree(bp);
466 bp->b_flags |= B_BUSY;
467 splx(s);
468 bawrite(bp);
469 goto loop;
470 }
471 if (ap->a_waitfor == MNT_WAIT) {
472 while (vp->v_numoutput) {
473 vp->v_flag |= VBWAIT;
474 sleep((caddr_t)&vp->v_numoutput, PRIBIO + 1);
475 }
476 #ifdef DIAGNOSTIC
477 if (vp->v_dirtyblkhd.lh_first) {
478 vprint("spec_fsync: dirty", vp);
479 goto loop;
480 }
481 #endif
482 }
483 splx(s);
484 return (0);
485 }
486
487 /*
488 * Just call the device strategy routine
489 */
490 spec_strategy(ap)
491 struct vop_strategy_args /* {
492 struct buf *a_bp;
493 } */ *ap;
494 {
495
496 (*bdevsw[major(ap->a_bp->b_dev)].d_strategy)(ap->a_bp);
497 return (0);
498 }
499
500 /*
501 * This is a noop, simply returning what one has been given.
502 */
503 spec_bmap(ap)
504 struct vop_bmap_args /* {
505 struct vnode *a_vp;
506 daddr_t a_bn;
507 struct vnode **a_vpp;
508 daddr_t *a_bnp;
509 } */ *ap;
510 {
511
512 if (ap->a_vpp != NULL)
513 *ap->a_vpp = ap->a_vp;
514 if (ap->a_bnp != NULL)
515 *ap->a_bnp = ap->a_bn;
516 return (0);
517 }
518
519 /*
520 * At the moment we do not do any locking.
521 */
522 /* ARGSUSED */
523 spec_lock(ap)
524 struct vop_lock_args /* {
525 struct vnode *a_vp;
526 } */ *ap;
527 {
528
529 return (0);
530 }
531
532 /* ARGSUSED */
533 spec_unlock(ap)
534 struct vop_unlock_args /* {
535 struct vnode *a_vp;
536 } */ *ap;
537 {
538
539 return (0);
540 }
541
542 /*
543 * Device close routine
544 */
545 /* ARGSUSED */
546 spec_close(ap)
547 struct vop_close_args /* {
548 struct vnode *a_vp;
549 int a_fflag;
550 struct ucred *a_cred;
551 struct proc *a_p;
552 } */ *ap;
553 {
554 register struct vnode *vp = ap->a_vp;
555 dev_t dev = vp->v_rdev;
556 int (*devclose) __P((dev_t, int, int, struct proc *));
557 int mode, error;
558
559 switch (vp->v_type) {
560
561 case VCHR:
562 /*
563 * Hack: a tty device that is a controlling terminal
564 * has a reference from the session structure.
565 * We cannot easily tell that a character device is
566 * a controlling terminal, unless it is the closing
567 * process' controlling terminal. In that case,
568 * if the reference count is 2 (this last descriptor
569 * plus the session), release the reference from the session.
570 */
571 if (vcount(vp) == 2 && ap->a_p &&
572 vp == ap->a_p->p_session->s_ttyvp) {
573 vrele(vp);
574 ap->a_p->p_session->s_ttyvp = NULL;
575 }
576 /*
577 * If the vnode is locked, then we are in the midst
578 * of forcably closing the device, otherwise we only
579 * close on last reference.
580 */
581 if (vcount(vp) > 1 && (vp->v_flag & VXLOCK) == 0)
582 return (0);
583 devclose = cdevsw[major(dev)].d_close;
584 mode = S_IFCHR;
585 break;
586
587 case VBLK:
588 /*
589 * On last close of a block device (that isn't mounted)
590 * we must invalidate any in core blocks, so that
591 * we can, for instance, change floppy disks.
592 */
593 if (error = vinvalbuf(vp, V_SAVE, ap->a_cred, ap->a_p, 0, 0))
594 return (error);
595 /*
596 * We do not want to really close the device if it
597 * is still in use unless we are trying to close it
598 * forcibly. Since every use (buffer, vnode, swap, cmap)
599 * holds a reference to the vnode, and because we mark
600 * any other vnodes that alias this device, when the
601 * sum of the reference counts on all the aliased
602 * vnodes descends to one, we are on last close.
603 */
604 if (vcount(vp) > 1 && (vp->v_flag & VXLOCK) == 0)
605 return (0);
606 devclose = bdevsw[major(dev)].d_close;
607 mode = S_IFBLK;
608 break;
609
610 default:
611 panic("spec_close: not special");
612 }
613
614 return ((*devclose)(dev, ap->a_fflag, mode, ap->a_p));
615 }
616
617 /*
618 * Print out the contents of a special device vnode.
619 */
620 spec_print(ap)
621 struct vop_print_args /* {
622 struct vnode *a_vp;
623 } */ *ap;
624 {
625
626 printf("tag VT_NON, dev %d, %d\n", major(ap->a_vp->v_rdev),
627 minor(ap->a_vp->v_rdev));
628 }
629
630 /*
631 * Return POSIX pathconf information applicable to special devices.
632 */
633 spec_pathconf(ap)
634 struct vop_pathconf_args /* {
635 struct vnode *a_vp;
636 int a_name;
637 register_t *a_retval;
638 } */ *ap;
639 {
640
641 switch (ap->a_name) {
642 case _PC_LINK_MAX:
643 *ap->a_retval = LINK_MAX;
644 return (0);
645 case _PC_MAX_CANON:
646 *ap->a_retval = MAX_CANON;
647 return (0);
648 case _PC_MAX_INPUT:
649 *ap->a_retval = MAX_INPUT;
650 return (0);
651 case _PC_PIPE_BUF:
652 *ap->a_retval = PIPE_BUF;
653 return (0);
654 case _PC_CHOWN_RESTRICTED:
655 *ap->a_retval = 1;
656 return (0);
657 case _PC_VDISABLE:
658 *ap->a_retval = _POSIX_VDISABLE;
659 return (0);
660 default:
661 return (EINVAL);
662 }
663 /* NOTREACHED */
664 }
665
666 /*
667 * Special device advisory byte-level locks.
668 */
669 /* ARGSUSED */
670 spec_advlock(ap)
671 struct vop_advlock_args /* {
672 struct vnode *a_vp;
673 caddr_t a_id;
674 int a_op;
675 struct flock *a_fl;
676 int a_flags;
677 } */ *ap;
678 {
679
680 return (EOPNOTSUPP);
681 }
682
683 /*
684 * Special device failed operation
685 */
686 spec_ebadf()
687 {
688
689 return (EBADF);
690 }
691
692 /*
693 * Special device bad operation
694 */
695 spec_badop()
696 {
697
698 panic("spec_badop called");
699 /* NOTREACHED */
700 }
701