[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

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