[BACK]Return to spec_vnops.c CVS log [TXT][DIR] Up to [local] / sys / miscfs / specfs

Annotation of sys/miscfs/specfs/spec_vnops.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: spec_vnops.c,v 1.43 2007/06/18 08:30:07 jasper Exp $  */
        !             2: /*     $NetBSD: spec_vnops.c,v 1.29 1996/04/22 01:42:38 christos Exp $ */
        !             3:
        !             4: /*
        !             5:  * Copyright (c) 1989, 1993
        !             6:  *     The Regents of the University of California.  All rights reserved.
        !             7:  *
        !             8:  * Redistribution and use in source and binary forms, with or without
        !             9:  * modification, are permitted provided that the following conditions
        !            10:  * are met:
        !            11:  * 1. Redistributions of source code must retain the above copyright
        !            12:  *    notice, this list of conditions and the following disclaimer.
        !            13:  * 2. Redistributions in binary form must reproduce the above copyright
        !            14:  *    notice, this list of conditions and the following disclaimer in the
        !            15:  *    documentation and/or other materials provided with the distribution.
        !            16:  * 3. Neither the name of the University nor the names of its contributors
        !            17:  *    may be used to endorse or promote products derived from this software
        !            18:  *    without specific prior written permission.
        !            19:  *
        !            20:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
        !            21:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            22:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            23:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
        !            24:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            25:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            26:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            27:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            28:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            29:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            30:  * SUCH DAMAGE.
        !            31:  *
        !            32:  *     @(#)spec_vnops.c        8.8 (Berkeley) 11/21/94
        !            33:  */
        !            34:
        !            35: #include <sys/param.h>
        !            36: #include <sys/proc.h>
        !            37: #include <sys/systm.h>
        !            38: #include <sys/kernel.h>
        !            39: #include <sys/conf.h>
        !            40: #include <sys/buf.h>
        !            41: #include <sys/mount.h>
        !            42: #include <sys/namei.h>
        !            43: #include <sys/vnode.h>
        !            44: #include <sys/stat.h>
        !            45: #include <sys/errno.h>
        !            46: #include <sys/ioctl.h>
        !            47: #include <sys/file.h>
        !            48: #include <sys/disklabel.h>
        !            49: #include <sys/lockf.h>
        !            50: #include <sys/poll.h>
        !            51:
        !            52: #include <miscfs/specfs/specdev.h>
        !            53:
        !            54: #define v_lastr v_specinfo->si_lastr
        !            55:
        !            56: struct vnode *speclisth[SPECHSZ];
        !            57:
        !            58: int (**spec_vnodeop_p)(void *);
        !            59: struct vnodeopv_entry_desc spec_vnodeop_entries[] = {
        !            60:        { &vop_default_desc, vn_default_error },
        !            61:        { &vop_lookup_desc, spec_lookup },              /* lookup */
        !            62:        { &vop_create_desc, spec_create },              /* create */
        !            63:        { &vop_mknod_desc, spec_mknod },                /* mknod */
        !            64:        { &vop_open_desc, spec_open },                  /* open */
        !            65:        { &vop_close_desc, spec_close },                /* close */
        !            66:        { &vop_access_desc, spec_access },              /* access */
        !            67:        { &vop_getattr_desc, spec_getattr },            /* getattr */
        !            68:        { &vop_setattr_desc, spec_setattr },            /* setattr */
        !            69:        { &vop_read_desc, spec_read },                  /* read */
        !            70:        { &vop_write_desc, spec_write },                /* write */
        !            71:        { &vop_ioctl_desc, spec_ioctl },                /* ioctl */
        !            72:        { &vop_poll_desc, spec_poll },                  /* poll */
        !            73:        { &vop_kqfilter_desc, spec_kqfilter },          /* kqfilter */
        !            74:        { &vop_revoke_desc, spec_revoke },              /* revoke */
        !            75:        { &vop_fsync_desc, spec_fsync },                /* fsync */
        !            76:        { &vop_remove_desc, spec_remove },              /* remove */
        !            77:        { &vop_link_desc, spec_link },                  /* link */
        !            78:        { &vop_rename_desc, spec_rename },              /* rename */
        !            79:        { &vop_mkdir_desc, spec_mkdir },                /* mkdir */
        !            80:        { &vop_rmdir_desc, spec_rmdir },                /* rmdir */
        !            81:        { &vop_symlink_desc, spec_symlink },            /* symlink */
        !            82:        { &vop_readdir_desc, spec_readdir },            /* readdir */
        !            83:        { &vop_readlink_desc, spec_readlink },          /* readlink */
        !            84:        { &vop_abortop_desc, spec_abortop },            /* abortop */
        !            85:        { &vop_inactive_desc, spec_inactive },          /* inactive */
        !            86:        { &vop_reclaim_desc, spec_reclaim },            /* reclaim */
        !            87:        { &vop_lock_desc, spec_lock },                  /* lock */
        !            88:        { &vop_unlock_desc, spec_unlock },              /* unlock */
        !            89:        { &vop_bmap_desc, spec_bmap },                  /* bmap */
        !            90:        { &vop_strategy_desc, spec_strategy },          /* strategy */
        !            91:        { &vop_print_desc, spec_print },                /* print */
        !            92:        { &vop_islocked_desc, spec_islocked },          /* islocked */
        !            93:        { &vop_pathconf_desc, spec_pathconf },          /* pathconf */
        !            94:        { &vop_advlock_desc, spec_advlock },            /* advlock */
        !            95:        { &vop_bwrite_desc, spec_bwrite },              /* bwrite */
        !            96:        { NULL, NULL }
        !            97: };
        !            98: struct vnodeopv_desc spec_vnodeop_opv_desc =
        !            99:        { &spec_vnodeop_p, spec_vnodeop_entries };
        !           100:
        !           101: int
        !           102: spec_vnoperate(void *v)
        !           103: {
        !           104:        struct vop_generic_args *ap = v;
        !           105:
        !           106:        return (VOCALL(spec_vnodeop_p, ap->a_desc->vdesc_offset, ap));
        !           107: }
        !           108:
        !           109: /*
        !           110:  * Trivial lookup routine that always fails.
        !           111:  */
        !           112: int
        !           113: spec_lookup(void *v)
        !           114: {
        !           115:        struct vop_lookup_args *ap = v;
        !           116:
        !           117:        *ap->a_vpp = NULL;
        !           118:        return (ENOTDIR);
        !           119: }
        !           120:
        !           121: /*
        !           122:  * Open a special file.
        !           123:  */
        !           124: /* ARGSUSED */
        !           125: int
        !           126: spec_open(void *v)
        !           127: {
        !           128:        struct vop_open_args *ap = v;
        !           129:        struct proc *p = ap->a_p;
        !           130:        struct vnode *vp = ap->a_vp;
        !           131:        struct vnode *bvp;
        !           132:        dev_t bdev;
        !           133:        dev_t dev = (dev_t)vp->v_rdev;
        !           134:        int maj = major(dev);
        !           135:        int error;
        !           136:
        !           137:        /*
        !           138:         * Don't allow open if fs is mounted -nodev.
        !           139:         */
        !           140:        if (vp->v_mount && (vp->v_mount->mnt_flag & MNT_NODEV))
        !           141:                return (ENXIO);
        !           142:
        !           143:        switch (vp->v_type) {
        !           144:
        !           145:        case VCHR:
        !           146:                if ((u_int)maj >= nchrdev)
        !           147:                        return (ENXIO);
        !           148:                if (ap->a_cred != FSCRED && (ap->a_mode & FWRITE)) {
        !           149:                        /*
        !           150:                         * When running in very secure mode, do not allow
        !           151:                         * opens for writing of any disk character devices.
        !           152:                         */
        !           153:                        if (securelevel >= 2 && cdevsw[maj].d_type == D_DISK)
        !           154:                                return (EPERM);
        !           155:                        /*
        !           156:                         * When running in secure mode, do not allow opens
        !           157:                         * for writing of /dev/mem, /dev/kmem, or character
        !           158:                         * devices whose corresponding block devices are
        !           159:                         * currently mounted.
        !           160:                         */
        !           161:                        if (securelevel >= 1) {
        !           162:                                if ((bdev = chrtoblk(dev)) != NODEV &&
        !           163:                                    vfinddev(bdev, VBLK, &bvp) &&
        !           164:                                    bvp->v_usecount > 0 &&
        !           165:                                    (error = vfs_mountedon(bvp)))
        !           166:                                        return (error);
        !           167:                                if (iskmemdev(dev))
        !           168:                                        return (EPERM);
        !           169:                        }
        !           170:                }
        !           171:                if (cdevsw[maj].d_type == D_TTY)
        !           172:                        vp->v_flag |= VISTTY;
        !           173:                if (cdevsw[maj].d_flags & D_CLONE)
        !           174:                        return (spec_open_clone(ap));
        !           175:                VOP_UNLOCK(vp, 0, p);
        !           176:                error = (*cdevsw[maj].d_open)(dev, ap->a_mode, S_IFCHR, ap->a_p);
        !           177:                vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
        !           178:                return (error);
        !           179:
        !           180:        case VBLK:
        !           181:                if ((u_int)maj >= nblkdev)
        !           182:                        return (ENXIO);
        !           183:                /*
        !           184:                 * When running in very secure mode, do not allow
        !           185:                 * opens for writing of any disk block devices.
        !           186:                 */
        !           187:                if (securelevel >= 2 && ap->a_cred != FSCRED &&
        !           188:                    (ap->a_mode & FWRITE) && bdevsw[maj].d_type == D_DISK)
        !           189:                        return (EPERM);
        !           190:                /*
        !           191:                 * Do not allow opens of block devices that are
        !           192:                 * currently mounted.
        !           193:                 */
        !           194:                if ((error = vfs_mountedon(vp)) != 0)
        !           195:                        return (error);
        !           196:                return ((*bdevsw[maj].d_open)(dev, ap->a_mode, S_IFBLK, ap->a_p));
        !           197:        case VNON:
        !           198:        case VLNK:
        !           199:        case VDIR:
        !           200:        case VREG:
        !           201:        case VBAD:
        !           202:        case VFIFO:
        !           203:        case VSOCK:
        !           204:                break;
        !           205:        }
        !           206:        return (0);
        !           207: }
        !           208:
        !           209: /*
        !           210:  * Vnode op for read
        !           211:  */
        !           212: /* ARGSUSED */
        !           213: int
        !           214: spec_read(void *v)
        !           215: {
        !           216:        struct vop_read_args *ap = v;
        !           217:        struct vnode *vp = ap->a_vp;
        !           218:        struct uio *uio = ap->a_uio;
        !           219:        struct proc *p = uio->uio_procp;
        !           220:        struct buf *bp;
        !           221:        daddr64_t bn, nextbn, bscale;
        !           222:        int bsize;
        !           223:        struct partinfo dpart;
        !           224:        int n, on, majordev;
        !           225:        int (*ioctl)(dev_t, u_long, caddr_t, int, struct proc *);
        !           226:        int error = 0;
        !           227:
        !           228: #ifdef DIAGNOSTIC
        !           229:        if (uio->uio_rw != UIO_READ)
        !           230:                panic("spec_read mode");
        !           231:        if (uio->uio_segflg == UIO_USERSPACE && uio->uio_procp != curproc)
        !           232:                panic("spec_read proc");
        !           233: #endif
        !           234:        if (uio->uio_resid == 0)
        !           235:                return (0);
        !           236:
        !           237:        switch (vp->v_type) {
        !           238:
        !           239:        case VCHR:
        !           240:                VOP_UNLOCK(vp, 0, p);
        !           241:                error = (*cdevsw[major(vp->v_rdev)].d_read)
        !           242:                        (vp->v_rdev, uio, ap->a_ioflag);
        !           243:                vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
        !           244:                return (error);
        !           245:
        !           246:        case VBLK:
        !           247:                if (uio->uio_offset < 0)
        !           248:                        return (EINVAL);
        !           249:                bsize = BLKDEV_IOSIZE;
        !           250:                if ((majordev = major(vp->v_rdev)) < nblkdev &&
        !           251:                    (ioctl = bdevsw[majordev].d_ioctl) != NULL &&
        !           252:                    (*ioctl)(vp->v_rdev, DIOCGPART, (caddr_t)&dpart, FREAD, p) == 0) {
        !           253:                        u_int32_t frag =
        !           254:                            DISKLABELV1_FFS_FRAG(dpart.part->p_fragblock);
        !           255:                        u_int32_t fsize =
        !           256:                            DISKLABELV1_FFS_FSIZE(dpart.part->p_fragblock);
        !           257:                        if (dpart.part->p_fstype == FS_BSDFFS && frag != 0 &&
        !           258:                            fsize != 0)
        !           259:                                bsize = frag * fsize;
        !           260:                }
        !           261:                bscale = btodb(bsize);
        !           262:                do {
        !           263:                        bn = btodb(uio->uio_offset) & ~(bscale - 1);
        !           264:                        on = uio->uio_offset % bsize;
        !           265:                        n = min((bsize - on), uio->uio_resid);
        !           266:                        if (vp->v_lastr + bscale == bn) {
        !           267:                                nextbn = bn + bscale;
        !           268:                                error = breadn(vp, bn, bsize, &nextbn, &bsize,
        !           269:                                    1, NOCRED, &bp);
        !           270:                        } else
        !           271:                                error = bread(vp, bn, bsize, NOCRED, &bp);
        !           272:                        vp->v_lastr = bn;
        !           273:                        n = min(n, bsize - bp->b_resid);
        !           274:                        if (error) {
        !           275:                                brelse(bp);
        !           276:                                return (error);
        !           277:                        }
        !           278:                        error = uiomove((char *)bp->b_data + on, n, uio);
        !           279:                        brelse(bp);
        !           280:                } while (error == 0 && uio->uio_resid > 0 && n != 0);
        !           281:                return (error);
        !           282:
        !           283:        default:
        !           284:                panic("spec_read type");
        !           285:        }
        !           286:        /* NOTREACHED */
        !           287: }
        !           288:
        !           289: int
        !           290: spec_inactive(void *v)
        !           291: {
        !           292:        struct vop_inactive_args *ap = v;
        !           293:
        !           294:        VOP_UNLOCK(ap->a_vp, 0, ap->a_p);
        !           295:        return (0);
        !           296: }
        !           297:
        !           298: /*
        !           299:  * Vnode op for write
        !           300:  */
        !           301: /* ARGSUSED */
        !           302: int
        !           303: spec_write(void *v)
        !           304: {
        !           305:        struct vop_write_args *ap = v;
        !           306:        struct vnode *vp = ap->a_vp;
        !           307:        struct uio *uio = ap->a_uio;
        !           308:        struct proc *p = uio->uio_procp;
        !           309:        struct buf *bp;
        !           310:        daddr64_t bn, bscale;
        !           311:        int bsize;
        !           312:        struct partinfo dpart;
        !           313:        int n, on, majordev;
        !           314:        int (*ioctl)(dev_t, u_long, caddr_t, int, struct proc *);
        !           315:        int error = 0;
        !           316:
        !           317: #ifdef DIAGNOSTIC
        !           318:        if (uio->uio_rw != UIO_WRITE)
        !           319:                panic("spec_write mode");
        !           320:        if (uio->uio_segflg == UIO_USERSPACE && uio->uio_procp != curproc)
        !           321:                panic("spec_write proc");
        !           322: #endif
        !           323:
        !           324:        switch (vp->v_type) {
        !           325:
        !           326:        case VCHR:
        !           327:                VOP_UNLOCK(vp, 0, p);
        !           328:                error = (*cdevsw[major(vp->v_rdev)].d_write)
        !           329:                        (vp->v_rdev, uio, ap->a_ioflag);
        !           330:                vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
        !           331:                return (error);
        !           332:
        !           333:        case VBLK:
        !           334:                if (uio->uio_resid == 0)
        !           335:                        return (0);
        !           336:                if (uio->uio_offset < 0)
        !           337:                        return (EINVAL);
        !           338:                bsize = BLKDEV_IOSIZE;
        !           339:                if ((majordev = major(vp->v_rdev)) < nblkdev &&
        !           340:                    (ioctl = bdevsw[majordev].d_ioctl) != NULL &&
        !           341:                    (*ioctl)(vp->v_rdev, DIOCGPART, (caddr_t)&dpart, FREAD, p) == 0) {
        !           342:                        u_int32_t frag =
        !           343:                            DISKLABELV1_FFS_FRAG(dpart.part->p_fragblock);
        !           344:                        u_int32_t fsize =
        !           345:                            DISKLABELV1_FFS_FSIZE(dpart.part->p_fragblock);
        !           346:                        if (dpart.part->p_fstype == FS_BSDFFS && frag != 0 &&
        !           347:                            fsize != 0)
        !           348:                                bsize = frag * fsize;
        !           349:                }
        !           350:                bscale = btodb(bsize);
        !           351:                do {
        !           352:                        bn = btodb(uio->uio_offset) & ~(bscale - 1);
        !           353:                        on = uio->uio_offset % bsize;
        !           354:                        n = min((bsize - on), uio->uio_resid);
        !           355:                        error = bread(vp, bn, bsize, NOCRED, &bp);
        !           356:                        n = min(n, bsize - bp->b_resid);
        !           357:                        if (error) {
        !           358:                                brelse(bp);
        !           359:                                return (error);
        !           360:                        }
        !           361:                        error = uiomove((char *)bp->b_data + on, n, uio);
        !           362:                        if (n + on == bsize)
        !           363:                                bawrite(bp);
        !           364:                        else
        !           365:                                bdwrite(bp);
        !           366:                } while (error == 0 && uio->uio_resid > 0 && n != 0);
        !           367:                return (error);
        !           368:
        !           369:        default:
        !           370:                panic("spec_write type");
        !           371:        }
        !           372:        /* NOTREACHED */
        !           373: }
        !           374:
        !           375: /*
        !           376:  * Device ioctl operation.
        !           377:  */
        !           378: /* ARGSUSED */
        !           379: int
        !           380: spec_ioctl(void *v)
        !           381: {
        !           382:        struct vop_ioctl_args *ap = v;
        !           383:        dev_t dev = ap->a_vp->v_rdev;
        !           384:        int maj = major(dev);
        !           385:
        !           386:        switch (ap->a_vp->v_type) {
        !           387:
        !           388:        case VCHR:
        !           389:                return ((*cdevsw[maj].d_ioctl)(dev, ap->a_command, ap->a_data,
        !           390:                    ap->a_fflag, ap->a_p));
        !           391:
        !           392:        case VBLK:
        !           393:                return ((*bdevsw[maj].d_ioctl)(dev, ap->a_command, ap->a_data,
        !           394:                    ap->a_fflag, ap->a_p));
        !           395:
        !           396:        default:
        !           397:                panic("spec_ioctl");
        !           398:                /* NOTREACHED */
        !           399:        }
        !           400: }
        !           401:
        !           402: /* ARGSUSED */
        !           403: int
        !           404: spec_poll(void *v)
        !           405: {
        !           406:        struct vop_poll_args *ap = v;
        !           407:        dev_t dev;
        !           408:
        !           409:        switch (ap->a_vp->v_type) {
        !           410:
        !           411:        default:
        !           412:                return (ap->a_events &
        !           413:                    (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM));
        !           414:
        !           415:        case VCHR:
        !           416:                dev = ap->a_vp->v_rdev;
        !           417:                return (*cdevsw[major(dev)].d_poll)(dev, ap->a_events, ap->a_p);
        !           418:        }
        !           419: }
        !           420: /* ARGSUSED */
        !           421: int
        !           422: spec_kqfilter(void *v)
        !           423: {
        !           424:        struct vop_kqfilter_args *ap = v;
        !           425:
        !           426:        dev_t dev;
        !           427:
        !           428:        dev = ap->a_vp->v_rdev;
        !           429:        if (cdevsw[major(dev)].d_flags & D_KQFILTER)
        !           430:                return (*cdevsw[major(dev)].d_kqfilter)(dev, ap->a_kn);
        !           431:        return (1);
        !           432: }
        !           433:
        !           434: /*
        !           435:  * Synch buffers associated with a block device
        !           436:  */
        !           437: /* ARGSUSED */
        !           438: int
        !           439: spec_fsync(void *v)
        !           440: {
        !           441:        struct vop_fsync_args *ap = v;
        !           442:        struct vnode *vp = ap->a_vp;
        !           443:        struct buf *bp;
        !           444:        struct buf *nbp;
        !           445:        int s;
        !           446:
        !           447:        if (vp->v_type == VCHR)
        !           448:                return (0);
        !           449:        /*
        !           450:         * Flush all dirty buffers associated with a block device.
        !           451:         */
        !           452: loop:
        !           453:        s = splbio();
        !           454:        for (bp = LIST_FIRST(&vp->v_dirtyblkhd);
        !           455:            bp != LIST_END(&vp->v_dirtyblkhd); bp = nbp) {
        !           456:                nbp = LIST_NEXT(bp, b_vnbufs);
        !           457:                if ((bp->b_flags & B_BUSY))
        !           458:                        continue;
        !           459:                if ((bp->b_flags & B_DELWRI) == 0)
        !           460:                        panic("spec_fsync: not dirty");
        !           461:                bremfree(bp);
        !           462:                bp->b_flags |= B_BUSY;
        !           463:                splx(s);
        !           464:                bawrite(bp);
        !           465:                goto loop;
        !           466:        }
        !           467:        if (ap->a_waitfor == MNT_WAIT) {
        !           468:                vwaitforio (vp, 0, "spec_fsync", 0);
        !           469:
        !           470: #ifdef DIAGNOSTIC
        !           471:                if (!LIST_EMPTY(&vp->v_dirtyblkhd)) {
        !           472:                        splx(s);
        !           473:                        vprint("spec_fsync: dirty", vp);
        !           474:                        goto loop;
        !           475:                }
        !           476: #endif
        !           477:        }
        !           478:        splx(s);
        !           479:        return (0);
        !           480: }
        !           481:
        !           482: int
        !           483: spec_strategy(void *v)
        !           484: {
        !           485:        struct vop_strategy_args *ap = v;
        !           486:        struct buf *bp = ap->a_bp;
        !           487:        int maj = major(bp->b_dev);
        !           488:
        !           489:        if (LIST_FIRST(&bp->b_dep) != NULL)
        !           490:                buf_start(bp);
        !           491:
        !           492:        (*bdevsw[maj].d_strategy)(bp);
        !           493:        return (0);
        !           494: }
        !           495:
        !           496: /*
        !           497:  * This is a noop, simply returning what one has been given.
        !           498:  */
        !           499: int
        !           500: spec_bmap(void *v)
        !           501: {
        !           502:        struct vop_bmap_args *ap = v;
        !           503:
        !           504:        if (ap->a_vpp != NULL)
        !           505:                *ap->a_vpp = ap->a_vp;
        !           506:        if (ap->a_bnp != NULL)
        !           507:                *ap->a_bnp = ap->a_bn;
        !           508:        if (ap->a_runp != NULL)
        !           509:                *ap->a_runp = 0;
        !           510:
        !           511:        return (0);
        !           512: }
        !           513:
        !           514: /*
        !           515:  * Device close routine
        !           516:  */
        !           517: /* ARGSUSED */
        !           518: int
        !           519: spec_close(void *v)
        !           520: {
        !           521:        struct vop_close_args *ap = v;
        !           522:        struct vnode *vp = ap->a_vp;
        !           523:        dev_t dev = vp->v_rdev;
        !           524:        int (*devclose)(dev_t, int, int, struct proc *);
        !           525:        int mode, error;
        !           526:
        !           527:        switch (vp->v_type) {
        !           528:
        !           529:        case VCHR:
        !           530:                /*
        !           531:                 * Hack: a tty device that is a controlling terminal
        !           532:                 * has a reference from the session structure.
        !           533:                 * We cannot easily tell that a character device is
        !           534:                 * a controlling terminal, unless it is the closing
        !           535:                 * process' controlling terminal.  In that case,
        !           536:                 * if the reference count is 2 (this last descriptor
        !           537:                 * plus the session), release the reference from the session.
        !           538:                 */
        !           539:                if (vcount(vp) == 2 && ap->a_p &&
        !           540:                    vp == ap->a_p->p_session->s_ttyvp) {
        !           541:                        vrele(vp);
        !           542:                        ap->a_p->p_session->s_ttyvp = NULL;
        !           543:                }
        !           544:                /*
        !           545:                 * If the vnode is locked, then we are in the midst
        !           546:                 * of forcably closing the device, otherwise we only
        !           547:                 * close on last reference.
        !           548:                 */
        !           549:                if (vcount(vp) > 1 && (vp->v_flag & VXLOCK) == 0)
        !           550:                        return (0);
        !           551:                if (cdevsw[major(dev)].d_flags & D_CLONE)
        !           552:                        return (spec_close_clone(ap));
        !           553:                devclose = cdevsw[major(dev)].d_close;
        !           554:                mode = S_IFCHR;
        !           555:                break;
        !           556:
        !           557:        case VBLK:
        !           558:                /*
        !           559:                 * On last close of a block device (that isn't mounted)
        !           560:                 * we must invalidate any in core blocks, so that
        !           561:                 * we can, for instance, change floppy disks. In order to do
        !           562:                 * that, we must lock the vnode. If we are coming from
        !           563:                 * vclean(), the vnode is already locked.
        !           564:                 */
        !           565:                if (!(vp->v_flag & VXLOCK))
        !           566:                        vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, ap->a_p);
        !           567:                error = vinvalbuf(vp, V_SAVE, ap->a_cred, ap->a_p, 0, 0);
        !           568:                if (!(vp->v_flag & VXLOCK))
        !           569:                        VOP_UNLOCK(vp, 0, ap->a_p);
        !           570:                if (error)
        !           571:                        return (error);
        !           572:                /*
        !           573:                 * We do not want to really close the device if it
        !           574:                 * is still in use unless we are trying to close it
        !           575:                 * forcibly. Since every use (buffer, vnode, swap, cmap)
        !           576:                 * holds a reference to the vnode, and because we mark
        !           577:                 * any other vnodes that alias this device, when the
        !           578:                 * sum of the reference counts on all the aliased
        !           579:                 * vnodes descends to one, we are on last close.
        !           580:                 */
        !           581:                if (vcount(vp) > 1 && (vp->v_flag & VXLOCK) == 0)
        !           582:                        return (0);
        !           583:                devclose = bdevsw[major(dev)].d_close;
        !           584:                mode = S_IFBLK;
        !           585:                break;
        !           586:
        !           587:        default:
        !           588:                panic("spec_close: not special");
        !           589:        }
        !           590:
        !           591:        return ((*devclose)(dev, ap->a_fflag, mode, ap->a_p));
        !           592: }
        !           593:
        !           594: /*
        !           595:  * Print out the contents of a special device vnode.
        !           596:  */
        !           597: int
        !           598: spec_print(void *v)
        !           599: {
        !           600:        struct vop_print_args *ap = v;
        !           601:
        !           602:        printf("tag VT_NON, dev %d, %d\n", major(ap->a_vp->v_rdev),
        !           603:                minor(ap->a_vp->v_rdev));
        !           604:        return 0;
        !           605: }
        !           606:
        !           607: /*
        !           608:  * Return POSIX pathconf information applicable to special devices.
        !           609:  */
        !           610: int
        !           611: spec_pathconf(void *v)
        !           612: {
        !           613:        struct vop_pathconf_args *ap = v;
        !           614:
        !           615:        switch (ap->a_name) {
        !           616:        case _PC_LINK_MAX:
        !           617:                *ap->a_retval = LINK_MAX;
        !           618:                return (0);
        !           619:        case _PC_MAX_CANON:
        !           620:                *ap->a_retval = MAX_CANON;
        !           621:                return (0);
        !           622:        case _PC_MAX_INPUT:
        !           623:                *ap->a_retval = MAX_INPUT;
        !           624:                return (0);
        !           625:        case _PC_PIPE_BUF:
        !           626:                *ap->a_retval = PIPE_BUF;
        !           627:                return (0);
        !           628:        case _PC_CHOWN_RESTRICTED:
        !           629:                *ap->a_retval = 1;
        !           630:                return (0);
        !           631:        case _PC_VDISABLE:
        !           632:                *ap->a_retval = _POSIX_VDISABLE;
        !           633:                return (0);
        !           634:        default:
        !           635:                return (EINVAL);
        !           636:        }
        !           637:        /* NOTREACHED */
        !           638: }
        !           639:
        !           640: /*
        !           641:  * Special device advisory byte-level locks.
        !           642:  */
        !           643: /* ARGSUSED */
        !           644: int
        !           645: spec_advlock(void *v)
        !           646: {
        !           647:        struct vop_advlock_args *ap = v;
        !           648:        struct vnode *vp = ap->a_vp;
        !           649:
        !           650:        return (lf_advlock(&vp->v_speclockf, (off_t)0, ap->a_id,
        !           651:                ap->a_op, ap->a_fl, ap->a_flags));
        !           652: }
        !           653:
        !           654: /*
        !           655:  * Special device failed operation
        !           656:  */
        !           657: /*ARGSUSED*/
        !           658: int
        !           659: spec_ebadf(void *v)
        !           660: {
        !           661:
        !           662:        return (EBADF);
        !           663: }
        !           664:
        !           665: /*
        !           666:  * Special device bad operation
        !           667:  */
        !           668: /*ARGSUSED*/
        !           669: int
        !           670: spec_badop(void *v)
        !           671: {
        !           672:
        !           673:        panic("spec_badop called");
        !           674:        /* NOTREACHED */
        !           675: }

CVSweb