LCOV - code coverage report
Current view: top level - kern - vfs_subr.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 1064 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 64 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*      $OpenBSD: vfs_subr.c,v 1.277 2018/07/13 09:25:23 beck Exp $     */
       2             : /*      $NetBSD: vfs_subr.c,v 1.53 1996/04/22 01:39:13 christos Exp $   */
       3             : 
       4             : /*
       5             :  * Copyright (c) 1989, 1993
       6             :  *      The Regents of the University of California.  All rights reserved.
       7             :  * (c) UNIX System Laboratories, Inc.
       8             :  * All or some portions of this file are derived from material licensed
       9             :  * to the University of California by American Telephone and Telegraph
      10             :  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
      11             :  * the permission of UNIX System Laboratories, Inc.
      12             :  *
      13             :  * Redistribution and use in source and binary forms, with or without
      14             :  * modification, are permitted provided that the following conditions
      15             :  * are met:
      16             :  * 1. Redistributions of source code must retain the above copyright
      17             :  *    notice, this list of conditions and the following disclaimer.
      18             :  * 2. Redistributions in binary form must reproduce the above copyright
      19             :  *    notice, this list of conditions and the following disclaimer in the
      20             :  *    documentation and/or other materials provided with the distribution.
      21             :  * 3. Neither the name of the University nor the names of its contributors
      22             :  *    may be used to endorse or promote products derived from this software
      23             :  *    without specific prior written permission.
      24             :  *
      25             :  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
      26             :  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      27             :  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
      28             :  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
      29             :  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
      30             :  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
      31             :  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
      32             :  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
      33             :  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
      34             :  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
      35             :  * SUCH DAMAGE.
      36             :  *
      37             :  *      @(#)vfs_subr.c  8.13 (Berkeley) 4/18/94
      38             :  */
      39             : 
      40             : /*
      41             :  * External virtual filesystem routines
      42             :  */
      43             : 
      44             : #include <sys/param.h>
      45             : #include <sys/systm.h>
      46             : #include <sys/proc.h>
      47             : #include <sys/sysctl.h>
      48             : #include <sys/mount.h>
      49             : #include <sys/time.h>
      50             : #include <sys/fcntl.h>
      51             : #include <sys/kernel.h>
      52             : #include <sys/conf.h>
      53             : #include <sys/vnode.h>
      54             : #include <sys/lock.h>
      55             : #include <sys/stat.h>
      56             : #include <sys/acct.h>
      57             : #include <sys/namei.h>
      58             : #include <sys/ucred.h>
      59             : #include <sys/buf.h>
      60             : #include <sys/errno.h>
      61             : #include <sys/malloc.h>
      62             : #include <sys/mbuf.h>
      63             : #include <sys/syscallargs.h>
      64             : #include <sys/pool.h>
      65             : #include <sys/tree.h>
      66             : #include <sys/specdev.h>
      67             : 
      68             : #include <netinet/in.h>
      69             : 
      70             : #include <uvm/uvm_extern.h>
      71             : #include <uvm/uvm_vnode.h>
      72             : 
      73             : #include "softraid.h"
      74             : 
      75             : void sr_quiesce(void);
      76             : 
      77             : enum vtype iftovt_tab[16] = {
      78             :         VNON, VFIFO, VCHR, VNON, VDIR, VNON, VBLK, VNON,
      79             :         VREG, VNON, VLNK, VNON, VSOCK, VNON, VNON, VBAD,
      80             : };
      81             : 
      82             : int     vttoif_tab[9] = {
      83             :         0, S_IFREG, S_IFDIR, S_IFBLK, S_IFCHR, S_IFLNK,
      84             :         S_IFSOCK, S_IFIFO, S_IFMT,
      85             : };
      86             : 
      87             : int prtactive = 0;              /* 1 => print out reclaim of active vnodes */
      88             : int suid_clear = 1;             /* 1 => clear SUID / SGID on owner change */
      89             : 
      90             : /*
      91             :  * Insq/Remq for the vnode usage lists.
      92             :  */
      93             : #define bufinsvn(bp, dp)        LIST_INSERT_HEAD(dp, bp, b_vnbufs)
      94             : #define bufremvn(bp) {                                                  \
      95             :         LIST_REMOVE(bp, b_vnbufs);                                      \
      96             :         LIST_NEXT(bp, b_vnbufs) = NOLIST;                               \
      97             : }
      98             : 
      99             : struct freelst vnode_hold_list; /* list of vnodes referencing buffers */
     100             : struct freelst vnode_free_list; /* vnode free list */
     101             : 
     102             : struct mntlist mountlist;       /* mounted filesystem list */
     103             : 
     104             : void    vclean(struct vnode *, int, struct proc *);
     105             : 
     106             : void insmntque(struct vnode *, struct mount *);
     107             : int getdevvp(dev_t, struct vnode **, enum vtype);
     108             : 
     109             : int vfs_hang_addrlist(struct mount *, struct netexport *,
     110             :                                   struct export_args *);
     111             : int vfs_free_netcred(struct radix_node *, void *, u_int);
     112             : void vfs_free_addrlist(struct netexport *);
     113             : void vputonfreelist(struct vnode *);
     114             : 
     115             : int vflush_vnode(struct vnode *, void *);
     116             : int maxvnodes;
     117             : 
     118             : void vfs_unmountall(void);
     119             : 
     120             : #ifdef DEBUG
     121             : void printlockedvnodes(void);
     122             : #endif
     123             : 
     124             : struct pool vnode_pool;
     125             : struct pool uvm_vnode_pool;
     126             : 
     127             : static inline int rb_buf_compare(const struct buf *b1, const struct buf *b2);
     128           0 : RBT_GENERATE(buf_rb_bufs, buf, b_rbbufs, rb_buf_compare);
     129             : 
     130             : static inline int
     131           0 : rb_buf_compare(const struct buf *b1, const struct buf *b2)
     132             : {
     133           0 :         if (b1->b_lblkno < b2->b_lblkno)
     134           0 :                 return(-1);
     135           0 :         if (b1->b_lblkno > b2->b_lblkno)
     136           0 :                 return(1);
     137           0 :         return(0);
     138           0 : }
     139             : 
     140             : /*
     141             :  * Initialize the vnode management data structures.
     142             :  */
     143             : void
     144           0 : vntblinit(void)
     145             : {
     146             :         /* buffer cache may need a vnode for each buffer */
     147           0 :         maxvnodes = 2 * initialvnodes;
     148           0 :         pool_init(&vnode_pool, sizeof(struct vnode), 0, IPL_NONE,
     149             :             PR_WAITOK, "vnodes", NULL);
     150           0 :         pool_init(&uvm_vnode_pool, sizeof(struct uvm_vnode), 0, IPL_NONE,
     151             :             PR_WAITOK, "uvmvnodes", NULL);
     152           0 :         TAILQ_INIT(&vnode_hold_list);
     153           0 :         TAILQ_INIT(&vnode_free_list);
     154           0 :         TAILQ_INIT(&mountlist);
     155             :         /*
     156             :          * Initialize the filesystem syncer.
     157             :          */
     158           0 :         vn_initialize_syncerd();
     159             : 
     160             : #ifdef NFSSERVER
     161           0 :         rn_init(sizeof(struct sockaddr_in));
     162             : #endif /* NFSSERVER */
     163           0 : }
     164             : 
     165             : /*
     166             :  * Mark a mount point as busy. Used to synchronize access and to delay
     167             :  * unmounting.
     168             :  *
     169             :  * Default behaviour is to attempt getting a READ lock and in case of an
     170             :  * ongoing unmount, to wait for it to finish and then return failure.
     171             :  */
     172             : int
     173           0 : vfs_busy(struct mount *mp, int flags)
     174             : {
     175             :         int rwflags = 0;
     176             : 
     177             :         /* new mountpoints need their lock initialised */
     178           0 :         if (mp->mnt_lock.rwl_name == NULL)
     179           0 :                 rw_init_flags(&mp->mnt_lock, "vfslock", RWL_IS_VNODE);
     180             : 
     181           0 :         if (flags & VB_WRITE)
     182           0 :                 rwflags |= RW_WRITE;
     183             :         else
     184             :                 rwflags |= RW_READ;
     185             : 
     186           0 :         if (flags & VB_WAIT)
     187           0 :                 rwflags |= RW_SLEEPFAIL;
     188             :         else
     189           0 :                 rwflags |= RW_NOSLEEP;
     190             : 
     191             : #ifdef WITNESS
     192             :         if (flags & VB_DUPOK)
     193             :                 rwflags |= RW_DUPOK;
     194             : #endif
     195             : 
     196           0 :         if (rw_enter(&mp->mnt_lock, rwflags))
     197           0 :                 return (EBUSY);
     198             : 
     199           0 :         return (0);
     200           0 : }
     201             : 
     202             : /*
     203             :  * Free a busy file system
     204             :  */
     205             : void
     206           0 : vfs_unbusy(struct mount *mp)
     207             : {
     208           0 :         rw_exit(&mp->mnt_lock);
     209           0 : }
     210             : 
     211             : int
     212           0 : vfs_isbusy(struct mount *mp) 
     213             : {
     214           0 :         if (RWLOCK_OWNER(&mp->mnt_lock) > 0)
     215           0 :                 return (1);
     216             :         else
     217           0 :                 return (0);
     218           0 : }
     219             : 
     220             : /*
     221             :  * Lookup a filesystem type, and if found allocate and initialize
     222             :  * a mount structure for it.
     223             :  *
     224             :  * Devname is usually updated by mount(8) after booting.
     225             :  */
     226             : int
     227           0 : vfs_rootmountalloc(char *fstypename, char *devname, struct mount **mpp)
     228             : {
     229             :         struct vfsconf *vfsp;
     230             :         struct mount *mp;
     231             : 
     232           0 :         for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next)
     233           0 :                 if (!strcmp(vfsp->vfc_name, fstypename))
     234             :                         break;
     235           0 :         if (vfsp == NULL)
     236           0 :                 return (ENODEV);
     237           0 :         mp = malloc(sizeof(*mp), M_MOUNT, M_WAITOK|M_ZERO);
     238           0 :         (void)vfs_busy(mp, VB_READ|VB_NOWAIT);
     239           0 :         LIST_INIT(&mp->mnt_vnodelist);
     240           0 :         mp->mnt_vfc = vfsp;
     241           0 :         mp->mnt_op = vfsp->vfc_vfsops;
     242           0 :         mp->mnt_flag = MNT_RDONLY;
     243           0 :         mp->mnt_vnodecovered = NULLVP;
     244           0 :         vfsp->vfc_refcount++;
     245           0 :         mp->mnt_flag |= vfsp->vfc_flags & MNT_VISFLAGMASK;
     246           0 :         strncpy(mp->mnt_stat.f_fstypename, vfsp->vfc_name, MFSNAMELEN);
     247           0 :         mp->mnt_stat.f_mntonname[0] = '/';
     248           0 :         copystr(devname, mp->mnt_stat.f_mntfromname, MNAMELEN, 0);
     249           0 :         copystr(devname, mp->mnt_stat.f_mntfromspec, MNAMELEN, 0);
     250           0 :         *mpp = mp;
     251           0 :         return (0);
     252           0 :  }
     253             : 
     254             : /*
     255             :  * Lookup a mount point by filesystem identifier.
     256             :  */
     257             : struct mount *
     258           0 : vfs_getvfs(fsid_t *fsid)
     259             : {
     260             :         struct mount *mp;
     261             : 
     262           0 :         TAILQ_FOREACH(mp, &mountlist, mnt_list) {
     263           0 :                 if (mp->mnt_stat.f_fsid.val[0] == fsid->val[0] &&
     264           0 :                     mp->mnt_stat.f_fsid.val[1] == fsid->val[1]) {
     265           0 :                         return (mp);
     266             :                 }
     267             :         }
     268             : 
     269           0 :         return (NULL);
     270           0 : }
     271             : 
     272             : 
     273             : /*
     274             :  * Get a new unique fsid
     275             :  */
     276             : void
     277           0 : vfs_getnewfsid(struct mount *mp)
     278             : {
     279             :         static u_short xxxfs_mntid;
     280             : 
     281           0 :         fsid_t tfsid;
     282             :         int mtype;
     283             : 
     284           0 :         mtype = mp->mnt_vfc->vfc_typenum;
     285           0 :         mp->mnt_stat.f_fsid.val[0] = makedev(nblkdev + mtype, 0);
     286           0 :         mp->mnt_stat.f_fsid.val[1] = mtype;
     287           0 :         if (xxxfs_mntid == 0)
     288           0 :                 ++xxxfs_mntid;
     289           0 :         tfsid.val[0] = makedev(nblkdev + mtype, xxxfs_mntid);
     290           0 :         tfsid.val[1] = mtype;
     291           0 :         if (!TAILQ_EMPTY(&mountlist)) {
     292           0 :                 while (vfs_getvfs(&tfsid)) {
     293           0 :                         tfsid.val[0]++;
     294           0 :                         xxxfs_mntid++;
     295             :                 }
     296             :         }
     297           0 :         mp->mnt_stat.f_fsid.val[0] = tfsid.val[0];
     298           0 : }
     299             : 
     300             : /*
     301             :  * Set vnode attributes to VNOVAL
     302             :  */
     303             : void
     304           0 : vattr_null(struct vattr *vap)
     305             : {
     306             : 
     307           0 :         vap->va_type = VNON;
     308             :         /*
     309             :          * Don't get fancy: u_quad_t = u_int = VNOVAL leaves the u_quad_t
     310             :          * with 2^31-1 instead of 2^64-1.  Just write'm out and let
     311             :          * the compiler do its job.
     312             :          */
     313           0 :         vap->va_mode = VNOVAL;
     314           0 :         vap->va_nlink = VNOVAL;
     315           0 :         vap->va_uid = VNOVAL;
     316           0 :         vap->va_gid = VNOVAL;
     317           0 :         vap->va_fsid = VNOVAL;
     318           0 :         vap->va_fileid = VNOVAL;
     319           0 :         vap->va_size = VNOVAL;
     320           0 :         vap->va_blocksize = VNOVAL;
     321           0 :         vap->va_atime.tv_sec = VNOVAL;
     322           0 :         vap->va_atime.tv_nsec = VNOVAL;
     323           0 :         vap->va_mtime.tv_sec = VNOVAL;
     324           0 :         vap->va_mtime.tv_nsec = VNOVAL;
     325           0 :         vap->va_ctime.tv_sec = VNOVAL;
     326           0 :         vap->va_ctime.tv_nsec = VNOVAL;
     327           0 :         vap->va_gen = VNOVAL;
     328           0 :         vap->va_flags = VNOVAL;
     329           0 :         vap->va_rdev = VNOVAL;
     330           0 :         vap->va_bytes = VNOVAL;
     331           0 :         vap->va_filerev = VNOVAL;
     332           0 :         vap->va_vaflags = 0;
     333           0 : }
     334             : 
     335             : /*
     336             :  * Routines having to do with the management of the vnode table.
     337             :  */
     338             : long numvnodes;
     339             : 
     340             : /*
     341             :  * Return the next vnode from the free list.
     342             :  */
     343             : int
     344           0 : getnewvnode(enum vtagtype tag, struct mount *mp, struct vops *vops,
     345             :     struct vnode **vpp)
     346             : {
     347           0 :         struct proc *p = curproc;
     348             :         struct freelst *listhd;
     349             :         static int toggle;
     350             :         struct vnode *vp;
     351             :         int s;
     352             : 
     353             :         /*
     354             :          * allow maxvnodes to increase if the buffer cache itself
     355             :          * is big enough to justify it. (we don't shrink it ever)
     356             :          */
     357           0 :         maxvnodes = maxvnodes < bcstats.numbufs ? bcstats.numbufs
     358             :             : maxvnodes;
     359             : 
     360             :         /*
     361             :          * We must choose whether to allocate a new vnode or recycle an
     362             :          * existing one. The criterion for allocating a new one is that
     363             :          * the total number of vnodes is less than the number desired or
     364             :          * there are no vnodes on either free list. Generally we only
     365             :          * want to recycle vnodes that have no buffers associated with
     366             :          * them, so we look first on the vnode_free_list. If it is empty,
     367             :          * we next consider vnodes with referencing buffers on the
     368             :          * vnode_hold_list. The toggle ensures that half the time we
     369             :          * will use a buffer from the vnode_hold_list, and half the time
     370             :          * we will allocate a new one unless the list has grown to twice
     371             :          * the desired size. We are reticent to recycle vnodes from the
     372             :          * vnode_hold_list because we will lose the identity of all its
     373             :          * referencing buffers.
     374             :          */
     375           0 :         toggle ^= 1;
     376           0 :         if (numvnodes / 2 > maxvnodes)
     377             :                 toggle = 0;
     378             : 
     379           0 :         s = splbio();
     380           0 :         if ((numvnodes < maxvnodes) ||
     381           0 :             ((TAILQ_FIRST(listhd = &vnode_free_list) == NULL) &&
     382           0 :             ((TAILQ_FIRST(listhd = &vnode_hold_list) == NULL) || toggle))) {
     383           0 :                 splx(s);
     384           0 :                 vp = pool_get(&vnode_pool, PR_WAITOK | PR_ZERO);
     385           0 :                 vp->v_uvm = pool_get(&uvm_vnode_pool, PR_WAITOK | PR_ZERO);
     386           0 :                 vp->v_uvm->u_vnode = vp;
     387           0 :                 RBT_INIT(buf_rb_bufs, &vp->v_bufs_tree);
     388           0 :                 cache_tree_init(&vp->v_nc_tree);
     389           0 :                 TAILQ_INIT(&vp->v_cache_dst);
     390           0 :                 numvnodes++;
     391           0 :         } else {
     392           0 :                 TAILQ_FOREACH(vp, listhd, v_freelist) {
     393           0 :                         if (VOP_ISLOCKED(vp) == 0)
     394             :                                 break;
     395             :                 }
     396             :                 /*
     397             :                  * Unless this is a bad time of the month, at most
     398             :                  * the first NCPUS items on the free list are
     399             :                  * locked, so this is close enough to being empty.
     400             :                  */
     401           0 :                 if (vp == NULL) {
     402           0 :                         splx(s);
     403           0 :                         tablefull("vnode");
     404           0 :                         *vpp = 0;
     405           0 :                         return (ENFILE);
     406             :                 }
     407             : 
     408             : #ifdef DIAGNOSTIC
     409           0 :                 if (vp->v_usecount) {
     410           0 :                         vprint("free vnode", vp);
     411           0 :                         panic("free vnode isn't");
     412             :                 }
     413             : #endif
     414             : 
     415           0 :                 TAILQ_REMOVE(listhd, vp, v_freelist);
     416           0 :                 vp->v_bioflag &= ~VBIOONFREELIST;
     417           0 :                 splx(s);
     418             : 
     419           0 :                 if (vp->v_type != VBAD)
     420           0 :                         vgonel(vp, p);
     421             : #ifdef DIAGNOSTIC
     422           0 :                 if (vp->v_data) {
     423           0 :                         vprint("cleaned vnode", vp);
     424           0 :                         panic("cleaned vnode isn't");
     425             :                 }
     426           0 :                 s = splbio();
     427           0 :                 if (vp->v_numoutput)
     428           0 :                         panic("Clean vnode has pending I/O's");
     429           0 :                 splx(s);
     430             : #endif
     431           0 :                 vp->v_flag = 0;
     432           0 :                 vp->v_socket = 0;
     433             :         }
     434           0 :         cache_purge(vp);
     435           0 :         vp->v_type = VNON;
     436           0 :         vp->v_tag = tag;
     437           0 :         vp->v_op = vops;
     438           0 :         insmntque(vp, mp);
     439           0 :         *vpp = vp;
     440           0 :         vp->v_usecount = 1;
     441           0 :         vp->v_data = 0;
     442           0 :         return (0);
     443           0 : }
     444             : 
     445             : /*
     446             :  * Move a vnode from one mount queue to another.
     447             :  */
     448             : void
     449           0 : insmntque(struct vnode *vp, struct mount *mp)
     450             : {
     451             :         /*
     452             :          * Delete from old mount point vnode list, if on one.
     453             :          */
     454           0 :         if (vp->v_mount != NULL)
     455           0 :                 LIST_REMOVE(vp, v_mntvnodes);
     456             :         /*
     457             :          * Insert into list of vnodes for the new mount point, if available.
     458             :          */
     459           0 :         if ((vp->v_mount = mp) != NULL)
     460           0 :                 LIST_INSERT_HEAD(&mp->mnt_vnodelist, vp, v_mntvnodes);
     461           0 : }
     462             : 
     463             : /*
     464             :  * Create a vnode for a block device.
     465             :  * Used for root filesystem, argdev, and swap areas.
     466             :  * Also used for memory file system special devices.
     467             :  */
     468             : int
     469           0 : bdevvp(dev_t dev, struct vnode **vpp)
     470             : {
     471           0 :         return (getdevvp(dev, vpp, VBLK));
     472             : }
     473             : 
     474             : /*
     475             :  * Create a vnode for a character device.
     476             :  * Used for console handling.
     477             :  */
     478             : int
     479           0 : cdevvp(dev_t dev, struct vnode **vpp)
     480             : {
     481           0 :         return (getdevvp(dev, vpp, VCHR));
     482             : }
     483             : 
     484             : /*
     485             :  * Create a vnode for a device.
     486             :  * Used by bdevvp (block device) for root file system etc.,
     487             :  * and by cdevvp (character device) for console.
     488             :  */
     489             : int
     490           0 : getdevvp(dev_t dev, struct vnode **vpp, enum vtype type)
     491             : {
     492             :         struct vnode *vp;
     493           0 :         struct vnode *nvp;
     494             :         int error;
     495             : 
     496           0 :         if (dev == NODEV) {
     497           0 :                 *vpp = NULLVP;
     498           0 :                 return (0);
     499             :         }
     500           0 :         error = getnewvnode(VT_NON, NULL, &spec_vops, &nvp);
     501           0 :         if (error) {
     502           0 :                 *vpp = NULLVP;
     503           0 :                 return (error);
     504             :         }
     505           0 :         vp = nvp;
     506           0 :         vp->v_type = type;
     507           0 :         if ((nvp = checkalias(vp, dev, NULL)) != 0) {
     508           0 :                 vput(vp);
     509           0 :                 vp = nvp;
     510           0 :         }
     511           0 :         if (vp->v_type == VCHR && cdevsw[major(vp->v_rdev)].d_type == D_TTY)
     512           0 :                 vp->v_flag |= VISTTY;
     513           0 :         *vpp = vp;
     514           0 :         return (0);
     515           0 : }
     516             : 
     517             : /*
     518             :  * Check to see if the new vnode represents a special device
     519             :  * for which we already have a vnode (either because of
     520             :  * bdevvp() or because of a different vnode representing
     521             :  * the same block device). If such an alias exists, deallocate
     522             :  * the existing contents and return the aliased vnode. The
     523             :  * caller is responsible for filling it with its new contents.
     524             :  */
     525             : struct vnode *
     526           0 : checkalias(struct vnode *nvp, dev_t nvp_rdev, struct mount *mp)
     527             : {
     528           0 :         struct proc *p = curproc;
     529             :         struct vnode *vp;
     530             :         struct vnode **vpp;
     531             : 
     532           0 :         if (nvp->v_type != VBLK && nvp->v_type != VCHR)
     533           0 :                 return (NULLVP);
     534             : 
     535           0 :         vpp = &speclisth[SPECHASH(nvp_rdev)];
     536             : loop:
     537           0 :         for (vp = *vpp; vp; vp = vp->v_specnext) {
     538           0 :                 if (nvp_rdev != vp->v_rdev || nvp->v_type != vp->v_type) {
     539             :                         continue;
     540             :                 }
     541             :                 /*
     542             :                  * Alias, but not in use, so flush it out.
     543             :                  */
     544           0 :                 if (vp->v_usecount == 0) {
     545           0 :                         vgonel(vp, p);
     546           0 :                         goto loop;
     547             :                 }
     548           0 :                 if (vget(vp, LK_EXCLUSIVE)) {
     549           0 :                         goto loop;
     550             :                 }
     551             :                 break;
     552             :         }
     553             : 
     554             :         /*
     555             :          * Common case is actually in the if statement
     556             :          */
     557           0 :         if (vp == NULL || !(vp->v_tag == VT_NON && vp->v_type == VBLK)) {
     558           0 :                 nvp->v_specinfo = malloc(sizeof(struct specinfo), M_VNODE,
     559             :                         M_WAITOK);
     560           0 :                 nvp->v_rdev = nvp_rdev;
     561           0 :                 nvp->v_hashchain = vpp;
     562           0 :                 nvp->v_specnext = *vpp;
     563           0 :                 nvp->v_specmountpoint = NULL;
     564           0 :                 nvp->v_speclockf = NULL;
     565           0 :                 nvp->v_specbitmap = NULL;
     566           0 :                 if (nvp->v_type == VCHR &&
     567           0 :                     (cdevsw[major(nvp_rdev)].d_flags & D_CLONE) &&
     568           0 :                     (minor(nvp_rdev) >> CLONE_SHIFT == 0)) {
     569           0 :                         if (vp != NULLVP)
     570           0 :                                 nvp->v_specbitmap = vp->v_specbitmap;
     571             :                         else
     572           0 :                                 nvp->v_specbitmap = malloc(CLONE_MAPSZ,
     573             :                                     M_VNODE, M_WAITOK | M_ZERO);
     574             :                 }
     575           0 :                 *vpp = nvp;
     576           0 :                 if (vp != NULLVP) {
     577           0 :                         nvp->v_flag |= VALIASED;
     578           0 :                         vp->v_flag |= VALIASED;
     579           0 :                         vput(vp);
     580           0 :                 }
     581           0 :                 return (NULLVP);
     582             :         }
     583             : 
     584             :         /*
     585             :          * This code is the uncommon case. It is called in case
     586             :          * we found an alias that was VT_NON && vtype of VBLK
     587             :          * This means we found a block device that was created
     588             :          * using bdevvp.
     589             :          * An example of such a vnode is the root partition device vnode
     590             :          * created in ffs_mountroot.
     591             :          *
     592             :          * The vnodes created by bdevvp should not be aliased (why?).
     593             :          */
     594             : 
     595           0 :         VOP_UNLOCK(vp);
     596           0 :         vclean(vp, 0, p);
     597           0 :         vp->v_op = nvp->v_op;
     598           0 :         vp->v_tag = nvp->v_tag;
     599           0 :         nvp->v_type = VNON;
     600           0 :         insmntque(vp, mp);
     601           0 :         return (vp);
     602           0 : }
     603             : 
     604             : /*
     605             :  * Grab a particular vnode from the free list, increment its
     606             :  * reference count and lock it. If the vnode lock bit is set,
     607             :  * the vnode is being eliminated in vgone. In that case, we
     608             :  * cannot grab it, so the process is awakened when the
     609             :  * transition is completed, and an error code is returned to
     610             :  * indicate that the vnode is no longer usable, possibly
     611             :  * having been changed to a new file system type.
     612             :  */
     613             : int
     614           0 : vget(struct vnode *vp, int flags)
     615             : {
     616             :         int error, s, onfreelist;
     617             : 
     618             :         /*
     619             :          * If the vnode is in the process of being cleaned out for
     620             :          * another use, we wait for the cleaning to finish and then
     621             :          * return failure. Cleaning is determined by checking that
     622             :          * the VXLOCK flag is set.
     623             :          */
     624             : 
     625           0 :         if (vp->v_flag & VXLOCK) {
     626           0 :                 if (flags & LK_NOWAIT) {
     627           0 :                         return (EBUSY);
     628             :                 }
     629             : 
     630           0 :                 vp->v_flag |= VXWANT;
     631           0 :                 tsleep(vp, PINOD, "vget", 0);
     632           0 :                 return (ENOENT);
     633             :         }
     634             : 
     635           0 :         onfreelist = vp->v_bioflag & VBIOONFREELIST;
     636           0 :         if (vp->v_usecount == 0 && onfreelist) {
     637           0 :                 s = splbio();
     638           0 :                 if (vp->v_holdcnt > 0)
     639           0 :                         TAILQ_REMOVE(&vnode_hold_list, vp, v_freelist);
     640             :                 else
     641           0 :                         TAILQ_REMOVE(&vnode_free_list, vp, v_freelist);
     642           0 :                 vp->v_bioflag &= ~VBIOONFREELIST;
     643           0 :                 splx(s);
     644           0 :         }
     645             : 
     646           0 :         vp->v_usecount++;
     647           0 :         if (flags & LK_TYPE_MASK) {
     648           0 :                 if ((error = vn_lock(vp, flags)) != 0) {
     649           0 :                         vp->v_usecount--;
     650           0 :                         if (vp->v_usecount == 0 && onfreelist)
     651           0 :                                 vputonfreelist(vp);
     652             :                 }
     653           0 :                 return (error);
     654             :         }
     655             : 
     656           0 :         return (0);
     657           0 : }
     658             : 
     659             : 
     660             : /* Vnode reference. */
     661             : void
     662           0 : vref(struct vnode *vp)
     663             : {
     664             : #ifdef DIAGNOSTIC
     665           0 :         if (vp->v_usecount == 0)
     666           0 :                 panic("vref used where vget required");
     667           0 :         if (vp->v_type == VNON)
     668           0 :                 panic("vref on a VNON vnode");
     669             : #endif
     670           0 :         vp->v_usecount++;
     671           0 : }
     672             : 
     673             : void
     674           0 : vputonfreelist(struct vnode *vp)
     675             : {
     676             :         int s;
     677             :         struct freelst *lst;
     678             : 
     679           0 :         s = splbio();
     680             : #ifdef DIAGNOSTIC
     681           0 :         if (vp->v_usecount != 0)
     682           0 :                 panic("Use count is not zero!");
     683             : 
     684           0 :         if (vp->v_bioflag & VBIOONFREELIST) {
     685           0 :                 vprint("vnode already on free list: ", vp);
     686           0 :                 panic("vnode already on free list");
     687             :         }
     688             : #endif
     689             : 
     690           0 :         vp->v_bioflag |= VBIOONFREELIST;
     691             : 
     692           0 :         if (vp->v_holdcnt > 0)
     693           0 :                 lst = &vnode_hold_list;
     694             :         else
     695             :                 lst = &vnode_free_list;
     696             : 
     697           0 :         if (vp->v_type == VBAD)
     698           0 :                 TAILQ_INSERT_HEAD(lst, vp, v_freelist);
     699             :         else
     700           0 :                 TAILQ_INSERT_TAIL(lst, vp, v_freelist);
     701             : 
     702           0 :         splx(s);
     703           0 : }
     704             : 
     705             : /*
     706             :  * vput(), just unlock and vrele()
     707             :  */
     708             : void
     709           0 : vput(struct vnode *vp)
     710             : {
     711           0 :         struct proc *p = curproc;
     712             : 
     713             : #ifdef DIAGNOSTIC
     714           0 :         if (vp == NULL)
     715           0 :                 panic("vput: null vp");
     716             : #endif
     717             : 
     718             : #ifdef DIAGNOSTIC
     719           0 :         if (vp->v_usecount == 0) {
     720           0 :                 vprint("vput: bad ref count", vp);
     721           0 :                 panic("vput: ref cnt");
     722             :         }
     723             : #endif
     724           0 :         vp->v_usecount--;
     725           0 :         KASSERT(vp->v_usecount > 0 || vp->v_uvcount == 0);
     726           0 :         if (vp->v_usecount > 0) {
     727           0 :                 VOP_UNLOCK(vp);
     728           0 :                 return;
     729             :         }
     730             : 
     731             : #ifdef DIAGNOSTIC
     732           0 :         if (vp->v_writecount != 0) {
     733           0 :                 vprint("vput: bad writecount", vp);
     734           0 :                 panic("vput: v_writecount != 0");
     735             :         }
     736             : #endif
     737             : 
     738           0 :         VOP_INACTIVE(vp, p);
     739             : 
     740           0 :         if (vp->v_usecount == 0 && !(vp->v_bioflag & VBIOONFREELIST))
     741           0 :                 vputonfreelist(vp);
     742           0 : }
     743             : 
     744             : /*
     745             :  * Vnode release - use for active VNODES.
     746             :  * If count drops to zero, call inactive routine and return to freelist.
     747             :  * Returns 0 if it did not sleep.
     748             :  */
     749             : int
     750           0 : vrele(struct vnode *vp)
     751             : {
     752           0 :         struct proc *p = curproc;
     753             : 
     754             : #ifdef DIAGNOSTIC
     755           0 :         if (vp == NULL)
     756           0 :                 panic("vrele: null vp");
     757             : #endif
     758             : #ifdef DIAGNOSTIC
     759           0 :         if (vp->v_usecount == 0) {
     760           0 :                 vprint("vrele: bad ref count", vp);
     761           0 :                 panic("vrele: ref cnt");
     762             :         }
     763             : #endif
     764           0 :         vp->v_usecount--;
     765           0 :         if (vp->v_usecount > 0) {
     766           0 :                 return (0);
     767             :         }
     768             : 
     769             : #ifdef DIAGNOSTIC
     770           0 :         if (vp->v_writecount != 0) {
     771           0 :                 vprint("vrele: bad writecount", vp);
     772           0 :                 panic("vrele: v_writecount != 0");
     773             :         }
     774             : #endif
     775             : 
     776           0 :         if (vn_lock(vp, LK_EXCLUSIVE)) {
     777             : #ifdef DIAGNOSTIC
     778           0 :                 vprint("vrele: cannot lock", vp);
     779             : #endif
     780           0 :                 return (1);
     781             :         }
     782             : 
     783           0 :         VOP_INACTIVE(vp, p);
     784             : 
     785           0 :         if (vp->v_usecount == 0 && !(vp->v_bioflag & VBIOONFREELIST))
     786           0 :                 vputonfreelist(vp);
     787           0 :         return (1);
     788           0 : }
     789             : 
     790             : /* Page or buffer structure gets a reference. */
     791             : void
     792           0 : vhold(struct vnode *vp)
     793             : {
     794             :         /*
     795             :          * If it is on the freelist and the hold count is currently
     796             :          * zero, move it to the hold list.
     797             :          */
     798           0 :         if ((vp->v_bioflag & VBIOONFREELIST) &&
     799           0 :             vp->v_holdcnt == 0 && vp->v_usecount == 0) {
     800           0 :                 TAILQ_REMOVE(&vnode_free_list, vp, v_freelist);
     801           0 :                 TAILQ_INSERT_TAIL(&vnode_hold_list, vp, v_freelist);
     802           0 :         }
     803           0 :         vp->v_holdcnt++;
     804           0 : }
     805             : 
     806             : /* Lose interest in a vnode. */
     807             : void
     808           0 : vdrop(struct vnode *vp)
     809             : {
     810             : #ifdef DIAGNOSTIC
     811           0 :         if (vp->v_holdcnt == 0)
     812           0 :                 panic("vdrop: zero holdcnt");
     813             : #endif
     814             : 
     815           0 :         vp->v_holdcnt--;
     816             : 
     817             :         /*
     818             :          * If it is on the holdlist and the hold count drops to
     819             :          * zero, move it to the free list.
     820             :          */
     821           0 :         if ((vp->v_bioflag & VBIOONFREELIST) &&
     822           0 :             vp->v_holdcnt == 0 && vp->v_usecount == 0) {
     823           0 :                 TAILQ_REMOVE(&vnode_hold_list, vp, v_freelist);
     824           0 :                 TAILQ_INSERT_TAIL(&vnode_free_list, vp, v_freelist);
     825           0 :         }
     826           0 : }
     827             : 
     828             : /*
     829             :  * Remove any vnodes in the vnode table belonging to mount point mp.
     830             :  *
     831             :  * If MNT_NOFORCE is specified, there should not be any active ones,
     832             :  * return error if any are found (nb: this is a user error, not a
     833             :  * system error). If MNT_FORCE is specified, detach any active vnodes
     834             :  * that are found.
     835             :  */
     836             : #ifdef DEBUG
     837             : int busyprt = 0;        /* print out busy vnodes */
     838             : struct ctldebug debug1 = { "busyprt", &busyprt };
     839             : #endif
     840             : 
     841             : int
     842           0 : vfs_mount_foreach_vnode(struct mount *mp, 
     843             :     int (*func)(struct vnode *, void *), void *arg) {
     844             :         struct vnode *vp, *nvp;
     845           0 :         int error = 0;
     846             : 
     847             : loop:
     848           0 :         LIST_FOREACH_SAFE(vp , &mp->mnt_vnodelist, v_mntvnodes, nvp) {
     849           0 :                 if (vp->v_mount != mp)
     850           0 :                         goto loop;
     851             : 
     852           0 :                 error = func(vp, arg);
     853             : 
     854           0 :                 if (error != 0)
     855             :                         break;
     856             :         }
     857             : 
     858           0 :         return (error);
     859             : }
     860             : 
     861             : struct vflush_args {
     862             :         struct vnode *skipvp;
     863             :         int busy;
     864             :         int flags;
     865             : };
     866             : 
     867             : int
     868           0 : vflush_vnode(struct vnode *vp, void *arg)
     869             : {
     870           0 :         struct vflush_args *va = arg;
     871           0 :         struct proc *p = curproc;
     872             : 
     873           0 :         if (vp == va->skipvp) {
     874           0 :                 return (0);
     875             :         }
     876             : 
     877           0 :         if ((va->flags & SKIPSYSTEM) && (vp->v_flag & VSYSTEM)) {
     878           0 :                 return (0);
     879             :         }
     880             : 
     881             :         /*
     882             :          * If WRITECLOSE is set, only flush out regular file
     883             :          * vnodes open for writing.
     884             :          */
     885           0 :         if ((va->flags & WRITECLOSE) &&
     886           0 :             (vp->v_writecount == 0 || vp->v_type != VREG)) {
     887           0 :                 return (0);
     888             :         }
     889             : 
     890             :         /*
     891             :          * With v_usecount == 0, all we need to do is clear
     892             :          * out the vnode data structures and we are done.
     893             :          */
     894           0 :         if (vp->v_usecount == 0) {
     895           0 :                 vgonel(vp, p);
     896           0 :                 return (0);
     897             :         }
     898             : 
     899             :         /*
     900             :          * If FORCECLOSE is set, forcibly close the vnode.
     901             :          * For block or character devices, revert to an
     902             :          * anonymous device. For all other files, just kill them.
     903             :          */
     904           0 :         if (va->flags & FORCECLOSE) {
     905           0 :                 if (vp->v_type != VBLK && vp->v_type != VCHR) {
     906           0 :                         vgonel(vp, p);
     907           0 :                 } else {
     908           0 :                         vclean(vp, 0, p);
     909           0 :                         vp->v_op = &spec_vops;
     910           0 :                         insmntque(vp, NULL);
     911             :                 }
     912           0 :                 return (0);
     913             :         }
     914             : 
     915             :         /*
     916             :          * If set, this is allowed to ignore vnodes which don't
     917             :          * have changes pending to disk.
     918             :          * XXX Might be nice to check per-fs "inode" flags, but
     919             :          * generally the filesystem is sync'd already, right?
     920             :          */
     921           0 :         if ((va->flags & IGNORECLEAN) &&
     922           0 :             LIST_EMPTY(&vp->v_dirtyblkhd))
     923           0 :                 return (0);
     924             : 
     925             : #ifdef DEBUG
     926             :         if (busyprt)
     927             :                 vprint("vflush: busy vnode", vp);
     928             : #endif
     929           0 :         va->busy++;
     930           0 :         return (0);
     931           0 : }
     932             : 
     933             : int
     934           0 : vflush(struct mount *mp, struct vnode *skipvp, int flags)
     935             : {
     936           0 :         struct vflush_args va;
     937           0 :         va.skipvp = skipvp;
     938           0 :         va.busy = 0;
     939           0 :         va.flags = flags;
     940             : 
     941           0 :         vfs_mount_foreach_vnode(mp, vflush_vnode, &va);
     942             : 
     943           0 :         if (va.busy)
     944           0 :                 return (EBUSY);
     945           0 :         return (0);
     946           0 : }
     947             : 
     948             : /*
     949             :  * Disassociate the underlying file system from a vnode.
     950             :  */
     951             : void
     952           0 : vclean(struct vnode *vp, int flags, struct proc *p)
     953             : {
     954             :         int active;
     955             : 
     956             :         /*
     957             :          * Check to see if the vnode is in use.
     958             :          * If so we have to reference it before we clean it out
     959             :          * so that its count cannot fall to zero and generate a
     960             :          * race against ourselves to recycle it.
     961             :          */
     962           0 :         if ((active = vp->v_usecount) != 0)
     963           0 :                 vp->v_usecount++;
     964             : 
     965             :         /*
     966             :          * Prevent the vnode from being recycled or
     967             :          * brought into use while we clean it out.
     968             :          */
     969           0 :         if (vp->v_flag & VXLOCK)
     970           0 :                 panic("vclean: deadlock");
     971           0 :         vp->v_flag |= VXLOCK;
     972             :         /*
     973             :          * Even if the count is zero, the VOP_INACTIVE routine may still
     974             :          * have the object locked while it cleans it out. The VOP_LOCK
     975             :          * ensures that the VOP_INACTIVE routine is done with its work.
     976             :          * For active vnodes, it ensures that no other activity can
     977             :          * occur while the underlying object is being cleaned out.
     978             :          */
     979           0 :         VOP_LOCK(vp, LK_DRAIN | LK_EXCLUSIVE);
     980             : 
     981             :         /*
     982             :          * Clean out any VM data associated with the vnode.
     983             :          */
     984           0 :         uvm_vnp_terminate(vp);
     985             :         /*
     986             :          * Clean out any buffers associated with the vnode.
     987             :          */
     988           0 :         if (flags & DOCLOSE)
     989           0 :                 vinvalbuf(vp, V_SAVE, NOCRED, p, 0, 0);
     990             :         /*
     991             :          * If purging an active vnode, it must be closed and
     992             :          * deactivated before being reclaimed. Note that the
     993             :          * VOP_INACTIVE will unlock the vnode
     994             :          */
     995           0 :         if (active) {
     996           0 :                 if (flags & DOCLOSE)
     997           0 :                         VOP_CLOSE(vp, FNONBLOCK, NOCRED, p);
     998           0 :                 VOP_INACTIVE(vp, p);
     999           0 :         } else {
    1000             :                 /*
    1001             :                  * Any other processes trying to obtain this lock must first
    1002             :                  * wait for VXLOCK to clear, then call the new lock operation.
    1003             :                  */
    1004           0 :                 VOP_UNLOCK(vp);
    1005             :         }
    1006             : 
    1007             :         /*
    1008             :          * Reclaim the vnode.
    1009             :          */
    1010           0 :         if (VOP_RECLAIM(vp, p))
    1011           0 :                 panic("vclean: cannot reclaim");
    1012           0 :         if (active) {
    1013           0 :                 vp->v_usecount--;
    1014           0 :                 if (vp->v_usecount == 0) {
    1015           0 :                         if (vp->v_holdcnt > 0)
    1016           0 :                                 panic("vclean: not clean");
    1017           0 :                         vputonfreelist(vp);
    1018           0 :                 }
    1019             :         }
    1020           0 :         cache_purge(vp);
    1021             : 
    1022             :         /*
    1023             :          * Done with purge, notify sleepers of the grim news.
    1024             :          */
    1025           0 :         vp->v_op = &dead_vops;
    1026           0 :         VN_KNOTE(vp, NOTE_REVOKE);
    1027           0 :         vp->v_tag = VT_NON;
    1028           0 :         vp->v_flag &= ~VXLOCK;
    1029             : #ifdef VFSLCKDEBUG
    1030             :         vp->v_flag &= ~VLOCKSWORK;
    1031             : #endif
    1032           0 :         if (vp->v_flag & VXWANT) {
    1033           0 :                 vp->v_flag &= ~VXWANT;
    1034           0 :                 wakeup(vp);
    1035           0 :         }
    1036           0 : }
    1037             : 
    1038             : /*
    1039             :  * Recycle an unused vnode to the front of the free list.
    1040             :  */
    1041             : int
    1042           0 : vrecycle(struct vnode *vp, struct proc *p)
    1043             : {
    1044           0 :         if (vp->v_usecount == 0) {
    1045           0 :                 vgonel(vp, p);
    1046           0 :                 return (1);
    1047             :         }
    1048           0 :         return (0);
    1049           0 : }
    1050             : 
    1051             : /*
    1052             :  * Eliminate all activity associated with a vnode
    1053             :  * in preparation for reuse.
    1054             :  */
    1055             : void
    1056           0 : vgone(struct vnode *vp)
    1057             : {
    1058           0 :         struct proc *p = curproc;
    1059           0 :         vgonel(vp, p);
    1060           0 : }
    1061             : 
    1062             : /*
    1063             :  * vgone, with struct proc.
    1064             :  */
    1065             : void
    1066           0 : vgonel(struct vnode *vp, struct proc *p)
    1067             : {
    1068             :         struct vnode *vq;
    1069             :         struct vnode *vx;
    1070             : 
    1071           0 :         KASSERT(vp->v_uvcount == 0);
    1072             : 
    1073             :         /*
    1074             :          * If a vgone (or vclean) is already in progress,
    1075             :          * wait until it is done and return.
    1076             :          */
    1077           0 :         if (vp->v_flag & VXLOCK) {
    1078           0 :                 vp->v_flag |= VXWANT;
    1079           0 :                 tsleep(vp, PINOD, "vgone", 0);
    1080           0 :                 return;
    1081             :         }
    1082             : 
    1083             :         /*
    1084             :          * Clean out the filesystem specific data.
    1085             :          */
    1086           0 :         vclean(vp, DOCLOSE, p);
    1087             :         /*
    1088             :          * Delete from old mount point vnode list, if on one.
    1089             :          */
    1090           0 :         if (vp->v_mount != NULL)
    1091           0 :                 insmntque(vp, NULL);
    1092             :         /*
    1093             :          * If special device, remove it from special device alias list
    1094             :          * if it is on one.
    1095             :          */
    1096           0 :         if ((vp->v_type == VBLK || vp->v_type == VCHR) && vp->v_specinfo != 0) {
    1097           0 :                 if ((vp->v_flag & VALIASED) == 0 && vp->v_type == VCHR &&
    1098           0 :                     (cdevsw[major(vp->v_rdev)].d_flags & D_CLONE) &&
    1099           0 :                     (minor(vp->v_rdev) >> CLONE_SHIFT == 0)) {
    1100           0 :                         free(vp->v_specbitmap, M_VNODE, CLONE_MAPSZ);
    1101           0 :                 }
    1102           0 :                 if (*vp->v_hashchain == vp) {
    1103           0 :                         *vp->v_hashchain = vp->v_specnext;
    1104           0 :                 } else {
    1105           0 :                         for (vq = *vp->v_hashchain; vq; vq = vq->v_specnext) {
    1106           0 :                                 if (vq->v_specnext != vp)
    1107             :                                         continue;
    1108           0 :                                 vq->v_specnext = vp->v_specnext;
    1109           0 :                                 break;
    1110             :                         }
    1111           0 :                         if (vq == NULL)
    1112           0 :                                 panic("missing bdev");
    1113             :                 }
    1114           0 :                 if (vp->v_flag & VALIASED) {
    1115             :                         vx = NULL;
    1116           0 :                         for (vq = *vp->v_hashchain; vq; vq = vq->v_specnext) {
    1117           0 :                                 if (vq->v_rdev != vp->v_rdev ||
    1118           0 :                                     vq->v_type != vp->v_type)
    1119             :                                         continue;
    1120           0 :                                 if (vx)
    1121             :                                         break;
    1122             :                                 vx = vq;
    1123           0 :                         }
    1124           0 :                         if (vx == NULL)
    1125           0 :                                 panic("missing alias");
    1126           0 :                         if (vq == NULL)
    1127           0 :                                 vx->v_flag &= ~VALIASED;
    1128           0 :                         vp->v_flag &= ~VALIASED;
    1129           0 :                 }
    1130           0 :                 free(vp->v_specinfo, M_VNODE, sizeof(struct specinfo));
    1131           0 :                 vp->v_specinfo = NULL;
    1132           0 :         }
    1133             :         /*
    1134             :          * If it is on the freelist and not already at the head,
    1135             :          * move it to the head of the list.
    1136             :          */
    1137           0 :         vp->v_type = VBAD;
    1138             : 
    1139             :         /*
    1140             :          * Move onto the free list, unless we were called from
    1141             :          * getnewvnode and we're not on any free list
    1142             :          */
    1143           0 :         if (vp->v_usecount == 0 &&
    1144           0 :             (vp->v_bioflag & VBIOONFREELIST)) {
    1145             :                 int s;
    1146             : 
    1147           0 :                 s = splbio();
    1148             : 
    1149           0 :                 if (vp->v_holdcnt > 0)
    1150           0 :                         panic("vgonel: not clean");
    1151             : 
    1152           0 :                 if (TAILQ_FIRST(&vnode_free_list) != vp) {
    1153           0 :                         TAILQ_REMOVE(&vnode_free_list, vp, v_freelist);
    1154           0 :                         TAILQ_INSERT_HEAD(&vnode_free_list, vp, v_freelist);
    1155           0 :                 }
    1156           0 :                 splx(s);
    1157           0 :         }
    1158           0 : }
    1159             : 
    1160             : /*
    1161             :  * Lookup a vnode by device number.
    1162             :  */
    1163             : int
    1164           0 : vfinddev(dev_t dev, enum vtype type, struct vnode **vpp)
    1165             : {
    1166             :         struct vnode *vp;
    1167             :         int rc =0;
    1168             : 
    1169           0 :         for (vp = speclisth[SPECHASH(dev)]; vp; vp = vp->v_specnext) {
    1170           0 :                 if (dev != vp->v_rdev || type != vp->v_type)
    1171             :                         continue;
    1172           0 :                 *vpp = vp;
    1173             :                 rc = 1;
    1174           0 :                 break;
    1175             :         }
    1176           0 :         return (rc);
    1177             : }
    1178             : 
    1179             : /*
    1180             :  * Revoke all the vnodes corresponding to the specified minor number
    1181             :  * range (endpoints inclusive) of the specified major.
    1182             :  */
    1183             : void
    1184           0 : vdevgone(int maj, int minl, int minh, enum vtype type)
    1185             : {
    1186           0 :         struct vnode *vp;
    1187             :         int mn;
    1188             : 
    1189           0 :         for (mn = minl; mn <= minh; mn++)
    1190           0 :                 if (vfinddev(makedev(maj, mn), type, &vp))
    1191           0 :                         VOP_REVOKE(vp, REVOKEALL);
    1192           0 : }
    1193             : 
    1194             : /*
    1195             :  * Calculate the total number of references to a special device.
    1196             :  */
    1197             : int
    1198           0 : vcount(struct vnode *vp)
    1199             : {
    1200             :         struct vnode *vq, *vnext;
    1201           0 :         int count;
    1202             : 
    1203             : loop:
    1204           0 :         if ((vp->v_flag & VALIASED) == 0)
    1205           0 :                 return (vp->v_usecount);
    1206           0 :         for (count = 0, vq = *vp->v_hashchain; vq; vq = vnext) {
    1207           0 :                 vnext = vq->v_specnext;
    1208           0 :                 if (vq->v_rdev != vp->v_rdev || vq->v_type != vp->v_type)
    1209             :                         continue;
    1210             :                 /*
    1211             :                  * Alias, but not in use, so flush it out.
    1212             :                  */
    1213           0 :                 if (vq->v_usecount == 0 && vq != vp) {
    1214           0 :                         vgone(vq);
    1215           0 :                         goto loop;
    1216             :                 }
    1217           0 :                 count += vq->v_usecount;
    1218           0 :         }
    1219           0 :         return (count);
    1220           0 : }
    1221             : 
    1222             : #if defined(DEBUG) || defined(DIAGNOSTIC)
    1223             : /*
    1224             :  * Print out a description of a vnode.
    1225             :  */
    1226             : static char *typename[] =
    1227             :    { "VNON", "VREG", "VDIR", "VBLK", "VCHR", "VLNK", "VSOCK", "VFIFO", "VBAD" };
    1228             : 
    1229             : void
    1230           0 : vprint(char *label, struct vnode *vp)
    1231             : {
    1232           0 :         char buf[64];
    1233             : 
    1234           0 :         if (label != NULL)
    1235           0 :                 printf("%s: ", label);
    1236           0 :         printf("%p, type %s, use %u, write %u, hold %u,",
    1237           0 :                 vp, typename[vp->v_type], vp->v_usecount, vp->v_writecount,
    1238           0 :                 vp->v_holdcnt);
    1239           0 :         buf[0] = '\0';
    1240           0 :         if (vp->v_flag & VROOT)
    1241           0 :                 strlcat(buf, "|VROOT", sizeof buf);
    1242           0 :         if (vp->v_flag & VTEXT)
    1243           0 :                 strlcat(buf, "|VTEXT", sizeof buf);
    1244           0 :         if (vp->v_flag & VSYSTEM)
    1245           0 :                 strlcat(buf, "|VSYSTEM", sizeof buf);
    1246           0 :         if (vp->v_flag & VXLOCK)
    1247           0 :                 strlcat(buf, "|VXLOCK", sizeof buf);
    1248           0 :         if (vp->v_flag & VXWANT)
    1249           0 :                 strlcat(buf, "|VXWANT", sizeof buf);
    1250           0 :         if (vp->v_bioflag & VBIOWAIT)
    1251           0 :                 strlcat(buf, "|VBIOWAIT", sizeof buf);
    1252           0 :         if (vp->v_bioflag & VBIOONFREELIST)
    1253           0 :                 strlcat(buf, "|VBIOONFREELIST", sizeof buf);
    1254           0 :         if (vp->v_bioflag & VBIOONSYNCLIST)
    1255           0 :                 strlcat(buf, "|VBIOONSYNCLIST", sizeof buf);
    1256           0 :         if (vp->v_flag & VALIASED)
    1257           0 :                 strlcat(buf, "|VALIASED", sizeof buf);
    1258           0 :         if (buf[0] != '\0')
    1259           0 :                 printf(" flags (%s)", &buf[1]);
    1260           0 :         if (vp->v_data == NULL) {
    1261           0 :                 printf("\n");
    1262           0 :         } else {
    1263           0 :                 printf("\n\t");
    1264           0 :                 VOP_PRINT(vp);
    1265             :         }
    1266           0 : }
    1267             : #endif /* DEBUG || DIAGNOSTIC */
    1268             : 
    1269             : #ifdef DEBUG
    1270             : /*
    1271             :  * List all of the locked vnodes in the system.
    1272             :  * Called when debugging the kernel.
    1273             :  */
    1274             : void
    1275             : printlockedvnodes(void)
    1276             : {
    1277             :         struct mount *mp;
    1278             :         struct vnode *vp;
    1279             : 
    1280             :         printf("Locked vnodes\n");
    1281             : 
    1282             :         TAILQ_FOREACH(mp, &mountlist, mnt_list) {
    1283             :                 if (vfs_busy(mp, VB_READ|VB_NOWAIT))
    1284             :                         continue;
    1285             :                 LIST_FOREACH(vp, &mp->mnt_vnodelist, v_mntvnodes) {
    1286             :                         if (VOP_ISLOCKED(vp))
    1287             :                                 vprint(NULL, vp);
    1288             :                 }
    1289             :                 vfs_unbusy(mp);
    1290             :         }
    1291             : 
    1292             : }
    1293             : #endif
    1294             : 
    1295             : /*
    1296             :  * Top level filesystem related information gathering.
    1297             :  */
    1298             : int
    1299           0 : vfs_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp,
    1300             :     size_t newlen, struct proc *p)
    1301             : {
    1302             :         struct vfsconf *vfsp, *tmpvfsp;
    1303             :         int ret;
    1304             : 
    1305             :         /* all sysctl names at this level are at least name and field */
    1306           0 :         if (namelen < 2)
    1307           0 :                 return (ENOTDIR);               /* overloaded */
    1308             : 
    1309           0 :         if (name[0] != VFS_GENERIC) {
    1310           0 :                 for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next)
    1311           0 :                         if (vfsp->vfc_typenum == name[0])
    1312             :                                 break;
    1313             : 
    1314           0 :                 if (vfsp == NULL || vfsp->vfc_vfsops->vfs_sysctl == NULL)
    1315           0 :                         return (EOPNOTSUPP);
    1316             : 
    1317           0 :                 return ((*vfsp->vfc_vfsops->vfs_sysctl)(&name[1], namelen - 1,
    1318             :                     oldp, oldlenp, newp, newlen, p));
    1319             :         }
    1320             : 
    1321           0 :         switch (name[1]) {
    1322             :         case VFS_MAXTYPENUM:
    1323           0 :                 return (sysctl_rdint(oldp, oldlenp, newp, maxvfsconf));
    1324             : 
    1325             :         case VFS_CONF:
    1326           0 :                 if (namelen < 3)
    1327           0 :                         return (ENOTDIR);       /* overloaded */
    1328             : 
    1329           0 :                 for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next)
    1330           0 :                         if (vfsp->vfc_typenum == name[2])
    1331             :                                 break;
    1332             : 
    1333           0 :                 if (vfsp == NULL)
    1334           0 :                         return (EOPNOTSUPP);
    1335             : 
    1336             :                 /* Make a copy, clear out kernel pointers */
    1337           0 :                 tmpvfsp = malloc(sizeof(*tmpvfsp), M_TEMP, M_WAITOK|M_ZERO);
    1338           0 :                 memcpy(tmpvfsp, vfsp, sizeof(*tmpvfsp));
    1339           0 :                 tmpvfsp->vfc_vfsops = NULL;
    1340           0 :                 tmpvfsp->vfc_next = NULL;
    1341             : 
    1342           0 :                 ret = sysctl_rdstruct(oldp, oldlenp, newp, tmpvfsp,
    1343             :                     sizeof(struct vfsconf));
    1344             : 
    1345           0 :                 free(tmpvfsp, M_TEMP, sizeof(*tmpvfsp));
    1346           0 :                 return (ret);
    1347             :         case VFS_BCACHESTAT:    /* buffer cache statistics */
    1348           0 :                 ret = sysctl_rdstruct(oldp, oldlenp, newp, &bcstats,
    1349             :                     sizeof(struct bcachestats));
    1350           0 :                 return(ret);
    1351             :         }
    1352           0 :         return (EOPNOTSUPP);
    1353           0 : }
    1354             : 
    1355             : /*
    1356             :  * Check to see if a filesystem is mounted on a block device.
    1357             :  */
    1358             : int
    1359           0 : vfs_mountedon(struct vnode *vp)
    1360             : {
    1361             :         struct vnode *vq;
    1362             :         int error = 0;
    1363             : 
    1364           0 :         if (vp->v_specmountpoint != NULL)
    1365           0 :                 return (EBUSY);
    1366           0 :         if (vp->v_flag & VALIASED) {
    1367           0 :                 for (vq = *vp->v_hashchain; vq; vq = vq->v_specnext) {
    1368           0 :                         if (vq->v_rdev != vp->v_rdev ||
    1369           0 :                             vq->v_type != vp->v_type)
    1370             :                                 continue;
    1371           0 :                         if (vq->v_specmountpoint != NULL) {
    1372             :                                 error = EBUSY;
    1373           0 :                                 break;
    1374             :                         }
    1375             :                 }
    1376             :         }
    1377           0 :         return (error);
    1378           0 : }
    1379             : 
    1380             : #ifdef NFSSERVER
    1381             : /*
    1382             :  * Build hash lists of net addresses and hang them off the mount point.
    1383             :  * Called by vfs_export() to set up the lists of export addresses.
    1384             :  */
    1385             : int
    1386           0 : vfs_hang_addrlist(struct mount *mp, struct netexport *nep,
    1387             :     struct export_args *argp)
    1388             : {
    1389             :         struct netcred *np;
    1390             :         struct radix_node_head *rnh;
    1391             :         int nplen, i;
    1392             :         struct radix_node *rn;
    1393             :         struct sockaddr *saddr, *smask = 0;
    1394             :         int error;
    1395             : 
    1396           0 :         if (argp->ex_addrlen == 0) {
    1397           0 :                 if (mp->mnt_flag & MNT_DEFEXPORTED)
    1398           0 :                         return (EPERM);
    1399           0 :                 np = &nep->ne_defexported;
    1400             :                 /* fill in the kernel's ucred from userspace's xucred */
    1401           0 :                 if ((error = crfromxucred(&np->netc_anon, &argp->ex_anon)))
    1402           0 :                         return (error);
    1403           0 :                 mp->mnt_flag |= MNT_DEFEXPORTED;
    1404           0 :                 goto finish;
    1405             :         }
    1406           0 :         if (argp->ex_addrlen > MLEN || argp->ex_masklen > MLEN ||
    1407           0 :             argp->ex_addrlen < 0 || argp->ex_masklen < 0)
    1408           0 :                 return (EINVAL);
    1409           0 :         nplen = sizeof(struct netcred) + argp->ex_addrlen + argp->ex_masklen;
    1410           0 :         np = (struct netcred *)malloc(nplen, M_NETADDR, M_WAITOK|M_ZERO);
    1411           0 :         saddr = (struct sockaddr *)(np + 1);
    1412           0 :         error = copyin(argp->ex_addr, saddr, argp->ex_addrlen);
    1413           0 :         if (error)
    1414             :                 goto out;
    1415           0 :         if (saddr->sa_len > argp->ex_addrlen)
    1416           0 :                 saddr->sa_len = argp->ex_addrlen;
    1417           0 :         if (argp->ex_masklen) {
    1418           0 :                 smask = (struct sockaddr *)((caddr_t)saddr + argp->ex_addrlen);
    1419           0 :                 error = copyin(argp->ex_mask, smask, argp->ex_masklen);
    1420           0 :                 if (error)
    1421             :                         goto out;
    1422           0 :                 if (smask->sa_len > argp->ex_masklen)
    1423           0 :                         smask->sa_len = argp->ex_masklen;
    1424             :         }
    1425             :         /* fill in the kernel's ucred from userspace's xucred */
    1426           0 :         if ((error = crfromxucred(&np->netc_anon, &argp->ex_anon)))
    1427             :                 goto out;
    1428           0 :         i = saddr->sa_family;
    1429           0 :         switch (i) {
    1430             :         case AF_INET:
    1431           0 :                 if ((rnh = nep->ne_rtable_inet) == NULL) {
    1432           0 :                         if (!rn_inithead((void **)&nep->ne_rtable_inet,
    1433             :                             offsetof(struct sockaddr_in, sin_addr))) {
    1434             :                                 error = ENOBUFS;
    1435           0 :                                 goto out;
    1436             :                         }
    1437           0 :                         rnh = nep->ne_rtable_inet;
    1438           0 :                 }
    1439             :                 break;
    1440             :         default:
    1441             :                 error = EINVAL;
    1442           0 :                 goto out;
    1443             :         }
    1444           0 :         rn = rn_addroute(saddr, smask, rnh, np->netc_rnodes, 0);
    1445           0 :         if (rn == 0 || np != (struct netcred *)rn) { /* already exists */
    1446             :                 error = EPERM;
    1447           0 :                 goto out;
    1448             :         }
    1449             : finish:
    1450           0 :         np->netc_exflags = argp->ex_flags;
    1451           0 :         return (0);
    1452             : out:
    1453           0 :         free(np, M_NETADDR, nplen);
    1454           0 :         return (error);
    1455           0 : }
    1456             : 
    1457             : int
    1458           0 : vfs_free_netcred(struct radix_node *rn, void *w, u_int id)
    1459             : {
    1460           0 :         struct radix_node_head *rnh = (struct radix_node_head *)w;
    1461             : 
    1462           0 :         rn_delete(rn->rn_key, rn->rn_mask, rnh, NULL);
    1463           0 :         free(rn, M_NETADDR, 0);
    1464           0 :         return (0);
    1465             : }
    1466             : 
    1467             : /*
    1468             :  * Free the net address hash lists that are hanging off the mount points.
    1469             :  */
    1470             : void
    1471           0 : vfs_free_addrlist(struct netexport *nep)
    1472             : {
    1473             :         struct radix_node_head *rnh;
    1474             : 
    1475           0 :         if ((rnh = nep->ne_rtable_inet) != NULL) {
    1476           0 :                 rn_walktree(rnh, vfs_free_netcred, rnh);
    1477           0 :                 free(rnh, M_RTABLE, 0);
    1478           0 :                 nep->ne_rtable_inet = NULL;
    1479           0 :         }
    1480           0 : }
    1481             : #endif /* NFSSERVER */
    1482             : 
    1483             : int
    1484           0 : vfs_export(struct mount *mp, struct netexport *nep, struct export_args *argp)
    1485             : {
    1486             : #ifdef NFSSERVER
    1487             :         int error;
    1488             : 
    1489           0 :         if (argp->ex_flags & MNT_DELEXPORT) {
    1490           0 :                 vfs_free_addrlist(nep);
    1491           0 :                 mp->mnt_flag &= ~(MNT_EXPORTED | MNT_DEFEXPORTED);
    1492           0 :         }
    1493           0 :         if (argp->ex_flags & MNT_EXPORTED) {
    1494           0 :                 if ((error = vfs_hang_addrlist(mp, nep, argp)) != 0)
    1495           0 :                         return (error);
    1496           0 :                 mp->mnt_flag |= MNT_EXPORTED;
    1497           0 :         }
    1498           0 :         return (0);
    1499             : #else
    1500             :         return (ENOTSUP);
    1501             : #endif /* NFSSERVER */
    1502           0 : }
    1503             : 
    1504             : struct netcred *
    1505           0 : vfs_export_lookup(struct mount *mp, struct netexport *nep, struct mbuf *nam)
    1506             : {
    1507             : #ifdef NFSSERVER
    1508             :         struct netcred *np;
    1509             :         struct radix_node_head *rnh;
    1510             :         struct sockaddr *saddr;
    1511             : 
    1512             :         np = NULL;
    1513           0 :         if (mp->mnt_flag & MNT_EXPORTED) {
    1514             :                 /*
    1515             :                  * Lookup in the export list first.
    1516             :                  */
    1517           0 :                 if (nam != NULL) {
    1518           0 :                         saddr = mtod(nam, struct sockaddr *);
    1519           0 :                         switch(saddr->sa_family) {
    1520             :                         case AF_INET:
    1521           0 :                                 rnh = nep->ne_rtable_inet;
    1522           0 :                                 break;
    1523             :                         default:
    1524             :                                 rnh = NULL;
    1525           0 :                                 break;
    1526             :                         }
    1527           0 :                         if (rnh != NULL)
    1528           0 :                                 np = (struct netcred *)rn_match(saddr, rnh);
    1529             :                 }
    1530             :                 /*
    1531             :                  * If no address match, use the default if it exists.
    1532             :                  */
    1533           0 :                 if (np == NULL && mp->mnt_flag & MNT_DEFEXPORTED)
    1534           0 :                         np = &nep->ne_defexported;
    1535             :         }
    1536           0 :         return (np);
    1537             : #else
    1538             :         return (NULL);
    1539             : #endif /* NFSSERVER */
    1540             : }
    1541             : 
    1542             : /*
    1543             :  * Do the usual access checking.
    1544             :  * file_mode, uid and gid are from the vnode in question,
    1545             :  * while acc_mode and cred are from the VOP_ACCESS parameter list
    1546             :  */
    1547             : int
    1548           0 : vaccess(enum vtype type, mode_t file_mode, uid_t uid, gid_t gid,
    1549             :     mode_t acc_mode, struct ucred *cred)
    1550             : {
    1551             :         mode_t mask;
    1552             : 
    1553             :         /* User id 0 always gets read/write access. */
    1554           0 :         if (cred->cr_uid == 0) {
    1555             :                 /* For VEXEC, at least one of the execute bits must be set. */
    1556           0 :                 if ((acc_mode & VEXEC) && type != VDIR &&
    1557           0 :                     (file_mode & (S_IXUSR|S_IXGRP|S_IXOTH)) == 0)
    1558           0 :                         return EACCES;
    1559           0 :                 return 0;
    1560             :         }
    1561             : 
    1562             :         mask = 0;
    1563             : 
    1564             :         /* Otherwise, check the owner. */
    1565           0 :         if (cred->cr_uid == uid) {
    1566           0 :                 if (acc_mode & VEXEC)
    1567           0 :                         mask |= S_IXUSR;
    1568           0 :                 if (acc_mode & VREAD)
    1569           0 :                         mask |= S_IRUSR;
    1570           0 :                 if (acc_mode & VWRITE)
    1571           0 :                         mask |= S_IWUSR;
    1572           0 :                 return (file_mode & mask) == mask ? 0 : EACCES;
    1573             :         }
    1574             : 
    1575             :         /* Otherwise, check the groups. */
    1576           0 :         if (groupmember(gid, cred)) {
    1577           0 :                 if (acc_mode & VEXEC)
    1578           0 :                         mask |= S_IXGRP;
    1579           0 :                 if (acc_mode & VREAD)
    1580           0 :                         mask |= S_IRGRP;
    1581           0 :                 if (acc_mode & VWRITE)
    1582           0 :                         mask |= S_IWGRP;
    1583           0 :                 return (file_mode & mask) == mask ? 0 : EACCES;
    1584             :         }
    1585             : 
    1586             :         /* Otherwise, check everyone else. */
    1587           0 :         if (acc_mode & VEXEC)
    1588           0 :                 mask |= S_IXOTH;
    1589           0 :         if (acc_mode & VREAD)
    1590           0 :                 mask |= S_IROTH;
    1591           0 :         if (acc_mode & VWRITE)
    1592           0 :                 mask |= S_IWOTH;
    1593           0 :         return (file_mode & mask) == mask ? 0 : EACCES;
    1594           0 : }
    1595             : 
    1596             : struct rwlock vfs_stall_lock = RWLOCK_INITIALIZER("vfs_stall");
    1597             : 
    1598             : int
    1599           0 : vfs_stall(struct proc *p, int stall)
    1600             : {
    1601             :         struct mount *mp;
    1602             :         int allerror = 0, error;
    1603             : 
    1604           0 :         if (stall)
    1605           0 :                 rw_enter_write(&vfs_stall_lock);
    1606             : 
    1607             :         /*
    1608             :          * The loop variable mp is protected by vfs_busy() so that it cannot
    1609             :          * be unmounted while VFS_SYNC() sleeps.  Traverse forward to keep the
    1610             :          * lock order consistent with dounmount().
    1611             :          */
    1612           0 :         TAILQ_FOREACH(mp, &mountlist, mnt_list) {
    1613           0 :                 if (stall) {
    1614           0 :                         error = vfs_busy(mp, VB_WRITE|VB_WAIT|VB_DUPOK);
    1615           0 :                         if (error) {
    1616           0 :                                 printf("%s: busy\n", mp->mnt_stat.f_mntonname);
    1617             :                                 allerror = error;
    1618           0 :                                 continue;
    1619             :                         }
    1620           0 :                         uvm_vnp_sync(mp);
    1621           0 :                         error = VFS_SYNC(mp, MNT_WAIT, stall, p->p_ucred, p);
    1622           0 :                         if (error) {
    1623           0 :                                 printf("%s: failed to sync\n", mp->mnt_stat.f_mntonname);
    1624           0 :                                 vfs_unbusy(mp);
    1625             :                                 allerror = error;
    1626           0 :                                 continue;
    1627             :                         }
    1628           0 :                         mp->mnt_flag |= MNT_STALLED;
    1629           0 :                 } else {
    1630           0 :                         if (mp->mnt_flag & MNT_STALLED) {
    1631           0 :                                 vfs_unbusy(mp);
    1632           0 :                                 mp->mnt_flag &= ~MNT_STALLED;
    1633           0 :                         }
    1634             :                 }
    1635             :         }
    1636             : 
    1637           0 :         if (!stall)
    1638           0 :                 rw_exit_write(&vfs_stall_lock);
    1639             : 
    1640           0 :         return (allerror);
    1641             : }
    1642             : 
    1643             : void
    1644           0 : vfs_stall_barrier(void)
    1645             : {
    1646           0 :         rw_enter_read(&vfs_stall_lock);
    1647           0 :         rw_exit_read(&vfs_stall_lock);
    1648           0 : }
    1649             : 
    1650             : /*
    1651             :  * Unmount all file systems.
    1652             :  * We traverse the list in reverse order under the assumption that doing so
    1653             :  * will avoid needing to worry about dependencies.
    1654             :  */
    1655             : void
    1656           0 : vfs_unmountall(void)
    1657             : {
    1658             :         struct mount *mp, *nmp;
    1659           0 :         int allerror, error, again = 1;
    1660             : 
    1661             :  retry:
    1662             :         allerror = 0;
    1663           0 :         TAILQ_FOREACH_REVERSE_SAFE(mp, &mountlist, mntlist, mnt_list, nmp) {
    1664           0 :                 if (vfs_busy(mp, VB_WRITE|VB_NOWAIT))
    1665             :                         continue;
    1666             :                 /* XXX Here is a race, the next pointer is not locked. */
    1667           0 :                 if ((error = dounmount(mp, MNT_FORCE, curproc)) != 0) {
    1668           0 :                         printf("unmount of %s failed with error %d\n",
    1669           0 :                             mp->mnt_stat.f_mntonname, error);
    1670             :                         allerror = 1;
    1671           0 :                 }
    1672             :         }
    1673             : 
    1674           0 :         if (allerror) {
    1675           0 :                 printf("WARNING: some file systems would not unmount\n");
    1676           0 :                 if (again) {
    1677           0 :                         printf("retrying\n");
    1678             :                         again = 0;
    1679           0 :                         goto retry;
    1680             :                 }
    1681             :         }
    1682           0 : }
    1683             : 
    1684             : /*
    1685             :  * Sync and unmount file systems before shutting down.
    1686             :  */
    1687             : void
    1688           0 : vfs_shutdown(struct proc *p)
    1689             : {
    1690             : #ifdef ACCOUNTING
    1691           0 :         acct_shutdown();
    1692             : #endif
    1693             : 
    1694           0 :         printf("syncing disks... ");
    1695             : 
    1696           0 :         if (panicstr == 0) {
    1697             :                 /* Sync before unmount, in case we hang on something. */
    1698           0 :                 sys_sync(p, NULL, NULL);
    1699           0 :                 vfs_unmountall();
    1700           0 :         }
    1701             : 
    1702             : #if NSOFTRAID > 0
    1703           0 :         sr_quiesce();
    1704             : #endif
    1705             : 
    1706           0 :         if (vfs_syncwait(p, 1))
    1707           0 :                 printf("giving up\n");
    1708             :         else
    1709           0 :                 printf("done\n");
    1710           0 : }
    1711             : 
    1712             : /*
    1713             :  * perform sync() operation and wait for buffers to flush.
    1714             :  */
    1715             : int
    1716           0 : vfs_syncwait(struct proc *p, int verbose)
    1717             : {
    1718             :         struct buf *bp;
    1719             :         int iter, nbusy, dcount, s;
    1720             : #ifdef MULTIPROCESSOR
    1721             :         int hold_count;
    1722             : #endif
    1723             : 
    1724           0 :         sys_sync(p, NULL, NULL);
    1725             : 
    1726             :         /* Wait for sync to finish. */
    1727             :         dcount = 10000;
    1728           0 :         for (iter = 0; iter < 20; iter++) {
    1729             :                 nbusy = 0;
    1730           0 :                 LIST_FOREACH(bp, &bufhead, b_list) {
    1731           0 :                         if ((bp->b_flags & (B_BUSY|B_INVAL|B_READ)) == B_BUSY)
    1732           0 :                                 nbusy++;
    1733             :                         /*
    1734             :                          * With soft updates, some buffers that are
    1735             :                          * written will be remarked as dirty until other
    1736             :                          * buffers are written.
    1737             :                          */
    1738           0 :                         if (bp->b_flags & B_DELWRI) {
    1739           0 :                                 s = splbio();
    1740           0 :                                 bremfree(bp);
    1741           0 :                                 buf_acquire(bp);
    1742           0 :                                 splx(s);
    1743           0 :                                 nbusy++;
    1744           0 :                                 bawrite(bp);
    1745           0 :                                 if (dcount-- <= 0) {
    1746           0 :                                         if (verbose)
    1747           0 :                                                 printf("softdep ");
    1748           0 :                                         return 1;
    1749             :                                 }
    1750             :                         }
    1751             :                 }
    1752           0 :                 if (nbusy == 0)
    1753             :                         break;
    1754           0 :                 if (verbose)
    1755           0 :                         printf("%d ", nbusy);
    1756             : #ifdef MULTIPROCESSOR
    1757           0 :                 if (_kernel_lock_held())
    1758           0 :                         hold_count = __mp_release_all(&kernel_lock);
    1759             :                 else
    1760             :                         hold_count = 0;
    1761             : #endif
    1762           0 :                 DELAY(40000 * iter);
    1763             : #ifdef MULTIPROCESSOR
    1764           0 :                 if (hold_count)
    1765           0 :                         __mp_acquire_count(&kernel_lock, hold_count);
    1766             : #endif
    1767             :         }
    1768             : 
    1769           0 :         return nbusy;
    1770           0 : }
    1771             : 
    1772             : /*
    1773             :  * posix file system related system variables.
    1774             :  */
    1775             : int
    1776           0 : fs_posix_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp,
    1777             :     void *newp, size_t newlen, struct proc *p)
    1778             : {
    1779             :         /* all sysctl names at this level are terminal */
    1780           0 :         if (namelen != 1)
    1781           0 :                 return (ENOTDIR);
    1782             : 
    1783           0 :         switch (name[0]) {
    1784             :         case FS_POSIX_SETUID:
    1785           0 :                 if (newp && securelevel > 0)
    1786           0 :                         return (EPERM);
    1787           0 :                 return(sysctl_int(oldp, oldlenp, newp, newlen, &suid_clear));
    1788             :         default:
    1789           0 :                 return (EOPNOTSUPP);
    1790             :         }
    1791             :         /* NOTREACHED */
    1792           0 : }
    1793             : 
    1794             : /*
    1795             :  * file system related system variables.
    1796             :  */
    1797             : int
    1798           0 : fs_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp,
    1799             :     size_t newlen, struct proc *p)
    1800             : {
    1801             :         sysctlfn *fn;
    1802             : 
    1803           0 :         switch (name[0]) {
    1804             :         case FS_POSIX:
    1805             :                 fn = fs_posix_sysctl;
    1806             :                 break;
    1807             :         default:
    1808           0 :                 return (EOPNOTSUPP);
    1809             :         }
    1810           0 :         return (*fn)(name + 1, namelen - 1, oldp, oldlenp, newp, newlen, p);
    1811           0 : }
    1812             : 
    1813             : 
    1814             : /*
    1815             :  * Routines dealing with vnodes and buffers
    1816             :  */
    1817             : 
    1818             : /*
    1819             :  * Wait for all outstanding I/Os to complete
    1820             :  *
    1821             :  * Manipulates v_numoutput. Must be called at splbio()
    1822             :  */
    1823             : int
    1824           0 : vwaitforio(struct vnode *vp, int slpflag, char *wmesg, int timeo)
    1825             : {
    1826             :         int error = 0;
    1827             : 
    1828           0 :         splassert(IPL_BIO);
    1829             : 
    1830           0 :         while (vp->v_numoutput) {
    1831           0 :                 vp->v_bioflag |= VBIOWAIT;
    1832           0 :                 error = tsleep(&vp->v_numoutput,
    1833           0 :                     slpflag | (PRIBIO + 1), wmesg, timeo);
    1834           0 :                 if (error)
    1835             :                         break;
    1836             :         }
    1837             : 
    1838           0 :         return (error);
    1839             : }
    1840             : 
    1841             : /*
    1842             :  * Update outstanding I/O count and do wakeup if requested.
    1843             :  *
    1844             :  * Manipulates v_numoutput. Must be called at splbio()
    1845             :  */
    1846             : void
    1847           0 : vwakeup(struct vnode *vp)
    1848             : {
    1849           0 :         splassert(IPL_BIO);
    1850             : 
    1851           0 :         if (vp != NULL) {
    1852           0 :                 if (vp->v_numoutput-- == 0)
    1853           0 :                         panic("vwakeup: neg numoutput");
    1854           0 :                 if ((vp->v_bioflag & VBIOWAIT) && vp->v_numoutput == 0) {
    1855           0 :                         vp->v_bioflag &= ~VBIOWAIT;
    1856           0 :                         wakeup(&vp->v_numoutput);
    1857           0 :                 }
    1858             :         }
    1859           0 : }
    1860             : 
    1861             : /*
    1862             :  * Flush out and invalidate all buffers associated with a vnode.
    1863             :  * Called with the underlying object locked.
    1864             :  */
    1865             : int
    1866           0 : vinvalbuf(struct vnode *vp, int flags, struct ucred *cred, struct proc *p,
    1867             :     int slpflag, int slptimeo)
    1868             : {
    1869             :         struct buf *bp;
    1870             :         struct buf *nbp, *blist;
    1871             :         int s, error;
    1872             : 
    1873             : #ifdef VFSLCKDEBUG
    1874             :         if ((vp->v_flag & VLOCKSWORK) && !VOP_ISLOCKED(vp))
    1875             :                 panic("%s: vp isn't locked, vp %p", __func__, vp);
    1876             : #endif
    1877             : 
    1878           0 :         if (flags & V_SAVE) {
    1879           0 :                 s = splbio();
    1880           0 :                 vwaitforio(vp, 0, "vinvalbuf", 0);
    1881           0 :                 if (!LIST_EMPTY(&vp->v_dirtyblkhd)) {
    1882           0 :                         splx(s);
    1883           0 :                         if ((error = VOP_FSYNC(vp, cred, MNT_WAIT, p)) != 0)
    1884           0 :                                 return (error);
    1885           0 :                         s = splbio();
    1886           0 :                         if (vp->v_numoutput > 0 ||
    1887           0 :                             !LIST_EMPTY(&vp->v_dirtyblkhd))
    1888           0 :                                 panic("%s: dirty bufs, vp %p", __func__, vp);
    1889             :                 }
    1890           0 :                 splx(s);
    1891           0 :         }
    1892             : loop:
    1893           0 :         s = splbio();
    1894           0 :         for (;;) {
    1895           0 :                 if ((blist = LIST_FIRST(&vp->v_cleanblkhd)) &&
    1896           0 :                     (flags & V_SAVEMETA))
    1897           0 :                         while (blist && blist->b_lblkno < 0)
    1898           0 :                                 blist = LIST_NEXT(blist, b_vnbufs);
    1899           0 :                 if (blist == NULL &&
    1900           0 :                     (blist = LIST_FIRST(&vp->v_dirtyblkhd)) &&
    1901           0 :                     (flags & V_SAVEMETA))
    1902           0 :                         while (blist && blist->b_lblkno < 0)
    1903           0 :                                 blist = LIST_NEXT(blist, b_vnbufs);
    1904           0 :                 if (!blist)
    1905             :                         break;
    1906             : 
    1907           0 :                 for (bp = blist; bp; bp = nbp) {
    1908           0 :                         nbp = LIST_NEXT(bp, b_vnbufs);
    1909           0 :                         if (flags & V_SAVEMETA && bp->b_lblkno < 0)
    1910             :                                 continue;
    1911           0 :                         if (bp->b_flags & B_BUSY) {
    1912           0 :                                 bp->b_flags |= B_WANTED;
    1913           0 :                                 error = tsleep(bp, slpflag | (PRIBIO + 1),
    1914             :                                     "vinvalbuf", slptimeo);
    1915           0 :                                 if (error) {
    1916           0 :                                         splx(s);
    1917           0 :                                         return (error);
    1918             :                                 }
    1919             :                                 break;
    1920             :                         }
    1921           0 :                         bremfree(bp);
    1922             :                         /*
    1923             :                          * XXX Since there are no node locks for NFS, I believe
    1924             :                          * there is a slight chance that a delayed write will
    1925             :                          * occur while sleeping just above, so check for it.
    1926             :                          */
    1927           0 :                         if ((bp->b_flags & B_DELWRI) && (flags & V_SAVE)) {
    1928           0 :                                 buf_acquire(bp);
    1929           0 :                                 splx(s);
    1930           0 :                                 (void) VOP_BWRITE(bp);
    1931           0 :                                 goto loop;
    1932             :                         }
    1933           0 :                         buf_acquire_nomap(bp);
    1934           0 :                         bp->b_flags |= B_INVAL;
    1935           0 :                         brelse(bp);
    1936           0 :                 }
    1937             :         }
    1938           0 :         if (!(flags & V_SAVEMETA) &&
    1939           0 :             (!LIST_EMPTY(&vp->v_dirtyblkhd) || !LIST_EMPTY(&vp->v_cleanblkhd)))
    1940           0 :                 panic("%s: flush failed, vp %p", __func__, vp);
    1941           0 :         splx(s);
    1942           0 :         return (0);
    1943           0 : }
    1944             : 
    1945             : void
    1946           0 : vflushbuf(struct vnode *vp, int sync)
    1947             : {
    1948             :         struct buf *bp, *nbp;
    1949           0 :         int s;
    1950             : 
    1951             : loop:
    1952           0 :         s = splbio();
    1953           0 :         LIST_FOREACH_SAFE(bp, &vp->v_dirtyblkhd, b_vnbufs, nbp) {
    1954           0 :                 if ((bp->b_flags & B_BUSY))
    1955             :                         continue;
    1956           0 :                 if ((bp->b_flags & B_DELWRI) == 0)
    1957           0 :                         panic("vflushbuf: not dirty");
    1958           0 :                 bremfree(bp);
    1959           0 :                 buf_acquire(bp);
    1960           0 :                 splx(s);
    1961             :                 /*
    1962             :                  * Wait for I/O associated with indirect blocks to complete,
    1963             :                  * since there is no way to quickly wait for them below.
    1964             :                  */
    1965           0 :                 if (bp->b_vp == vp || sync == 0)
    1966           0 :                         (void) bawrite(bp);
    1967             :                 else
    1968           0 :                         (void) bwrite(bp);
    1969           0 :                 goto loop;
    1970             :         }
    1971           0 :         if (sync == 0) {
    1972           0 :                 splx(s);
    1973           0 :                 return;
    1974             :         }
    1975           0 :         vwaitforio(vp, 0, "vflushbuf", 0);
    1976           0 :         if (!LIST_EMPTY(&vp->v_dirtyblkhd)) {
    1977             :                 splx(s);
    1978             : #ifdef DIAGNOSTIC
    1979           0 :                 vprint("vflushbuf: dirty", vp);
    1980             : #endif
    1981           0 :                 goto loop;
    1982             :         }
    1983             :         splx(s);
    1984           0 : }
    1985             : 
    1986             : /*
    1987             :  * Associate a buffer with a vnode.
    1988             :  *
    1989             :  * Manipulates buffer vnode queues. Must be called at splbio().
    1990             :  */
    1991             : void
    1992           0 : bgetvp(struct vnode *vp, struct buf *bp)
    1993             : {
    1994           0 :         splassert(IPL_BIO);
    1995             : 
    1996             : 
    1997           0 :         if (bp->b_vp)
    1998           0 :                 panic("bgetvp: not free");
    1999           0 :         vhold(vp);
    2000           0 :         bp->b_vp = vp;
    2001           0 :         if (vp->v_type == VBLK || vp->v_type == VCHR)
    2002           0 :                 bp->b_dev = vp->v_rdev;
    2003             :         else
    2004           0 :                 bp->b_dev = NODEV;
    2005             :         /*
    2006             :          * Insert onto list for new vnode.
    2007             :          */
    2008           0 :         bufinsvn(bp, &vp->v_cleanblkhd);
    2009           0 : }
    2010             : 
    2011             : /*
    2012             :  * Disassociate a buffer from a vnode.
    2013             :  *
    2014             :  * Manipulates vnode buffer queues. Must be called at splbio().
    2015             :  */
    2016             : void
    2017           0 : brelvp(struct buf *bp)
    2018             : {
    2019             :         struct vnode *vp;
    2020             : 
    2021           0 :         splassert(IPL_BIO);
    2022             : 
    2023           0 :         if ((vp = bp->b_vp) == (struct vnode *) 0)
    2024           0 :                 panic("brelvp: NULL");
    2025             :         /*
    2026             :          * Delete from old vnode list, if on one.
    2027             :          */
    2028           0 :         if (LIST_NEXT(bp, b_vnbufs) != NOLIST)
    2029           0 :                 bufremvn(bp);
    2030           0 :         if ((vp->v_bioflag & VBIOONSYNCLIST) &&
    2031           0 :             LIST_EMPTY(&vp->v_dirtyblkhd)) {
    2032           0 :                 vp->v_bioflag &= ~VBIOONSYNCLIST;
    2033           0 :                 LIST_REMOVE(vp, v_synclist);
    2034           0 :         }
    2035           0 :         bp->b_vp = NULL;
    2036             : 
    2037           0 :         vdrop(vp);
    2038           0 : }
    2039             : 
    2040             : /*
    2041             :  * Replaces the current vnode associated with the buffer, if any,
    2042             :  * with a new vnode.
    2043             :  *
    2044             :  * If an output I/O is pending on the buffer, the old vnode
    2045             :  * I/O count is adjusted.
    2046             :  *
    2047             :  * Ignores vnode buffer queues. Must be called at splbio().
    2048             :  */
    2049             : void
    2050           0 : buf_replacevnode(struct buf *bp, struct vnode *newvp)
    2051             : {
    2052           0 :         struct vnode *oldvp = bp->b_vp;
    2053             : 
    2054           0 :         splassert(IPL_BIO);
    2055             : 
    2056           0 :         if (oldvp)
    2057           0 :                 brelvp(bp);
    2058             : 
    2059           0 :         if ((bp->b_flags & (B_READ | B_DONE)) == 0) {
    2060           0 :                 newvp->v_numoutput++;        /* put it on swapdev */
    2061           0 :                 vwakeup(oldvp);
    2062           0 :         }
    2063             : 
    2064           0 :         bgetvp(newvp, bp);
    2065           0 :         bufremvn(bp);
    2066           0 : }
    2067             : 
    2068             : /*
    2069             :  * Used to assign buffers to the appropriate clean or dirty list on
    2070             :  * the vnode and to add newly dirty vnodes to the appropriate
    2071             :  * filesystem syncer list.
    2072             :  *
    2073             :  * Manipulates vnode buffer queues. Must be called at splbio().
    2074             :  */
    2075             : void
    2076           0 : reassignbuf(struct buf *bp)
    2077             : {
    2078             :         struct buflists *listheadp;
    2079             :         int delay;
    2080           0 :         struct vnode *vp = bp->b_vp;
    2081             : 
    2082           0 :         splassert(IPL_BIO);
    2083             : 
    2084             :         /*
    2085             :          * Delete from old vnode list, if on one.
    2086             :          */
    2087           0 :         if (LIST_NEXT(bp, b_vnbufs) != NOLIST)
    2088           0 :                 bufremvn(bp);
    2089             : 
    2090             :         /*
    2091             :          * If dirty, put on list of dirty buffers;
    2092             :          * otherwise insert onto list of clean buffers.
    2093             :          */
    2094           0 :         if ((bp->b_flags & B_DELWRI) == 0) {
    2095           0 :                 listheadp = &vp->v_cleanblkhd;
    2096           0 :                 if ((vp->v_bioflag & VBIOONSYNCLIST) &&
    2097           0 :                     LIST_EMPTY(&vp->v_dirtyblkhd)) {
    2098           0 :                         vp->v_bioflag &= ~VBIOONSYNCLIST;
    2099           0 :                         LIST_REMOVE(vp, v_synclist);
    2100           0 :                 }
    2101             :         } else {
    2102           0 :                 listheadp = &vp->v_dirtyblkhd;
    2103           0 :                 if ((vp->v_bioflag & VBIOONSYNCLIST) == 0) {
    2104           0 :                         switch (vp->v_type) {
    2105             :                         case VDIR:
    2106           0 :                                 delay = syncdelay / 2;
    2107           0 :                                 break;
    2108             :                         case VBLK:
    2109           0 :                                 if (vp->v_specmountpoint != NULL) {
    2110           0 :                                         delay = syncdelay / 3;
    2111           0 :                                         break;
    2112             :                                 }
    2113             :                                 /* FALLTHROUGH */
    2114             :                         default:
    2115           0 :                                 delay = syncdelay;
    2116           0 :                         }
    2117           0 :                         vn_syncer_add_to_worklist(vp, delay);
    2118           0 :                 }
    2119             :         }
    2120           0 :         bufinsvn(bp, listheadp);
    2121           0 : }
    2122             : 
    2123             : int
    2124           0 : vfs_register(struct vfsconf *vfs)
    2125             : {
    2126             :         struct vfsconf *vfsp;
    2127             :         struct vfsconf **vfspp;
    2128             : 
    2129             : #ifdef DIAGNOSTIC
    2130             :         /* Paranoia? */
    2131           0 :         if (vfs->vfc_refcount != 0)
    2132           0 :                 printf("vfs_register called with vfc_refcount > 0\n");
    2133             : #endif
    2134             : 
    2135             :         /* Check if filesystem already known */
    2136           0 :         for (vfspp = &vfsconf, vfsp = vfsconf; vfsp;
    2137           0 :             vfspp = &vfsp->vfc_next, vfsp = vfsp->vfc_next)
    2138           0 :                 if (strcmp(vfsp->vfc_name, vfs->vfc_name) == 0)
    2139           0 :                         return (EEXIST);
    2140             : 
    2141           0 :         if (vfs->vfc_typenum > maxvfsconf)
    2142           0 :                 maxvfsconf = vfs->vfc_typenum;
    2143             : 
    2144           0 :         vfs->vfc_next = NULL;
    2145             : 
    2146             :         /* Add to the end of the list */
    2147           0 :         *vfspp = vfs;
    2148             : 
    2149             :         /* Call vfs_init() */
    2150           0 :         if (vfs->vfc_vfsops->vfs_init)
    2151           0 :                 (*(vfs->vfc_vfsops->vfs_init))(vfs);
    2152             : 
    2153           0 :         return 0;
    2154           0 : }
    2155             : 
    2156             : int
    2157           0 : vfs_unregister(struct vfsconf *vfs)
    2158             : {
    2159             :         struct vfsconf *vfsp;
    2160             :         struct vfsconf **vfspp;
    2161             :         int maxtypenum;
    2162             : 
    2163             :         /* Find our vfsconf struct */
    2164           0 :         for (vfspp = &vfsconf, vfsp = vfsconf; vfsp;
    2165           0 :             vfspp = &vfsp->vfc_next, vfsp = vfsp->vfc_next) {
    2166           0 :                 if (strcmp(vfsp->vfc_name, vfs->vfc_name) == 0)
    2167             :                         break;
    2168             :         }
    2169             : 
    2170           0 :         if (!vfsp)                      /* Not found */
    2171           0 :                 return (ENOENT);
    2172             : 
    2173           0 :         if (vfsp->vfc_refcount)              /* In use */
    2174           0 :                 return (EBUSY);
    2175             : 
    2176             :         /* Remove from list and free */
    2177           0 :         *vfspp = vfsp->vfc_next;
    2178             : 
    2179             :         maxtypenum = 0;
    2180             : 
    2181           0 :         for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next)
    2182           0 :                 if (vfsp->vfc_typenum > maxtypenum)
    2183           0 :                         maxtypenum = vfsp->vfc_typenum;
    2184             : 
    2185           0 :         maxvfsconf = maxtypenum;
    2186           0 :         return 0;
    2187           0 : }
    2188             : 
    2189             : /*
    2190             :  * Check if vnode represents a disk device
    2191             :  */
    2192             : int
    2193           0 : vn_isdisk(struct vnode *vp, int *errp)
    2194             : {
    2195           0 :         if (vp->v_type != VBLK && vp->v_type != VCHR)
    2196           0 :                 return (0);
    2197             : 
    2198           0 :         return (1);
    2199           0 : }
    2200             : 
    2201             : #ifdef DDB
    2202             : #include <machine/db_machdep.h>
    2203             : #include <ddb/db_interface.h>
    2204             : 
    2205             : void
    2206           0 : vfs_buf_print(void *b, int full,
    2207             :     int (*pr)(const char *, ...) __attribute__((__format__(__kprintf__,1,2))))
    2208             : {
    2209           0 :         struct buf *bp = b;
    2210             : 
    2211           0 :         (*pr)("  vp %p lblkno 0x%llx blkno 0x%llx dev 0x%x\n"
    2212             :               "  proc %p error %d flags %lb\n",
    2213           0 :             bp->b_vp, (int64_t)bp->b_lblkno, (int64_t)bp->b_blkno, bp->b_dev,
    2214           0 :             bp->b_proc, bp->b_error, bp->b_flags, B_BITS);
    2215             : 
    2216           0 :         (*pr)("  bufsize 0x%lx bcount 0x%lx resid 0x%lx\n"
    2217             :               "  data %p saveaddr %p dep %p iodone %p\n",
    2218           0 :             bp->b_bufsize, bp->b_bcount, (long)bp->b_resid,
    2219           0 :             bp->b_data, bp->b_saveaddr,
    2220           0 :             LIST_FIRST(&bp->b_dep), bp->b_iodone);
    2221             : 
    2222           0 :         (*pr)("  dirty {off 0x%x end 0x%x} valid {off 0x%x end 0x%x}\n",
    2223           0 :             bp->b_dirtyoff, bp->b_dirtyend, bp->b_validoff, bp->b_validend);
    2224             : 
    2225             : #ifdef FFS_SOFTUPDATES
    2226           0 :         if (full)
    2227           0 :                 softdep_print(bp, full, pr);
    2228             : #endif
    2229           0 : }
    2230             : 
    2231             : const char *vtypes[] = { VTYPE_NAMES };
    2232             : const char *vtags[] = { VTAG_NAMES };
    2233             : 
    2234             : void
    2235           0 : vfs_vnode_print(void *v, int full,
    2236             :     int (*pr)(const char *, ...) __attribute__((__format__(__kprintf__,1,2))))
    2237             : {
    2238           0 :         struct vnode *vp = v;
    2239             : 
    2240           0 :         (*pr)("tag %s(%d) type %s(%d) mount %p typedata %p\n",
    2241           0 :               (u_int)vp->v_tag >= nitems(vtags)? "<unk>":vtags[vp->v_tag],
    2242           0 :               vp->v_tag,
    2243           0 :               (u_int)vp->v_type >= nitems(vtypes)? "<unk>":vtypes[vp->v_type],
    2244           0 :               vp->v_type, vp->v_mount, vp->v_mountedhere);
    2245             : 
    2246           0 :         (*pr)("data %p usecount %d writecount %d holdcnt %d numoutput %d\n",
    2247           0 :               vp->v_data, vp->v_usecount, vp->v_writecount,
    2248           0 :               vp->v_holdcnt, vp->v_numoutput);
    2249             : 
    2250             :         /* uvm_object_printit(&vp->v_uobj, full, pr); */
    2251             : 
    2252           0 :         if (full) {
    2253             :                 struct buf *bp;
    2254             : 
    2255           0 :                 (*pr)("clean bufs:\n");
    2256           0 :                 LIST_FOREACH(bp, &vp->v_cleanblkhd, b_vnbufs) {
    2257           0 :                         (*pr)(" bp %p\n", bp);
    2258           0 :                         vfs_buf_print(bp, full, pr);
    2259             :                 }
    2260             : 
    2261           0 :                 (*pr)("dirty bufs:\n");
    2262           0 :                 LIST_FOREACH(bp, &vp->v_dirtyblkhd, b_vnbufs) {
    2263           0 :                         (*pr)(" bp %p\n", bp);
    2264           0 :                         vfs_buf_print(bp, full, pr);
    2265             :                 }
    2266           0 :         }
    2267           0 : }
    2268             : 
    2269             : void
    2270           0 : vfs_mount_print(struct mount *mp, int full,
    2271             :     int (*pr)(const char *, ...) __attribute__((__format__(__kprintf__,1,2))))
    2272             : {
    2273           0 :         struct vfsconf *vfc = mp->mnt_vfc;
    2274             :         struct vnode *vp;
    2275             :         int cnt;
    2276             : 
    2277           0 :         (*pr)("flags %b\nvnodecovered %p syncer %p data %p\n",
    2278           0 :             mp->mnt_flag, MNT_BITS,
    2279           0 :             mp->mnt_vnodecovered, mp->mnt_syncer, mp->mnt_data);
    2280             : 
    2281           0 :         (*pr)("vfsconf: ops %p name \"%s\" num %d ref %d flags 0x%x\n",
    2282           0 :             vfc->vfc_vfsops, vfc->vfc_name, vfc->vfc_typenum,
    2283           0 :             vfc->vfc_refcount, vfc->vfc_flags);
    2284             : 
    2285           0 :         (*pr)("statvfs cache: bsize %x iosize %x\nblocks %llu free %llu avail %lld\n",
    2286           0 :             mp->mnt_stat.f_bsize, mp->mnt_stat.f_iosize, mp->mnt_stat.f_blocks,
    2287           0 :             mp->mnt_stat.f_bfree, mp->mnt_stat.f_bavail);
    2288             : 
    2289           0 :         (*pr)("  files %llu ffiles %llu favail %lld\n", mp->mnt_stat.f_files,
    2290           0 :             mp->mnt_stat.f_ffree, mp->mnt_stat.f_favail);
    2291             : 
    2292           0 :         (*pr)("  f_fsidx {0x%x, 0x%x} owner %u ctime 0x%llx\n",
    2293           0 :             mp->mnt_stat.f_fsid.val[0], mp->mnt_stat.f_fsid.val[1],
    2294           0 :             mp->mnt_stat.f_owner, mp->mnt_stat.f_ctime);
    2295             : 
    2296           0 :         (*pr)("  syncwrites %llu asyncwrites = %llu\n",
    2297           0 :             mp->mnt_stat.f_syncwrites, mp->mnt_stat.f_asyncwrites);
    2298             : 
    2299           0 :         (*pr)("  syncreads %llu asyncreads = %llu\n",
    2300           0 :             mp->mnt_stat.f_syncreads, mp->mnt_stat.f_asyncreads);
    2301             : 
    2302           0 :         (*pr)("  fstype \"%s\" mnton \"%s\" mntfrom \"%s\" mntspec \"%s\"\n",
    2303           0 :             mp->mnt_stat.f_fstypename, mp->mnt_stat.f_mntonname,
    2304           0 :             mp->mnt_stat.f_mntfromname, mp->mnt_stat.f_mntfromspec);
    2305             : 
    2306           0 :         (*pr)("locked vnodes:");
    2307             :         /* XXX would take mountlist lock, except ddb has no context */
    2308             :         cnt = 0;
    2309           0 :         LIST_FOREACH(vp, &mp->mnt_vnodelist, v_mntvnodes) {
    2310           0 :                 if (VOP_ISLOCKED(vp)) {
    2311           0 :                         if (cnt == 0)
    2312           0 :                                 (*pr)("\n  %p", vp);
    2313           0 :                         else if ((cnt % (72 / (sizeof(void *) * 2 + 4))) == 0)
    2314           0 :                                 (*pr)(",\n  %p", vp);
    2315             :                         else
    2316           0 :                                 (*pr)(", %p", vp);
    2317           0 :                         cnt++;
    2318           0 :                 }
    2319             :         }
    2320           0 :         (*pr)("\n");
    2321             : 
    2322           0 :         if (full) {
    2323           0 :                 (*pr)("all vnodes:");
    2324             :                 /* XXX would take mountlist lock, except ddb has no context */
    2325             :                 cnt = 0;
    2326           0 :                 LIST_FOREACH(vp, &mp->mnt_vnodelist, v_mntvnodes) {
    2327           0 :                         if (cnt == 0)
    2328           0 :                                 (*pr)("\n  %p", vp);
    2329           0 :                         else if ((cnt % (72 / (sizeof(void *) * 2 + 4))) == 0)
    2330           0 :                                 (*pr)(",\n  %p", vp);
    2331             :                         else
    2332           0 :                                 (*pr)(", %p", vp);
    2333           0 :                         cnt++;
    2334             :                 }
    2335           0 :                 (*pr)("\n");
    2336           0 :         }
    2337           0 : }
    2338             : #endif /* DDB */
    2339             : 
    2340             : void
    2341           0 : copy_statfs_info(struct statfs *sbp, const struct mount *mp)
    2342             : {
    2343             :         const struct statfs *mbp;
    2344             : 
    2345           0 :         strncpy(sbp->f_fstypename, mp->mnt_vfc->vfc_name, MFSNAMELEN);
    2346             : 
    2347           0 :         if (sbp == (mbp = &mp->mnt_stat))
    2348           0 :                 return;
    2349             : 
    2350           0 :         sbp->f_fsid = mbp->f_fsid;
    2351           0 :         sbp->f_owner = mbp->f_owner;
    2352           0 :         sbp->f_flags = mbp->f_flags;
    2353           0 :         sbp->f_syncwrites = mbp->f_syncwrites;
    2354           0 :         sbp->f_asyncwrites = mbp->f_asyncwrites;
    2355           0 :         sbp->f_syncreads = mbp->f_syncreads;
    2356           0 :         sbp->f_asyncreads = mbp->f_asyncreads;
    2357           0 :         sbp->f_namemax = mbp->f_namemax;
    2358           0 :         memcpy(sbp->f_mntonname, mp->mnt_stat.f_mntonname, MNAMELEN);
    2359           0 :         memcpy(sbp->f_mntfromname, mp->mnt_stat.f_mntfromname, MNAMELEN);
    2360           0 :         memcpy(sbp->f_mntfromspec, mp->mnt_stat.f_mntfromspec, MNAMELEN);
    2361           0 :         memcpy(&sbp->mount_info, &mp->mnt_stat.mount_info,
    2362             :             sizeof(union mount_info));
    2363           0 : }

Generated by: LCOV version 1.13