Annotation of kernel/bsd/vfs/vfs_subr.c, revision 1.1.1.2

1.1       root        1: /*
                      2:  * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
                      3:  *
                      4:  * @APPLE_LICENSE_HEADER_START@
                      5:  * 
                      6:  * Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
                      7:  * Reserved.  This file contains Original Code and/or Modifications of
                      8:  * Original Code as defined in and that are subject to the Apple Public
                      9:  * Source License Version 1.1 (the "License").  You may not use this file
                     10:  * except in compliance with the License.  Please obtain a copy of the
                     11:  * License at http://www.apple.com/publicsource and read it before using
                     12:  * this file.
                     13:  * 
                     14:  * The Original Code and all software distributed under the License are
                     15:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
                     16:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
                     17:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
                     18:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
                     19:  * License for the specific language governing rights and limitations
                     20:  * under the License.
                     21:  * 
                     22:  * @APPLE_LICENSE_HEADER_END@
                     23:  */
                     24: 
                     25: /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
                     26: /*
                     27:  * Copyright (c) 1989, 1993
                     28:  *     The Regents of the University of California.  All rights reserved.
                     29:  * (c) UNIX System Laboratories, Inc.
                     30:  * All or some portions of this file are derived from material licensed
                     31:  * to the University of California by American Telephone and Telegraph
                     32:  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
                     33:  * the permission of UNIX System Laboratories, Inc.
                     34:  *
                     35:  * Redistribution and use in source and binary forms, with or without
                     36:  * modification, are permitted provided that the following conditions
                     37:  * are met:
                     38:  * 1. Redistributions of source code must retain the above copyright
                     39:  *    notice, this list of conditions and the following disclaimer.
                     40:  * 2. Redistributions in binary form must reproduce the above copyright
                     41:  *    notice, this list of conditions and the following disclaimer in the
                     42:  *    documentation and/or other materials provided with the distribution.
                     43:  * 3. All advertising materials mentioning features or use of this software
                     44:  *    must display the following acknowledgement:
                     45:  *     This product includes software developed by the University of
                     46:  *     California, Berkeley and its contributors.
                     47:  * 4. Neither the name of the University nor the names of its contributors
                     48:  *    may be used to endorse or promote products derived from this software
                     49:  *    without specific prior written permission.
                     50:  *
                     51:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     52:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     53:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     54:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     55:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     56:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     57:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     58:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     59:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     60:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     61:  * SUCH DAMAGE.
                     62:  *
                     63:  *     @(#)vfs_subr.c  8.31 (Berkeley) 5/26/95
                     64:  */
                     65: 
                     66: /*
                     67:  * External virtual filesystem routines
                     68:  */
                     69: 
                     70: #include <mach_nbc.h>
                     71: #include <sys/param.h>
                     72: #include <sys/systm.h>
                     73: #include <sys/proc.h>
                     74: #include <sys/mount.h>
                     75: #include <sys/time.h>
                     76: #include <sys/vnode.h>
                     77: #include <sys/stat.h>
                     78: #include <sys/namei.h>
                     79: #include <sys/ucred.h>
                     80: #include <sys/buf.h>
                     81: #include <sys/errno.h>
                     82: #include <sys/malloc.h>
                     83: #include <sys/domain.h>
                     84: #include <sys/mbuf.h>
                     85: #include <sys/syslog.h>
                     86: 
                     87: #include <sys/vm.h>
                     88: #include <sys/sysctl.h>
                     89: 
                     90: #include <miscfs/specfs/specdev.h>
                     91: 
                     92: #if MACH_NBC
                     93: #include <kern/mapfs.h>
                     94: #endif /* MACH_NBC */
                     95: 
                     96: enum vtype iftovt_tab[16] = {
                     97:        VNON, VFIFO, VCHR, VNON, VDIR, VNON, VBLK, VNON,
                     98:        VREG, VNON, VLNK, VNON, VSOCK, VNON, VNON, VBAD,
                     99: };
                    100: int    vttoif_tab[9] = {
                    101:        0, S_IFREG, S_IFDIR, S_IFBLK, S_IFCHR, S_IFLNK,
                    102:        S_IFSOCK, S_IFIFO, S_IFMT,
                    103: };
                    104: 
                    105: /*
                    106:  * Insq/Remq for the vnode usage lists.
                    107:  */
                    108: #define        bufinsvn(bp, dp)        LIST_INSERT_HEAD(dp, bp, b_vnbufs)
                    109: #define        bufremvn(bp) {                                                  \
                    110:        LIST_REMOVE(bp, b_vnbufs);                                      \
                    111:        (bp)->b_vnbufs.le_next = NOLIST;                                \
                    112: }
                    113: TAILQ_HEAD(freelst, vnode) vnode_free_list;    /* vnode free list */
                    114: struct mntlist mountlist;                      /* mounted filesystem list */
                    115: 
                    116: /*
                    117:  * Have to declare first two locks as actual data even if !MACH_SLOCKS, since
                    118:  * a pointers to them get passed around.
                    119:  */
                    120: simple_lock_data_t mountlist_slock;
                    121: simple_lock_data_t mntvnode_slock;
                    122: decl_simple_lock_data(,mntid_slock);
                    123: decl_simple_lock_data(,vnode_free_list_slock);
                    124: decl_simple_lock_data(,spechash_slock);
                    125: 
                    126: extern struct lock__bsd__      exchangelock;
                    127: 
                    128: /*
                    129:  * vnodetarget is the amount of vnodes we expect to get back from the
                    130:  * VM object cache. As vm_object_cache_steal() is a cpu bound operation
                    131:  * for faster processers this number could be higher.
                    132:  * Having this number too high introduces longer delays in the execution
                    133:  * of getnewvnode().
                    134:  */
                    135: unsigned long vnodetarget;             /* target for vm_object_cache_steal() */
                    136: #define VNODE_FREE_TARGET      20      /* Default value for vnodetarget */
                    137: 
                    138: /*
                    139:  * We need quite a few vnodes on the free list to sustain the
                    140:  * rapid stat() the compilation process does, and still benefit from the name
                    141:  * cache. Having too few vnodes on the free list causes serious disk
                    142:  * thrashing as we cycle through them.
                    143:  */
                    144: #define VNODE_FREE_MIN         100     /* freelist should have at least these many */
                    145: 
                    146: /*
                    147:  * We need to get vnodes back from the VM object cache when a certain #
                    148:  * of vnodes are reused from the freelist. This is essential for the
                    149:  * caching to be effective in the namecache and the buffer cache [for the
                    150:  * metadata].
                    151:  */
                    152: #define        VNODE_TOOMANY_REUSED    (VNODE_FREE_MIN/4)
                    153: 
                    154: /*
                    155:  * If we have enough vnodes on the freelist we do not want to reclaim
                    156:  * the vnodes from the VM object cache.
                    157:  */
                    158: #define VNODE_FREE_ENOUGH      (VNODE_FREE_MIN + (VNODE_FREE_MIN/2))
                    159: /*
                    160:  * Initialize the vnode management data structures.
                    161:  */
                    162: void
                    163: vntblinit()
                    164: {
                    165:        simple_lock_init(&mountlist_slock);
                    166:        simple_lock_init(&mntvnode_slock);
                    167:        simple_lock_init(&mntid_slock);
                    168:        simple_lock_init(&spechash_slock);
                    169:        TAILQ_INIT(&vnode_free_list);
                    170:        simple_lock_init(&vnode_free_list_slock);
                    171:        CIRCLEQ_INIT(&mountlist);
                    172:     lockinit(&exchangelock, PVFS, "exchange", 0, 0);
                    173: 
                    174:        if (!vnodetarget)
                    175:                vnodetarget = VNODE_FREE_TARGET;
                    176:        
                    177:        adjust_vm_object_cache(0, desiredvnodes - VNODE_FREE_MIN);
                    178: }
                    179: 
                    180: /* Reset the VM Object Cache with the values passed in */
                    181: kern_return_t
                    182: reset_vmobjectcache(unsigned int val1, unsigned int val2)
                    183: {
                    184:        return(adjust_vm_object_cache(val1-VNODE_FREE_MIN, val2 - VNODE_FREE_MIN));
                    185: }
                    186: 
                    187: 
                    188: 
                    189: /*
                    190:  * Mark a mount point as busy. Used to synchronize access and to delay
                    191:  * unmounting. Interlock is not released on failure.
                    192:  */
                    193: int
                    194: vfs_busy(mp, flags, interlkp, p)
                    195:        struct mount *mp;
                    196:        int flags;
                    197:        struct slock *interlkp;
                    198:        struct proc *p;
                    199: {
                    200:        int lkflags;
                    201: 
                    202:        if (mp->mnt_flag & MNT_UNMOUNT) {
                    203:                if (flags & LK_NOWAIT)
                    204:                        return (ENOENT);
                    205:                mp->mnt_flag |= MNT_MWAIT;
                    206:                if (interlkp)
                    207:                        simple_unlock(interlkp);
                    208:                /*
                    209:                 * Since all busy locks are shared except the exclusive
                    210:                 * lock granted when unmounting, the only place that a
                    211:                 * wakeup needs to be done is at the release of the
                    212:                 * exclusive lock at the end of dounmount.
                    213:                 */
                    214:                sleep((caddr_t)mp, PVFS);
                    215:                if (interlkp)
                    216:                        simple_lock(interlkp);
                    217:                return (ENOENT);
                    218:        }
                    219:        lkflags = LK_SHARED;
                    220:        if (interlkp)
                    221:                lkflags |= LK_INTERLOCK;
                    222:        if (lockmgr(&mp->mnt_lock, lkflags, interlkp, p))
                    223:                panic("vfs_busy: unexpected lock failure");
                    224:        return (0);
                    225: }
                    226: 
                    227: /*
                    228:  * Free a busy filesystem.
                    229:  */
                    230: void
                    231: vfs_unbusy(mp, p)
                    232:        struct mount *mp;
                    233:        struct proc *p;
                    234: {
                    235: 
                    236:        lockmgr(&mp->mnt_lock, LK_RELEASE, NULL, p);
                    237: }
                    238: 
                    239: /*
                    240:  * Lookup a filesystem type, and if found allocate and initialize
                    241:  * a mount structure for it.
                    242:  *
                    243:  * Devname is usually updated by mount(8) after booting.
                    244:  */
                    245: int
                    246: vfs_rootmountalloc(fstypename, devname, mpp)
                    247:        char *fstypename;
                    248:        char *devname;
                    249:        struct mount **mpp;
                    250: {
                    251:        struct proc *p = current_proc();        /* XXX */
                    252:        struct vfsconf *vfsp;
                    253:        struct mount *mp;
                    254: 
                    255:        for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next)
                    256:                if (!strcmp(vfsp->vfc_name, fstypename))
                    257:                        break;
                    258:        if (vfsp == NULL)
                    259:                return (ENODEV);
                    260:        mp = _MALLOC_ZONE((u_long)sizeof(struct mount), M_MOUNT, M_WAITOK);
                    261:        bzero((char *)mp, (u_long)sizeof(struct mount));
                    262:        lockinit(&mp->mnt_lock, PVFS, "vfslock", 0, 0);
                    263:        (void)vfs_busy(mp, LK_NOWAIT, 0, p);
                    264:        LIST_INIT(&mp->mnt_vnodelist);
                    265:        mp->mnt_vfc = vfsp;
                    266:        mp->mnt_op = vfsp->vfc_vfsops;
                    267:        mp->mnt_flag = MNT_RDONLY;
                    268:        mp->mnt_vnodecovered = NULLVP;
                    269:        vfsp->vfc_refcount++;
                    270:        mp->mnt_stat.f_type = vfsp->vfc_typenum;
                    271:        mp->mnt_flag |= vfsp->vfc_flags & MNT_VISFLAGMASK;
                    272:        strncpy(mp->mnt_stat.f_fstypename, vfsp->vfc_name, MFSNAMELEN);
                    273:        mp->mnt_stat.f_mntonname[0] = '/';
                    274:        (void) copystr(devname, mp->mnt_stat.f_mntfromname, MNAMELEN - 1, 0);
                    275:        *mpp = mp;
                    276:        return (0);
                    277: }
                    278: 
                    279: /*
                    280:  * Find an appropriate filesystem to use for the root. If a filesystem
                    281:  * has not been preselected, walk through the list of known filesystems
                    282:  * trying those that have mountroot routines, and try them until one
                    283:  * works or we have tried them all.
                    284:  */
                    285: int
                    286: vfs_mountroot()
                    287: {
                    288:        struct vfsconf *vfsp;
                    289:        extern int (*mountroot)(void);
                    290:        int error;
                    291: 
                    292:        if (mountroot != NULL) {
                    293:                error = (*mountroot)();
                    294:                return (error);
                    295:        }
                    296:        
                    297:        for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next) {
                    298:                if (vfsp->vfc_mountroot == NULL)
                    299:                        continue;
                    300:                if ((error = (*vfsp->vfc_mountroot)()) == 0)
                    301:                        return (0);
                    302:                printf("%s_mountroot failed: %d\n", vfsp->vfc_name, error);
                    303:        }
                    304:        return (ENODEV);
                    305: }
                    306: 
                    307: /*
                    308:  * Lookup a mount point by filesystem identifier.
                    309:  */
                    310: struct mount *
                    311: vfs_getvfs(fsid)
                    312:        fsid_t *fsid;
                    313: {
                    314:        register struct mount *mp;
                    315: 
                    316:        simple_lock(&mountlist_slock);
                    317:        for (mp = mountlist.cqh_first; mp != (void *)&mountlist;
                    318:             mp = mp->mnt_list.cqe_next) {
                    319:                if (mp->mnt_stat.f_fsid.val[0] == fsid->val[0] &&
                    320:                    mp->mnt_stat.f_fsid.val[1] == fsid->val[1]) {
                    321:                        simple_unlock(&mountlist_slock);
                    322:                        return (mp);
                    323:                }
                    324:        }
                    325:        simple_unlock(&mountlist_slock);
                    326:        return ((struct mount *)0);
                    327: }
                    328: 
                    329: /*
                    330:  * Get a new unique fsid
                    331:  */
                    332: void
                    333: vfs_getnewfsid(mp)
                    334:        struct mount *mp;
                    335: {
                    336: static u_short xxxfs_mntid;
                    337: 
                    338:        fsid_t tfsid;
                    339:        int mtype;
                    340: 
                    341:        simple_lock(&mntid_slock);
                    342:        mtype = mp->mnt_vfc->vfc_typenum;
                    343:        mp->mnt_stat.f_fsid.val[0] = makedev(nblkdev + mtype, 0);
                    344:        mp->mnt_stat.f_fsid.val[1] = mtype;
                    345:        if (xxxfs_mntid == 0)
                    346:                ++xxxfs_mntid;
                    347:        tfsid.val[0] = makedev(nblkdev + mtype, xxxfs_mntid);
                    348:        tfsid.val[1] = mtype;
                    349:        if (mountlist.cqh_first != (void *)&mountlist) {
                    350:                while (vfs_getvfs(&tfsid)) {
                    351:                        tfsid.val[0]++;
                    352:                        xxxfs_mntid++;
                    353:                }
                    354:        }
                    355:        mp->mnt_stat.f_fsid.val[0] = tfsid.val[0];
                    356:        simple_unlock(&mntid_slock);
                    357: }
                    358: 
                    359: /*
                    360:  * Set vnode attributes to VNOVAL
                    361:  */
                    362: void
                    363: vattr_null(vap)
                    364:        register struct vattr *vap;
                    365: {
                    366: 
                    367:        vap->va_type = VNON;
                    368:        vap->va_size = vap->va_bytes = VNOVAL;
                    369:        vap->va_mode = vap->va_nlink = vap->va_uid = vap->va_gid =
                    370:                vap->va_fsid = vap->va_fileid =
                    371:                vap->va_blocksize = vap->va_rdev =
                    372:                vap->va_atime.tv_sec = vap->va_atime.tv_nsec =
                    373:                vap->va_mtime.tv_sec = vap->va_mtime.tv_nsec =
                    374:                vap->va_ctime.tv_sec = vap->va_ctime.tv_nsec =
                    375:                vap->va_flags = vap->va_gen = VNOVAL;
                    376:        vap->va_vaflags = 0;
                    377: }
                    378: 
                    379: /*
                    380:  * Routines having to do with the management of the vnode table.
                    381:  */
                    382: extern int (**dead_vnodeop_p)();
                    383: static void vclean __P((struct vnode *vp, int flag, struct proc *p));
                    384: extern void vgonel __P((struct vnode *vp, struct proc *p));
                    385: long numvnodes, freevnodes;
                    386: 
                    387: extern struct vattr va_null;
                    388: 
                    389: /*
                    390:  * Return the next vnode from the free list.
                    391:  */
                    392: int
                    393: getnewvnode(tag, mp, vops, vpp)
                    394:        enum vtagtype tag;
                    395:        struct mount *mp;
                    396:        int (**vops)();
                    397:        struct vnode **vpp;
                    398: {
                    399:        struct proc *p = current_proc();        /* XXX */
                    400:        struct vnode *vp;
                    401:        int cnt, didretry = 0;
                    402:        static int reused = 0;                                          /* track the reuse rate */
                    403: 
                    404: retry:
                    405:        simple_lock(&vnode_free_list_slock);
                    406:        /*
                    407:         * MALLOC a vnode if the number of vnodes is not reached the desired
                    408:         * value. There might be vnodes on the free list, but we do not
                    409:         * reuse from the freelist because reusing a vnode implies reusing
                    410:         * the name cache entry.
                    411:         */
                    412:        if (numvnodes < desiredvnodes) {
                    413:                numvnodes++;
                    414:                simple_unlock(&vnode_free_list_slock);
                    415:                MALLOC_ZONE(vp, struct vnode *, sizeof *vp, M_VNODE, M_WAITOK);
                    416:                bzero((char *)vp, sizeof *vp);
                    417:                simple_lock_init(&vp->v_interlock);
                    418:        } else {
                    419:                /*
                    420:                 * Once the desired number of vnodes are allocated, we start reusing
                    421:                 * from the freelist.
                    422:                 */
                    423:                if (freevnodes < VNODE_FREE_MIN) {
                    424:                        /*
                    425:                         * if we are low on vnodes on the freelist attempt to get
                    426:                         * some back from the VM object cache
                    427:                         */
                    428:                        simple_unlock(&vnode_free_list_slock);
                    429:                        vm_object_cache_steal(vnodetarget);
                    430:                        simple_lock(&vnode_free_list_slock);
                    431:                }
                    432:                        
                    433:                for (cnt = 0, vp = vnode_free_list.tqh_first;
                    434:                                vp != NULLVP; cnt++, vp = vp->v_freelist.tqe_next) {
                    435:                        if (simple_lock_try(&vp->v_interlock))
                    436:                                break;
                    437:                }
                    438:                /*
                    439:                 * Unless this is a bad time of the month, at most
                    440:                 * the first NCPUS items on the free list are
                    441:                 * locked, so this is close enough to being empty.
                    442:                 */
                    443:                if (vp == NULLVP) {
                    444:                        simple_unlock(&vnode_free_list_slock);
                    445:                        if (!(didretry++) && (vm_object_cache_steal(vnodetarget) > 0))
                    446:                                goto retry;
                    447:                        tablefull("vnode");
                    448:                        log(LOG_EMERG, "%d vnodes locked, %d desired, %d numvnodes\n",
                    449:                                cnt, desiredvnodes, numvnodes);
                    450:                        *vpp = 0;
                    451:                        return (ENFILE);
                    452:                }
                    453: 
                    454:                if (vp->v_usecount)
                    455:                        panic("free vnode isn't: v_type = %d, v_usecount = %d?",
                    456:                                        vp->v_type, vp->v_usecount);
                    457: 
                    458:                if (reused > VNODE_TOOMANY_REUSED) {
                    459:                        reused = 0;
                    460:                        if (freevnodes < VNODE_FREE_ENOUGH) {
                    461:                                simple_unlock(&vnode_free_list_slock);
                    462:                                simple_unlock(&vp->v_interlock);
                    463:                                vm_object_cache_steal(vnodetarget);
                    464:                                /*
                    465:                                 * The vnode we have right now can potentially have dirty
                    466:                                 * buffers associated with it. So we do not want to reuse it
                    467:                                 * given a choice. The vnodes reclimed from VM object cache are
                    468:                                 * put on the front of the freelist. So retry can potentially
                    469:                                 * avoid IO, which is a good thing.
                    470:                                 */
                    471:                                goto retry;
                    472:                        }
                    473:                }
                    474: 
                    475:                TAILQ_REMOVE(&vnode_free_list, vp, v_freelist);
                    476:                /* see comment on why 0xdeadb is set at end of vgone (below) */
                    477:                vp->v_freelist.tqe_prev = (struct vnode **)0xdeadb;
                    478:                freevnodes--;
                    479:                reused++;
                    480:                simple_unlock(&vnode_free_list_slock);
                    481:                vp->v_lease = NULL;
                    482:                if (vp->v_type != VBAD)
                    483:                        vgonel(vp, p);
                    484:                else
                    485:                        simple_unlock(&vp->v_interlock);
                    486: #if DIAGNOSTIC
                    487:                if (vp->v_data)
                    488:                        panic("cleaned vnode isn't");
                    489:                {
                    490:                int s = splbio();
                    491:                if (vp->v_numoutput)
                    492:                        panic("Clean vnode has pending I/O's");
                    493:                splx(s);
                    494:                }
                    495: #endif
                    496:                vp->v_flag = 0;
                    497:                vp->v_lastr = 0;
                    498:                vp->v_ralen = 0;
                    499:                vp->v_maxra = 0;
                    500:                vp->v_lastw = 0;
                    501:                vp->v_lasta = 0;
                    502:                vp->v_cstart = 0;
                    503:                vp->v_clen = 0;
                    504:                vp->v_socket = 0;
                    505:                vp->v_bread = vp->v_consumed = 0;
                    506:        }
                    507:        vp->v_power = 5;       /* 32k speculative reads */
                    508:        vp->v_trigger = 16 * 8;
                    509:        vp->v_type = VNON;
                    510:        cache_purge(vp);
                    511:        vp->v_tag = tag;
                    512:        vp->v_op = vops;
                    513:        insmntque(vp, mp);
                    514:        *vpp = vp;
                    515:        vp->v_usecount = 1;
                    516:        vp->v_data = 0;
                    517:        return (0);
                    518: }
                    519: 
                    520: /*
                    521:  * Move a vnode from one mount queue to another.
                    522:  */
                    523: void
                    524: insmntque(vp, mp)
                    525:        struct vnode *vp;
                    526:        struct mount *mp;
                    527: {
                    528: 
                    529:        simple_lock(&mntvnode_slock);
                    530:        /*
                    531:         * Delete from old mount point vnode list, if on one.
                    532:         */
                    533:        if (vp->v_mount != NULL)
                    534:                LIST_REMOVE(vp, v_mntvnodes);
                    535:        /*
                    536:         * Insert into list of vnodes for the new mount point, if available.
                    537:         */
                    538:        if ((vp->v_mount = mp) != NULL)
                    539:                LIST_INSERT_HEAD(&mp->mnt_vnodelist, vp, v_mntvnodes);
                    540:        simple_unlock(&mntvnode_slock);
                    541: }
                    542: 
                    543: /*
                    544:  * Update outstanding I/O count and do wakeup if requested.
                    545:  */
                    546: void
                    547: vwakeup(bp)
                    548:        register struct buf *bp;
                    549: {
                    550:        register struct vnode *vp;
                    551: 
                    552:        bp->b_flags &= ~B_WRITEINPROG;
                    553:        if (vp = bp->b_vp) {
                    554:                if (--vp->v_numoutput < 0)
                    555:                        panic("vwakeup: neg numoutput");
                    556:                if ((vp->v_flag & VBWAIT) && vp->v_numoutput <= 0) {
                    557:                        if (vp->v_numoutput < 0)
                    558:                                panic("vwakeup: neg numoutput 2");
                    559:                        vp->v_flag &= ~VBWAIT;
                    560:                        wakeup((caddr_t)&vp->v_numoutput);
                    561:                }
                    562:        }
                    563: }
                    564: 
                    565: /*
                    566:  * Flush out and invalidate all buffers associated with a vnode.
                    567:  * Called with the underlying object locked.
                    568:  */
                    569: int
                    570: vinvalbuf(vp, flags, cred, p, slpflag, slptimeo)
                    571:        register struct vnode *vp;
                    572:        int flags;
                    573:        struct ucred *cred;
                    574:        struct proc *p;
                    575:        int slpflag, slptimeo;
                    576: {
                    577:        register struct buf *bp;
                    578:        struct buf *nbp, *blist;
                    579:        int s, error = 0;
                    580: 
                    581:        if (flags & V_SAVE) {
                    582: #if MACH_NBC
                    583:                if ((vp->v_type == VREG) && (vp->v_vm_info) && (vp->v_vm_info->mapped))
                    584:                        if ((error = mapfs_fsync(vp)))
                    585:                                return (error);
                    586: #endif /* MACH_NBC */
                    587:                if (error = VOP_FSYNC(vp, cred, MNT_WAIT, p))
                    588:                        return (error);
                    589:                if (vp->v_dirtyblkhd.lh_first != NULL)
                    590:                        panic("vinvalbuf: dirty bufs");
                    591:        }
                    592: 
                    593:        /*
                    594:         * make sure we don't have any lingering state
                    595:         * associated with cluster writes
                    596:         */
                    597:        vp->v_cstart = 0;
                    598:        vp->v_clen = 0;
                    599:        vp->v_lasta = 0;
                    600:        vp->v_lastw = 0;
                    601: 
                    602: #if MACH_NBC
                    603:        if (vp->v_type == VREG) {
                    604:                error = mapfs_invalidate(vp);
                    605: #if DIAGNOSTIC
                    606:                if (error)
                    607:                        kprintf("vinvalbuf: mapfs_invalidate(0x%x) returned %d\n", vp, error);
                    608: #endif
                    609:        }
                    610: #endif /* MACH_NBC */
                    611: 
                    612:        for (;;) {
                    613:                if ((blist = vp->v_cleanblkhd.lh_first) && flags & V_SAVEMETA)
                    614:                        while (blist && blist->b_lblkno < 0)
                    615:                                blist = blist->b_vnbufs.le_next;
                    616:                if (!blist && (blist = vp->v_dirtyblkhd.lh_first) &&
                    617:                    (flags & V_SAVEMETA))
                    618:                        while (blist && blist->b_lblkno < 0)
                    619:                                blist = blist->b_vnbufs.le_next;
                    620:                if (!blist)
                    621:                        break;
                    622: 
                    623:                for (bp = blist; bp; bp = nbp) {
                    624:                        nbp = bp->b_vnbufs.le_next;
                    625:                        if (flags & V_SAVEMETA && bp->b_lblkno < 0)
                    626:                                continue;
                    627:                        s = splbio();
                    628:                        if (bp->b_flags & B_BUSY) {
                    629:                                bp->b_flags |= B_WANTED;
                    630:                                error = tsleep((caddr_t)bp,
                    631:                                        slpflag | (PRIBIO + 1), "vinvalbuf",
                    632:                                        slptimeo);
                    633:                                splx(s);
                    634:                                if (error)
                    635:                                        return (error);
                    636:                                break;
                    637:                        }
                    638:                        bremfree(bp);
                    639:                        bp->b_flags |= B_BUSY;
                    640:                        splx(s);
                    641:                        /*
                    642:                         * XXX Since there are no node locks for NFS, I believe
                    643:                         * there is a slight chance that a delayed write will
                    644:                         * occur while sleeping just above, so check for it.
                    645:                         */
                    646:                        if ((bp->b_flags & B_DELWRI) && (flags & V_SAVE)) {
                    647:                                (void) VOP_BWRITE(bp);
                    648:                                break;
                    649:                        }
                    650:                        bp->b_flags |= B_INVAL;
                    651:                        brelse(bp);
                    652:                }
                    653:        }
                    654:        if (!(flags & V_SAVEMETA) &&
                    655:            (vp->v_dirtyblkhd.lh_first || vp->v_cleanblkhd.lh_first))
                    656:                panic("vinvalbuf: flush failed");
                    657:        return (0);
                    658: }
                    659: 
                    660: /*
                    661:  * Associate a buffer with a vnode.
                    662:  */
                    663: void
                    664: bgetvp(vp, bp)
                    665:        register struct vnode *vp;
                    666:        register struct buf *bp;
                    667: {
                    668: 
                    669:        if (bp->b_vp)
                    670:                panic("bgetvp: not free");
                    671:        VHOLD(vp);
                    672:        bp->b_vp = vp;
                    673:        if (vp->v_type == VBLK || vp->v_type == VCHR)
                    674:                bp->b_dev = vp->v_rdev;
                    675:        else
                    676:                bp->b_dev = NODEV;
                    677:        /*
                    678:         * Insert onto list for new vnode.
                    679:         */
                    680:        bufinsvn(bp, &vp->v_cleanblkhd);
                    681: }
                    682: 
                    683: /*
                    684:  * Disassociate a buffer from a vnode.
                    685:  */
                    686: void
                    687: brelvp(bp)
                    688:        register struct buf *bp;
                    689: {
                    690:        struct vnode *vp;
                    691: 
                    692:        if (bp->b_vp == (struct vnode *) 0)
                    693:                panic("brelvp: NULL");
                    694:        /*
                    695:         * Delete from old vnode list, if on one.
                    696:         */
                    697:        if (bp->b_vnbufs.le_next != NOLIST)
                    698:                bufremvn(bp);
                    699:        vp = bp->b_vp;
                    700:        bp->b_vp = (struct vnode *) 0;
                    701:        HOLDRELE(vp);
                    702: }
                    703: 
                    704: /*
                    705:  * Reassign a buffer from one vnode to another.
                    706:  * Used to assign file specific control information
                    707:  * (indirect blocks) to the vnode to which they belong.
                    708:  */
                    709: void
                    710: reassignbuf(bp, newvp)
                    711:        register struct buf *bp;
                    712:        register struct vnode *newvp;
                    713: {
                    714:        register struct buflists *listheadp;
                    715: 
                    716:        if (newvp == NULL) {
                    717:                printf("reassignbuf: NULL");
                    718:                return;
                    719:        }
                    720:        /*
                    721:         * Delete from old vnode list, if on one.
                    722:         */
                    723:        if (bp->b_vnbufs.le_next != NOLIST)
                    724:                bufremvn(bp);
                    725:        /*
                    726:         * If dirty, put on list of dirty buffers;
                    727:         * otherwise insert onto list of clean buffers.
                    728:         */
                    729:        if (bp->b_flags & B_DELWRI)
                    730:                listheadp = &newvp->v_dirtyblkhd;
                    731:        else
                    732:                listheadp = &newvp->v_cleanblkhd;
                    733:        bufinsvn(bp, listheadp);
                    734: }
                    735: 
                    736: /*
                    737:  * Create a vnode for a block device.
                    738:  * Used for root filesystem, argdev, and swap areas.
                    739:  * Also used for memory file system special devices.
                    740:  */
                    741: int
                    742: bdevvp(dev, vpp)
                    743:        dev_t dev;
                    744:        struct vnode **vpp;
                    745: {
                    746:        register struct vnode *vp;
                    747:        struct vnode *nvp;
                    748:        int error;
                    749: 
                    750:        if (dev == NODEV) {
                    751:                *vpp = NULLVP;
                    752:                return (ENODEV);
                    753:        }
                    754:        error = getnewvnode(VT_NON, (struct mount *)0, spec_vnodeop_p, &nvp);
                    755:        if (error) {
                    756:                *vpp = NULLVP;
                    757:                return (error);
                    758:        }
                    759:        vp = nvp;
                    760:        vp->v_type = VBLK;
                    761:        if (nvp = checkalias(vp, dev, (struct mount *)0)) {
                    762:                vput(vp);
                    763:                vp = nvp;
                    764:        }
                    765:        *vpp = vp;
                    766:        return (0);
                    767: }
                    768: 
                    769: /*
                    770:  * Check to see if the new vnode represents a special device
                    771:  * for which we already have a vnode (either because of
                    772:  * bdevvp() or because of a different vnode representing
                    773:  * the same block device). If such an alias exists, deallocate
                    774:  * the existing contents and return the aliased vnode. The
                    775:  * caller is responsible for filling it with its new contents.
                    776:  */
                    777: struct vnode *
                    778: checkalias(nvp, nvp_rdev, mp)
                    779:        register struct vnode *nvp;
                    780:        dev_t nvp_rdev;
                    781:        struct mount *mp;
                    782: {
                    783:        struct proc *p = current_proc();        /* XXX */
                    784:        struct vnode *vp;
                    785:        struct vnode **vpp;
                    786: 
                    787:        if (nvp->v_type != VBLK && nvp->v_type != VCHR)
                    788:                return (NULLVP);
                    789: 
                    790:        vpp = &speclisth[SPECHASH(nvp_rdev)];
                    791: loop:
                    792:        simple_lock(&spechash_slock);
                    793:        for (vp = *vpp; vp; vp = vp->v_specnext) {
                    794:                if (nvp_rdev != vp->v_rdev || nvp->v_type != vp->v_type)
                    795:                        continue;
                    796:                /*
                    797:                 * Alias, but not in use, so flush it out.
                    798:                 */
                    799:                simple_lock(&vp->v_interlock);
                    800:                if (vp->v_usecount == 0) {
                    801:                        simple_unlock(&spechash_slock);
                    802:                        vgonel(vp, p);
                    803:                        goto loop;
                    804:                }
                    805:                if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, p)) {
                    806:                        simple_unlock(&spechash_slock);
                    807:                        goto loop;
                    808:                }
                    809:                break;
                    810:        }
                    811:        if (vp == NULL || vp->v_tag != VT_NON) {
                    812:                MALLOC_ZONE(nvp->v_specinfo, struct specinfo *,
                    813:                                sizeof(struct specinfo), M_VNODE, M_WAITOK);
                    814:                bzero(nvp->v_specinfo, sizeof(struct specinfo));
                    815:                nvp->v_rdev = nvp_rdev;
                    816:                nvp->v_hashchain = vpp;
                    817:                nvp->v_specnext = *vpp;
                    818:                nvp->v_specflags = 0;
                    819:                simple_unlock(&spechash_slock);
                    820:                *vpp = nvp;
                    821:                if (vp != NULLVP) {
                    822:                        nvp->v_flag |= VALIASED;
                    823:                        vp->v_flag |= VALIASED;
                    824:                        vput(vp);
                    825:                }
                    826:                return (NULLVP);
                    827:        }
                    828:        simple_unlock(&spechash_slock);
                    829:        VOP_UNLOCK(vp, 0, p);
                    830:        simple_lock(&vp->v_interlock);
                    831:        vclean(vp, 0, p);
                    832:        vp->v_op = nvp->v_op;
                    833:        vp->v_tag = nvp->v_tag;
                    834:        nvp->v_type = VNON;
                    835:        insmntque(vp, mp);
                    836:        return (vp);
                    837: }
                    838: 
                    839: /*
                    840:  * Grab a particular vnode from the free list, increment its
                    841:  * reference count and lock it. The vnode lock bit is set the
                    842:  * vnode is being eliminated in vgone. The process is awakened
                    843:  * when the transition is completed, and an error returned to
                    844:  * indicate that the vnode is no longer usable (possibly having
                    845:  * been changed to a new file system type).
                    846:  */
                    847: int
                    848: vget(vp, flags, p)
                    849:        struct vnode *vp;
                    850:        int flags;
                    851:        struct proc *p;
                    852: {
                    853:        int error;
                    854: 
                    855:        /*
                    856:         * If the vnode is in the process of being cleaned out for
                    857:         * another use, we wait for the cleaning to finish and then
                    858:         * return failure. Cleaning is determined by checking that
                    859:         * the VXLOCK flag is set.
                    860:         */
                    861:        if ((flags & LK_INTERLOCK) == 0)
                    862:                simple_lock(&vp->v_interlock);
                    863:        if (vp->v_flag & VXLOCK) {
                    864:                vp->v_flag |= VXWANT;
                    865:                simple_unlock(&vp->v_interlock);
                    866:                tsleep((caddr_t)vp, PINOD, "vget", 0);
                    867:                return (ENOENT);
                    868:        }
                    869:        if (vp->v_usecount == 0) {
                    870:                simple_lock(&vnode_free_list_slock);
                    871:                TAILQ_REMOVE(&vnode_free_list, vp, v_freelist);
                    872:                freevnodes--;
                    873:                simple_unlock(&vnode_free_list_slock);
                    874:        }
1.1.1.2 ! root      875:         if (++vp->v_usecount <= 0)
        !           876:                 panic("vget: v_usecount");                     
1.1       root      877:        if (flags & LK_TYPE_MASK) {
                    878:                if (error = vn_lock(vp, flags | LK_INTERLOCK, p))
                    879:                        vrele(vp);
                    880:                return (error);
                    881:        }
                    882:        simple_unlock(&vp->v_interlock);
                    883:        return (0);
                    884: }
                    885: 
                    886: /*
                    887:  * Stubs to use when there is no locking to be done on the underlying object.
                    888:  * A minimal shared lock is necessary to ensure that the underlying object
                    889:  * is not revoked while an operation is in progress. So, an active shared
                    890:  * count is maintained in an auxillary vnode lock structure.
                    891:  */
                    892: int
                    893: vop_nolock(ap)
                    894:        struct vop_lock_args /* {
                    895:                struct vnode *a_vp;
                    896:                int a_flags;
                    897:                struct proc *a_p;
                    898:        } */ *ap;
                    899: {
                    900: #ifdef notyet
                    901:        /*
                    902:         * This code cannot be used until all the non-locking filesystems
                    903:         * (notably NFS) are converted to properly lock and release nodes.
                    904:         * Also, certain vnode operations change the locking state within
                    905:         * the operation (create, mknod, remove, link, rename, mkdir, rmdir,
                    906:         * and symlink). Ideally these operations should not change the
                    907:         * lock state, but should be changed to let the caller of the
                    908:         * function unlock them. Otherwise all intermediate vnode layers
                    909:         * (such as union, umapfs, etc) must catch these functions to do
                    910:         * the necessary locking at their layer. Note that the inactive
                    911:         * and lookup operations also change their lock state, but this 
                    912:         * cannot be avoided, so these two operations will always need
                    913:         * to be handled in intermediate layers.
                    914:         */
                    915:        struct vnode *vp = ap->a_vp;
                    916:        int vnflags, flags = ap->a_flags;
                    917: 
                    918:        if (vp->v_vnlock == NULL) {
                    919:                if ((flags & LK_TYPE_MASK) == LK_DRAIN)
                    920:                        return (0);
                    921:                MALLOC_ZONE(vp->v_vnlock, struct lock__bsd__ *,
                    922:                                sizeof(struct lock__bsd__), M_VNODE, M_WAITOK);
                    923:                lockinit(vp->v_vnlock, PVFS, "vnlock", 0, 0);
                    924:        }
                    925:        switch (flags & LK_TYPE_MASK) {
                    926:        case LK_DRAIN:
                    927:                vnflags = LK_DRAIN;
                    928:                break;
                    929:        case LK_EXCLUSIVE:
                    930:        case LK_SHARED:
                    931:                vnflags = LK_SHARED;
                    932:                break;
                    933:        case LK_UPGRADE:
                    934:        case LK_EXCLUPGRADE:
                    935:        case LK_DOWNGRADE:
                    936:                return (0);
                    937:        case LK_RELEASE:
                    938:        default:
                    939:                panic("vop_nolock: bad operation %d", flags & LK_TYPE_MASK);
                    940:        }
                    941:        if (flags & LK_INTERLOCK)
                    942:                vnflags |= LK_INTERLOCK;
                    943:        return(lockmgr(vp->v_vnlock, vnflags, &vp->v_interlock, ap->a_p));
                    944: #else /* for now */
                    945:        /*
                    946:         * Since we are not using the lock manager, we must clear
                    947:         * the interlock here.
                    948:         */
                    949:        if (ap->a_flags & LK_INTERLOCK)
                    950:                simple_unlock(&ap->a_vp->v_interlock);
                    951:        return (0);
                    952: #endif
                    953: }
                    954: 
                    955: /*
                    956:  * Decrement the active use count.
                    957:  */
                    958: int
                    959: vop_nounlock(ap)
                    960:        struct vop_unlock_args /* {
                    961:                struct vnode *a_vp;
                    962:                int a_flags;
                    963:                struct proc *a_p;
                    964:        } */ *ap;
                    965: {
                    966:        struct vnode *vp = ap->a_vp;
                    967: 
                    968:        if (vp->v_vnlock == NULL)
                    969:                return (0);
                    970:        return (lockmgr(vp->v_vnlock, LK_RELEASE, NULL, ap->a_p));
                    971: }
                    972: 
                    973: /*
                    974:  * Return whether or not the node is in use.
                    975:  */
                    976: int
                    977: vop_noislocked(ap)
                    978:        struct vop_islocked_args /* {
                    979:                struct vnode *a_vp;
                    980:        } */ *ap;
                    981: {
                    982:        struct vnode *vp = ap->a_vp;
                    983: 
                    984:        if (vp->v_vnlock == NULL)
                    985:                return (0);
                    986:        return (lockstatus(vp->v_vnlock));
                    987: }
                    988: 
                    989: /*
                    990:  * Vnode reference.
                    991:  */
                    992: void
                    993: vref(vp)
                    994:        struct vnode *vp;
                    995: {
                    996:        simple_lock(&vp->v_interlock);
                    997:        if (vp->v_usecount <= 0)
                    998:                panic("vref used where vget required");
1.1.1.2 ! root      999:         if (++vp->v_usecount <= 0)
        !          1000:                 panic("vref v_usecount");                     
1.1       root     1001:        simple_unlock(&vp->v_interlock);
                   1002: }
                   1003: 
                   1004: /*
                   1005:  * vput(), just unlock and vrele()
                   1006:  */
                   1007: void
                   1008: vput(vp)
                   1009:        struct vnode *vp;
                   1010: {
                   1011:        struct proc *p = current_proc();        /* XXX */
                   1012: 
1.1.1.2 ! root     1013: #if DIAGNOSTIC
1.1       root     1014:        if (vp == NULL)
                   1015:                panic("vput: null vp");
                   1016: #endif
                   1017:        simple_lock(&vp->v_interlock);
                   1018:        vp->v_usecount--;
                   1019:        if (vp->v_usecount > 0) {
                   1020:                simple_unlock(&vp->v_interlock);
                   1021:                VOP_UNLOCK(vp, 0, p);
                   1022:                return;
                   1023:        }
                   1024: #if DIAGNOSTIC
                   1025:        if (vp->v_usecount < 0 || vp->v_writecount != 0) {
                   1026:                vprint("vput: bad ref count", vp);
                   1027:                panic("vput: ref cnt");
                   1028:        }
                   1029: #endif
                   1030:        /*
                   1031:         * insert at tail of LRU list
                   1032:         */
                   1033:        simple_lock(&vnode_free_list_slock);
                   1034:        TAILQ_INSERT_TAIL(&vnode_free_list, vp, v_freelist);
                   1035:        freevnodes++;
                   1036:        simple_unlock(&vnode_free_list_slock);
                   1037:        simple_unlock(&vp->v_interlock);
                   1038:        VOP_INACTIVE(vp, p);
                   1039: }
                   1040: 
                   1041: /*
                   1042:  * Vnode release.
                   1043:  * If count drops to zero, call inactive routine and return to freelist.
                   1044:  */
                   1045: void
                   1046: vrele(vp)
                   1047:        struct vnode *vp;
                   1048: {
                   1049:        struct proc *p = current_proc();        /* XXX */
                   1050: 
                   1051: #if DIAGNOSTIC
                   1052:        if (vp == NULL)
                   1053:                panic("vrele: null vp");
                   1054: #endif
                   1055:        simple_lock(&vp->v_interlock);
                   1056:        vp->v_usecount--;
                   1057:        if (vp->v_usecount > 0) {
                   1058:                simple_unlock(&vp->v_interlock);
                   1059:                return;
                   1060:        }
                   1061: #if DIAGNOSTIC
                   1062:        if (vp->v_usecount < 0 || vp->v_writecount != 0) {
                   1063:                vprint("vrele: bad ref count", vp);
                   1064:                panic("vrele: ref cnt");
                   1065:        }
                   1066: #endif
                   1067:        /*
                   1068:         * insert at tail of LRU list
                   1069:         */
                   1070:        simple_lock(&vnode_free_list_slock);
                   1071:        if (vp->v_flag & VAGE) {
                   1072:                TAILQ_INSERT_HEAD(&vnode_free_list, vp, v_freelist);
                   1073:                vp->v_flag &= ~VAGE;
                   1074:        } else
                   1075:        TAILQ_INSERT_TAIL(&vnode_free_list, vp, v_freelist);
                   1076:        freevnodes++;
                   1077:        simple_unlock(&vnode_free_list_slock);
                   1078:        if ((vp->v_flag & VXLOCK) == 0) {
                   1079:                if (vn_lock(vp, LK_EXCLUSIVE | LK_INTERLOCK, p) == 0)
                   1080:                        VOP_INACTIVE(vp, p);
                   1081: #if DIAGNOSTIC
                   1082:                else
                   1083:                        kprintf("vrele: vn_lock() failed for vp = 0x%08x\n", vp);
                   1084:        } else {
                   1085:                kprintf("vrele: attempted deadlock!\n");
                   1086: #endif
                   1087:                simple_unlock(&vp->v_interlock);
                   1088:        }
                   1089: 
                   1090: }
                   1091: 
                   1092: /*
                   1093:  * Page or buffer structure gets a reference.
                   1094:  */
                   1095: void
                   1096: vhold(vp)
                   1097:        register struct vnode *vp;
                   1098: {
                   1099: 
                   1100:        simple_lock(&vp->v_interlock);
                   1101:        vp->v_holdcnt++;
                   1102:        simple_unlock(&vp->v_interlock);
                   1103: }
                   1104: 
                   1105: /*
                   1106:  * Page or buffer structure frees a reference.
                   1107:  */
                   1108: void
                   1109: holdrele(vp)
                   1110:        register struct vnode *vp;
                   1111: {
                   1112: 
                   1113:        simple_lock(&vp->v_interlock);
                   1114:        if (vp->v_holdcnt <= 0)
                   1115:                panic("holdrele: holdcnt");
                   1116:        vp->v_holdcnt--;
                   1117:        simple_unlock(&vp->v_interlock);
                   1118: }
                   1119: 
                   1120: /*
                   1121:  * Remove any vnodes in the vnode table belonging to mount point mp.
                   1122:  *
                   1123:  * If MNT_NOFORCE is specified, there should not be any active ones,
                   1124:  * return error if any are found (nb: this is a user error, not a
                   1125:  * system error). If MNT_FORCE is specified, detach any active vnodes
                   1126:  * that are found.
                   1127:  */
                   1128: #if DIAGNOSTIC
                   1129: int busyprt = 0;       /* print out busy vnodes */
                   1130: struct ctldebug debug1 = { "busyprt", &busyprt };
                   1131: #endif
                   1132: 
                   1133: int
                   1134: vflush(mp, skipvp, flags)
                   1135:        struct mount *mp;
                   1136:        struct vnode *skipvp;
                   1137:        int flags;
                   1138: {
                   1139:        struct proc *p = current_proc();        /* XXX */
                   1140:        struct vnode *vp, *nvp;
                   1141:        int busy = 0;
                   1142: 
                   1143:        simple_lock(&mntvnode_slock);
                   1144: loop:
                   1145:        for (vp = mp->mnt_vnodelist.lh_first; vp; vp = nvp) {
                   1146:                if (vp->v_mount != mp)
                   1147:                        goto loop;
                   1148:                nvp = vp->v_mntvnodes.le_next;
                   1149:                /*
                   1150:                 * Skip over a selected vnode.
                   1151:                 */
                   1152:                if (vp == skipvp)
                   1153:                        continue;
                   1154: 
                   1155:                simple_lock(&vp->v_interlock);
                   1156:                /*
                   1157:                 * Skip over a vnodes marked VSYSTEM.
                   1158:                 */
                   1159:                if ((flags & SKIPSYSTEM) && (vp->v_flag & VSYSTEM)) {
                   1160:                        simple_unlock(&vp->v_interlock);
                   1161:                        continue;
                   1162:                }
                   1163:                /*
                   1164:                 * If WRITECLOSE is set, only flush out regular file
                   1165:                 * vnodes open for writing.
                   1166:                 */
                   1167:                if ((flags & WRITECLOSE) &&
                   1168:                    (vp->v_writecount == 0 || vp->v_type != VREG)) {
                   1169:                        simple_unlock(&vp->v_interlock);
                   1170:                        continue;
                   1171:                }
                   1172:                /*
                   1173:                 * With v_usecount == 0, all we need to do is clear
                   1174:                 * out the vnode data structures and we are done.
                   1175:                 */
                   1176:                if (vp->v_usecount == 0) {
                   1177:                        simple_unlock(&mntvnode_slock);
                   1178:                        vgonel(vp, p);
                   1179:                        simple_lock(&mntvnode_slock);
                   1180:                        continue;
                   1181:                }
                   1182:                /*
                   1183:                 * If FORCECLOSE is set, forcibly close the vnode.
                   1184:                 * For block or character devices, revert to an
                   1185:                 * anonymous device. For all other files, just kill them.
                   1186:                 */
                   1187:                if (flags & FORCECLOSE) {
                   1188:                        simple_unlock(&mntvnode_slock);
                   1189:                        if (vp->v_type != VBLK && vp->v_type != VCHR) {
                   1190:                                vgonel(vp, p);
                   1191:                        } else {
                   1192:                                vclean(vp, 0, p);
                   1193:                                vp->v_op = spec_vnodeop_p;
                   1194:                                insmntque(vp, (struct mount *)0);
                   1195:                        }
                   1196:                        simple_lock(&mntvnode_slock);
                   1197:                        continue;
                   1198:                }
                   1199: #if DIAGNOSTIC
                   1200:                if (busyprt)
                   1201:                        vprint("vflush: busy vnode", vp);
                   1202: #endif
                   1203:                simple_unlock(&vp->v_interlock);
                   1204:                busy++;
                   1205:        }
                   1206:        simple_unlock(&mntvnode_slock);
                   1207:        if (busy)
                   1208:                return (EBUSY);
                   1209:        return (0);
                   1210: }
                   1211: 
                   1212: /*
                   1213:  * Disassociate the underlying file system from a vnode.
                   1214:  * The vnode interlock is held on entry.
                   1215:  */
                   1216: static void
                   1217: vclean(vp, flags, p)
                   1218:        struct vnode *vp;
                   1219:        int flags;
                   1220:        struct proc *p;
                   1221: {
                   1222:        int active;
                   1223: 
                   1224:        /*
                   1225:         * Check to see if the vnode is in use.
                   1226:         * If so we have to reference it before we clean it out
                   1227:         * so that its count cannot fall to zero and generate a
                   1228:         * race against ourselves to recycle it.
                   1229:         */
                   1230:        if (active = vp->v_usecount)
1.1.1.2 ! root     1231:                if (++vp->v_usecount <= 0)
        !          1232:                        panic("vclean: v_usecount");
1.1       root     1233:        /*
                   1234:         * Prevent the vnode from being recycled or
                   1235:         * brought into use while we clean it out.
                   1236:         */
                   1237:        if (vp->v_flag & VXLOCK)
                   1238:                panic("vclean: deadlock");
                   1239:        vp->v_flag |= VXLOCK;
                   1240:        /*
                   1241:         * Even if the count is zero, the VOP_INACTIVE routine may still
                   1242:         * have the object locked while it cleans it out. The VOP_LOCK
                   1243:         * ensures that the VOP_INACTIVE routine is done with its work.
                   1244:         * For active vnodes, it ensures that no other activity can
                   1245:         * occur while the underlying object is being cleaned out.
                   1246:         */
                   1247:        VOP_LOCK(vp, LK_DRAIN | LK_INTERLOCK, p);
                   1248:        /*
                   1249:         * Clean out any buffers associated with the vnode.
                   1250:         */
                   1251:        if (flags & DOCLOSE)
                   1252:                vinvalbuf(vp, V_SAVE, NOCRED, p, 0, 0);
                   1253: 
                   1254:        if ((vp->v_type == VREG) && (vp->v_vm_info != NULL))
                   1255:        {
                   1256:                vm_info_free(vp);
                   1257:                vp->v_vm_info = NULL;
                   1258:        }
                   1259:        /*
                   1260:         * If purging an active vnode, it must be closed and
                   1261:         * deactivated before being reclaimed. Note that the
                   1262:         * VOP_INACTIVE will unlock the vnode.
                   1263:         */
                   1264:        if (active) {
                   1265:                if (flags & DOCLOSE)
                   1266:                        VOP_CLOSE(vp, IO_NDELAY, NOCRED, p);
                   1267:                VOP_INACTIVE(vp, p);
                   1268:        } else {
                   1269:                /*
                   1270:                 * Any other processes trying to obtain this lock must first
                   1271:                 * wait for VXLOCK to clear, then call the new lock operation.
                   1272:                 */
                   1273:                VOP_UNLOCK(vp, 0, p);
                   1274:        }
                   1275:        /*
                   1276:         * Reclaim the vnode.
                   1277:         */
                   1278:        if (VOP_RECLAIM(vp, p))
                   1279:                panic("vclean: cannot reclaim");
                   1280:        if (active)
                   1281:                vrele(vp);
                   1282:        cache_purge(vp);
                   1283:        if (vp->v_vnlock) {
                   1284:                if ((vp->v_vnlock->lk_flags & LK_DRAINED) == 0)
                   1285:                        vprint("vclean: lock not drained", vp);
                   1286:                FREE_ZONE(vp->v_vnlock, sizeof (struct lock__bsd__), M_VNODE);
                   1287:                vp->v_vnlock = NULL;
                   1288:        }
                   1289: 
                   1290: 
                   1291:        /*
                   1292:         * Done with purge, notify sleepers of the grim news.
                   1293:         */
                   1294:        vp->v_op = dead_vnodeop_p;
                   1295:        vp->v_tag = VT_NON;
                   1296:        vp->v_flag &= ~VXLOCK;
                   1297:        if (vp->v_flag & VXWANT) {
                   1298:                vp->v_flag &= ~VXWANT;
                   1299:                wakeup((caddr_t)vp);
                   1300:        }
                   1301: }
                   1302: 
                   1303: /*
                   1304:  * Eliminate all activity associated with  the requested vnode
                   1305:  * and with all vnodes aliased to the requested vnode.
                   1306:  */
                   1307: int
                   1308: vop_revoke(ap)
                   1309:        struct vop_revoke_args /* {
                   1310:                struct vnode *a_vp;
                   1311:                int a_flags;
                   1312:        } */ *ap;
                   1313: {
                   1314:        struct vnode *vp, *vq;
                   1315:        struct proc *p = current_proc();        /* XXX */
                   1316: 
                   1317: #if DIAGNOSTIC
                   1318:        if ((ap->a_flags & REVOKEALL) == 0)
                   1319:                panic("vop_revoke");
                   1320: #endif
                   1321: 
                   1322:        vp = ap->a_vp;
                   1323:        simple_lock(&vp->v_interlock);
                   1324: 
                   1325:        if (vp->v_flag & VALIASED) {
                   1326:                /*
                   1327:                 * If a vgone (or vclean) is already in progress,
                   1328:                 * wait until it is done and return.
                   1329:                 */
                   1330:                if (vp->v_flag & VXLOCK) {
                   1331:                        vp->v_flag |= VXWANT;
                   1332:                        simple_unlock(&vp->v_interlock);
                   1333:                        tsleep((caddr_t)vp, PINOD, "vop_revokeall", 0);
                   1334:                        return (0);
                   1335:                }
                   1336:                /*
                   1337:                 * Ensure that vp will not be vgone'd while we
                   1338:                 * are eliminating its aliases.
                   1339:                 */
                   1340:                vp->v_flag |= VXLOCK;
                   1341:                simple_unlock(&vp->v_interlock);
                   1342:                while (vp->v_flag & VALIASED) {
                   1343:                        simple_lock(&spechash_slock);
                   1344:                        for (vq = *vp->v_hashchain; vq; vq = vq->v_specnext) {
                   1345:                                if (vq->v_rdev != vp->v_rdev ||
                   1346:                                    vq->v_type != vp->v_type || vp == vq)
                   1347:                                        continue;
                   1348:                                simple_unlock(&spechash_slock);
                   1349:                                vgone(vq);
                   1350:                                break;
                   1351:                        }
                   1352:                        if (vq == NULLVP)
                   1353:                                simple_unlock(&spechash_slock);
                   1354:                }
                   1355:                /*
                   1356:                 * Remove the lock so that vgone below will
                   1357:                 * really eliminate the vnode after which time
                   1358:                 * vgone will awaken any sleepers.
                   1359:                 */
                   1360:                simple_lock(&vp->v_interlock);
                   1361:                vp->v_flag &= ~VXLOCK;
                   1362:        }
                   1363:        vgonel(vp, p);
                   1364:        return (0);
                   1365: }
                   1366: 
                   1367: /*
                   1368:  * Recycle an unused vnode to the front of the free list.
                   1369:  * Release the passed interlock if the vnode will be recycled.
                   1370:  */
                   1371: int
                   1372: vrecycle(vp, inter_lkp, p)
                   1373:        struct vnode *vp;
                   1374:        struct slock *inter_lkp;
                   1375:        struct proc *p;
                   1376: {
                   1377: 
                   1378:        simple_lock(&vp->v_interlock);
                   1379:        if (vp->v_usecount == 0) {
                   1380:                if (inter_lkp)
                   1381:                        simple_unlock(inter_lkp);
                   1382:                vgonel(vp, p);
                   1383:                return (1);
                   1384:        }
                   1385:        simple_unlock(&vp->v_interlock);
                   1386:        return (0);
                   1387: }
                   1388: 
                   1389: /*
                   1390:  * Eliminate all activity associated with a vnode
                   1391:  * in preparation for reuse.
                   1392:  */
                   1393: void
                   1394: vgone(vp)
                   1395:        struct vnode *vp;
                   1396: {
                   1397:        struct proc *p = current_proc();        /* XXX */
                   1398: 
                   1399:        simple_lock(&vp->v_interlock);
                   1400:        vgonel(vp, p);
                   1401: }
                   1402: 
                   1403: /*
                   1404:  * vgone, with the vp interlock held.
                   1405:  */
                   1406: void
                   1407: vgonel(vp, p)
                   1408:        struct vnode *vp;
                   1409:        struct proc *p;
                   1410: {
                   1411:        struct vnode *vq;
                   1412:        struct vnode *vx;
                   1413: 
                   1414:        /*
                   1415:         * If a vgone (or vclean) is already in progress,
                   1416:         * wait until it is done and return.
                   1417:         */
                   1418:        if (vp->v_flag & VXLOCK) {
                   1419:                vp->v_flag |= VXWANT;
                   1420:                simple_unlock(&vp->v_interlock);
                   1421:                tsleep((caddr_t)vp, PINOD, "vgone", 0);
                   1422:                return;
                   1423:        }
                   1424:        /*
                   1425:         * Clean out the filesystem specific data.
                   1426:         */
                   1427:        vclean(vp, DOCLOSE, p);
                   1428:        /*
                   1429:         * Delete from old mount point vnode list, if on one.
                   1430:         */
                   1431:        if (vp->v_mount != NULL)
                   1432:                insmntque(vp, (struct mount *)0);
                   1433:        /*
                   1434:         * If special device, remove it from special device alias list
                   1435:         * if it is on one.
                   1436:         */
                   1437:        if ((vp->v_type == VBLK || vp->v_type == VCHR) && vp->v_specinfo != 0) {
                   1438:                simple_lock(&spechash_slock);
                   1439:                if (*vp->v_hashchain == vp) {
                   1440:                        *vp->v_hashchain = vp->v_specnext;
                   1441:                } else {
                   1442:                        for (vq = *vp->v_hashchain; vq; vq = vq->v_specnext) {
                   1443:                                if (vq->v_specnext != vp)
                   1444:                                        continue;
                   1445:                                vq->v_specnext = vp->v_specnext;
                   1446:                                break;
                   1447:                        }
                   1448:                        if (vq == NULL)
                   1449:                                panic("missing bdev");
                   1450:                }
                   1451:                if (vp->v_flag & VALIASED) {
                   1452:                        vx = NULL;
                   1453:                        for (vq = *vp->v_hashchain; vq; vq = vq->v_specnext) {
                   1454:                                if (vq->v_rdev != vp->v_rdev ||
                   1455:                                    vq->v_type != vp->v_type)
                   1456:                                        continue;
                   1457:                                if (vx)
                   1458:                                        break;
                   1459:                                vx = vq;
                   1460:                        }
                   1461:                        if (vx == NULL)
                   1462:                                panic("missing alias");
                   1463:                        if (vq == NULL)
                   1464:                                vx->v_flag &= ~VALIASED;
                   1465:                        vp->v_flag &= ~VALIASED;
                   1466:                }
                   1467:                simple_unlock(&spechash_slock);
                   1468:                FREE_ZONE(vp->v_specinfo, sizeof (struct specinfo), M_VNODE);
                   1469:                vp->v_specinfo = NULL;
                   1470:        }
                   1471:        /*
                   1472:         * If it is on the freelist and not already at the head,
                   1473:         * move it to the head of the list. The test of the back
                   1474:         * pointer and the reference count of zero is because
                   1475:         * it will be removed from the free list by getnewvnode,
                   1476:         * but will not have its reference count incremented until
                   1477:         * after calling vgone. If the reference count were
                   1478:         * incremented first, vgone would (incorrectly) try to
                   1479:         * close the previous instance of the underlying object.
                   1480:         * So, the back pointer is explicitly set to `0xdeadb' in
                   1481:         * getnewvnode after removing it from the freelist to ensure
                   1482:         * that we do not try to move it here.
                   1483:         */
                   1484:        if (vp->v_usecount == 0) {
                   1485:                simple_lock(&vnode_free_list_slock);
                   1486:                if ((vp->v_freelist.tqe_prev != (struct vnode **)0xdeadb) &&
                   1487:                    vnode_free_list.tqh_first != vp) {
                   1488:                        TAILQ_REMOVE(&vnode_free_list, vp, v_freelist);
                   1489:                        TAILQ_INSERT_HEAD(&vnode_free_list, vp, v_freelist);
                   1490:                }
                   1491:                simple_unlock(&vnode_free_list_slock);
                   1492:        }
                   1493:        vp->v_type = VBAD;
                   1494: }
                   1495: 
                   1496: /*
                   1497:  * Lookup a vnode by device number.
                   1498:  */
                   1499: int
                   1500: vfinddev(dev, type, vpp)
                   1501:        dev_t dev;
                   1502:        enum vtype type;
                   1503:        struct vnode **vpp;
                   1504: {
                   1505:        struct vnode *vp;
                   1506:        int rc = 0;
                   1507: 
                   1508:        simple_lock(&spechash_slock);
                   1509:        for (vp = speclisth[SPECHASH(dev)]; vp; vp = vp->v_specnext) {
                   1510:                if (dev != vp->v_rdev || type != vp->v_type)
                   1511:                        continue;
                   1512:                *vpp = vp;
                   1513:                rc = 1;
                   1514:                break;
                   1515:        }
                   1516:        simple_unlock(&spechash_slock);
                   1517:        return (rc);
                   1518: }
                   1519: 
                   1520: /*
                   1521:  * Calculate the total number of references to a special device.
                   1522:  */
                   1523: int
                   1524: vcount(vp)
                   1525:        struct vnode *vp;
                   1526: {
                   1527:        struct vnode *vq, *vnext;
                   1528:        int count;
                   1529: 
                   1530: loop:
                   1531:        if ((vp->v_flag & VALIASED) == 0)
                   1532:                return (vp->v_usecount);
                   1533:        simple_lock(&spechash_slock);
                   1534:        for (count = 0, vq = *vp->v_hashchain; vq; vq = vnext) {
                   1535:                vnext = vq->v_specnext;
                   1536:                if (vq->v_rdev != vp->v_rdev || vq->v_type != vp->v_type)
                   1537:                        continue;
                   1538:                /*
                   1539:                 * Alias, but not in use, so flush it out.
                   1540:                 */
                   1541:                if (vq->v_usecount == 0 && vq != vp) {
                   1542:                        simple_unlock(&spechash_slock);
                   1543:                        vgone(vq);
                   1544:                        goto loop;
                   1545:                }
                   1546:                count += vq->v_usecount;
                   1547:        }
                   1548:        simple_unlock(&spechash_slock);
                   1549:        return (count);
                   1550: }
                   1551: 
                   1552: /*
                   1553:  * Print out a description of a vnode.
                   1554:  */
                   1555: static char *typename[] =
                   1556:    { "VNON", "VREG", "VDIR", "VBLK", "VCHR", "VLNK", "VSOCK", "VFIFO", "VBAD" };
                   1557: 
                   1558: void
                   1559: vprint(label, vp)
                   1560:        char *label;
                   1561:        register struct vnode *vp;
                   1562: {
                   1563:        char buf[64];
                   1564: 
                   1565:        if (label != NULL)
                   1566:                printf("%s: ", label);
                   1567:        printf("type %s, usecount %d, writecount %d, refcount %d,",
                   1568:                typename[vp->v_type], vp->v_usecount, vp->v_writecount,
                   1569:                vp->v_holdcnt);
                   1570:        buf[0] = '\0';
                   1571:        if (vp->v_flag & VROOT)
                   1572:                strcat(buf, "|VROOT");
                   1573:        if (vp->v_flag & VTEXT)
                   1574:                strcat(buf, "|VTEXT");
                   1575:        if (vp->v_flag & VSYSTEM)
                   1576:                strcat(buf, "|VSYSTEM");
                   1577:        if (vp->v_flag & VXLOCK)
                   1578:                strcat(buf, "|VXLOCK");
                   1579:        if (vp->v_flag & VXWANT)
                   1580:                strcat(buf, "|VXWANT");
                   1581:        if (vp->v_flag & VBWAIT)
                   1582:                strcat(buf, "|VBWAIT");
                   1583:        if (vp->v_flag & VALIASED)
                   1584:                strcat(buf, "|VALIASED");
                   1585:        if (buf[0] != '\0')
                   1586:                printf(" flags (%s)", &buf[1]);
                   1587:        if (vp->v_data == NULL) {
                   1588:                printf("\n");
                   1589:        } else {
                   1590:                printf("\n\t");
                   1591:                VOP_PRINT(vp);
                   1592:        }
                   1593: }
                   1594: 
                   1595: #ifdef DEBUG
                   1596: /*
                   1597:  * List all of the locked vnodes in the system.
                   1598:  * Called when debugging the kernel.
                   1599:  */
                   1600: void
                   1601: printlockedvnodes()
                   1602: {
                   1603:        struct proc *p = current_proc();        /* XXX */
                   1604:        struct mount *mp, *nmp;
                   1605:        struct vnode *vp;
                   1606: 
                   1607:        printf("Locked vnodes\n");
                   1608:        simple_lock(&mountlist_slock);
                   1609:        for (mp = mountlist.cqh_first; mp != (void *)&mountlist; mp = nmp) {
                   1610:                if (vfs_busy(mp, LK_NOWAIT, &mountlist_slock, p)) {
                   1611:                        nmp = mp->mnt_list.cqe_next;
                   1612:                        continue;
                   1613:                }
                   1614:                for (vp = mp->mnt_vnodelist.lh_first;
                   1615:                     vp != NULL;
                   1616:                     vp = vp->v_mntvnodes.le_next) {
                   1617:                        if (VOP_ISLOCKED(vp))
                   1618:                                vprint((char *)0, vp);
                   1619:                }
                   1620:                simple_lock(&mountlist_slock);
                   1621:                nmp = mp->mnt_list.cqe_next;
                   1622:                vfs_unbusy(mp, p);
                   1623:        }
                   1624:        simple_unlock(&mountlist_slock);
                   1625: }
                   1626: #endif
                   1627: 
                   1628: /*
                   1629:  * Top level filesystem related information gathering.
                   1630:  */
                   1631: int
                   1632: vfs_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
                   1633:        int *name;
                   1634:        u_int namelen;
                   1635:        void *oldp;
                   1636:        size_t *oldlenp;
                   1637:        void *newp;
                   1638:        size_t newlen;
                   1639:        struct proc *p;
                   1640: {
                   1641:        struct ctldebug *cdp;
                   1642:        struct vfsconf *vfsp;
                   1643: 
                   1644: #ifdef NeXT
                   1645:        if (name[0] == VFS_NUMMNTOPS) {
                   1646:        extern unsigned int vfs_nummntops;
                   1647:                return (sysctl_rdint(oldp, oldlenp, newp, vfs_nummntops));
                   1648:        }
                   1649: #endif
                   1650:        /* all sysctl names at this level are at least name and field */
                   1651:        if (namelen < 2)
                   1652:                return (ENOTDIR);               /* overloaded */
                   1653:        if (name[0] != VFS_GENERIC) {
                   1654:                for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next)
                   1655:                        if (vfsp->vfc_typenum == name[0])
                   1656:                                break;
                   1657:                if (vfsp == NULL)
                   1658:                        return (EOPNOTSUPP);
                   1659:                return ((*vfsp->vfc_vfsops->vfs_sysctl)(&name[1], namelen - 1,
                   1660:                    oldp, oldlenp, newp, newlen, p));
                   1661:        }
                   1662:        switch (name[1]) {
                   1663:        case VFS_MAXTYPENUM:
                   1664:                return (sysctl_rdint(oldp, oldlenp, newp, maxvfsconf));
                   1665:        case VFS_CONF:
                   1666:                if (namelen < 3)
                   1667:                        return (ENOTDIR);       /* overloaded */
                   1668:                for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next)
                   1669:                        if (vfsp->vfc_typenum == name[2])
                   1670:                                break;
                   1671:                if (vfsp == NULL)
                   1672:                        return (EOPNOTSUPP);
                   1673:                return (sysctl_rdstruct(oldp, oldlenp, newp, vfsp,
                   1674:                    sizeof(struct vfsconf)));
                   1675:        }
                   1676:        return (EOPNOTSUPP);
                   1677: }
                   1678: 
                   1679: int kinfo_vdebug = 1;
                   1680: int kinfo_vgetfailed;
                   1681: #define KINFO_VNODESLOP        10
                   1682: /*
                   1683:  * Dump vnode list (via sysctl).
                   1684:  * Copyout address of vnode followed by vnode.
                   1685:  */
                   1686: /* ARGSUSED */
                   1687: int
                   1688: sysctl_vnode(where, sizep, p)
                   1689:        char *where;
                   1690:        size_t *sizep;
                   1691:        struct proc *p;
                   1692: {
                   1693:        struct mount *mp, *nmp;
                   1694:        struct vnode *nvp, *vp;
                   1695:        char *bp = where, *savebp;
                   1696:        char *ewhere;
                   1697:        int error;
                   1698: 
                   1699: #define VPTRSZ sizeof (struct vnode *)
                   1700: #define VNODESZ        sizeof (struct vnode)
                   1701:        if (where == NULL) {
                   1702:                *sizep = (numvnodes + KINFO_VNODESLOP) * (VPTRSZ + VNODESZ);
                   1703:                return (0);
                   1704:        }
                   1705:        ewhere = where + *sizep;
                   1706:                
                   1707:        simple_lock(&mountlist_slock);
                   1708:        for (mp = mountlist.cqh_first; mp != (void *)&mountlist; mp = nmp) {
                   1709:                if (vfs_busy(mp, LK_NOWAIT, &mountlist_slock, p)) {
                   1710:                        nmp = mp->mnt_list.cqe_next;
                   1711:                        continue;
                   1712:                }
                   1713:                savebp = bp;
                   1714: again:
                   1715:                simple_lock(&mntvnode_slock);
                   1716:                for (vp = mp->mnt_vnodelist.lh_first;
                   1717:                     vp != NULL;
                   1718:                     vp = nvp) {
                   1719:                        /*
                   1720:                         * Check that the vp is still associated with
                   1721:                         * this filesystem.  RACE: could have been
                   1722:                         * recycled onto the same filesystem.
                   1723:                         */
                   1724:                        if (vp->v_mount != mp) {
                   1725:                                simple_unlock(&mntvnode_slock);
                   1726:                                if (kinfo_vdebug)
                   1727:                                        printf("kinfo: vp changed\n");
                   1728:                                bp = savebp;
                   1729:                                goto again;
                   1730:                        }
                   1731:                        nvp = vp->v_mntvnodes.le_next;
                   1732:                        if (bp + VPTRSZ + VNODESZ > ewhere) {
                   1733:                                simple_unlock(&mntvnode_slock);
                   1734:                                *sizep = bp - where;
                   1735:                                return (ENOMEM);
                   1736:                        }
                   1737:                        simple_unlock(&mntvnode_slock);
                   1738:                        if ((error = copyout((caddr_t)&vp, bp, VPTRSZ)) ||
                   1739:                           (error = copyout((caddr_t)vp, bp + VPTRSZ, VNODESZ)))
                   1740:                                return (error);
                   1741:                        bp += VPTRSZ + VNODESZ;
                   1742:                        simple_lock(&mntvnode_slock);
                   1743:                }
                   1744:                simple_unlock(&mntvnode_slock);
                   1745:                simple_lock(&mountlist_slock);
                   1746:                nmp = mp->mnt_list.cqe_next;
                   1747:                vfs_unbusy(mp, p);
                   1748:        }
                   1749:        simple_unlock(&mountlist_slock);
                   1750: 
                   1751:        *sizep = bp - where;
                   1752:        return (0);
                   1753: }
                   1754: 
                   1755: /*
                   1756:  * Check to see if a filesystem is mounted on a block device.
                   1757:  */
                   1758: int
                   1759: vfs_mountedon(vp)
                   1760:        struct vnode *vp;
                   1761: {
                   1762:        struct vnode *vq;
                   1763:        int error = 0;
                   1764: 
                   1765:        if (vp->v_specflags & SI_MOUNTEDON)
                   1766:                return (EBUSY);
                   1767:        if (vp->v_flag & VALIASED) {
                   1768:                simple_lock(&spechash_slock);
                   1769:                for (vq = *vp->v_hashchain; vq; vq = vq->v_specnext) {
                   1770:                        if (vq->v_rdev != vp->v_rdev ||
                   1771:                            vq->v_type != vp->v_type)
                   1772:                                continue;
                   1773:                        if (vq->v_specflags & SI_MOUNTEDON) {
                   1774:                                error = EBUSY;
                   1775:                                break;
                   1776:                        }
                   1777:                }
                   1778:                simple_unlock(&spechash_slock);
                   1779:        }
                   1780:        return (error);
                   1781: }
                   1782: 
                   1783: /*
                   1784:  * Unmount all filesystems. The list is traversed in reverse order
                   1785:  * of mounting to avoid dependencies.
                   1786:  */
                   1787: void
                   1788: vfs_unmountall()
                   1789: {
                   1790:        struct mount *mp, *nmp;
                   1791:        struct proc *p = current_proc();        /* XXX */
                   1792: 
                   1793:        /*
                   1794:         * Since this only runs when rebooting, it is not interlocked.
                   1795:         */
                   1796:        for (mp = mountlist.cqh_last; mp != (void *)&mountlist; mp = nmp) {
                   1797:                nmp = mp->mnt_list.cqe_prev;
                   1798:                (void) dounmount(mp, MNT_FORCE, p);
                   1799:        }
                   1800: }
                   1801: 
                   1802: /*
                   1803:  * Build hash lists of net addresses and hang them off the mount point.
                   1804:  * Called by ufs_mount() to set up the lists of export addresses.
                   1805:  */
                   1806: static int
                   1807: vfs_hang_addrlist(mp, nep, argp)
                   1808:        struct mount *mp;
                   1809:        struct netexport *nep;
                   1810:        struct export_args *argp;
                   1811: {
                   1812:        register struct netcred *np;
                   1813:        register struct radix_node_head *rnh;
                   1814:        register int i;
                   1815:        struct radix_node *rn;
                   1816:        struct sockaddr *saddr, *smask = 0;
                   1817:        struct domain *dom;
                   1818:        int error;
                   1819: 
                   1820:        if (argp->ex_addrlen == 0) {
                   1821:                if (mp->mnt_flag & MNT_DEFEXPORTED)
                   1822:                        return (EPERM);
                   1823:                np = &nep->ne_defexported;
                   1824:                np->netc_exflags = argp->ex_flags;
                   1825:                np->netc_anon = argp->ex_anon;
                   1826:                np->netc_anon.cr_ref = 1;
                   1827:                mp->mnt_flag |= MNT_DEFEXPORTED;
                   1828:                return (0);
                   1829:        }
                   1830:        i = sizeof(struct netcred) + argp->ex_addrlen + argp->ex_masklen;
                   1831:        MALLOC(np, struct netcred *, i, M_NETADDR, M_WAITOK);
                   1832:        bzero((caddr_t)np, i);
                   1833:        saddr = (struct sockaddr *)(np + 1);
                   1834:        if (error = copyin(argp->ex_addr, (caddr_t)saddr, argp->ex_addrlen))
                   1835:                goto out;
                   1836:        if (saddr->sa_len > argp->ex_addrlen)
                   1837:                saddr->sa_len = argp->ex_addrlen;
                   1838:        if (argp->ex_masklen) {
                   1839:                smask = (struct sockaddr *)((caddr_t)saddr + argp->ex_addrlen);
                   1840:                error = copyin(argp->ex_addr, (caddr_t)smask, argp->ex_masklen);
                   1841:                if (error)
                   1842:                        goto out;
                   1843:                if (smask->sa_len > argp->ex_masklen)
                   1844:                        smask->sa_len = argp->ex_masklen;
                   1845:        }
                   1846:        i = saddr->sa_family;
                   1847:        if ((rnh = nep->ne_rtable[i]) == 0) {
                   1848:                /*
                   1849:                 * Seems silly to initialize every AF when most are not
                   1850:                 * used, do so on demand here
                   1851:                 */
                   1852:                for (dom = domains; dom; dom = dom->dom_next)
                   1853:                        if (dom->dom_family == i && dom->dom_rtattach) {
                   1854:                                dom->dom_rtattach((void **)&nep->ne_rtable[i],
                   1855:                                        dom->dom_rtoffset);
                   1856:                                break;
                   1857:                        }
                   1858:                if ((rnh = nep->ne_rtable[i]) == 0) {
                   1859:                        error = ENOBUFS;
                   1860:                        goto out;
                   1861:                }
                   1862:        }
                   1863:        rn = (*rnh->rnh_addaddr)((caddr_t)saddr, (caddr_t)smask, rnh,
                   1864:                np->netc_rnodes);
                   1865:        if (rn == 0) {
                   1866:                /*
                   1867:                 * One of the reasons that rnh_addaddr may fail is that
                   1868:                 * the entry already exists. To check for this case, we
                   1869:                 * look up the entry to see if it is there. If so, we
                   1870:                 * do not need to make a new entry but do return success.
                   1871:                 */
                   1872:                _FREE(np, M_NETADDR);
                   1873:                rn = (*rnh->rnh_matchaddr)((caddr_t)saddr, rnh);
                   1874:                if (rn != 0 && (rn->rn_flags & RNF_ROOT) == 0 &&
                   1875:                    ((struct netcred *)rn)->netc_exflags == argp->ex_flags &&
                   1876:                    !bcmp((caddr_t)&((struct netcred *)rn)->netc_anon,
                   1877:                            (caddr_t)&argp->ex_anon, sizeof(struct ucred)))
                   1878:                        return (0);
                   1879:                return (EPERM);
                   1880:        }
                   1881:        np->netc_exflags = argp->ex_flags;
                   1882:        np->netc_anon = argp->ex_anon;
                   1883:        np->netc_anon.cr_ref = 1;
                   1884:        return (0);
                   1885: out:
                   1886:        _FREE(np, M_NETADDR);
                   1887:        return (error);
                   1888: }
                   1889: 
                   1890: /* ARGSUSED */
                   1891: static int
                   1892: vfs_free_netcred(rn, w)
                   1893:        struct radix_node *rn;
                   1894:        caddr_t w;
                   1895: {
                   1896:        register struct radix_node_head *rnh = (struct radix_node_head *)w;
                   1897: 
                   1898:        (*rnh->rnh_deladdr)(rn->rn_key, rn->rn_mask, rnh);
                   1899:        _FREE((caddr_t)rn, M_NETADDR);
                   1900:        return (0);
                   1901: }
                   1902: 
                   1903: /*
                   1904:  * Free the net address hash lists that are hanging off the mount points.
                   1905:  */
                   1906: static void
                   1907: vfs_free_addrlist(nep)
                   1908:        struct netexport *nep;
                   1909: {
                   1910:        register int i;
                   1911:        register struct radix_node_head *rnh;
                   1912: 
                   1913:        for (i = 0; i <= AF_MAX; i++)
                   1914:                if (rnh = nep->ne_rtable[i]) {
                   1915:                        (*rnh->rnh_walktree)(rnh, vfs_free_netcred,
                   1916:                            (caddr_t)rnh);
                   1917:                        _FREE((caddr_t)rnh, M_RTABLE);
                   1918:                        nep->ne_rtable[i] = 0;
                   1919:                }
                   1920: }
                   1921: 
                   1922: int
                   1923: vfs_export(mp, nep, argp)
                   1924:        struct mount *mp;
                   1925:        struct netexport *nep;
                   1926:        struct export_args *argp;
                   1927: {
                   1928:        int error;
                   1929: 
                   1930:        if (argp->ex_flags & MNT_DELEXPORT) {
                   1931:                vfs_free_addrlist(nep);
                   1932:                mp->mnt_flag &= ~(MNT_EXPORTED | MNT_DEFEXPORTED);
                   1933:        }
                   1934:        if (argp->ex_flags & MNT_EXPORTED) {
                   1935:                if (error = vfs_hang_addrlist(mp, nep, argp))
                   1936:                        return (error);
                   1937:                mp->mnt_flag |= MNT_EXPORTED;
                   1938:        }
                   1939:        return (0);
                   1940: }
                   1941: 
                   1942: struct netcred *
                   1943: vfs_export_lookup(mp, nep, nam)
                   1944:        register struct mount *mp;
                   1945:        struct netexport *nep;
                   1946:        struct mbuf *nam;
                   1947: {
                   1948:        register struct netcred *np;
                   1949:        register struct radix_node_head *rnh;
                   1950:        struct sockaddr *saddr;
                   1951: 
                   1952:        np = NULL;
                   1953:        if (mp->mnt_flag & MNT_EXPORTED) {
                   1954:                /*
                   1955:                 * Lookup in the export list first.
                   1956:                 */
                   1957:                if (nam != NULL) {
                   1958:                        saddr = mtod(nam, struct sockaddr *);
                   1959:                        rnh = nep->ne_rtable[saddr->sa_family];
                   1960:                        if (rnh != NULL) {
                   1961:                                np = (struct netcred *)
                   1962:                                        (*rnh->rnh_matchaddr)((caddr_t)saddr,
                   1963:                                                              rnh);
                   1964:                                if (np && np->netc_rnodes->rn_flags & RNF_ROOT)
                   1965:                                        np = NULL;
                   1966:                        }
                   1967:                }
                   1968:                /*
                   1969:                 * If no address match, use the default if it exists.
                   1970:                 */
                   1971:                if (np == NULL && mp->mnt_flag & MNT_DEFEXPORTED)
                   1972:                        np = &nep->ne_defexported;
                   1973:        }
                   1974:        return (np);
                   1975: }
                   1976: 

unix.superglobalmegacorp.com

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