The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/kern/vfs_subr.c

Version: -  FREEBSD  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-2  -  FREEBSD-11-1  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-4  -  FREEBSD-10-3  -  FREEBSD-10-2  -  FREEBSD-10-1  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-3  -  FREEBSD-9-2  -  FREEBSD-9-1  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-4  -  FREEBSD-8-3  -  FREEBSD-8-2  -  FREEBSD-8-1  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-4  -  FREEBSD-7-3  -  FREEBSD-7-2  -  FREEBSD-7-1  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-4  -  FREEBSD-6-3  -  FREEBSD-6-2  -  FREEBSD-6-1  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-5  -  FREEBSD-5-4  -  FREEBSD-5-3  -  FREEBSD-5-2  -  FREEBSD-5-1  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  linux-2.6  -  linux-2.4.22  -  MK83  -  MK84  -  PLAN9  -  DFBSD  -  NETBSD  -  NETBSD5  -  NETBSD4  -  NETBSD3  -  NETBSD20  -  OPENBSD  -  xnu-517  -  xnu-792  -  xnu-792.6.70  -  xnu-1228  -  xnu-1456.1.26  -  xnu-1699.24.8  -  xnu-2050.18.24  -  OPENSOLARIS  -  minix-3-1-1 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: vfs_subr.c,v 1.422 2011/04/26 11:32:39 hannken Exp $   */
    2 
    3 /*-
    4  * Copyright (c) 1997, 1998, 2004, 2005, 2007, 2008 The NetBSD Foundation, Inc.
    5  * All rights reserved.
    6  *
    7  * This code is derived from software contributed to The NetBSD Foundation
    8  * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
    9  * NASA Ames Research Center, by Charles M. Hannum, and by Andrew Doran.
   10  *
   11  * Redistribution and use in source and binary forms, with or without
   12  * modification, are permitted provided that the following conditions
   13  * are met:
   14  * 1. Redistributions of source code must retain the above copyright
   15  *    notice, this list of conditions and the following disclaimer.
   16  * 2. Redistributions in binary form must reproduce the above copyright
   17  *    notice, this list of conditions and the following disclaimer in the
   18  *    documentation and/or other materials provided with the distribution.
   19  *
   20  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   21  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   22  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   23  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   24  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   25  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   26  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   27  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   28  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   29  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   30  * POSSIBILITY OF SUCH DAMAGE.
   31  */
   32 
   33 /*
   34  * Copyright (c) 1989, 1993
   35  *      The Regents of the University of California.  All rights reserved.
   36  * (c) UNIX System Laboratories, Inc.
   37  * All or some portions of this file are derived from material licensed
   38  * to the University of California by American Telephone and Telegraph
   39  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
   40  * the permission of UNIX System Laboratories, Inc.
   41  *
   42  * Redistribution and use in source and binary forms, with or without
   43  * modification, are permitted provided that the following conditions
   44  * are met:
   45  * 1. Redistributions of source code must retain the above copyright
   46  *    notice, this list of conditions and the following disclaimer.
   47  * 2. Redistributions in binary form must reproduce the above copyright
   48  *    notice, this list of conditions and the following disclaimer in the
   49  *    documentation and/or other materials provided with the distribution.
   50  * 3. Neither the name of the University nor the names of its contributors
   51  *    may be used to endorse or promote products derived from this software
   52  *    without specific prior written permission.
   53  *
   54  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   55  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   56  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   57  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   58  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   59  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   60  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   61  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   62  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   63  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   64  * SUCH DAMAGE.
   65  *
   66  *      @(#)vfs_subr.c  8.13 (Berkeley) 4/18/94
   67  */
   68 
   69 #include <sys/cdefs.h>
   70 __KERNEL_RCSID(0, "$NetBSD: vfs_subr.c,v 1.422 2011/04/26 11:32:39 hannken Exp $");
   71 
   72 #include "opt_ddb.h"
   73 #include "opt_compat_netbsd.h"
   74 #include "opt_compat_43.h"
   75 
   76 #include <sys/param.h>
   77 #include <sys/systm.h>
   78 #include <sys/conf.h>
   79 #include <sys/dirent.h>
   80 #include <sys/filedesc.h>
   81 #include <sys/kernel.h>
   82 #include <sys/mount.h>
   83 #include <sys/vnode.h>
   84 #include <sys/stat.h>
   85 #include <sys/sysctl.h>
   86 #include <sys/namei.h>
   87 #include <sys/buf.h>
   88 #include <sys/errno.h>
   89 #include <sys/kmem.h>
   90 #include <sys/syscallargs.h>
   91 #include <sys/kauth.h>
   92 #include <sys/module.h>
   93 
   94 #include <miscfs/genfs/genfs.h>
   95 #include <miscfs/syncfs/syncfs.h>
   96 #include <miscfs/specfs/specdev.h>
   97 #include <uvm/uvm_ddb.h>
   98 
   99 const enum vtype iftovt_tab[16] = {
  100         VNON, VFIFO, VCHR, VNON, VDIR, VNON, VBLK, VNON,
  101         VREG, VNON, VLNK, VNON, VSOCK, VNON, VNON, VBAD,
  102 };
  103 const int       vttoif_tab[9] = {
  104         0, S_IFREG, S_IFDIR, S_IFBLK, S_IFCHR, S_IFLNK,
  105         S_IFSOCK, S_IFIFO, S_IFMT,
  106 };
  107 
  108 /*
  109  * Insq/Remq for the vnode usage lists.
  110  */
  111 #define bufinsvn(bp, dp)        LIST_INSERT_HEAD(dp, bp, b_vnbufs)
  112 #define bufremvn(bp) {                                                  \
  113         LIST_REMOVE(bp, b_vnbufs);                                      \
  114         (bp)->b_vnbufs.le_next = NOLIST;                                \
  115 }
  116 
  117 int doforce = 1;                /* 1 => permit forcible unmounting */
  118 int prtactive = 0;              /* 1 => print out reclaim of active vnodes */
  119 
  120 /*
  121  * Local declarations.
  122  */
  123 
  124 static int getdevvp(dev_t, vnode_t **, enum vtype);
  125 
  126 /*
  127  * Initialize the vnode management data structures.
  128  */
  129 void
  130 vntblinit(void)
  131 {
  132 
  133         vn_initialize_syncerd();
  134         vfs_vnode_sysinit();
  135         vfs_mount_sysinit();
  136 }
  137 
  138 /*
  139  * Flush out and invalidate all buffers associated with a vnode.
  140  * Called with the underlying vnode locked, which should prevent new dirty
  141  * buffers from being queued.
  142  */
  143 int
  144 vinvalbuf(struct vnode *vp, int flags, kauth_cred_t cred, struct lwp *l,
  145           bool catch, int slptimeo)
  146 {
  147         struct buf *bp, *nbp;
  148         int error;
  149         int flushflags = PGO_ALLPAGES | PGO_FREE | PGO_SYNCIO |
  150             (flags & V_SAVE ? PGO_CLEANIT | PGO_RECLAIM : 0);
  151 
  152         /* XXXUBC this doesn't look at flags or slp* */
  153         mutex_enter(&vp->v_interlock);
  154         error = VOP_PUTPAGES(vp, 0, 0, flushflags);
  155         if (error) {
  156                 return error;
  157         }
  158 
  159         if (flags & V_SAVE) {
  160                 error = VOP_FSYNC(vp, cred, FSYNC_WAIT|FSYNC_RECLAIM, 0, 0);
  161                 if (error)
  162                         return (error);
  163                 KASSERT(LIST_EMPTY(&vp->v_dirtyblkhd));
  164         }
  165 
  166         mutex_enter(&bufcache_lock);
  167 restart:
  168         for (bp = LIST_FIRST(&vp->v_dirtyblkhd); bp; bp = nbp) {
  169                 nbp = LIST_NEXT(bp, b_vnbufs);
  170                 error = bbusy(bp, catch, slptimeo, NULL);
  171                 if (error != 0) {
  172                         if (error == EPASSTHROUGH)
  173                                 goto restart;
  174                         mutex_exit(&bufcache_lock);
  175                         return (error);
  176                 }
  177                 brelsel(bp, BC_INVAL | BC_VFLUSH);
  178         }
  179 
  180         for (bp = LIST_FIRST(&vp->v_cleanblkhd); bp; bp = nbp) {
  181                 nbp = LIST_NEXT(bp, b_vnbufs);
  182                 error = bbusy(bp, catch, slptimeo, NULL);
  183                 if (error != 0) {
  184                         if (error == EPASSTHROUGH)
  185                                 goto restart;
  186                         mutex_exit(&bufcache_lock);
  187                         return (error);
  188                 }
  189                 /*
  190                  * XXX Since there are no node locks for NFS, I believe
  191                  * there is a slight chance that a delayed write will
  192                  * occur while sleeping just above, so check for it.
  193                  */
  194                 if ((bp->b_oflags & BO_DELWRI) && (flags & V_SAVE)) {
  195 #ifdef DEBUG
  196                         printf("buffer still DELWRI\n");
  197 #endif
  198                         bp->b_cflags |= BC_BUSY | BC_VFLUSH;
  199                         mutex_exit(&bufcache_lock);
  200                         VOP_BWRITE(bp);
  201                         mutex_enter(&bufcache_lock);
  202                         goto restart;
  203                 }
  204                 brelsel(bp, BC_INVAL | BC_VFLUSH);
  205         }
  206 
  207 #ifdef DIAGNOSTIC
  208         if (!LIST_EMPTY(&vp->v_cleanblkhd) || !LIST_EMPTY(&vp->v_dirtyblkhd))
  209                 panic("vinvalbuf: flush failed, vp %p", vp);
  210 #endif
  211 
  212         mutex_exit(&bufcache_lock);
  213 
  214         return (0);
  215 }
  216 
  217 /*
  218  * Destroy any in core blocks past the truncation length.
  219  * Called with the underlying vnode locked, which should prevent new dirty
  220  * buffers from being queued.
  221  */
  222 int
  223 vtruncbuf(struct vnode *vp, daddr_t lbn, bool catch, int slptimeo)
  224 {
  225         struct buf *bp, *nbp;
  226         int error;
  227         voff_t off;
  228 
  229         off = round_page((voff_t)lbn << vp->v_mount->mnt_fs_bshift);
  230         mutex_enter(&vp->v_interlock);
  231         error = VOP_PUTPAGES(vp, off, 0, PGO_FREE | PGO_SYNCIO);
  232         if (error) {
  233                 return error;
  234         }
  235 
  236         mutex_enter(&bufcache_lock);
  237 restart:
  238         for (bp = LIST_FIRST(&vp->v_dirtyblkhd); bp; bp = nbp) {
  239                 nbp = LIST_NEXT(bp, b_vnbufs);
  240                 if (bp->b_lblkno < lbn)
  241                         continue;
  242                 error = bbusy(bp, catch, slptimeo, NULL);
  243                 if (error != 0) {
  244                         if (error == EPASSTHROUGH)
  245                                 goto restart;
  246                         mutex_exit(&bufcache_lock);
  247                         return (error);
  248                 }
  249                 brelsel(bp, BC_INVAL | BC_VFLUSH);
  250         }
  251 
  252         for (bp = LIST_FIRST(&vp->v_cleanblkhd); bp; bp = nbp) {
  253                 nbp = LIST_NEXT(bp, b_vnbufs);
  254                 if (bp->b_lblkno < lbn)
  255                         continue;
  256                 error = bbusy(bp, catch, slptimeo, NULL);
  257                 if (error != 0) {
  258                         if (error == EPASSTHROUGH)
  259                                 goto restart;
  260                         mutex_exit(&bufcache_lock);
  261                         return (error);
  262                 }
  263                 brelsel(bp, BC_INVAL | BC_VFLUSH);
  264         }
  265         mutex_exit(&bufcache_lock);
  266 
  267         return (0);
  268 }
  269 
  270 /*
  271  * Flush all dirty buffers from a vnode.
  272  * Called with the underlying vnode locked, which should prevent new dirty
  273  * buffers from being queued.
  274  */
  275 int
  276 vflushbuf(struct vnode *vp, int sync)
  277 {
  278         struct buf *bp, *nbp;
  279         int error, flags = PGO_CLEANIT | PGO_ALLPAGES | (sync ? PGO_SYNCIO : 0);
  280         bool dirty;
  281 
  282         mutex_enter(&vp->v_interlock);
  283         (void) VOP_PUTPAGES(vp, 0, 0, flags);
  284 
  285 loop:
  286         mutex_enter(&bufcache_lock);
  287         for (bp = LIST_FIRST(&vp->v_dirtyblkhd); bp; bp = nbp) {
  288                 nbp = LIST_NEXT(bp, b_vnbufs);
  289                 if ((bp->b_cflags & BC_BUSY))
  290                         continue;
  291                 if ((bp->b_oflags & BO_DELWRI) == 0)
  292                         panic("vflushbuf: not dirty, bp %p", bp);
  293                 bp->b_cflags |= BC_BUSY | BC_VFLUSH;
  294                 mutex_exit(&bufcache_lock);
  295                 /*
  296                  * Wait for I/O associated with indirect blocks to complete,
  297                  * since there is no way to quickly wait for them below.
  298                  */
  299                 if (bp->b_vp == vp || sync == 0)
  300                         (void) bawrite(bp);
  301                 else {
  302                         error = bwrite(bp);
  303                         if (error)
  304                                 return error;
  305                 }
  306                 goto loop;
  307         }
  308         mutex_exit(&bufcache_lock);
  309 
  310         if (sync == 0)
  311                 return 0;
  312 
  313         mutex_enter(&vp->v_interlock);
  314         while (vp->v_numoutput != 0)
  315                 cv_wait(&vp->v_cv, &vp->v_interlock);
  316         dirty = !LIST_EMPTY(&vp->v_dirtyblkhd);
  317         mutex_exit(&vp->v_interlock);
  318 
  319         if (dirty) {
  320                 vprint("vflushbuf: dirty", vp);
  321                 goto loop;
  322         }
  323 
  324         return 0;
  325 }
  326 
  327 /*
  328  * Create a vnode for a block device.
  329  * Used for root filesystem and swap areas.
  330  * Also used for memory file system special devices.
  331  */
  332 int
  333 bdevvp(dev_t dev, vnode_t **vpp)
  334 {
  335 
  336         return (getdevvp(dev, vpp, VBLK));
  337 }
  338 
  339 /*
  340  * Create a vnode for a character device.
  341  * Used for kernfs and some console handling.
  342  */
  343 int
  344 cdevvp(dev_t dev, vnode_t **vpp)
  345 {
  346 
  347         return (getdevvp(dev, vpp, VCHR));
  348 }
  349 
  350 /*
  351  * Associate a buffer with a vnode.  There must already be a hold on
  352  * the vnode.
  353  */
  354 void
  355 bgetvp(struct vnode *vp, struct buf *bp)
  356 {
  357 
  358         KASSERT(bp->b_vp == NULL);
  359         KASSERT(bp->b_objlock == &buffer_lock);
  360         KASSERT(mutex_owned(&vp->v_interlock));
  361         KASSERT(mutex_owned(&bufcache_lock));
  362         KASSERT((bp->b_cflags & BC_BUSY) != 0);
  363         KASSERT(!cv_has_waiters(&bp->b_done));
  364 
  365         vholdl(vp);
  366         bp->b_vp = vp;
  367         if (vp->v_type == VBLK || vp->v_type == VCHR)
  368                 bp->b_dev = vp->v_rdev;
  369         else
  370                 bp->b_dev = NODEV;
  371 
  372         /*
  373          * Insert onto list for new vnode.
  374          */
  375         bufinsvn(bp, &vp->v_cleanblkhd);
  376         bp->b_objlock = &vp->v_interlock;
  377 }
  378 
  379 /*
  380  * Disassociate a buffer from a vnode.
  381  */
  382 void
  383 brelvp(struct buf *bp)
  384 {
  385         struct vnode *vp = bp->b_vp;
  386 
  387         KASSERT(vp != NULL);
  388         KASSERT(bp->b_objlock == &vp->v_interlock);
  389         KASSERT(mutex_owned(&vp->v_interlock));
  390         KASSERT(mutex_owned(&bufcache_lock));
  391         KASSERT((bp->b_cflags & BC_BUSY) != 0);
  392         KASSERT(!cv_has_waiters(&bp->b_done));
  393 
  394         /*
  395          * Delete from old vnode list, if on one.
  396          */
  397         if (LIST_NEXT(bp, b_vnbufs) != NOLIST)
  398                 bufremvn(bp);
  399 
  400         if (vp->v_uobj.uo_npages == 0 && (vp->v_iflag & VI_ONWORKLST) &&
  401             LIST_FIRST(&vp->v_dirtyblkhd) == NULL) {
  402                 vp->v_iflag &= ~VI_WRMAPDIRTY;
  403                 vn_syncer_remove_from_worklist(vp);
  404         }
  405 
  406         bp->b_objlock = &buffer_lock;
  407         bp->b_vp = NULL;
  408         holdrelel(vp);
  409 }
  410 
  411 /*
  412  * Reassign a buffer from one vnode list to another.
  413  * The list reassignment must be within the same vnode.
  414  * Used to assign file specific control information
  415  * (indirect blocks) to the list to which they belong.
  416  */
  417 void
  418 reassignbuf(struct buf *bp, struct vnode *vp)
  419 {
  420         struct buflists *listheadp;
  421         int delayx;
  422 
  423         KASSERT(mutex_owned(&bufcache_lock));
  424         KASSERT(bp->b_objlock == &vp->v_interlock);
  425         KASSERT(mutex_owned(&vp->v_interlock));
  426         KASSERT((bp->b_cflags & BC_BUSY) != 0);
  427 
  428         /*
  429          * Delete from old vnode list, if on one.
  430          */
  431         if (LIST_NEXT(bp, b_vnbufs) != NOLIST)
  432                 bufremvn(bp);
  433 
  434         /*
  435          * If dirty, put on list of dirty buffers;
  436          * otherwise insert onto list of clean buffers.
  437          */
  438         if ((bp->b_oflags & BO_DELWRI) == 0) {
  439                 listheadp = &vp->v_cleanblkhd;
  440                 if (vp->v_uobj.uo_npages == 0 &&
  441                     (vp->v_iflag & VI_ONWORKLST) &&
  442                     LIST_FIRST(&vp->v_dirtyblkhd) == NULL) {
  443                         vp->v_iflag &= ~VI_WRMAPDIRTY;
  444                         vn_syncer_remove_from_worklist(vp);
  445                 }
  446         } else {
  447                 listheadp = &vp->v_dirtyblkhd;
  448                 if ((vp->v_iflag & VI_ONWORKLST) == 0) {
  449                         switch (vp->v_type) {
  450                         case VDIR:
  451                                 delayx = dirdelay;
  452                                 break;
  453                         case VBLK:
  454                                 if (vp->v_specmountpoint != NULL) {
  455                                         delayx = metadelay;
  456                                         break;
  457                                 }
  458                                 /* fall through */
  459                         default:
  460                                 delayx = filedelay;
  461                                 break;
  462                         }
  463                         if (!vp->v_mount ||
  464                             (vp->v_mount->mnt_flag & MNT_ASYNC) == 0)
  465                                 vn_syncer_add_to_worklist(vp, delayx);
  466                 }
  467         }
  468         bufinsvn(bp, listheadp);
  469 }
  470 
  471 /*
  472  * Create a vnode for a device.
  473  * Used by bdevvp (block device) for root file system etc.,
  474  * and by cdevvp (character device) for console and kernfs.
  475  */
  476 static int
  477 getdevvp(dev_t dev, vnode_t **vpp, enum vtype type)
  478 {
  479         vnode_t *vp;
  480         vnode_t *nvp;
  481         int error;
  482 
  483         if (dev == NODEV) {
  484                 *vpp = NULL;
  485                 return (0);
  486         }
  487         error = getnewvnode(VT_NON, NULL, spec_vnodeop_p, &nvp);
  488         if (error) {
  489                 *vpp = NULL;
  490                 return (error);
  491         }
  492         vp = nvp;
  493         vp->v_type = type;
  494         vp->v_vflag |= VV_MPSAFE;
  495         uvm_vnp_setsize(vp, 0);
  496         spec_node_init(vp, dev);
  497         *vpp = vp;
  498         return (0);
  499 }
  500 
  501 /*
  502  * Lookup a vnode by device number and return it referenced.
  503  */
  504 int
  505 vfinddev(dev_t dev, enum vtype type, vnode_t **vpp)
  506 {
  507         vnode_t *vp;
  508 
  509         mutex_enter(&device_lock);
  510         for (vp = specfs_hash[SPECHASH(dev)]; vp; vp = vp->v_specnext) {
  511                 if (dev == vp->v_rdev && type == vp->v_type)
  512                         break;
  513         }
  514         if (vp == NULL) {
  515                 mutex_exit(&device_lock);
  516                 return 0;
  517         }
  518         mutex_enter(&vp->v_interlock);
  519         mutex_exit(&device_lock);
  520         if (vget(vp, 0) != 0)
  521                 return 0;
  522         *vpp = vp;
  523         return 1;
  524 }
  525 
  526 /*
  527  * Revoke all the vnodes corresponding to the specified minor number
  528  * range (endpoints inclusive) of the specified major.
  529  */
  530 void
  531 vdevgone(int maj, int minl, int minh, enum vtype type)
  532 {
  533         vnode_t *vp, **vpp;
  534         dev_t dev;
  535         int mn;
  536 
  537         vp = NULL;      /* XXX gcc */
  538 
  539         mutex_enter(&device_lock);
  540         for (mn = minl; mn <= minh; mn++) {
  541                 dev = makedev(maj, mn);
  542                 vpp = &specfs_hash[SPECHASH(dev)];
  543                 for (vp = *vpp; vp != NULL;) {
  544                         mutex_enter(&vp->v_interlock);
  545                         if ((vp->v_iflag & VI_CLEAN) != 0 ||
  546                             dev != vp->v_rdev || type != vp->v_type) {
  547                                 mutex_exit(&vp->v_interlock);
  548                                 vp = vp->v_specnext;
  549                                 continue;
  550                         }
  551                         mutex_exit(&device_lock);
  552                         if (vget(vp, 0) == 0) {
  553                                 VOP_REVOKE(vp, REVOKEALL);
  554                                 vrele(vp);
  555                         }
  556                         mutex_enter(&device_lock);
  557                         vp = *vpp;
  558                 }
  559         }
  560         mutex_exit(&device_lock);
  561 }
  562 
  563 /*
  564  * sysctl helper routine to return list of supported fstypes
  565  */
  566 int
  567 sysctl_vfs_generic_fstypes(SYSCTLFN_ARGS)
  568 {
  569         char bf[sizeof(((struct statvfs *)NULL)->f_fstypename)];
  570         char *where = oldp;
  571         struct vfsops *v;
  572         size_t needed, left, slen;
  573         int error, first;
  574 
  575         if (newp != NULL)
  576                 return (EPERM);
  577         if (namelen != 0)
  578                 return (EINVAL);
  579 
  580         first = 1;
  581         error = 0;
  582         needed = 0;
  583         left = *oldlenp;
  584 
  585         sysctl_unlock();
  586         mutex_enter(&vfs_list_lock);
  587         LIST_FOREACH(v, &vfs_list, vfs_list) {
  588                 if (where == NULL)
  589                         needed += strlen(v->vfs_name) + 1;
  590                 else {
  591                         memset(bf, 0, sizeof(bf));
  592                         if (first) {
  593                                 strncpy(bf, v->vfs_name, sizeof(bf));
  594                                 first = 0;
  595                         } else {
  596                                 bf[0] = ' ';
  597                                 strncpy(bf + 1, v->vfs_name, sizeof(bf) - 1);
  598                         }
  599                         bf[sizeof(bf)-1] = '\0';
  600                         slen = strlen(bf);
  601                         if (left < slen + 1)
  602                                 break;
  603                         v->vfs_refcount++;
  604                         mutex_exit(&vfs_list_lock);
  605                         /* +1 to copy out the trailing NUL byte */
  606                         error = copyout(bf, where, slen + 1);
  607                         mutex_enter(&vfs_list_lock);
  608                         v->vfs_refcount--;
  609                         if (error)
  610                                 break;
  611                         where += slen;
  612                         needed += slen;
  613                         left -= slen;
  614                 }
  615         }
  616         mutex_exit(&vfs_list_lock);
  617         sysctl_relock();
  618         *oldlenp = needed;
  619         return (error);
  620 }
  621 
  622 int kinfo_vdebug = 1;
  623 int kinfo_vgetfailed;
  624 
  625 #define KINFO_VNODESLOP 10
  626 
  627 /*
  628  * Dump vnode list (via sysctl).
  629  * Copyout address of vnode followed by vnode.
  630  */
  631 int
  632 sysctl_kern_vnode(SYSCTLFN_ARGS)
  633 {
  634         char *where = oldp;
  635         size_t *sizep = oldlenp;
  636         struct mount *mp, *nmp;
  637         vnode_t *vp, *mvp, vbuf;
  638         char *bp = where;
  639         char *ewhere;
  640         int error;
  641 
  642         if (namelen != 0)
  643                 return (EOPNOTSUPP);
  644         if (newp != NULL)
  645                 return (EPERM);
  646 
  647 #define VPTRSZ  sizeof(vnode_t *)
  648 #define VNODESZ sizeof(vnode_t)
  649         if (where == NULL) {
  650                 *sizep = (numvnodes + KINFO_VNODESLOP) * (VPTRSZ + VNODESZ);
  651                 return (0);
  652         }
  653         ewhere = where + *sizep;
  654 
  655         sysctl_unlock();
  656         mutex_enter(&mountlist_lock);
  657         for (mp = CIRCLEQ_FIRST(&mountlist); mp != (void *)&mountlist;
  658             mp = nmp) {
  659                 if (vfs_busy(mp, &nmp)) {
  660                         continue;
  661                 }
  662                 /* Allocate a marker vnode. */
  663                 mvp = vnalloc(mp);
  664                 /* Should never fail for mp != NULL */
  665                 KASSERT(mvp != NULL);
  666                 mutex_enter(&mntvnode_lock);
  667                 for (vp = TAILQ_FIRST(&mp->mnt_vnodelist); vp;
  668                     vp = vunmark(mvp)) {
  669                         vmark(mvp, vp);
  670                         /*
  671                          * Check that the vp is still associated with
  672                          * this filesystem.  RACE: could have been
  673                          * recycled onto the same filesystem.
  674                          */
  675                         if (vp->v_mount != mp || vismarker(vp))
  676                                 continue;
  677                         if (bp + VPTRSZ + VNODESZ > ewhere) {
  678                                 (void)vunmark(mvp);
  679                                 mutex_exit(&mntvnode_lock);
  680                                 vnfree(mvp);
  681                                 vfs_unbusy(mp, false, NULL);
  682                                 sysctl_relock();
  683                                 *sizep = bp - where;
  684                                 return (ENOMEM);
  685                         }
  686                         memcpy(&vbuf, vp, VNODESZ);
  687                         mutex_exit(&mntvnode_lock);
  688                         if ((error = copyout(&vp, bp, VPTRSZ)) ||
  689                             (error = copyout(&vbuf, bp + VPTRSZ, VNODESZ))) {
  690                                 mutex_enter(&mntvnode_lock);
  691                                 (void)vunmark(mvp);
  692                                 mutex_exit(&mntvnode_lock);
  693                                 vnfree(mvp);
  694                                 vfs_unbusy(mp, false, NULL);
  695                                 sysctl_relock();
  696                                 return (error);
  697                         }
  698                         bp += VPTRSZ + VNODESZ;
  699                         mutex_enter(&mntvnode_lock);
  700                 }
  701                 mutex_exit(&mntvnode_lock);
  702                 vnfree(mvp);
  703                 vfs_unbusy(mp, false, &nmp);
  704         }
  705         mutex_exit(&mountlist_lock);
  706         sysctl_relock();
  707 
  708         *sizep = bp - where;
  709         return (0);
  710 }
  711 
  712 /*
  713  * Set vnode attributes to VNOVAL
  714  */
  715 void
  716 vattr_null(struct vattr *vap)
  717 {
  718 
  719         memset(vap, 0, sizeof(*vap));
  720 
  721         vap->va_type = VNON;
  722 
  723         /*
  724          * Assign individually so that it is safe even if size and
  725          * sign of each member are varied.
  726          */
  727         vap->va_mode = VNOVAL;
  728         vap->va_nlink = VNOVAL;
  729         vap->va_uid = VNOVAL;
  730         vap->va_gid = VNOVAL;
  731         vap->va_fsid = VNOVAL;
  732         vap->va_fileid = VNOVAL;
  733         vap->va_size = VNOVAL;
  734         vap->va_blocksize = VNOVAL;
  735         vap->va_atime.tv_sec =
  736             vap->va_mtime.tv_sec =
  737             vap->va_ctime.tv_sec =
  738             vap->va_birthtime.tv_sec = VNOVAL;
  739         vap->va_atime.tv_nsec =
  740             vap->va_mtime.tv_nsec =
  741             vap->va_ctime.tv_nsec =
  742             vap->va_birthtime.tv_nsec = VNOVAL;
  743         vap->va_gen = VNOVAL;
  744         vap->va_flags = VNOVAL;
  745         vap->va_rdev = VNOVAL;
  746         vap->va_bytes = VNOVAL;
  747 }
  748 
  749 #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof(arr[0]))
  750 #define ARRAY_PRINT(idx, arr) \
  751     ((unsigned int)(idx) < ARRAY_SIZE(arr) ? (arr)[(idx)] : "UNKNOWN")
  752 
  753 const char * const vnode_tags[] = { VNODE_TAGS };
  754 const char * const vnode_types[] = { VNODE_TYPES };
  755 const char vnode_flagbits[] = VNODE_FLAGBITS;
  756 
  757 /*
  758  * Print out a description of a vnode.
  759  */
  760 void
  761 vprint(const char *label, struct vnode *vp)
  762 {
  763         char bf[96];
  764         int flag;
  765 
  766         flag = vp->v_iflag | vp->v_vflag | vp->v_uflag;
  767         snprintb(bf, sizeof(bf), vnode_flagbits, flag);
  768 
  769         if (label != NULL)
  770                 printf("%s: ", label);
  771         printf("vnode @ %p, flags (%s)\n\ttag %s(%d), type %s(%d), "
  772             "usecount %d, writecount %d, holdcount %d\n"
  773             "\tfreelisthd %p, mount %p, data %p lock %p\n",
  774             vp, bf, ARRAY_PRINT(vp->v_tag, vnode_tags), vp->v_tag,
  775             ARRAY_PRINT(vp->v_type, vnode_types), vp->v_type,
  776             vp->v_usecount, vp->v_writecount, vp->v_holdcnt,
  777             vp->v_freelisthd, vp->v_mount, vp->v_data, &vp->v_lock);
  778         if (vp->v_data != NULL) {
  779                 printf("\t");
  780                 VOP_PRINT(vp);
  781         }
  782 }
  783 
  784 /* Deprecated. Kept for KPI compatibility. */
  785 int
  786 vaccess(enum vtype type, mode_t file_mode, uid_t uid, gid_t gid,
  787     mode_t acc_mode, kauth_cred_t cred)
  788 {
  789 
  790 #ifdef DIAGNOSTIC
  791         printf("vaccess: deprecated interface used.\n");
  792 #endif /* DIAGNOSTIC */
  793 
  794         return genfs_can_access(type, file_mode, uid, gid, acc_mode, cred);
  795 }
  796 
  797 /*
  798  * Given a file system name, look up the vfsops for that
  799  * file system, or return NULL if file system isn't present
  800  * in the kernel.
  801  */
  802 struct vfsops *
  803 vfs_getopsbyname(const char *name)
  804 {
  805         struct vfsops *v;
  806 
  807         mutex_enter(&vfs_list_lock);
  808         LIST_FOREACH(v, &vfs_list, vfs_list) {
  809                 if (strcmp(v->vfs_name, name) == 0)
  810                         break;
  811         }
  812         if (v != NULL)
  813                 v->vfs_refcount++;
  814         mutex_exit(&vfs_list_lock);
  815 
  816         return (v);
  817 }
  818 
  819 void
  820 copy_statvfs_info(struct statvfs *sbp, const struct mount *mp)
  821 {
  822         const struct statvfs *mbp;
  823 
  824         if (sbp == (mbp = &mp->mnt_stat))
  825                 return;
  826 
  827         (void)memcpy(&sbp->f_fsidx, &mbp->f_fsidx, sizeof(sbp->f_fsidx));
  828         sbp->f_fsid = mbp->f_fsid;
  829         sbp->f_owner = mbp->f_owner;
  830         sbp->f_flag = mbp->f_flag;
  831         sbp->f_syncwrites = mbp->f_syncwrites;
  832         sbp->f_asyncwrites = mbp->f_asyncwrites;
  833         sbp->f_syncreads = mbp->f_syncreads;
  834         sbp->f_asyncreads = mbp->f_asyncreads;
  835         (void)memcpy(sbp->f_spare, mbp->f_spare, sizeof(mbp->f_spare));
  836         (void)memcpy(sbp->f_fstypename, mbp->f_fstypename,
  837             sizeof(sbp->f_fstypename));
  838         (void)memcpy(sbp->f_mntonname, mbp->f_mntonname,
  839             sizeof(sbp->f_mntonname));
  840         (void)memcpy(sbp->f_mntfromname, mp->mnt_stat.f_mntfromname,
  841             sizeof(sbp->f_mntfromname));
  842         sbp->f_namemax = mbp->f_namemax;
  843 }
  844 
  845 int
  846 set_statvfs_info(const char *onp, int ukon, const char *fromp, int ukfrom,
  847     const char *vfsname, struct mount *mp, struct lwp *l)
  848 {
  849         int error;
  850         size_t size;
  851         struct statvfs *sfs = &mp->mnt_stat;
  852         int (*fun)(const void *, void *, size_t, size_t *);
  853 
  854         (void)strlcpy(mp->mnt_stat.f_fstypename, vfsname,
  855             sizeof(mp->mnt_stat.f_fstypename));
  856 
  857         if (onp) {
  858                 struct cwdinfo *cwdi = l->l_proc->p_cwdi;
  859                 fun = (ukon == UIO_SYSSPACE) ? copystr : copyinstr;
  860                 if (cwdi->cwdi_rdir != NULL) {
  861                         size_t len;
  862                         char *bp;
  863                         char *path = PNBUF_GET();
  864 
  865                         bp = path + MAXPATHLEN;
  866                         *--bp = '\0';
  867                         rw_enter(&cwdi->cwdi_lock, RW_READER);
  868                         error = getcwd_common(cwdi->cwdi_rdir, rootvnode, &bp,
  869                             path, MAXPATHLEN / 2, 0, l);
  870                         rw_exit(&cwdi->cwdi_lock);
  871                         if (error) {
  872                                 PNBUF_PUT(path);
  873                                 return error;
  874                         }
  875 
  876                         len = strlen(bp);
  877                         if (len > sizeof(sfs->f_mntonname) - 1)
  878                                 len = sizeof(sfs->f_mntonname) - 1;
  879                         (void)strncpy(sfs->f_mntonname, bp, len);
  880                         PNBUF_PUT(path);
  881 
  882                         if (len < sizeof(sfs->f_mntonname) - 1) {
  883                                 error = (*fun)(onp, &sfs->f_mntonname[len],
  884                                     sizeof(sfs->f_mntonname) - len - 1, &size);
  885                                 if (error)
  886                                         return error;
  887                                 size += len;
  888                         } else {
  889                                 size = len;
  890                         }
  891                 } else {
  892                         error = (*fun)(onp, &sfs->f_mntonname,
  893                             sizeof(sfs->f_mntonname) - 1, &size);
  894                         if (error)
  895                                 return error;
  896                 }
  897                 (void)memset(sfs->f_mntonname + size, 0,
  898                     sizeof(sfs->f_mntonname) - size);
  899         }
  900 
  901         if (fromp) {
  902                 fun = (ukfrom == UIO_SYSSPACE) ? copystr : copyinstr;
  903                 error = (*fun)(fromp, sfs->f_mntfromname,
  904                     sizeof(sfs->f_mntfromname) - 1, &size);
  905                 if (error)
  906                         return error;
  907                 (void)memset(sfs->f_mntfromname + size, 0,
  908                     sizeof(sfs->f_mntfromname) - size);
  909         }
  910         return 0;
  911 }
  912 
  913 void
  914 vfs_timestamp(struct timespec *ts)
  915 {
  916 
  917         nanotime(ts);
  918 }
  919 
  920 time_t  rootfstime;                     /* recorded root fs time, if known */
  921 void
  922 setrootfstime(time_t t)
  923 {
  924         rootfstime = t;
  925 }
  926 
  927 static const uint8_t vttodt_tab[9] = {
  928         DT_UNKNOWN,     /* VNON  */
  929         DT_REG,         /* VREG  */
  930         DT_DIR,         /* VDIR  */
  931         DT_BLK,         /* VBLK  */
  932         DT_CHR,         /* VCHR  */
  933         DT_LNK,         /* VLNK  */
  934         DT_SOCK,        /* VSUCK */
  935         DT_FIFO,        /* VFIFO */
  936         DT_UNKNOWN      /* VBAD  */
  937 };
  938 
  939 uint8_t
  940 vtype2dt(enum vtype vt)
  941 {
  942 
  943         CTASSERT(VBAD == __arraycount(vttodt_tab) - 1);
  944         return vttodt_tab[vt];
  945 }
  946 
  947 int
  948 VFS_MOUNT(struct mount *mp, const char *a, void *b, size_t *c)
  949 {
  950         int error;
  951 
  952         KERNEL_LOCK(1, NULL);
  953         error = (*(mp->mnt_op->vfs_mount))(mp, a, b, c);
  954         KERNEL_UNLOCK_ONE(NULL);
  955 
  956         return error;
  957 }
  958         
  959 int
  960 VFS_START(struct mount *mp, int a)
  961 {
  962         int error;
  963 
  964         if ((mp->mnt_iflag & IMNT_MPSAFE) == 0) {
  965                 KERNEL_LOCK(1, NULL);
  966         }
  967         error = (*(mp->mnt_op->vfs_start))(mp, a);
  968         if ((mp->mnt_iflag & IMNT_MPSAFE) == 0) {
  969                 KERNEL_UNLOCK_ONE(NULL);
  970         }
  971 
  972         return error;
  973 }
  974         
  975 int
  976 VFS_UNMOUNT(struct mount *mp, int a)
  977 {
  978         int error;
  979 
  980         KERNEL_LOCK(1, NULL);
  981         error = (*(mp->mnt_op->vfs_unmount))(mp, a);
  982         KERNEL_UNLOCK_ONE(NULL);
  983 
  984         return error;
  985 }
  986 
  987 int
  988 VFS_ROOT(struct mount *mp, struct vnode **a)
  989 {
  990         int error;
  991 
  992         if ((mp->mnt_iflag & IMNT_MPSAFE) == 0) {
  993                 KERNEL_LOCK(1, NULL);
  994         }
  995         error = (*(mp->mnt_op->vfs_root))(mp, a);
  996         if ((mp->mnt_iflag & IMNT_MPSAFE) == 0) {
  997                 KERNEL_UNLOCK_ONE(NULL);
  998         }
  999 
 1000         return error;
 1001 }
 1002 
 1003 int
 1004 VFS_QUOTACTL(struct mount *mp, prop_dictionary_t dict)
 1005 {
 1006         int error;
 1007 
 1008         if ((mp->mnt_iflag & IMNT_MPSAFE) == 0) {
 1009                 KERNEL_LOCK(1, NULL);
 1010         }
 1011         error = (*(mp->mnt_op->vfs_quotactl))(mp, dict);
 1012         if ((mp->mnt_iflag & IMNT_MPSAFE) == 0) {
 1013                 KERNEL_UNLOCK_ONE(NULL);
 1014         }
 1015 
 1016         return error;
 1017 }
 1018 
 1019 int
 1020 VFS_STATVFS(struct mount *mp, struct statvfs *a)
 1021 {
 1022         int error;
 1023 
 1024         if ((mp->mnt_iflag & IMNT_MPSAFE) == 0) {
 1025                 KERNEL_LOCK(1, NULL);
 1026         }
 1027         error = (*(mp->mnt_op->vfs_statvfs))(mp, a);
 1028         if ((mp->mnt_iflag & IMNT_MPSAFE) == 0) {
 1029                 KERNEL_UNLOCK_ONE(NULL);
 1030         }
 1031 
 1032         return error;
 1033 }
 1034 
 1035 int
 1036 VFS_SYNC(struct mount *mp, int a, struct kauth_cred *b)
 1037 {
 1038         int error;
 1039 
 1040         if ((mp->mnt_iflag & IMNT_MPSAFE) == 0) {
 1041                 KERNEL_LOCK(1, NULL);
 1042         }
 1043         error = (*(mp->mnt_op->vfs_sync))(mp, a, b);
 1044         if ((mp->mnt_iflag & IMNT_MPSAFE) == 0) {
 1045                 KERNEL_UNLOCK_ONE(NULL);
 1046         }
 1047 
 1048         return error;
 1049 }
 1050 
 1051 int
 1052 VFS_FHTOVP(struct mount *mp, struct fid *a, struct vnode **b)
 1053 {
 1054         int error;
 1055 
 1056         if ((mp->mnt_iflag & IMNT_MPSAFE) == 0) {
 1057                 KERNEL_LOCK(1, NULL);
 1058         }
 1059         error = (*(mp->mnt_op->vfs_fhtovp))(mp, a, b);
 1060         if ((mp->mnt_iflag & IMNT_MPSAFE) == 0) {
 1061                 KERNEL_UNLOCK_ONE(NULL);
 1062         }
 1063 
 1064         return error;
 1065 }
 1066 
 1067 int
 1068 VFS_VPTOFH(struct vnode *vp, struct fid *a, size_t *b)
 1069 {
 1070         int error;
 1071 
 1072         if ((vp->v_vflag & VV_MPSAFE) == 0) {
 1073                 KERNEL_LOCK(1, NULL);
 1074         }
 1075         error = (*(vp->v_mount->mnt_op->vfs_vptofh))(vp, a, b);
 1076         if ((vp->v_vflag & VV_MPSAFE) == 0) {
 1077                 KERNEL_UNLOCK_ONE(NULL);
 1078         }
 1079 
 1080         return error;
 1081 }
 1082 
 1083 int
 1084 VFS_SNAPSHOT(struct mount *mp, struct vnode *a, struct timespec *b)
 1085 {
 1086         int error;
 1087 
 1088         if ((mp->mnt_iflag & IMNT_MPSAFE) == 0) {
 1089                 KERNEL_LOCK(1, NULL);
 1090         }
 1091         error = (*(mp->mnt_op->vfs_snapshot))(mp, a, b);
 1092         if ((mp->mnt_iflag & IMNT_MPSAFE) == 0) {
 1093                 KERNEL_UNLOCK_ONE(NULL);
 1094         }
 1095 
 1096         return error;
 1097 }
 1098 
 1099 int
 1100 VFS_EXTATTRCTL(struct mount *mp, int a, struct vnode *b, int c, const char *d)
 1101 {
 1102         int error;
 1103 
 1104         KERNEL_LOCK(1, NULL);           /* XXXSMP check ffs */
 1105         error = (*(mp->mnt_op->vfs_extattrctl))(mp, a, b, c, d);
 1106         KERNEL_UNLOCK_ONE(NULL);        /* XXX */
 1107 
 1108         return error;
 1109 }
 1110 
 1111 int
 1112 VFS_SUSPENDCTL(struct mount *mp, int a)
 1113 {
 1114         int error;
 1115 
 1116         if ((mp->mnt_iflag & IMNT_MPSAFE) == 0) {
 1117                 KERNEL_LOCK(1, NULL);
 1118         }
 1119         error = (*(mp->mnt_op->vfs_suspendctl))(mp, a);
 1120         if ((mp->mnt_iflag & IMNT_MPSAFE) == 0) {
 1121                 KERNEL_UNLOCK_ONE(NULL);
 1122         }
 1123 
 1124         return error;
 1125 }
 1126 
 1127 #if defined(DDB) || defined(DEBUGPRINT)
 1128 static const char buf_flagbits[] = BUF_FLAGBITS;
 1129 
 1130 void
 1131 vfs_buf_print(struct buf *bp, int full, void (*pr)(const char *, ...))
 1132 {
 1133         char bf[1024];
 1134 
 1135         (*pr)("  vp %p lblkno 0x%"PRIx64" blkno 0x%"PRIx64" rawblkno 0x%"
 1136             PRIx64 " dev 0x%x\n",
 1137             bp->b_vp, bp->b_lblkno, bp->b_blkno, bp->b_rawblkno, bp->b_dev);
 1138 
 1139         snprintb(bf, sizeof(bf),
 1140             buf_flagbits, bp->b_flags | bp->b_oflags | bp->b_cflags);
 1141         (*pr)("  error %d flags 0x%s\n", bp->b_error, bf);
 1142 
 1143         (*pr)("  bufsize 0x%lx bcount 0x%lx resid 0x%lx\n",
 1144                   bp->b_bufsize, bp->b_bcount, bp->b_resid);
 1145         (*pr)("  data %p saveaddr %p\n",
 1146                   bp->b_data, bp->b_saveaddr);
 1147         (*pr)("  iodone %p objlock %p\n", bp->b_iodone, bp->b_objlock);
 1148 }
 1149 
 1150 void
 1151 vfs_vnode_print(struct vnode *vp, int full, void (*pr)(const char *, ...))
 1152 {
 1153         char bf[256];
 1154 
 1155         uvm_object_printit(&vp->v_uobj, full, pr);
 1156         snprintb(bf, sizeof(bf),
 1157             vnode_flagbits, vp->v_iflag | vp->v_vflag | vp->v_uflag);
 1158         (*pr)("\nVNODE flags %s\n", bf);
 1159         (*pr)("mp %p numoutput %d size 0x%llx writesize 0x%llx\n",
 1160               vp->v_mount, vp->v_numoutput, vp->v_size, vp->v_writesize);
 1161 
 1162         (*pr)("data %p writecount %ld holdcnt %ld\n",
 1163               vp->v_data, vp->v_writecount, vp->v_holdcnt);
 1164 
 1165         (*pr)("tag %s(%d) type %s(%d) mount %p typedata %p\n",
 1166               ARRAY_PRINT(vp->v_tag, vnode_tags), vp->v_tag,
 1167               ARRAY_PRINT(vp->v_type, vnode_types), vp->v_type,
 1168               vp->v_mount, vp->v_mountedhere);
 1169 
 1170         (*pr)("v_lock %p\n", &vp->v_lock);
 1171 
 1172         if (full) {
 1173                 struct buf *bp;
 1174 
 1175                 (*pr)("clean bufs:\n");
 1176                 LIST_FOREACH(bp, &vp->v_cleanblkhd, b_vnbufs) {
 1177                         (*pr)(" bp %p\n", bp);
 1178                         vfs_buf_print(bp, full, pr);
 1179                 }
 1180 
 1181                 (*pr)("dirty bufs:\n");
 1182                 LIST_FOREACH(bp, &vp->v_dirtyblkhd, b_vnbufs) {
 1183                         (*pr)(" bp %p\n", bp);
 1184                         vfs_buf_print(bp, full, pr);
 1185                 }
 1186         }
 1187 }
 1188 
 1189 void
 1190 vfs_mount_print(struct mount *mp, int full, void (*pr)(const char *, ...))
 1191 {
 1192         char sbuf[256];
 1193 
 1194         (*pr)("vnodecovered = %p syncer = %p data = %p\n",
 1195                         mp->mnt_vnodecovered,mp->mnt_syncer,mp->mnt_data);
 1196 
 1197         (*pr)("fs_bshift %d dev_bshift = %d\n",
 1198                         mp->mnt_fs_bshift,mp->mnt_dev_bshift);
 1199 
 1200         snprintb(sbuf, sizeof(sbuf), __MNT_FLAG_BITS, mp->mnt_flag);
 1201         (*pr)("flag = %s\n", sbuf);
 1202 
 1203         snprintb(sbuf, sizeof(sbuf), __IMNT_FLAG_BITS, mp->mnt_iflag);
 1204         (*pr)("iflag = %s\n", sbuf);
 1205 
 1206         (*pr)("refcnt = %d unmounting @ %p updating @ %p\n", mp->mnt_refcnt,
 1207             &mp->mnt_unmounting, &mp->mnt_updating);
 1208 
 1209         (*pr)("statvfs cache:\n");
 1210         (*pr)("\tbsize = %lu\n",mp->mnt_stat.f_bsize);
 1211         (*pr)("\tfrsize = %lu\n",mp->mnt_stat.f_frsize);
 1212         (*pr)("\tiosize = %lu\n",mp->mnt_stat.f_iosize);
 1213 
 1214         (*pr)("\tblocks = %"PRIu64"\n",mp->mnt_stat.f_blocks);
 1215         (*pr)("\tbfree = %"PRIu64"\n",mp->mnt_stat.f_bfree);
 1216         (*pr)("\tbavail = %"PRIu64"\n",mp->mnt_stat.f_bavail);
 1217         (*pr)("\tbresvd = %"PRIu64"\n",mp->mnt_stat.f_bresvd);
 1218 
 1219         (*pr)("\tfiles = %"PRIu64"\n",mp->mnt_stat.f_files);
 1220         (*pr)("\tffree = %"PRIu64"\n",mp->mnt_stat.f_ffree);
 1221         (*pr)("\tfavail = %"PRIu64"\n",mp->mnt_stat.f_favail);
 1222         (*pr)("\tfresvd = %"PRIu64"\n",mp->mnt_stat.f_fresvd);
 1223 
 1224         (*pr)("\tf_fsidx = { 0x%"PRIx32", 0x%"PRIx32" }\n",
 1225                         mp->mnt_stat.f_fsidx.__fsid_val[0],
 1226                         mp->mnt_stat.f_fsidx.__fsid_val[1]);
 1227 
 1228         (*pr)("\towner = %"PRIu32"\n",mp->mnt_stat.f_owner);
 1229         (*pr)("\tnamemax = %lu\n",mp->mnt_stat.f_namemax);
 1230 
 1231         snprintb(sbuf, sizeof(sbuf), __MNT_FLAG_BITS, mp->mnt_stat.f_flag);
 1232 
 1233         (*pr)("\tflag = %s\n",sbuf);
 1234         (*pr)("\tsyncwrites = %" PRIu64 "\n",mp->mnt_stat.f_syncwrites);
 1235         (*pr)("\tasyncwrites = %" PRIu64 "\n",mp->mnt_stat.f_asyncwrites);
 1236         (*pr)("\tsyncreads = %" PRIu64 "\n",mp->mnt_stat.f_syncreads);
 1237         (*pr)("\tasyncreads = %" PRIu64 "\n",mp->mnt_stat.f_asyncreads);
 1238         (*pr)("\tfstypename = %s\n",mp->mnt_stat.f_fstypename);
 1239         (*pr)("\tmntonname = %s\n",mp->mnt_stat.f_mntonname);
 1240         (*pr)("\tmntfromname = %s\n",mp->mnt_stat.f_mntfromname);
 1241 
 1242         {
 1243                 int cnt = 0;
 1244                 struct vnode *vp;
 1245                 (*pr)("locked vnodes =");
 1246                 TAILQ_FOREACH(vp, &mp->mnt_vnodelist, v_mntvnodes) {
 1247                         if (VOP_ISLOCKED(vp)) {
 1248                                 if ((++cnt % 6) == 0) {
 1249                                         (*pr)(" %p,\n\t", vp);
 1250                                 } else {
 1251                                         (*pr)(" %p,", vp);
 1252                                 }
 1253                         }
 1254                 }
 1255                 (*pr)("\n");
 1256         }
 1257 
 1258         if (full) {
 1259                 int cnt = 0;
 1260                 struct vnode *vp;
 1261                 (*pr)("all vnodes =");
 1262                 TAILQ_FOREACH(vp, &mp->mnt_vnodelist, v_mntvnodes) {
 1263                         if (!TAILQ_NEXT(vp, v_mntvnodes)) {
 1264                                 (*pr)(" %p", vp);
 1265                         } else if ((++cnt % 6) == 0) {
 1266                                 (*pr)(" %p,\n\t", vp);
 1267                         } else {
 1268                                 (*pr)(" %p,", vp);
 1269                         }
 1270                 }
 1271                 (*pr)("\n", vp);
 1272         }
 1273 }
 1274 
 1275 /*
 1276  * List all of the locked vnodes in the system.
 1277  */
 1278 void printlockedvnodes(void);
 1279 
 1280 void
 1281 printlockedvnodes(void)
 1282 {
 1283         struct mount *mp, *nmp;
 1284         struct vnode *vp;
 1285 
 1286         printf("Locked vnodes\n");
 1287         mutex_enter(&mountlist_lock);
 1288         for (mp = CIRCLEQ_FIRST(&mountlist); mp != (void *)&mountlist;
 1289              mp = nmp) {
 1290                 if (vfs_busy(mp, &nmp)) {
 1291                         continue;
 1292                 }
 1293                 TAILQ_FOREACH(vp, &mp->mnt_vnodelist, v_mntvnodes) {
 1294                         if (VOP_ISLOCKED(vp))
 1295                                 vprint(NULL, vp);
 1296                 }
 1297                 mutex_enter(&mountlist_lock);
 1298                 vfs_unbusy(mp, false, &nmp);
 1299         }
 1300         mutex_exit(&mountlist_lock);
 1301 }
 1302 
 1303 #endif /* DDB || DEBUGPRINT */

Cache object: 891e41b4329c8c499273e180ede10c79


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.