spec_vnops.c revision 1.21 1 /* $NetBSD: spec_vnops.c,v 1.21 1994/12/13 20:14:46 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 struct file *a_fp;
139 } */ *ap;
140 {
141 struct vnode *bvp, *vp = ap->a_vp;
142 dev_t bdev, dev = (dev_t)vp->v_rdev;
143 register int maj = major(dev);
144 int error;
145
146 /*
147 * Don't allow open if fs is mounted -nodev.
148 */
149 if (vp->v_mount && (vp->v_mount->mnt_flag & MNT_NODEV))
150 return (ENXIO);
151
152 switch (vp->v_type) {
153
154 case VCHR:
155 if ((u_int)maj >= nchrdev)
156 return (ENXIO);
157 if (ap->a_cred != FSCRED && (ap->a_mode & FWRITE)) {
158 /*
159 * When running in very secure mode, do not allow
160 * opens for writing of any disk character devices.
161 */
162 if (securelevel >= 2 && isdisk(dev, VCHR))
163 return (EPERM);
164 /*
165 * When running in secure mode, do not allow opens
166 * for writing of /dev/mem, /dev/kmem, or character
167 * devices whose corresponding block devices are
168 * currently mounted.
169 */
170 if (securelevel >= 1) {
171 if ((bdev = chrtoblk(dev)) != NODEV &&
172 vfinddev(bdev, VBLK, &bvp) &&
173 bvp->v_usecount > 0 &&
174 (error = vfs_mountedon(bvp)))
175 return (error);
176 if (iskmemdev(dev))
177 return (EPERM);
178 }
179 }
180 VOP_UNLOCK(vp);
181 error = (*cdevsw[maj].d_open)(dev, ap->a_mode, S_IFCHR,
182 ap->a_p, ap->a_fp);
183 VOP_LOCK(vp);
184 return (error);
185
186 case VBLK:
187 if ((u_int)maj >= nblkdev)
188 return (ENXIO);
189 /*
190 * When running in very secure mode, do not allow
191 * opens for writing of any disk block devices.
192 */
193 if (securelevel >= 2 && ap->a_cred != FSCRED &&
194 (ap->a_mode & FWRITE) && isdisk(dev, VBLK))
195 return (EPERM);
196 /*
197 * Do not allow opens of block devices that are
198 * currently mounted.
199 */
200 if (error = vfs_mountedon(vp))
201 return (error);
202 return ((*bdevsw[maj].d_open)(dev, ap->a_mode, S_IFBLK,
203 ap->a_p, ap->a_fp));
204 }
205 return (0);
206 }
207
208 /*
209 * Vnode op for read
210 */
211 /* ARGSUSED */
212 spec_read(ap)
213 struct vop_read_args /* {
214 struct vnode *a_vp;
215 struct uio *a_uio;
216 int a_ioflag;
217 struct ucred *a_cred;
218 } */ *ap;
219 {
220 register struct vnode *vp = ap->a_vp;
221 register struct uio *uio = ap->a_uio;
222 struct proc *p = uio->uio_procp;
223 struct buf *bp;
224 daddr_t bn, nextbn;
225 long bsize, bscale, ssize;
226 struct partinfo dpart;
227 int n, on, majordev, (*ioctl)();
228 int error = 0;
229 dev_t dev;
230
231 #ifdef DIAGNOSTIC
232 if (uio->uio_rw != UIO_READ)
233 panic("spec_read mode");
234 if (uio->uio_segflg == UIO_USERSPACE && uio->uio_procp != curproc)
235 panic("spec_read proc");
236 #endif
237 if (uio->uio_resid == 0)
238 return (0);
239
240 switch (vp->v_type) {
241
242 case VCHR:
243 VOP_UNLOCK(vp);
244 error = (*cdevsw[major(vp->v_rdev)].d_read)
245 (vp->v_rdev, uio, ap->a_ioflag);
246 VOP_LOCK(vp);
247 return (error);
248
249 case VBLK:
250 if (uio->uio_offset < 0)
251 return (EINVAL);
252 bsize = BLKDEV_IOSIZE;
253 ssize = DEV_BSIZE;
254 dev = vp->v_rdev;
255 if ((majordev = major(dev)) < nblkdev &&
256 (ioctl = bdevsw[majordev].d_ioctl) != NULL &&
257 (*ioctl)(dev, DIOCGPART, (caddr_t)&dpart, FREAD, p) == 0) {
258 if (dpart.part->p_fstype == FS_BSDFFS &&
259 dpart.part->p_frag != 0 && dpart.part->p_fsize != 0)
260 bsize = dpart.part->p_frag *
261 dpart.part->p_fsize;
262 if (dpart.disklab->d_secsize != 0)
263 ssize = dpart.disklab->d_secsize;
264 }
265 bscale = bsize / ssize;
266 do {
267 bn = (uio->uio_offset / ssize) &~ (bscale - 1);
268 on = uio->uio_offset % bsize;
269 n = min((unsigned)(bsize - on), uio->uio_resid);
270 if (vp->v_lastr + bscale == bn) {
271 nextbn = bn + bscale;
272 error = breadn(vp, bn, (int)bsize, &nextbn,
273 (int *)&bsize, 1, NOCRED, &bp);
274 } else
275 error = bread(vp, bn, (int)bsize, NOCRED, &bp);
276 vp->v_lastr = bn;
277 n = min(n, bsize - bp->b_resid);
278 if (error) {
279 brelse(bp);
280 return (error);
281 }
282 error = uiomove((char *)bp->b_data + on, n, uio);
283 if (n + on == bsize)
284 bp->b_flags |= B_AGE;
285 brelse(bp);
286 } while (error == 0 && uio->uio_resid > 0 && n != 0);
287 return (error);
288
289 default:
290 panic("spec_read type");
291 }
292 /* NOTREACHED */
293 }
294
295 /*
296 * Vnode op for write
297 */
298 /* ARGSUSED */
299 spec_write(ap)
300 struct vop_write_args /* {
301 struct vnode *a_vp;
302 struct uio *a_uio;
303 int a_ioflag;
304 struct ucred *a_cred;
305 } */ *ap;
306 {
307 register struct vnode *vp = ap->a_vp;
308 register struct uio *uio = ap->a_uio;
309 struct proc *p = uio->uio_procp;
310 struct buf *bp;
311 daddr_t bn;
312 int bsize, blkmask, ssize;
313 struct partinfo dpart;
314 register int n, on;
315 int error = 0;
316
317 #ifdef DIAGNOSTIC
318 if (uio->uio_rw != UIO_WRITE)
319 panic("spec_write mode");
320 if (uio->uio_segflg == UIO_USERSPACE && uio->uio_procp != curproc)
321 panic("spec_write proc");
322 #endif
323
324 switch (vp->v_type) {
325
326 case VCHR:
327 VOP_UNLOCK(vp);
328 error = (*cdevsw[major(vp->v_rdev)].d_write)
329 (vp->v_rdev, uio, ap->a_ioflag);
330 VOP_LOCK(vp);
331 return (error);
332
333 case VBLK:
334 if (uio->uio_resid == 0)
335 return (0);
336 if (uio->uio_offset < 0)
337 return (EINVAL);
338 bsize = BLKDEV_IOSIZE;
339 ssize = DEV_BSIZE;
340 if ((*bdevsw[major(vp->v_rdev)].d_ioctl)(vp->v_rdev, DIOCGPART,
341 (caddr_t)&dpart, FREAD, p) == 0) {
342 if (dpart.part->p_fstype == FS_BSDFFS &&
343 dpart.part->p_frag != 0 && dpart.part->p_fsize != 0)
344 bsize = dpart.part->p_frag *
345 dpart.part->p_fsize;
346 if (dpart.disklab->d_secsize != 0)
347 ssize = dpart.disklab->d_secsize;
348 }
349 blkmask = (bsize / ssize) - 1;
350 do {
351 bn = (uio->uio_offset / ssize) &~ blkmask;
352 on = uio->uio_offset % bsize;
353 n = min((unsigned)(bsize - on), uio->uio_resid);
354 if (n == bsize)
355 bp = getblk(vp, bn, bsize, 0, 0);
356 else
357 error = bread(vp, bn, bsize, NOCRED, &bp);
358 n = min(n, bsize - bp->b_resid);
359 if (error) {
360 brelse(bp);
361 return (error);
362 }
363 error = uiomove((char *)bp->b_data + on, n, uio);
364 if (n + on == bsize) {
365 bp->b_flags |= B_AGE;
366 bawrite(bp);
367 } else
368 bdwrite(bp);
369 } while (error == 0 && uio->uio_resid > 0 && n != 0);
370 return (error);
371
372 default:
373 panic("spec_write type");
374 }
375 /* NOTREACHED */
376 }
377
378 /*
379 * Device ioctl operation.
380 */
381 /* ARGSUSED */
382 spec_ioctl(ap)
383 struct vop_ioctl_args /* {
384 struct vnode *a_vp;
385 u_long a_command;
386 caddr_t a_data;
387 int a_fflag;
388 struct ucred *a_cred;
389 struct proc *a_p;
390 } */ *ap;
391 {
392 dev_t dev = ap->a_vp->v_rdev;
393
394 switch (ap->a_vp->v_type) {
395
396 case VCHR:
397 return ((*cdevsw[major(dev)].d_ioctl)(dev, ap->a_command, ap->a_data,
398 ap->a_fflag, ap->a_p));
399
400 case VBLK:
401 if (ap->a_command == 0 && (long)ap->a_data == B_TAPE)
402 if (bdevsw[major(dev)].d_flags & B_TAPE)
403 return (0);
404 else
405 return (1);
406 return ((*bdevsw[major(dev)].d_ioctl)(dev, ap->a_command, ap->a_data,
407 ap->a_fflag, ap->a_p));
408
409 default:
410 panic("spec_ioctl");
411 /* NOTREACHED */
412 }
413 }
414
415 /* ARGSUSED */
416 spec_select(ap)
417 struct vop_select_args /* {
418 struct vnode *a_vp;
419 int a_which;
420 int a_fflags;
421 struct ucred *a_cred;
422 struct proc *a_p;
423 } */ *ap;
424 {
425 register dev_t dev;
426
427 switch (ap->a_vp->v_type) {
428
429 default:
430 return (1); /* XXX */
431
432 case VCHR:
433 dev = ap->a_vp->v_rdev;
434 return (*cdevsw[major(dev)].d_select)(dev, ap->a_which, ap->a_p);
435 }
436 }
437 /*
438 * Synch buffers associated with a block device
439 */
440 /* ARGSUSED */
441 int
442 spec_fsync(ap)
443 struct vop_fsync_args /* {
444 struct vnode *a_vp;
445 struct ucred *a_cred;
446 int a_waitfor;
447 struct proc *a_p;
448 } */ *ap;
449 {
450 register struct vnode *vp = ap->a_vp;
451 register struct buf *bp;
452 struct buf *nbp;
453 int s;
454
455 if (vp->v_type == VCHR)
456 return (0);
457 /*
458 * Flush all dirty buffers associated with a block device.
459 */
460 loop:
461 s = splbio();
462 for (bp = vp->v_dirtyblkhd.lh_first; bp; bp = nbp) {
463 nbp = bp->b_vnbufs.le_next;
464 if ((bp->b_flags & B_BUSY))
465 continue;
466 if ((bp->b_flags & B_DELWRI) == 0)
467 panic("spec_fsync: not dirty");
468 bremfree(bp);
469 bp->b_flags |= B_BUSY;
470 splx(s);
471 bawrite(bp);
472 goto loop;
473 }
474 if (ap->a_waitfor == MNT_WAIT) {
475 while (vp->v_numoutput) {
476 vp->v_flag |= VBWAIT;
477 sleep((caddr_t)&vp->v_numoutput, PRIBIO + 1);
478 }
479 #ifdef DIAGNOSTIC
480 if (vp->v_dirtyblkhd.lh_first) {
481 vprint("spec_fsync: dirty", vp);
482 goto loop;
483 }
484 #endif
485 }
486 splx(s);
487 return (0);
488 }
489
490 /*
491 * Just call the device strategy routine
492 */
493 spec_strategy(ap)
494 struct vop_strategy_args /* {
495 struct buf *a_bp;
496 } */ *ap;
497 {
498
499 (*bdevsw[major(ap->a_bp->b_dev)].d_strategy)(ap->a_bp);
500 return (0);
501 }
502
503 /*
504 * This is a noop, simply returning what one has been given.
505 */
506 spec_bmap(ap)
507 struct vop_bmap_args /* {
508 struct vnode *a_vp;
509 daddr_t a_bn;
510 struct vnode **a_vpp;
511 daddr_t *a_bnp;
512 } */ *ap;
513 {
514
515 if (ap->a_vpp != NULL)
516 *ap->a_vpp = ap->a_vp;
517 if (ap->a_bnp != NULL)
518 *ap->a_bnp = ap->a_bn;
519 return (0);
520 }
521
522 /*
523 * At the moment we do not do any locking.
524 */
525 /* ARGSUSED */
526 spec_lock(ap)
527 struct vop_lock_args /* {
528 struct vnode *a_vp;
529 } */ *ap;
530 {
531
532 return (0);
533 }
534
535 /* ARGSUSED */
536 spec_unlock(ap)
537 struct vop_unlock_args /* {
538 struct vnode *a_vp;
539 } */ *ap;
540 {
541
542 return (0);
543 }
544
545 /*
546 * Device close routine
547 */
548 /* ARGSUSED */
549 spec_close(ap)
550 struct vop_close_args /* {
551 struct vnode *a_vp;
552 int a_fflag;
553 struct ucred *a_cred;
554 struct proc *a_p;
555 } */ *ap;
556 {
557 register struct vnode *vp = ap->a_vp;
558 dev_t dev = vp->v_rdev;
559 int (*devclose) __P((dev_t, int, int, struct proc *));
560 int mode, error;
561
562 switch (vp->v_type) {
563
564 case VCHR:
565 /*
566 * Hack: a tty device that is a controlling terminal
567 * has a reference from the session structure.
568 * We cannot easily tell that a character device is
569 * a controlling terminal, unless it is the closing
570 * process' controlling terminal. In that case,
571 * if the reference count is 2 (this last descriptor
572 * plus the session), release the reference from the session.
573 */
574 if (vcount(vp) == 2 && ap->a_p &&
575 vp == ap->a_p->p_session->s_ttyvp) {
576 vrele(vp);
577 ap->a_p->p_session->s_ttyvp = NULL;
578 }
579 /*
580 * If the vnode is locked, then we are in the midst
581 * of forcably closing the device, otherwise we only
582 * close on last reference.
583 */
584 if (vcount(vp) > 1 && (vp->v_flag & VXLOCK) == 0)
585 return (0);
586 devclose = cdevsw[major(dev)].d_close;
587 mode = S_IFCHR;
588 break;
589
590 case VBLK:
591 /*
592 * On last close of a block device (that isn't mounted)
593 * we must invalidate any in core blocks, so that
594 * we can, for instance, change floppy disks.
595 */
596 if (error = vinvalbuf(vp, V_SAVE, ap->a_cred, ap->a_p, 0, 0))
597 return (error);
598 /*
599 * We do not want to really close the device if it
600 * is still in use unless we are trying to close it
601 * forcibly. Since every use (buffer, vnode, swap, cmap)
602 * holds a reference to the vnode, and because we mark
603 * any other vnodes that alias this device, when the
604 * sum of the reference counts on all the aliased
605 * vnodes descends to one, we are on last close.
606 */
607 if (vcount(vp) > 1 && (vp->v_flag & VXLOCK) == 0)
608 return (0);
609 devclose = bdevsw[major(dev)].d_close;
610 mode = S_IFBLK;
611 break;
612
613 default:
614 panic("spec_close: not special");
615 }
616
617 return ((*devclose)(dev, ap->a_fflag, mode, ap->a_p));
618 }
619
620 /*
621 * Print out the contents of a special device vnode.
622 */
623 spec_print(ap)
624 struct vop_print_args /* {
625 struct vnode *a_vp;
626 } */ *ap;
627 {
628
629 printf("tag VT_NON, dev %d, %d\n", major(ap->a_vp->v_rdev),
630 minor(ap->a_vp->v_rdev));
631 }
632
633 /*
634 * Return POSIX pathconf information applicable to special devices.
635 */
636 spec_pathconf(ap)
637 struct vop_pathconf_args /* {
638 struct vnode *a_vp;
639 int a_name;
640 register_t *a_retval;
641 } */ *ap;
642 {
643
644 switch (ap->a_name) {
645 case _PC_LINK_MAX:
646 *ap->a_retval = LINK_MAX;
647 return (0);
648 case _PC_MAX_CANON:
649 *ap->a_retval = MAX_CANON;
650 return (0);
651 case _PC_MAX_INPUT:
652 *ap->a_retval = MAX_INPUT;
653 return (0);
654 case _PC_PIPE_BUF:
655 *ap->a_retval = PIPE_BUF;
656 return (0);
657 case _PC_CHOWN_RESTRICTED:
658 *ap->a_retval = 1;
659 return (0);
660 case _PC_VDISABLE:
661 *ap->a_retval = _POSIX_VDISABLE;
662 return (0);
663 default:
664 return (EINVAL);
665 }
666 /* NOTREACHED */
667 }
668
669 /*
670 * Special device advisory byte-level locks.
671 */
672 /* ARGSUSED */
673 spec_advlock(ap)
674 struct vop_advlock_args /* {
675 struct vnode *a_vp;
676 caddr_t a_id;
677 int a_op;
678 struct flock *a_fl;
679 int a_flags;
680 } */ *ap;
681 {
682
683 return (EOPNOTSUPP);
684 }
685
686 /*
687 * Special device failed operation
688 */
689 spec_ebadf()
690 {
691
692 return (EBADF);
693 }
694
695 /*
696 * Special device bad operation
697 */
698 spec_badop()
699 {
700
701 panic("spec_badop called");
702 /* NOTREACHED */
703 }
704