Annotation of kernel/bsd/miscfs/specfs/spec_vnops.c, revision 1.1.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.