Annotation of kernel/bsd/miscfs/specfs/spec_vnops.c, revision 1.1

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

unix.superglobalmegacorp.com

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