|
|
1.1 root 1: /*
2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7: * Reserved. This file contains Original Code and/or Modifications of
8: * Original Code as defined in and that are subject to the Apple Public
9: * Source License Version 1.1 (the "License"). You may not use this file
10: * except in compliance with the License. Please obtain a copy of the
11: * License at http://www.apple.com/publicsource and read it before using
12: * this file.
13: *
14: * The Original Code and all software distributed under the License are
15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19: * License for the specific language governing rights and limitations
20: * under the License.
21: *
22: * @APPLE_LICENSE_HEADER_END@
23: */
24:
25: /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
26: /*
27: * Copyright (c) 1989, 1993, 1995
28: * The Regents of the University of California. All rights reserved.
29: *
30: * Redistribution and use in source and binary forms, with or without
31: * modification, are permitted provided that the following conditions
32: * are met:
33: * 1. Redistributions of source code must retain the above copyright
34: * notice, this list of conditions and the following disclaimer.
35: * 2. Redistributions in binary form must reproduce the above copyright
36: * notice, this list of conditions and the following disclaimer in the
37: * documentation and/or other materials provided with the distribution.
38: * 3. All advertising materials mentioning features or use of this software
39: * must display the following acknowledgement:
40: * This product includes software developed by the University of
41: * California, Berkeley and its contributors.
42: * 4. Neither the name of the University nor the names of its contributors
43: * may be used to endorse or promote products derived from this software
44: * without specific prior written permission.
45: *
46: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
47: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
48: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
49: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
50: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
51: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
52: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
53: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
54: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
55: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
56: * SUCH DAMAGE.
57: *
58: * @(#)spec_vnops.c 8.14 (Berkeley) 5/21/95
59: */
60:
61: #include <sys/param.h>
62: #include <sys/proc.h>
63: #include <sys/systm.h>
64: #include <sys/kernel.h>
65: #include <sys/conf.h>
66: #include <sys/buf.h>
67: #include <sys/mount.h>
68: #include <sys/namei.h>
69: #include <sys/vnode.h>
70: #include <sys/stat.h>
71: #include <sys/errno.h>
72: #include <sys/ioctl.h>
73: #include <sys/file.h>
74: #ifdef NeXT
75: #include <sys/malloc.h>
76: #include <bsd/dev/disk.h>
77: #else
78: #include <sys/disklabel.h>
79: #endif
80: #include <miscfs/specfs/specdev.h>
81: #include <vfs/vfs_support.h>
82:
83: #ifdef NeXT
84: extern int doclusterread, doclusterwrite;
85: #endif
86:
87: struct vnode *speclisth[SPECHSZ];
88:
89: /* symbolic sleep message strings for devices */
90: char devopn[] = "devopn";
91: char devio[] = "devio";
92: char devwait[] = "devwait";
93: char devin[] = "devin";
94: char devout[] = "devout";
95: char devioc[] = "devioc";
96: char devcls[] = "devcls";
97:
98: int (**spec_vnodeop_p)();
99: struct vnodeopv_entry_desc spec_vnodeop_entries[] = {
100: { &vop_default_desc, vn_default_error },
101: { &vop_lookup_desc, spec_lookup }, /* lookup */
102: { &vop_create_desc, err_create }, /* create */
103: { &vop_mknod_desc, err_mknod }, /* mknod */
104: { &vop_open_desc, spec_open }, /* open */
105: { &vop_close_desc, spec_close }, /* close */
106: { &vop_access_desc, spec_access }, /* access */
107: { &vop_getattr_desc, spec_getattr }, /* getattr */
108: { &vop_setattr_desc, spec_setattr }, /* setattr */
109: { &vop_read_desc, spec_read }, /* read */
110: { &vop_write_desc, spec_write }, /* write */
111: { &vop_lease_desc, nop_lease }, /* lease */
112: { &vop_ioctl_desc, spec_ioctl }, /* ioctl */
113: { &vop_select_desc, spec_select }, /* select */
114: { &vop_revoke_desc, nop_revoke }, /* revoke */
115: { &vop_mmap_desc, err_mmap }, /* mmap */
116: { &vop_fsync_desc, spec_fsync }, /* fsync */
117: { &vop_seek_desc, err_seek }, /* seek */
118: { &vop_remove_desc, err_remove }, /* remove */
119: { &vop_link_desc, err_link }, /* link */
120: { &vop_rename_desc, err_rename }, /* rename */
121: { &vop_mkdir_desc, err_mkdir }, /* mkdir */
122: { &vop_rmdir_desc, err_rmdir }, /* rmdir */
123: { &vop_symlink_desc, err_symlink }, /* symlink */
124: { &vop_readdir_desc, err_readdir }, /* readdir */
125: { &vop_readlink_desc, err_readlink }, /* readlink */
126: { &vop_abortop_desc, err_abortop }, /* abortop */
127: { &vop_inactive_desc, nop_inactive }, /* inactive */
128: { &vop_reclaim_desc, nop_reclaim }, /* reclaim */
129: { &vop_lock_desc, nop_lock }, /* lock */
130: { &vop_unlock_desc, nop_unlock }, /* unlock */
131: { &vop_bmap_desc, spec_bmap }, /* bmap */
132: { &vop_strategy_desc, spec_strategy }, /* strategy */
133: { &vop_print_desc, spec_print }, /* print */
134: { &vop_islocked_desc, nop_islocked }, /* islocked */
135: { &vop_pathconf_desc, spec_pathconf }, /* pathconf */
136: { &vop_advlock_desc, err_advlock }, /* advlock */
137: { &vop_blkatoff_desc, err_blkatoff }, /* blkatoff */
138: { &vop_valloc_desc, err_valloc }, /* valloc */
139: { &vop_vfree_desc, err_vfree }, /* vfree */
140: { &vop_truncate_desc, nop_truncate }, /* truncate */
141: { &vop_update_desc, nop_update }, /* update */
142: { &vop_bwrite_desc, spec_bwrite }, /* bwrite */
143: #ifdef NeXT
144: { &vop_devblocksize_desc, spec_devblocksize }, /* devblocksize */
145: #endif /* NeXT */
146: { &vop_pagein_desc, spec_pagein }, /* Pagein */
147: { &vop_pageout_desc, spec_pageout }, /* Pageout */
148: { (struct vnodeop_desc*)NULL, (int(*)())NULL }
149: };
150: struct vnodeopv_desc spec_vnodeop_opv_desc =
151: { &spec_vnodeop_p, spec_vnodeop_entries };
152:
153: /*
154: * Trivial lookup routine that always fails.
155: */
156: int
157: spec_lookup(ap)
158: struct vop_lookup_args /* {
159: struct vnode *a_dvp;
160: struct vnode **a_vpp;
161: struct componentname *a_cnp;
162: } */ *ap;
163: {
164:
165: *ap->a_vpp = NULL;
166: return (ENOTDIR);
167: }
168:
169: #ifdef NeXT
170: void
171: set_blocksize(struct vnode *vp, dev_t dev)
172: {
173: int (*size)();
174: int rsize;
175:
176: if ((major(dev) < nblkdev) && (size = bdevsw[major(dev)].d_psize)) {
177: rsize = (*size)(dev);
178: if (rsize <= 0) /* did size fail? */
179: vp->v_specsize = DEV_BSIZE;
180: else
181: vp->v_specsize = rsize;
182: }
183: else
184: vp->v_specsize = DEV_BSIZE;
185: }
186: #endif /* NeXT */
187:
188: /*
189: * Open a special file.
190: */
191: /* ARGSUSED */
192: spec_open(ap)
193: struct vop_open_args /* {
194: struct vnode *a_vp;
195: int a_mode;
196: struct ucred *a_cred;
197: struct proc *a_p;
198: } */ *ap;
199: {
200: struct proc *p = ap->a_p;
201: struct vnode *bvp, *vp = ap->a_vp;
202: dev_t bdev, dev = (dev_t)vp->v_rdev;
203: int maj = major(dev);
204: int error;
205:
206: /*
207: * Don't allow open if fs is mounted -nodev.
208: */
209: if (vp->v_mount && (vp->v_mount->mnt_flag & MNT_NODEV))
210: return (ENXIO);
211:
212: switch (vp->v_type) {
213:
214: case VCHR:
215: if ((u_int)maj >= nchrdev)
216: return (ENXIO);
217: if (ap->a_cred != FSCRED && (ap->a_mode & FWRITE)) {
218: /*
219: * When running in very secure mode, do not allow
220: * opens for writing of any disk character devices.
221: */
222: if (securelevel >= 2 && isdisk(dev, VCHR))
223: return (EPERM);
224: /*
225: * When running in secure mode, do not allow opens
226: * for writing of /dev/mem, /dev/kmem, or character
227: * devices whose corresponding block devices are
228: * currently mounted.
229: */
230: if (securelevel >= 1) {
231: if ((bdev = chrtoblk(dev)) != NODEV &&
232: vfinddev(bdev, VBLK, &bvp) &&
233: bvp->v_usecount > 0 &&
234: (error = vfs_mountedon(bvp)))
235: return (error);
236: if (iskmemdev(dev))
237: return (EPERM);
238: }
239: }
240: if (cdevsw[maj].d_type == D_TTY)
241: vp->v_flag |= VISTTY;
242: VOP_UNLOCK(vp, 0, p);
243: error = (*cdevsw[maj].d_open)(dev, ap->a_mode, S_IFCHR, p);
244: vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
245: return (error);
246:
247: case VBLK:
248: if ((u_int)maj >= nblkdev)
249: return (ENXIO);
250: /*
251: * When running in very secure mode, do not allow
252: * opens for writing of any disk block devices.
253: */
254: if (securelevel >= 2 && ap->a_cred != FSCRED &&
255: (ap->a_mode & FWRITE) && bdevsw[maj].d_type == D_DISK)
256: return (EPERM);
257: /*
258: * Do not allow opens of block devices that are
259: * currently mounted.
260: */
261: if (error = vfs_mountedon(vp))
262: return (error);
263: #ifdef NeXT
264: error = (*bdevsw[maj].d_open)(dev, ap->a_mode, S_IFBLK, p);
265: if (!error) {
266: set_blocksize(vp, dev);
267: }
268: return(error);
269: #else
270: return ((*bdevsw[maj].d_open)(dev, ap->a_mode, S_IFBLK, p));
271: #endif /* NeXT */
272: }
273: return (0);
274: }
275:
276: /*
277: * Vnode op for read
278: */
279: /* ARGSUSED */
280: spec_read(ap)
281: struct vop_read_args /* {
282: struct vnode *a_vp;
283: struct uio *a_uio;
284: int a_ioflag;
285: struct ucred *a_cred;
286: } */ *ap;
287: {
288: register struct vnode *vp = ap->a_vp;
289: register struct uio *uio = ap->a_uio;
290: struct proc *p = uio->uio_procp;
291: struct buf *bp;
292: daddr_t bn, nextbn;
293: long bsize, bscale;
294: #ifdef NeXT
295: int devBlockSize=0;
296: int firstpass, seq;
297: #else
298: struct partinfo dpart;
299: #endif /* NeXT */
300: int n, on, majordev, (*ioctl)();
301: int error = 0;
302: dev_t dev;
303:
304: #if DIAGNOSTIC
305: if (uio->uio_rw != UIO_READ)
306: panic("spec_read mode");
307: if (uio->uio_segflg == UIO_USERSPACE && uio->uio_procp != current_proc())
308: panic("spec_read proc");
309: #endif
310: if (uio->uio_resid == 0)
311: return (0);
312:
313: switch (vp->v_type) {
314:
315: case VCHR:
316: VOP_UNLOCK(vp, 0, p);
317: error = (*cdevsw[major(vp->v_rdev)].d_read)
318: (vp->v_rdev, uio, ap->a_ioflag);
319: vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
320: return (error);
321:
322: case VBLK:
323: if (uio->uio_offset < 0)
324: return (EINVAL);
325: #ifdef NeXT
326: bsize = PAGE_SIZE;
327: #else
328: bsize = BLKDEV_IOSIZE;
329: #endif /* NeXT */
330:
331: dev = vp->v_rdev;
332: #ifndef NeXT
333: if ((majordev = major(dev)) < nblkdev &&
334: (ioctl = bdevsw[majordev].d_ioctl) != NULL &&
335: (*ioctl)(dev, DIOCGPART, (caddr_t)&dpart, FREAD, p) == 0 &&
336: dpart.part->p_fstype == FS_BSDFFS &&
337: dpart.part->p_frag != 0 && dpart.part->p_fsize != 0)
338: bsize = dpart.part->p_frag * dpart.part->p_fsize;
339: #endif /* NeXT */
340: #ifdef NeXT /*[ */
341: devBlockSize = vp->v_specsize;
342: bscale = bsize / devBlockSize;
343: firstpass = TRUE;
344:
345: do {
346: on = uio->uio_offset % bsize;
347:
348: if (doclusterread && doclusterwrite) {
349: bn = uio->uio_offset / bsize;
350:
351: error = cluster_read(vp, (u_quad_t)0x7fffffffffffffff, bn, bsize, NOCRED,
352: &bp, devBlockSize, firstpass, uio->uio_resid+on, &seq);
353: } else {
354: bn = (uio->uio_offset / devBlockSize) &~ (bscale - 1);
355:
356: if (vp->v_lastr + bscale == bn) {
357: nextbn = bn + bscale;
358: error = breadn(vp, bn, (int)bsize, &nextbn,
359: (int *)&bsize, 1, NOCRED, &bp);
360: } else
361: error = bread(vp, bn, (int)bsize, NOCRED, &bp);
362: }
363: firstpass = FALSE;
364:
365: vp->v_lastr = bn;
366: n = bsize - bp->b_resid;
367: if ((on > n) || error) {
368: if (!error)
369: error = EINVAL;
370: brelse(bp);
371: return (error);
372: }
373: n = min((unsigned)(n - on), uio->uio_resid);
374:
375: error = uiomove((char *)bp->b_data + on, n, uio);
376: if (n + on == bsize)
377: bp->b_flags |= B_AGE;
378: brelse(bp);
379: } while (error == 0 && uio->uio_resid > 0 && n != 0);
380: #else /*][ */
381: bscale = bsize / DEV_BSIZE;
382: do {
383: bn = (uio->uio_offset / DEV_BSIZE) &~ (bscale - 1);
384: on = uio->uio_offset % bsize;
385: n = min((unsigned)(bsize - on), uio->uio_resid);
386: if (vp->v_lastr + bscale == bn) {
387: nextbn = bn + bscale;
388: error = breadn(vp, bn, (int)bsize, &nextbn,
389: (int *)&bsize, 1, NOCRED, &bp);
390: } else
391: error = bread(vp, bn, (int)bsize, NOCRED, &bp);
392: vp->v_lastr = bn;
393: n = min(n, bsize - bp->b_resid);
394: if (error) {
395: brelse(bp);
396: return (error);
397: }
398: error = uiomove((char *)bp->b_data + on, n, uio);
399: if (n + on == bsize)
400: bp->b_flags |= B_AGE;
401: brelse(bp);
402: } while (error == 0 && uio->uio_resid > 0 && n != 0);
403: #endif NeXT /* ] */
404: return (error);
405:
406: default:
407: panic("spec_read type");
408: }
409: /* NOTREACHED */
410: }
411:
412: /*
413: * Vnode op for write
414: */
415: /* ARGSUSED */
416: spec_write(ap)
417: struct vop_write_args /* {
418: struct vnode *a_vp;
419: struct uio *a_uio;
420: int a_ioflag;
421: struct ucred *a_cred;
422: } */ *ap;
423: {
424: register struct vnode *vp = ap->a_vp;
425: register struct uio *uio = ap->a_uio;
426: struct proc *p = uio->uio_procp;
427: struct buf *bp;
428: daddr_t bn;
429: int bsize, blkmask;
430: #ifdef NeXT
431: register int io_sync;
432: register int io_size;
433: register int forcewrite;
434: int devBlockSize=0;
435: #else
436: struct partinfo dpart;
437: #endif
438: register int n, on;
439: int error = 0;
440: dev_t dev;
441:
442: #if DIAGNOSTIC
443: if (uio->uio_rw != UIO_WRITE)
444: panic("spec_write mode");
445: if (uio->uio_segflg == UIO_USERSPACE && uio->uio_procp != current_proc())
446: panic("spec_write proc");
447: #endif
448:
449: switch (vp->v_type) {
450:
451: case VCHR:
452: VOP_UNLOCK(vp, 0, p);
453: error = (*cdevsw[major(vp->v_rdev)].d_write)
454: (vp->v_rdev, uio, ap->a_ioflag);
455: vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
456: return (error);
457:
458: case VBLK:
459: if (uio->uio_resid == 0)
460: return (0);
461: if (uio->uio_offset < 0)
462: return (EINVAL);
463:
464: #ifdef NeXT
465: bsize = PAGE_SIZE;
466: io_sync = (ap->a_ioflag & IO_SYNC);
467: io_size = uio->uio_resid;
468: #else
469: bsize = BLKDEV_IOSIZE;
470: #endif /* NeXT */
471: dev = (vp->v_rdev);
472: #ifndef NeXT
473: if ((*bdevsw[major(vp->v_rdev)].d_ioctl)(vp->v_rdev, DIOCGPART,
474: (caddr_t)&dpart, FREAD, p) == 0) {
475: if (dpart.part->p_fstype == FS_BSDFFS &&
476: dpart.part->p_frag != 0 && dpart.part->p_fsize != 0)
477: bsize = dpart.part->p_frag *
478: dpart.part->p_fsize;
479: }
480: #endif /* NeXT */
481: #ifdef NeXT /* [ */
482: devBlockSize = vp->v_specsize;
483: blkmask = (bsize / devBlockSize) - 1;
484:
485: do {
486: forcewrite = 0;
487:
488: if (doclusterread && doclusterwrite)
489: bn = uio->uio_offset / bsize;
490: else
491: bn = (uio->uio_offset / devBlockSize) &~ blkmask;
492: on = uio->uio_offset % bsize;
493:
494: n = min((unsigned)(bsize - on), uio->uio_resid);
495:
496: if (doclusterread && doclusterwrite) {
497: bp = getblk(vp, bn, bsize, 0, 0);
498:
499: VOP_BMAP(vp, bn, NULL, &bp->b_blkno, NULL);
500:
501: if (n != bsize && !(bp->b_flags & (B_DONE|B_DELWRI))) {
502: if ((on % devBlockSize) || (n % devBlockSize)) {
503: bp->b_flags |= B_READ;
504: VOP_STRATEGY(bp);
505: error = biowait(bp);
506: } else {
507: if (on) {
508: bp->b_blkno += (on / devBlockSize);
509: on = 0;
510: }
511: forcewrite = 1;
512: bp->b_bcount = n;
513: bp->b_flags |= B_INVAL;
514: }
515: }
516: } else {
517: if (n == bsize)
518: bp = getblk(vp, bn, bsize, 0, 0);
519: else
520: error = bread(vp, bn, bsize, NOCRED, &bp);
521: }
522: if (error) {
523: brelse(bp);
524: return (error);
525: }
526: n = min(n, bsize - bp->b_resid);
527:
528: error = uiomove((char *)bp->b_data + on, n, uio);
529:
530: if (forcewrite) {
531: if (uio->uio_resid == 0)
532: bwrite(bp);
533: else
534: bawrite(bp);
535: } else if (((io_size >= bsize) || ((n + on) == bsize)) && doclusterread && doclusterwrite) {
536: if (io_sync) {
537: if (uio->uio_resid < bsize)
538: bp->b_flags |= (B_CLUST_SYNC | B_CLUST_COMMIT);
539: else
540: bp->b_flags |= B_CLUST_SYNC;
541:
542: error = cluster_write(bp, (u_quad_t)0x7fffffffffffffff, devBlockSize);
543: } else
544: cluster_write(bp, (u_quad_t)0x7fffffffffffffff, devBlockSize);
545: } else {
546: bp->b_flags |= B_AGE;
547:
548: if (io_sync)
549: bwrite(bp);
550: else {
551: if ((n + on) == bsize)
552: bawrite(bp);
553: else
554: bdwrite(bp);
555: }
556: }
557: } while (error == 0 && uio->uio_resid > 0 && n != 0);
558: #else /*][ */
559: blkmask = (bsize / DEV_BSIZE) - 1;
560: do {
561: bn = (uio->uio_offset / DEV_BSIZE) &~ blkmask;
562: on = uio->uio_offset % bsize;
563: n = min((unsigned)(bsize - on), uio->uio_resid);
564: if (n == bsize)
565: bp = getblk(vp, bn, bsize, 0, 0);
566: else
567: error = bread(vp, bn, bsize, NOCRED, &bp);
568: n = min(n, bsize - bp->b_resid);
569: if (error) {
570: brelse(bp);
571: return (error);
572: }
573: error = uiomove((char *)bp->b_data + on, n, uio);
574: if (n + on == bsize) {
575: bp->b_flags |= B_AGE;
576: bawrite(bp);
577: } else
578: bdwrite(bp);
579: } while (error == 0 && uio->uio_resid > 0 && n != 0);
580: #endif NeXT /* ] */
581: return (error);
582:
583: default:
584: panic("spec_write type");
585: }
586: /* NOTREACHED */
587: }
588:
589: /*
590: * Device ioctl operation.
591: */
592: /* ARGSUSED */
593: spec_ioctl(ap)
594: struct vop_ioctl_args /* {
595: struct vnode *a_vp;
596: int a_command;
597: caddr_t a_data;
598: int a_fflag;
599: struct ucred *a_cred;
600: struct proc *a_p;
601: } */ *ap;
602: {
603: dev_t dev = ap->a_vp->v_rdev;
604:
605: switch (ap->a_vp->v_type) {
606:
607: case VCHR:
608: return ((*cdevsw[major(dev)].d_ioctl)(dev, ap->a_command, ap->a_data,
609: ap->a_fflag, ap->a_p));
610:
611: case VBLK:
612: if (ap->a_command == 0 && (int)ap->a_data == B_TAPE)
613: if (bdevsw[major(dev)].d_type == D_TAPE)
614: return (0);
615: else
616: return (1);
617: return ((*bdevsw[major(dev)].d_ioctl)(dev, ap->a_command, ap->a_data,
618: ap->a_fflag, ap->a_p));
619:
620: default:
621: panic("spec_ioctl");
622: /* NOTREACHED */
623: }
624: }
625:
626: /* ARGSUSED */
627: spec_select(ap)
628: struct vop_select_args /* {
629: struct vnode *a_vp;
630: int a_which;
631: int a_fflags;
632: struct ucred *a_cred;
633: struct proc *a_p;
634: } */ *ap;
635: {
636: register dev_t dev;
637:
638: switch (ap->a_vp->v_type) {
639:
640: default:
641: return (1); /* XXX */
642:
643: case VCHR:
644: dev = ap->a_vp->v_rdev;
645: return (*cdevsw[major(dev)].d_select)(dev, ap->a_which, ap->a_p);
646: }
647: }
648: /*
649: * Synch buffers associated with a block device
650: */
651: /* ARGSUSED */
652: int
653: spec_fsync(ap)
654: struct vop_fsync_args /* {
655: struct vnode *a_vp;
656: struct ucred *a_cred;
657: int a_waitfor;
658: struct proc *a_p;
659: } */ *ap;
660: {
661: register struct vnode *vp = ap->a_vp;
662: register struct buf *bp;
663: struct buf *nbp;
664: int s;
665:
666: if (vp->v_type == VCHR)
667: return (0);
668: /*
669: * Flush all dirty buffers associated with a block device.
670: */
671: loop:
672: s = splbio();
673: for (bp = vp->v_dirtyblkhd.lh_first; bp; bp = nbp) {
674: nbp = bp->b_vnbufs.le_next;
675: if ((bp->b_flags & B_BUSY))
676: continue;
677: if ((bp->b_flags & B_DELWRI) == 0)
678: panic("spec_fsync: not dirty");
679: bremfree(bp);
680: bp->b_flags |= B_BUSY;
681: splx(s);
682: bawrite(bp);
683: goto loop;
684: }
685: if (ap->a_waitfor == MNT_WAIT) {
686: while (vp->v_numoutput) {
687: vp->v_flag |= VBWAIT;
688: tsleep((caddr_t)&vp->v_numoutput, PRIBIO + 1, "spec_fsync", 0);
689: }
690: #if DIAGNOSTIC
691: if (vp->v_dirtyblkhd.lh_first) {
692: vprint("spec_fsync: dirty", vp);
693: splx(s);
694: goto loop;
695: }
696: #endif
697: }
698: splx(s);
699: return (0);
700: }
701:
702: /*
703: * Just call the device strategy routine
704: */
705: spec_strategy(ap)
706: struct vop_strategy_args /* {
707: struct buf *a_bp;
708: } */ *ap;
709: {
710: (*bdevsw[major(ap->a_bp->b_dev)].d_strategy)(ap->a_bp);
711: return (0);
712: }
713:
714: /*
715: * This is a noop, simply returning what one has been given.
716: */
717: spec_bmap(ap)
718: struct vop_bmap_args /* {
719: struct vnode *a_vp;
720: daddr_t a_bn;
721: struct vnode **a_vpp;
722: daddr_t *a_bnp;
723: int *a_runp;
724: } */ *ap;
725: {
726:
727: if (ap->a_vpp != NULL)
728: *ap->a_vpp = ap->a_vp;
729: if (ap->a_bnp != NULL)
730: #ifdef NeXT
731: *ap->a_bnp = ap->a_bn * (PAGE_SIZE / ap->a_vp->v_specsize);
732: #else
733: *ap->a_bnp = ap->a_bn;
734: #endif
735: if (ap->a_runp != NULL)
736: #ifdef NeXT
737: *ap->a_runp = (MAXPHYSIO / PAGE_SIZE) - 1;
738: #else
739: *ap->a_runp = 0;
740: #endif
741: return (0);
742: }
743:
744: /*
745: * Device close routine
746: */
747: /* ARGSUSED */
748: spec_close(ap)
749: struct vop_close_args /* {
750: struct vnode *a_vp;
751: int a_fflag;
752: struct ucred *a_cred;
753: struct proc *a_p;
754: } */ *ap;
755: {
756: register struct vnode *vp = ap->a_vp;
757: dev_t dev = vp->v_rdev;
758: int (*devclose) __P((dev_t, int, int, struct proc *));
759: int mode, error;
760:
761: switch (vp->v_type) {
762:
763: case VCHR:
764: /*
765: * Hack: a tty device that is a controlling terminal
766: * has a reference from the session structure.
767: * We cannot easily tell that a character device is
768: * a controlling terminal, unless it is the closing
769: * process' controlling terminal. In that case,
770: * if the reference count is 2 (this last descriptor
771: * plus the session), release the reference from the session.
772: */
773: if (vcount(vp) == 2 && ap->a_p &&
774: vp == ap->a_p->p_session->s_ttyvp) {
775: vrele(vp);
776: ap->a_p->p_session->s_ttyvp = NULL;
777: }
778: /*
779: * If the vnode is locked, then we are in the midst
780: * of forcably closing the device, otherwise we only
781: * close on last reference.
782: */
783: if (vcount(vp) > 1 && (vp->v_flag & VXLOCK) == 0)
784: return (0);
785: devclose = cdevsw[major(dev)].d_close;
786: mode = S_IFCHR;
787: break;
788:
789: case VBLK:
790: /*
791: * On last close of a block device (that isn't mounted)
792: * we must invalidate any in core blocks, so that
793: * we can, for instance, change floppy disks.
794: */
795: if (error = vinvalbuf(vp, V_SAVE, ap->a_cred, ap->a_p, 0, 0))
796: return (error);
797: /*
798: * We do not want to really close the device if it
799: * is still in use unless we are trying to close it
800: * forcibly. Since every use (buffer, vnode, swap, cmap)
801: * holds a reference to the vnode, and because we mark
802: * any other vnodes that alias this device, when the
803: * sum of the reference counts on all the aliased
804: * vnodes descends to one, we are on last close.
805: */
806: if (vcount(vp) > 1 && (vp->v_flag & VXLOCK) == 0)
807: return (0);
808: devclose = bdevsw[major(dev)].d_close;
809: mode = S_IFBLK;
810: break;
811:
812: default:
813: panic("spec_close: not special");
814: }
815:
816: return ((*devclose)(dev, ap->a_fflag, mode, ap->a_p));
817: }
818:
819: /*
820: * Print out the contents of a special device vnode.
821: */
822: spec_print(ap)
823: struct vop_print_args /* {
824: struct vnode *a_vp;
825: } */ *ap;
826: {
827:
828: printf("tag VT_NON, dev %d, %d\n", major(ap->a_vp->v_rdev),
829: minor(ap->a_vp->v_rdev));
830: }
831:
832: /*
833: * Return POSIX pathconf information applicable to special devices.
834: */
835: spec_pathconf(ap)
836: struct vop_pathconf_args /* {
837: struct vnode *a_vp;
838: int a_name;
839: int *a_retval;
840: } */ *ap;
841: {
842:
843: switch (ap->a_name) {
844: case _PC_LINK_MAX:
845: *ap->a_retval = LINK_MAX;
846: return (0);
847: case _PC_MAX_CANON:
848: *ap->a_retval = MAX_CANON;
849: return (0);
850: case _PC_MAX_INPUT:
851: *ap->a_retval = MAX_INPUT;
852: return (0);
853: case _PC_PIPE_BUF:
854: *ap->a_retval = PIPE_BUF;
855: return (0);
856: case _PC_CHOWN_RESTRICTED:
857: *ap->a_retval = 1;
858: return (0);
859: case _PC_VDISABLE:
860: *ap->a_retval = _POSIX_VDISABLE;
861: return (0);
862: default:
863: return (EINVAL);
864: }
865: /* NOTREACHED */
866: }
867:
868: int
869: spec_devblocksize(ap)
870: struct vop_devblocksize_args /* {
871: struct vnode *a_vp;
872: int *a_retval;
873: } */ *ap;
874: {
875: *ap->a_retval = (ap->a_vp->v_specsize);
876: return (0);
877: }
878:
879: /*
880: * Special device failed operation
881: */
882: spec_ebadf()
883: {
884:
885: return (EBADF);
886: }
887:
888: /*
889: * Special device bad operation
890: */
891: spec_badop()
892: {
893:
894: panic("spec_badop called");
895: /* NOTREACHED */
896: }
897: /* Pagein */
898: spec_pagein(ap)
899: struct vop_pagein_args /* {
900: struct vnode *a_vp;
901: struct uio *a_uio;
902: int a_ioflag;
903: struct ucred *a_cred;
904: } */ *ap;
905: {
906: /* pass thru to read */
907: return (VOP_READ(ap->a_vp, ap->a_uio, ap->a_ioflag, ap->a_cred));
908: }
909:
910: /* Pageout */
911: spec_pageout(ap)
912: struct vop_pageout_args /* {
913: struct vnode *a_vp;
914: struct uio *a_uio;
915: int a_ioflag;
916: struct ucred *a_cred;
917: } */ *ap;
918: {
919: /* pass thru to write */
920: return (VOP_WRITE(ap->a_vp, ap->a_uio, ap->a_ioflag, ap->a_cred));
921: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.