Annotation of XNU/bsd/miscfs/specfs/spec_vnops.c, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.