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