[BACK]Return to spec_vnops.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / miscfs / specfs

Annotation of src/sys/miscfs/specfs/spec_vnops.c, Revision 1.118

1.118   ! ad          1: /*     $NetBSD: spec_vnops.c,v 1.117 2008/04/28 20:24:08 martin Exp $  */
1.112     ad          2:
                      3: /*-
                      4:  * Copyright (c) 2008 The NetBSD Foundation, Inc.
                      5:  * All rights reserved.
                      6:  *
                      7:  * Redistribution and use in source and binary forms, with or without
                      8:  * modification, are permitted provided that the following conditions
                      9:  * are met:
                     10:  * 1. Redistributions of source code must retain the above copyright
                     11:  *    notice, this list of conditions and the following disclaimer.
                     12:  * 2. Redistributions in binary form must reproduce the above copyright
                     13:  *    notice, this list of conditions and the following disclaimer in the
                     14:  *    documentation and/or other materials provided with the distribution.
                     15:  *
                     16:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
                     17:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
                     18:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                     19:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
                     20:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
                     21:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                     22:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     23:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     24:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     25:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     26:  * POSSIBILITY OF SUCH DAMAGE.
                     27:  */
1.16      cgd        28:
1.1       cgd        29: /*
1.15      mycroft    30:  * Copyright (c) 1989, 1993
                     31:  *     The Regents of the University of California.  All rights reserved.
1.1       cgd        32:  *
                     33:  * Redistribution and use in source and binary forms, with or without
                     34:  * modification, are permitted provided that the following conditions
                     35:  * are met:
                     36:  * 1. Redistributions of source code must retain the above copyright
                     37:  *    notice, this list of conditions and the following disclaimer.
                     38:  * 2. Redistributions in binary form must reproduce the above copyright
                     39:  *    notice, this list of conditions and the following disclaimer in the
                     40:  *    documentation and/or other materials provided with the distribution.
1.69      agc        41:  * 3. Neither the name of the University nor the names of its contributors
1.1       cgd        42:  *    may be used to endorse or promote products derived from this software
                     43:  *    without specific prior written permission.
                     44:  *
                     45:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     46:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     47:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     48:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     49:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     50:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     51:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     52:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     53:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     54:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     55:  * SUCH DAMAGE.
                     56:  *
1.39      fvdl       57:  *     @(#)spec_vnops.c        8.15 (Berkeley) 7/14/95
1.1       cgd        58:  */
1.60      lukem      59:
                     60: #include <sys/cdefs.h>
1.118   ! ad         61: __KERNEL_RCSID(0, "$NetBSD: spec_vnops.c,v 1.117 2008/04/28 20:24:08 martin Exp $");
1.1       cgd        62:
1.9       mycroft    63: #include <sys/param.h>
                     64: #include <sys/proc.h>
                     65: #include <sys/systm.h>
                     66: #include <sys/kernel.h>
                     67: #include <sys/conf.h>
                     68: #include <sys/buf.h>
                     69: #include <sys/mount.h>
                     70: #include <sys/namei.h>
                     71: #include <sys/vnode.h>
                     72: #include <sys/stat.h>
                     73: #include <sys/errno.h>
                     74: #include <sys/ioctl.h>
1.81      ws         75: #include <sys/poll.h>
1.9       mycroft    76: #include <sys/file.h>
                     77: #include <sys/disklabel.h>
1.35      kleink     78: #include <sys/lockf.h>
1.71      dsl        79: #include <sys/tty.h>
1.87      elad       80: #include <sys/kauth.h>
1.106     hannken    81: #include <sys/fstrans.h>
1.28      christos   82:
1.30      mycroft    83: #include <miscfs/genfs/genfs.h>
1.15      mycroft    84: #include <miscfs/specfs/specdev.h>
1.1       cgd        85:
                     86: /* symbolic sleep message strings for devices */
1.37      mycroft    87: const char     devopn[] = "devopn";
                     88: const char     devio[] = "devio";
                     89: const char     devwait[] = "devwait";
                     90: const char     devin[] = "devin";
                     91: const char     devout[] = "devout";
                     92: const char     devioc[] = "devioc";
                     93: const char     devcls[] = "devcls";
1.61      matt       94:
1.112     ad         95: vnode_t                *specfs_hash[SPECHSZ];
                     96: kmutex_t       specfs_lock;
1.46      sommerfe   97:
                     98: /*
1.112     ad         99:  * This vnode operations vector is used for special device nodes
                    100:  * created from whole cloth by the kernel.  For the ops vector for
                    101:  * vnodes built from special devices found in a filesystem, see (e.g)
                    102:  * ffs_specop_entries[] in ffs_vnops.c or the equivalent for other
                    103:  * filesystems.
1.46      sommerfe  104:  */
1.1       cgd       105:
1.82      xtraeme   106: int (**spec_vnodeop_p)(void *);
1.53      jdolecek  107: const struct vnodeopv_entry_desc spec_vnodeop_entries[] = {
1.15      mycroft   108:        { &vop_default_desc, vn_default_error },
                    109:        { &vop_lookup_desc, spec_lookup },              /* lookup */
                    110:        { &vop_create_desc, spec_create },              /* create */
                    111:        { &vop_mknod_desc, spec_mknod },                /* mknod */
                    112:        { &vop_open_desc, spec_open },                  /* open */
                    113:        { &vop_close_desc, spec_close },                /* close */
                    114:        { &vop_access_desc, spec_access },              /* access */
                    115:        { &vop_getattr_desc, spec_getattr },            /* getattr */
                    116:        { &vop_setattr_desc, spec_setattr },            /* setattr */
                    117:        { &vop_read_desc, spec_read },                  /* read */
                    118:        { &vop_write_desc, spec_write },                /* write */
1.47      sommerfe  119:        { &vop_fcntl_desc, spec_fcntl },                /* fcntl */
1.15      mycroft   120:        { &vop_ioctl_desc, spec_ioctl },                /* ioctl */
1.32      mycroft   121:        { &vop_poll_desc, spec_poll },                  /* poll */
1.65      jdolecek  122:        { &vop_kqfilter_desc, spec_kqfilter },          /* kqfilter */
1.39      fvdl      123:        { &vop_revoke_desc, spec_revoke },              /* revoke */
1.15      mycroft   124:        { &vop_mmap_desc, spec_mmap },                  /* mmap */
                    125:        { &vop_fsync_desc, spec_fsync },                /* fsync */
                    126:        { &vop_seek_desc, spec_seek },                  /* seek */
                    127:        { &vop_remove_desc, spec_remove },              /* remove */
                    128:        { &vop_link_desc, spec_link },                  /* link */
                    129:        { &vop_rename_desc, spec_rename },              /* rename */
                    130:        { &vop_mkdir_desc, spec_mkdir },                /* mkdir */
                    131:        { &vop_rmdir_desc, spec_rmdir },                /* rmdir */
                    132:        { &vop_symlink_desc, spec_symlink },            /* symlink */
                    133:        { &vop_readdir_desc, spec_readdir },            /* readdir */
                    134:        { &vop_readlink_desc, spec_readlink },          /* readlink */
                    135:        { &vop_abortop_desc, spec_abortop },            /* abortop */
                    136:        { &vop_inactive_desc, spec_inactive },          /* inactive */
                    137:        { &vop_reclaim_desc, spec_reclaim },            /* reclaim */
                    138:        { &vop_lock_desc, spec_lock },                  /* lock */
                    139:        { &vop_unlock_desc, spec_unlock },              /* unlock */
                    140:        { &vop_bmap_desc, spec_bmap },                  /* bmap */
                    141:        { &vop_strategy_desc, spec_strategy },          /* strategy */
                    142:        { &vop_print_desc, spec_print },                /* print */
                    143:        { &vop_islocked_desc, spec_islocked },          /* islocked */
                    144:        { &vop_pathconf_desc, spec_pathconf },          /* pathconf */
                    145:        { &vop_advlock_desc, spec_advlock },            /* advlock */
1.28      christos  146:        { &vop_bwrite_desc, spec_bwrite },              /* bwrite */
1.55      chs       147:        { &vop_getpages_desc, spec_getpages },          /* getpages */
                    148:        { &vop_putpages_desc, spec_putpages },          /* putpages */
                    149:        { NULL, NULL }
1.1       cgd       150: };
1.53      jdolecek  151: const struct vnodeopv_desc spec_vnodeop_opv_desc =
1.15      mycroft   152:        { &spec_vnodeop_p, spec_vnodeop_entries };
1.1       cgd       153:
                    154: /*
1.112     ad        155:  * Returns true if dev is /dev/mem or /dev/kmem.
                    156:  */
                    157: int
                    158: iskmemdev(dev_t dev)
                    159: {
                    160:        /* mem_no is emitted by config(8) to generated devsw.c */
                    161:        extern const int mem_no;
                    162:
                    163:        /* minor 14 is /dev/io on i386 with COMPAT_10 */
                    164:        return (major(dev) == mem_no && (minor(dev) < 2 || minor(dev) == 14));
                    165: }
                    166:
                    167: /*
                    168:  * Initialize a vnode that represents a device.
                    169:  */
                    170: void
                    171: spec_node_init(vnode_t *vp, dev_t rdev)
                    172: {
                    173:        specnode_t *sn;
                    174:        specdev_t *sd;
                    175:        vnode_t *vp2;
                    176:        vnode_t **vpp;
                    177:
                    178:        KASSERT(vp->v_type == VBLK || vp->v_type == VCHR);
                    179:        KASSERT(vp->v_specnode == NULL);
                    180:
                    181:        /*
                    182:         * Search the hash table for this device.  If known, add a
                    183:         * reference to the device structure.  If not known, create
                    184:         * a new entry to represent the device.  In all cases add
                    185:         * the vnode to the hash table.
                    186:         */
                    187:        sn = kmem_alloc(sizeof(*sn), KM_SLEEP);
                    188:        if (sn == NULL) {
                    189:                /* XXX */
                    190:                panic("spec_node_init: unable to allocate memory");
                    191:        }
                    192:        sd = kmem_alloc(sizeof(*sd), KM_SLEEP);
                    193:        if (sd == NULL) {
                    194:                /* XXX */
                    195:                panic("spec_node_init: unable to allocate memory");
                    196:        }
                    197:        mutex_enter(&specfs_lock);
                    198:        vpp = &specfs_hash[SPECHASH(rdev)];
                    199:        for (vp2 = *vpp; vp2 != NULL; vp2 = vp2->v_specnext) {
                    200:                KASSERT(vp2->v_specnode != NULL);
                    201:                if (rdev == vp2->v_rdev && vp->v_type == vp2->v_type) {
                    202:                        break;
                    203:                }
                    204:        }
                    205:        if (vp2 == NULL) {
                    206:                /* No existing record, create a new one. */
                    207:                sd->sd_rdev = rdev;
                    208:                sd->sd_mountpoint = NULL;
                    209:                sd->sd_lockf = NULL;
                    210:                sd->sd_refcnt = 1;
                    211:                sd->sd_opencnt = 0;
                    212:                sd->sd_bdevvp = NULL;
                    213:                sn->sn_dev = sd;
                    214:                sd = NULL;
                    215:        } else {
                    216:                /* Use the existing record. */
                    217:                sn->sn_dev = vp2->v_specnode->sn_dev;
                    218:                sn->sn_dev->sd_refcnt++;
                    219:        }
                    220:        /* Insert vnode into the hash chain. */
                    221:        sn->sn_opencnt = 0;
                    222:        sn->sn_rdev = rdev;
                    223:        sn->sn_gone = false;
                    224:        vp->v_specnode = sn;
                    225:        vp->v_specnext = *vpp;
                    226:        *vpp = vp;
                    227:        mutex_exit(&specfs_lock);
                    228:
                    229:        /* Free the record we allocated if unused. */
                    230:        if (sd != NULL) {
                    231:                kmem_free(sd, sizeof(*sd));
                    232:        }
                    233: }
                    234:
                    235: /*
                    236:  * A vnode representing a special device is going away.  Close
                    237:  * the device if the vnode holds it open.
                    238:  */
                    239: void
                    240: spec_node_revoke(vnode_t *vp)
                    241: {
                    242:        specnode_t *sn;
                    243:        specdev_t *sd;
                    244:
                    245:        sn = vp->v_specnode;
                    246:        sd = sn->sn_dev;
                    247:
                    248:        KASSERT(vp->v_type == VBLK || vp->v_type == VCHR);
                    249:        KASSERT(vp->v_specnode != NULL);
                    250:        KASSERT((vp->v_iflag & VI_XLOCK) != 0);
                    251:        KASSERT(sn->sn_gone == false);
                    252:
                    253:        mutex_enter(&specfs_lock);
                    254:        KASSERT(sn->sn_opencnt <= sd->sd_opencnt);
                    255:        if (sn->sn_opencnt != 0) {
                    256:                sd->sd_opencnt -= (sn->sn_opencnt - 1);
                    257:                sn->sn_opencnt = 1;
                    258:                sn->sn_gone = true;
                    259:                mutex_exit(&specfs_lock);
                    260:
                    261:                VOP_CLOSE(vp, FNONBLOCK, NOCRED);
                    262:
                    263:                mutex_enter(&specfs_lock);
                    264:                KASSERT(sn->sn_opencnt == 0);
                    265:        }
                    266:        mutex_exit(&specfs_lock);
                    267: }
                    268:
                    269: /*
                    270:  * A vnode representing a special device is being recycled.
                    271:  * Destroy the specfs component.
                    272:  */
                    273: void
                    274: spec_node_destroy(vnode_t *vp)
                    275: {
                    276:        specnode_t *sn;
                    277:        specdev_t *sd;
                    278:        vnode_t **vpp, *vp2;
                    279:        int refcnt;
                    280:
                    281:        sn = vp->v_specnode;
                    282:        sd = sn->sn_dev;
                    283:
                    284:        KASSERT(vp->v_type == VBLK || vp->v_type == VCHR);
                    285:        KASSERT(vp->v_specnode != NULL);
                    286:        KASSERT(sn->sn_opencnt == 0);
                    287:
                    288:        mutex_enter(&specfs_lock);
                    289:        /* Remove from the hash and destroy the node. */
                    290:        vpp = &specfs_hash[SPECHASH(vp->v_rdev)];
                    291:        for (vp2 = *vpp;; vp2 = vp2->v_specnext) {
                    292:                if (vp2 == NULL) {
                    293:                        panic("spec_node_destroy: corrupt hash");
                    294:                }
                    295:                if (vp2 == vp) {
                    296:                        KASSERT(vp == *vpp);
                    297:                        *vpp = vp->v_specnext;
                    298:                        break;
                    299:                }
                    300:                if (vp2->v_specnext == vp) {
                    301:                        vp2->v_specnext = vp->v_specnext;
                    302:                        break;
                    303:                }
                    304:        }
                    305:        sn = vp->v_specnode;
                    306:        vp->v_specnode = NULL;
                    307:        refcnt = sd->sd_refcnt--;
                    308:        KASSERT(refcnt > 0);
                    309:        mutex_exit(&specfs_lock);
                    310:
                    311:        /* If the device is no longer in use, destroy our record. */
                    312:        if (refcnt == 1) {
                    313:                KASSERT(sd->sd_opencnt == 0);
                    314:                KASSERT(sd->sd_bdevvp == NULL);
                    315:                kmem_free(sd, sizeof(*sd));
                    316:        }
                    317:        kmem_free(sn, sizeof(*sn));
                    318: }
                    319:
                    320: /*
1.1       cgd       321:  * Trivial lookup routine that always fails.
                    322:  */
1.4       andrew    323: int
1.104     pooka     324: spec_lookup(void *v)
1.28      christos  325: {
1.15      mycroft   326:        struct vop_lookup_args /* {
                    327:                struct vnode *a_dvp;
                    328:                struct vnode **a_vpp;
                    329:                struct componentname *a_cnp;
1.28      christos  330:        } */ *ap = v;
1.1       cgd       331:
1.15      mycroft   332:        *ap->a_vpp = NULL;
1.1       cgd       333:        return (ENOTDIR);
1.66      jdolecek  334: }
                    335:
                    336: /*
1.15      mycroft   337:  * Open a special file.
1.1       cgd       338:  */
                    339: /* ARGSUSED */
1.28      christos  340: int
1.104     pooka     341: spec_open(void *v)
1.28      christos  342: {
1.15      mycroft   343:        struct vop_open_args /* {
                    344:                struct vnode *a_vp;
                    345:                int  a_mode;
1.87      elad      346:                kauth_cred_t a_cred;
1.28      christos  347:        } */ *ap = v;
1.112     ad        348:        struct lwp *l;
                    349:        struct vnode *vp;
                    350:        dev_t dev;
1.1       cgd       351:        int error;
1.55      chs       352:        struct partinfo pi;
1.96      elad      353:        enum kauth_device_req req;
1.112     ad        354:        specnode_t *sn;
                    355:        specdev_t *sd;
                    356:
                    357:        l = curlwp;
                    358:        vp = ap->a_vp;
                    359:        dev = vp->v_rdev;
                    360:        sn = vp->v_specnode;
                    361:        sd = sn->sn_dev;
1.1       cgd       362:
1.15      mycroft   363:        /*
                    364:         * Don't allow open if fs is mounted -nodev.
                    365:         */
1.1       cgd       366:        if (vp->v_mount && (vp->v_mount->mnt_flag & MNT_NODEV))
                    367:                return (ENXIO);
                    368:
1.112     ad        369:        switch (ap->a_mode & (FREAD | FWRITE)) {
                    370:        case FREAD | FWRITE:
                    371:                req = KAUTH_REQ_DEVICE_RAWIO_SPEC_RW;
                    372:                break;
                    373:        case FWRITE:
                    374:                req = KAUTH_REQ_DEVICE_RAWIO_SPEC_WRITE;
                    375:                break;
                    376:        default:
                    377:                req = KAUTH_REQ_DEVICE_RAWIO_SPEC_READ;
                    378:                break;
                    379:        }
1.89      elad      380:
1.1       cgd       381:        switch (vp->v_type) {
                    382:        case VCHR:
1.96      elad      383:                error = kauth_authorize_device_spec(ap->a_cred, req, vp);
1.112     ad        384:                if (error != 0)
1.96      elad      385:                        return (error);
1.89      elad      386:
1.112     ad        387:                /*
                    388:                 * Character devices can accept opens from multiple
                    389:                 * vnodes.
                    390:                 */
                    391:                mutex_enter(&specfs_lock);
                    392:                if (sn->sn_gone) {
                    393:                        mutex_exit(&specfs_lock);
                    394:                        return (EBADF);
                    395:                }
                    396:                sd->sd_opencnt++;
                    397:                sn->sn_opencnt++;
                    398:                mutex_exit(&specfs_lock);
1.100     ad        399:                if (cdev_type(dev) == D_TTY)
1.108     ad        400:                        vp->v_vflag |= VV_ISTTY;
1.39      fvdl      401:                VOP_UNLOCK(vp, 0);
1.100     ad        402:                error = cdev_open(dev, ap->a_mode, S_IFCHR, l);
1.39      fvdl      403:                vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
1.70      dsl       404:                break;
1.1       cgd       405:
                    406:        case VBLK:
1.96      elad      407:                error = kauth_authorize_device_spec(ap->a_cred, req, vp);
1.112     ad        408:                if (error != 0)
1.96      elad      409:                        return (error);
1.112     ad        410:
                    411:                /*
                    412:                 * For block devices, permit only one open.  The buffer
                    413:                 * cache cannot remain self-consistent with multiple
                    414:                 * vnodes holding a block device open.
                    415:                 */
                    416:                mutex_enter(&specfs_lock);
                    417:                if (sn->sn_gone) {
                    418:                        mutex_exit(&specfs_lock);
                    419:                        return (EBADF);
                    420:                }
                    421:                if (sd->sd_opencnt != 0) {
                    422:                        mutex_exit(&specfs_lock);
                    423:                        return EBUSY;
                    424:                }
                    425:                sn->sn_opencnt = 1;
                    426:                sd->sd_opencnt = 1;
                    427:                sd->sd_bdevvp = vp;
                    428:                mutex_exit(&specfs_lock);
                    429:
1.100     ad        430:                error = bdev_open(dev, ap->a_mode, S_IFBLK, l);
1.70      dsl       431:                break;
1.55      chs       432:
1.28      christos  433:        case VNON:
                    434:        case VLNK:
                    435:        case VDIR:
                    436:        case VREG:
                    437:        case VBAD:
                    438:        case VFIFO:
                    439:        case VSOCK:
1.70      dsl       440:        default:
                    441:                return 0;
1.1       cgd       442:        }
1.70      dsl       443:
1.112     ad        444:        mutex_enter(&specfs_lock);
                    445:        if (sn->sn_gone) {
                    446:                if (error == 0)
                    447:                        error = EBADF;
                    448:        } else if (error != 0) {
                    449:                sd->sd_opencnt--;
                    450:                sn->sn_opencnt--;
1.115     hannken   451:                if (vp->v_type == VBLK)
                    452:                        sd->sd_bdevvp = NULL;
                    453:
1.112     ad        454:        }
                    455:        mutex_exit(&specfs_lock);
1.89      elad      456:
1.112     ad        457:        if (cdev_type(dev) != D_DISK || error != 0)
1.70      dsl       458:                return error;
1.112     ad        459:
1.100     ad        460:        if (vp->v_type == VCHR)
                    461:                error = cdev_ioctl(vp->v_rdev, DIOCGPART, &pi, FREAD, curlwp);
                    462:        else
                    463:                error = bdev_ioctl(vp->v_rdev, DIOCGPART, &pi, FREAD, curlwp);
                    464:        if (error == 0)
1.99      yamt      465:                uvm_vnp_setsize(vp,
                    466:                    (voff_t)pi.disklab->d_secsize * pi.part->p_size);
1.70      dsl       467:        return 0;
1.1       cgd       468: }
                    469:
                    470: /*
                    471:  * Vnode op for read
                    472:  */
                    473: /* ARGSUSED */
1.28      christos  474: int
1.104     pooka     475: spec_read(void *v)
1.28      christos  476: {
1.15      mycroft   477:        struct vop_read_args /* {
                    478:                struct vnode *a_vp;
                    479:                struct uio *a_uio;
                    480:                int  a_ioflag;
1.87      elad      481:                kauth_cred_t a_cred;
1.28      christos  482:        } */ *ap = v;
1.48      augustss  483:        struct vnode *vp = ap->a_vp;
                    484:        struct uio *uio = ap->a_uio;
1.86      yamt      485:        struct lwp *l = curlwp;
1.56      chs       486:        struct buf *bp;
1.57      chs       487:        daddr_t bn;
1.59      chs       488:        int bsize, bscale;
1.56      chs       489:        struct partinfo dpart;
1.64      gehenna   490:        int n, on;
1.1       cgd       491:        int error = 0;
                    492:
                    493: #ifdef DIAGNOSTIC
                    494:        if (uio->uio_rw != UIO_READ)
                    495:                panic("spec_read mode");
1.86      yamt      496:        if (&uio->uio_vmspace->vm_map != kernel_map &&
                    497:            uio->uio_vmspace != curproc->p_vmspace)
1.1       cgd       498:                panic("spec_read proc");
                    499: #endif
                    500:        if (uio->uio_resid == 0)
                    501:                return (0);
                    502:
1.56      chs       503:        switch (vp->v_type) {
                    504:
                    505:        case VCHR:
1.39      fvdl      506:                VOP_UNLOCK(vp, 0);
1.100     ad        507:                error = cdev_read(vp->v_rdev, uio, ap->a_ioflag);
1.58      chs       508:                vn_lock(vp, LK_SHARED | LK_RETRY);
1.1       cgd       509:                return (error);
                    510:
1.56      chs       511:        case VBLK:
1.112     ad        512:                KASSERT(vp == vp->v_specnode->sn_dev->sd_bdevvp);
1.56      chs       513:                if (uio->uio_offset < 0)
                    514:                        return (EINVAL);
                    515:                bsize = BLKDEV_IOSIZE;
1.100     ad        516:                if (bdev_ioctl(vp->v_rdev, DIOCGPART, &dpart, FREAD, l) == 0) {
1.56      chs       517:                        if (dpart.part->p_fstype == FS_BSDFFS &&
                    518:                            dpart.part->p_frag != 0 && dpart.part->p_fsize != 0)
                    519:                                bsize = dpart.part->p_frag *
                    520:                                    dpart.part->p_fsize;
                    521:                }
1.59      chs       522:                bscale = bsize >> DEV_BSHIFT;
1.56      chs       523:                do {
1.59      chs       524:                        bn = (uio->uio_offset >> DEV_BSHIFT) &~ (bscale - 1);
1.56      chs       525:                        on = uio->uio_offset % bsize;
                    526:                        n = min((unsigned)(bsize - on), uio->uio_resid);
1.57      chs       527:                        error = bread(vp, bn, bsize, NOCRED, &bp);
1.56      chs       528:                        n = min(n, bsize - bp->b_resid);
                    529:                        if (error) {
1.107     ad        530:                                brelse(bp, 0);
1.56      chs       531:                                return (error);
                    532:                        }
                    533:                        error = uiomove((char *)bp->b_data + on, n, uio);
1.107     ad        534:                        brelse(bp, 0);
1.56      chs       535:                } while (error == 0 && uio->uio_resid > 0 && n != 0);
                    536:                return (error);
                    537:
                    538:        default:
                    539:                panic("spec_read type");
1.1       cgd       540:        }
1.56      chs       541:        /* NOTREACHED */
1.1       cgd       542: }
                    543:
                    544: /*
                    545:  * Vnode op for write
                    546:  */
                    547: /* ARGSUSED */
1.28      christos  548: int
1.104     pooka     549: spec_write(void *v)
1.28      christos  550: {
1.15      mycroft   551:        struct vop_write_args /* {
                    552:                struct vnode *a_vp;
                    553:                struct uio *a_uio;
                    554:                int  a_ioflag;
1.87      elad      555:                kauth_cred_t a_cred;
1.28      christos  556:        } */ *ap = v;
1.48      augustss  557:        struct vnode *vp = ap->a_vp;
                    558:        struct uio *uio = ap->a_uio;
1.86      yamt      559:        struct lwp *l = curlwp;
1.56      chs       560:        struct buf *bp;
                    561:        daddr_t bn;
1.59      chs       562:        int bsize, bscale;
1.56      chs       563:        struct partinfo dpart;
1.64      gehenna   564:        int n, on;
1.1       cgd       565:        int error = 0;
                    566:
                    567: #ifdef DIAGNOSTIC
                    568:        if (uio->uio_rw != UIO_WRITE)
                    569:                panic("spec_write mode");
1.86      yamt      570:        if (&uio->uio_vmspace->vm_map != kernel_map &&
                    571:            uio->uio_vmspace != curproc->p_vmspace)
1.1       cgd       572:                panic("spec_write proc");
                    573: #endif
                    574:
1.56      chs       575:        switch (vp->v_type) {
                    576:
                    577:        case VCHR:
1.39      fvdl      578:                VOP_UNLOCK(vp, 0);
1.100     ad        579:                error = cdev_write(vp->v_rdev, uio, ap->a_ioflag);
1.39      fvdl      580:                vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
1.1       cgd       581:                return (error);
1.56      chs       582:
                    583:        case VBLK:
1.112     ad        584:                KASSERT(vp == vp->v_specnode->sn_dev->sd_bdevvp);
1.56      chs       585:                if (uio->uio_resid == 0)
                    586:                        return (0);
                    587:                if (uio->uio_offset < 0)
                    588:                        return (EINVAL);
                    589:                bsize = BLKDEV_IOSIZE;
1.100     ad        590:                if (bdev_ioctl(vp->v_rdev, DIOCGPART, &dpart, FREAD, l) == 0) {
1.56      chs       591:                        if (dpart.part->p_fstype == FS_BSDFFS &&
                    592:                            dpart.part->p_frag != 0 && dpart.part->p_fsize != 0)
                    593:                                bsize = dpart.part->p_frag *
                    594:                                    dpart.part->p_fsize;
                    595:                }
1.59      chs       596:                bscale = bsize >> DEV_BSHIFT;
1.56      chs       597:                do {
1.59      chs       598:                        bn = (uio->uio_offset >> DEV_BSHIFT) &~ (bscale - 1);
1.56      chs       599:                        on = uio->uio_offset % bsize;
                    600:                        n = min((unsigned)(bsize - on), uio->uio_resid);
                    601:                        if (n == bsize)
                    602:                                bp = getblk(vp, bn, bsize, 0, 0);
                    603:                        else
                    604:                                error = bread(vp, bn, bsize, NOCRED, &bp);
                    605:                        if (error) {
1.107     ad        606:                                brelse(bp, 0);
1.56      chs       607:                                return (error);
                    608:                        }
                    609:                        n = min(n, bsize - bp->b_resid);
                    610:                        error = uiomove((char *)bp->b_data + on, n, uio);
                    611:                        if (error)
1.107     ad        612:                                brelse(bp, 0);
1.56      chs       613:                        else {
                    614:                                if (n + on == bsize)
                    615:                                        bawrite(bp);
                    616:                                else
                    617:                                        bdwrite(bp);
1.107     ad        618:                                error = bp->b_error;
1.56      chs       619:                        }
                    620:                } while (error == 0 && uio->uio_resid > 0 && n != 0);
                    621:                return (error);
                    622:
                    623:        default:
                    624:                panic("spec_write type");
1.55      chs       625:        }
1.56      chs       626:        /* NOTREACHED */
1.1       cgd       627: }
                    628:
                    629: /*
                    630:  * Device ioctl operation.
                    631:  */
                    632: /* ARGSUSED */
1.28      christos  633: int
1.104     pooka     634: spec_ioctl(void *v)
1.28      christos  635: {
1.15      mycroft   636:        struct vop_ioctl_args /* {
                    637:                struct vnode *a_vp;
1.19      cgd       638:                u_long a_command;
1.78      jrf       639:                void  *a_data;
1.15      mycroft   640:                int  a_fflag;
1.87      elad      641:                kauth_cred_t a_cred;
1.28      christos  642:        } */ *ap = v;
1.83      chs       643:        struct vnode *vp;
                    644:        dev_t dev;
1.1       cgd       645:
1.83      chs       646:        /*
                    647:         * Extract all the info we need from the vnode, taking care to
                    648:         * avoid a race with VOP_REVOKE().
                    649:         */
                    650:
                    651:        vp = ap->a_vp;
                    652:        dev = NODEV;
1.111     ad        653:        mutex_enter(&vp->v_interlock);
1.112     ad        654:        if ((vp->v_iflag & VI_XLOCK) == 0 && vp->v_specnode) {
1.83      chs       655:                dev = vp->v_rdev;
                    656:        }
1.111     ad        657:        mutex_exit(&vp->v_interlock);
1.83      chs       658:        if (dev == NODEV) {
                    659:                return ENXIO;
                    660:        }
                    661:
                    662:        switch (vp->v_type) {
1.1       cgd       663:
                    664:        case VCHR:
1.100     ad        665:                return cdev_ioctl(dev, ap->a_command, ap->a_data,
1.109     pooka     666:                    ap->a_fflag, curlwp);
1.1       cgd       667:
                    668:        case VBLK:
1.112     ad        669:                KASSERT(vp == vp->v_specnode->sn_dev->sd_bdevvp);
1.100     ad        670:                return bdev_ioctl(dev, ap->a_command, ap->a_data,
1.109     pooka     671:                   ap->a_fflag, curlwp);
1.1       cgd       672:
                    673:        default:
                    674:                panic("spec_ioctl");
                    675:                /* NOTREACHED */
                    676:        }
                    677: }
                    678:
                    679: /* ARGSUSED */
1.28      christos  680: int
1.104     pooka     681: spec_poll(void *v)
1.28      christos  682: {
1.32      mycroft   683:        struct vop_poll_args /* {
1.15      mycroft   684:                struct vnode *a_vp;
1.32      mycroft   685:                int a_events;
1.28      christos  686:        } */ *ap = v;
1.91      jld       687:        struct vnode *vp;
1.48      augustss  688:        dev_t dev;
1.1       cgd       689:
1.91      jld       690:        /*
                    691:         * Extract all the info we need from the vnode, taking care to
                    692:         * avoid a race with VOP_REVOKE().
                    693:         */
                    694:
                    695:        vp = ap->a_vp;
                    696:        dev = NODEV;
1.111     ad        697:        mutex_enter(&vp->v_interlock);
1.112     ad        698:        if ((vp->v_iflag & VI_XLOCK) == 0 && vp->v_specnode) {
1.91      jld       699:                dev = vp->v_rdev;
                    700:        }
1.111     ad        701:        mutex_exit(&vp->v_interlock);
1.91      jld       702:        if (dev == NODEV) {
1.92      jld       703:                return POLLERR;
1.91      jld       704:        }
                    705:
                    706:        switch (vp->v_type) {
1.1       cgd       707:
                    708:        case VCHR:
1.109     pooka     709:                return cdev_poll(dev, ap->a_events, curlwp);
1.30      mycroft   710:
                    711:        default:
1.32      mycroft   712:                return (genfs_poll(v));
1.15      mycroft   713:        }
                    714: }
1.65      jdolecek  715:
                    716: /* ARGSUSED */
                    717: int
1.104     pooka     718: spec_kqfilter(void *v)
1.65      jdolecek  719: {
                    720:        struct vop_kqfilter_args /* {
                    721:                struct vnode    *a_vp;
                    722:                struct proc     *a_kn;
                    723:        } */ *ap = v;
                    724:        dev_t dev;
                    725:
                    726:        switch (ap->a_vp->v_type) {
                    727:
                    728:        case VCHR:
                    729:                dev = ap->a_vp->v_rdev;
1.100     ad        730:                return cdev_kqfilter(dev, ap->a_kn);
1.65      jdolecek  731:        default:
                    732:                /*
                    733:                 * Block devices don't support kqfilter, and refuse it
                    734:                 * for any other files (like those vflush()ed) too.
                    735:                 */
                    736:                return (EOPNOTSUPP);
                    737:        }
                    738: }
                    739:
1.15      mycroft   740: /*
1.101     pooka     741:  * Allow mapping of only D_DISK.  This is called only for VBLK.
                    742:  */
                    743: int
1.104     pooka     744: spec_mmap(void *v)
1.101     pooka     745: {
                    746:        struct vop_mmap_args /* {
                    747:                struct vnode *a_vp;
1.102     pooka     748:                vm_prot_t a_prot;
1.101     pooka     749:                kauth_cred_t a_cred;
                    750:        } */ *ap = v;
                    751:        struct vnode *vp = ap->a_vp;
                    752:
                    753:        KASSERT(vp->v_type == VBLK);
                    754:        if (bdev_type(vp->v_rdev) != D_DISK)
                    755:                return EINVAL;
                    756:
                    757:        return 0;
                    758: }
                    759:
                    760: /*
1.15      mycroft   761:  * Synch buffers associated with a block device
                    762:  */
                    763: /* ARGSUSED */
                    764: int
1.104     pooka     765: spec_fsync(void *v)
1.28      christos  766: {
1.15      mycroft   767:        struct vop_fsync_args /* {
                    768:                struct vnode *a_vp;
1.87      elad      769:                kauth_cred_t a_cred;
1.40      kleink    770:                int  a_flags;
1.50      fvdl      771:                off_t offlo;
                    772:                off_t offhi;
1.28      christos  773:        } */ *ap = v;
1.48      augustss  774:        struct vnode *vp = ap->a_vp;
1.118   ! ad        775:        struct mount *mp;
        !           776:        int error;
1.15      mycroft   777:
1.112     ad        778:        if (vp->v_type == VBLK) {
1.118   ! ad        779:                if ((mp = vp->v_specmountpoint) != NULL) {
        !           780:                        error = VFS_FSYNC(mp, vp, ap->a_flags | FSYNC_VFS);
        !           781:                        if (error != EOPNOTSUPP)
        !           782:                                return error;
        !           783:                }
1.40      kleink    784:                vflushbuf(vp, (ap->a_flags & FSYNC_WAIT) != 0);
1.112     ad        785:        }
1.15      mycroft   786:        return (0);
1.1       cgd       787: }
                    788:
                    789: /*
                    790:  * Just call the device strategy routine
                    791:  */
1.28      christos  792: int
1.104     pooka     793: spec_strategy(void *v)
1.28      christos  794: {
1.15      mycroft   795:        struct vop_strategy_args /* {
1.76      hannken   796:                struct vnode *a_vp;
1.15      mycroft   797:                struct buf *a_bp;
1.28      christos  798:        } */ *ap = v;
1.76      hannken   799:        struct vnode *vp = ap->a_vp;
                    800:        struct buf *bp = ap->a_bp;
1.106     hannken   801:        int error;
1.1       cgd       802:
1.112     ad        803:        KASSERT(vp == vp->v_specnode->sn_dev->sd_bdevvp);
                    804:
1.79      hannken   805:        error = 0;
1.76      hannken   806:        bp->b_dev = vp->v_rdev;
1.45      fvdl      807:        if (!(bp->b_flags & B_READ) &&
1.105     pooka     808:            (LIST_FIRST(&bp->b_dep)) != NULL && bioopsp)
                    809:                bioopsp->io_start(bp);
1.77      hannken   810:
1.106     hannken   811:        if (!(bp->b_flags & B_READ))
1.110     hannken   812:                error = fscow_run(bp, false);
1.77      hannken   813:
1.79      hannken   814:        if (error) {
                    815:                bp->b_error = error;
                    816:                biodone(bp);
                    817:                return (error);
                    818:        }
                    819:
1.100     ad        820:        bdev_strategy(bp);
1.76      hannken   821:
1.1       cgd       822:        return (0);
                    823: }
                    824:
1.39      fvdl      825: int
1.104     pooka     826: spec_inactive(void *v)
1.39      fvdl      827: {
                    828:        struct vop_inactive_args /* {
                    829:                struct vnode *a_vp;
1.85      christos  830:                struct proc *a_l;
1.39      fvdl      831:        } */ *ap = v;
                    832:
                    833:        VOP_UNLOCK(ap->a_vp, 0);
                    834:        return (0);
                    835: }
                    836:
1.1       cgd       837: /*
                    838:  * This is a noop, simply returning what one has been given.
                    839:  */
1.28      christos  840: int
1.104     pooka     841: spec_bmap(void *v)
1.28      christos  842: {
1.15      mycroft   843:        struct vop_bmap_args /* {
                    844:                struct vnode *a_vp;
                    845:                daddr_t  a_bn;
                    846:                struct vnode **a_vpp;
                    847:                daddr_t *a_bnp;
1.39      fvdl      848:                int *a_runp;
1.28      christos  849:        } */ *ap = v;
1.1       cgd       850:
1.15      mycroft   851:        if (ap->a_vpp != NULL)
                    852:                *ap->a_vpp = ap->a_vp;
                    853:        if (ap->a_bnp != NULL)
                    854:                *ap->a_bnp = ap->a_bn;
1.39      fvdl      855:        if (ap->a_runp != NULL)
1.55      chs       856:                *ap->a_runp = (MAXBSIZE >> DEV_BSHIFT) - 1;
1.1       cgd       857:        return (0);
                    858: }
                    859:
                    860: /*
                    861:  * Device close routine
                    862:  */
                    863: /* ARGSUSED */
1.28      christos  864: int
1.104     pooka     865: spec_close(void *v)
1.28      christos  866: {
1.15      mycroft   867:        struct vop_close_args /* {
                    868:                struct vnode *a_vp;
                    869:                int  a_fflag;
1.87      elad      870:                kauth_cred_t a_cred;
1.28      christos  871:        } */ *ap = v;
1.48      augustss  872:        struct vnode *vp = ap->a_vp;
1.71      dsl       873:        struct session *sess;
1.1       cgd       874:        dev_t dev = vp->v_rdev;
1.112     ad        875:        int mode, error, flags, flags1, count;
                    876:        specnode_t *sn;
                    877:        specdev_t *sd;
1.44      wrstuden  878:
1.108     ad        879:        flags = vp->v_iflag;
1.112     ad        880:        sn = vp->v_specnode;
                    881:        sd = sn->sn_dev;
1.1       cgd       882:
                    883:        switch (vp->v_type) {
                    884:
                    885:        case VCHR:
1.11      cgd       886:                /*
                    887:                 * Hack: a tty device that is a controlling terminal
1.112     ad        888:                 * has a reference from the session structure.  We
                    889:                 * cannot easily tell that a character device is a
                    890:                 * controlling terminal, unless it is the closing
                    891:                 * process' controlling terminal.  In that case, if the
                    892:                 * open count is 1 release the reference from the
                    893:                 * session.  Also, remove the link from the tty back to
                    894:                 * the session and pgrp.
                    895:                 *
                    896:                 * XXX V. fishy.
1.11      cgd       897:                 */
1.116     ad        898:                mutex_enter(proc_lock);
1.112     ad        899:                sess = curlwp->l_proc->p_session;
                    900:                if (sn->sn_opencnt == 1 && vp == sess->s_ttyvp) {
                    901:                        mutex_spin_enter(&tty_lock);
1.71      dsl       902:                        sess->s_ttyvp = NULL;
1.72      pk        903:                        if (sess->s_ttyp->t_session != NULL) {
                    904:                                sess->s_ttyp->t_pgrp = NULL;
                    905:                                sess->s_ttyp->t_session = NULL;
1.112     ad        906:                                mutex_spin_exit(&tty_lock);
                    907:                                SESSRELE(sess);
1.116     ad        908:                                mutex_exit(proc_lock);
1.100     ad        909:                        } else {
1.112     ad        910:                                mutex_spin_exit(&tty_lock);
1.100     ad        911:                                if (sess->s_ttyp->t_pgrp != NULL)
                    912:                                        panic("spec_close: spurious pgrp ref");
1.116     ad        913:                                mutex_exit(proc_lock);
1.100     ad        914:                        }
1.11      cgd       915:                        vrele(vp);
1.100     ad        916:                } else
1.116     ad        917:                        mutex_exit(proc_lock);
1.100     ad        918:
1.1       cgd       919:                /*
                    920:                 * If the vnode is locked, then we are in the midst
                    921:                 * of forcably closing the device, otherwise we only
                    922:                 * close on last reference.
                    923:                 */
                    924:                mode = S_IFCHR;
                    925:                break;
                    926:
                    927:        case VBLK:
1.112     ad        928:                KASSERT(vp == vp->v_specnode->sn_dev->sd_bdevvp);
1.1       cgd       929:                /*
                    930:                 * On last close of a block device (that isn't mounted)
                    931:                 * we must invalidate any in core blocks, so that
                    932:                 * we can, for instance, change floppy disks.
                    933:                 */
1.109     pooka     934:                error = vinvalbuf(vp, V_SAVE, ap->a_cred, curlwp, 0, 0);
1.28      christos  935:                if (error)
1.15      mycroft   936:                        return (error);
1.1       cgd       937:                /*
                    938:                 * We do not want to really close the device if it
                    939:                 * is still in use unless we are trying to close it
                    940:                 * forcibly. Since every use (buffer, vnode, swap, cmap)
                    941:                 * holds a reference to the vnode, and because we mark
                    942:                 * any other vnodes that alias this device, when the
                    943:                 * sum of the reference counts on all the aliased
                    944:                 * vnodes descends to one, we are on last close.
                    945:                 */
                    946:                mode = S_IFBLK;
                    947:                break;
1.5       cgd       948:
1.1       cgd       949:        default:
                    950:                panic("spec_close: not special");
                    951:        }
                    952:
1.112     ad        953:        mutex_enter(&specfs_lock);
                    954:        sn->sn_opencnt--;
                    955:        count = --sd->sd_opencnt;
                    956:        if (vp->v_type == VBLK)
                    957:                sd->sd_bdevvp = NULL;
                    958:        mutex_exit(&specfs_lock);
                    959:
                    960:        if (count != 0)
                    961:                return 0;
                    962:
1.44      wrstuden  963:        flags1 = ap->a_fflag;
                    964:
                    965:        /*
1.108     ad        966:         * if VI_XLOCK is set, then we're going away soon, so make this
1.44      wrstuden  967:         * non-blocking. Also ensures that we won't wedge in vn_lock below.
                    968:         */
1.108     ad        969:        if (flags & VI_XLOCK)
1.44      wrstuden  970:                flags1 |= FNONBLOCK;
                    971:
                    972:        /*
1.62      wiz       973:         * If we're able to block, release the vnode lock & reacquire. We
1.72      pk        974:         * might end up sleeping for someone else who wants our queues. They
1.108     ad        975:         * won't get them if we hold the vnode locked. Also, if VI_XLOCK is
1.100     ad        976:         * set, don't release the lock as we won't be able to regain it.
1.44      wrstuden  977:         */
                    978:        if (!(flags1 & FNONBLOCK))
                    979:                VOP_UNLOCK(vp, 0);
                    980:
1.100     ad        981:        if (vp->v_type == VBLK)
1.109     pooka     982:                error = bdev_close(dev, flags1, mode, curlwp);
1.64      gehenna   983:        else
1.109     pooka     984:                error = cdev_close(dev, flags1, mode, curlwp);
1.44      wrstuden  985:
                    986:        if (!(flags1 & FNONBLOCK))
                    987:                vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
                    988:
                    989:        return (error);
1.1       cgd       990: }
                    991:
                    992: /*
                    993:  * Print out the contents of a special device vnode.
                    994:  */
1.28      christos  995: int
1.104     pooka     996: spec_print(void *v)
1.28      christos  997: {
1.15      mycroft   998:        struct vop_print_args /* {
                    999:                struct vnode *a_vp;
1.28      christos 1000:        } */ *ap = v;
1.15      mycroft  1001:
1.112     ad       1002:        printf("dev %d, %d\n", major(ap->a_vp->v_rdev),
1.33      christos 1003:            minor(ap->a_vp->v_rdev));
1.28      christos 1004:        return 0;
1.15      mycroft  1005: }
                   1006:
                   1007: /*
                   1008:  * Return POSIX pathconf information applicable to special devices.
                   1009:  */
1.28      christos 1010: int
1.104     pooka    1011: spec_pathconf(void *v)
1.28      christos 1012: {
1.15      mycroft  1013:        struct vop_pathconf_args /* {
                   1014:                struct vnode *a_vp;
                   1015:                int a_name;
1.18      cgd      1016:                register_t *a_retval;
1.28      christos 1017:        } */ *ap = v;
1.1       cgd      1018:
1.15      mycroft  1019:        switch (ap->a_name) {
                   1020:        case _PC_LINK_MAX:
                   1021:                *ap->a_retval = LINK_MAX;
                   1022:                return (0);
                   1023:        case _PC_MAX_CANON:
                   1024:                *ap->a_retval = MAX_CANON;
                   1025:                return (0);
                   1026:        case _PC_MAX_INPUT:
                   1027:                *ap->a_retval = MAX_INPUT;
                   1028:                return (0);
                   1029:        case _PC_PIPE_BUF:
                   1030:                *ap->a_retval = PIPE_BUF;
                   1031:                return (0);
                   1032:        case _PC_CHOWN_RESTRICTED:
                   1033:                *ap->a_retval = 1;
                   1034:                return (0);
                   1035:        case _PC_VDISABLE:
                   1036:                *ap->a_retval = _POSIX_VDISABLE;
1.41      kleink   1037:                return (0);
                   1038:        case _PC_SYNC_IO:
                   1039:                *ap->a_retval = 1;
1.15      mycroft  1040:                return (0);
                   1041:        default:
                   1042:                return (EINVAL);
                   1043:        }
1.1       cgd      1044:        /* NOTREACHED */
1.35      kleink   1045: }
                   1046:
1.80      perry    1047: /*
1.35      kleink   1048:  * Advisory record locking support.
                   1049:  */
                   1050: int
1.104     pooka    1051: spec_advlock(void *v)
1.35      kleink   1052: {
                   1053:        struct vop_advlock_args /* {
                   1054:                struct vnode *a_vp;
1.78      jrf      1055:                void *a_id;
1.35      kleink   1056:                int a_op;
                   1057:                struct flock *a_fl;
                   1058:                int a_flags;
                   1059:        } */ *ap = v;
1.48      augustss 1060:        struct vnode *vp = ap->a_vp;
1.35      kleink   1061:
1.49      jdolecek 1062:        return lf_advlock(ap, &vp->v_speclockf, (off_t)0);
1.1       cgd      1063: }

CVSweb <webmaster@jp.NetBSD.org>