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

          Line data    Source code
       1             : /*      $OpenBSD: ffs_vfsops.c,v 1.178 2018/07/11 17:44:57 kn Exp $     */
       2             : /*      $NetBSD: ffs_vfsops.c,v 1.19 1996/02/09 22:22:26 christos Exp $ */
       3             : 
       4             : /*
       5             :  * Copyright (c) 1989, 1991, 1993, 1994
       6             :  *      The Regents of the University of California.  All rights reserved.
       7             :  *
       8             :  * Redistribution and use in source and binary forms, with or without
       9             :  * modification, are permitted provided that the following conditions
      10             :  * are met:
      11             :  * 1. Redistributions of source code must retain the above copyright
      12             :  *    notice, this list of conditions and the following disclaimer.
      13             :  * 2. Redistributions in binary form must reproduce the above copyright
      14             :  *    notice, this list of conditions and the following disclaimer in the
      15             :  *    documentation and/or other materials provided with the distribution.
      16             :  * 3. Neither the name of the University nor the names of its contributors
      17             :  *    may be used to endorse or promote products derived from this software
      18             :  *    without specific prior written permission.
      19             :  *
      20             :  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
      21             :  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      22             :  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
      23             :  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
      24             :  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
      25             :  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
      26             :  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
      27             :  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
      28             :  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
      29             :  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
      30             :  * SUCH DAMAGE.
      31             :  *
      32             :  *      @(#)ffs_vfsops.c        8.14 (Berkeley) 11/28/94
      33             :  */
      34             : 
      35             : #include <sys/param.h>
      36             : #include <sys/systm.h>
      37             : #include <sys/namei.h>
      38             : #include <sys/proc.h>
      39             : #include <sys/kernel.h>
      40             : #include <sys/vnode.h>
      41             : #include <sys/socket.h>
      42             : #include <sys/mount.h>
      43             : #include <sys/buf.h>
      44             : #include <sys/mbuf.h>
      45             : #include <sys/fcntl.h>
      46             : #include <sys/ioctl.h>
      47             : #include <sys/errno.h>
      48             : #include <sys/malloc.h>
      49             : #include <sys/sysctl.h>
      50             : #include <sys/pool.h>
      51             : #include <sys/dkio.h>
      52             : #include <sys/disk.h>
      53             : #include <sys/specdev.h>
      54             : 
      55             : #include <ufs/ufs/quota.h>
      56             : #include <ufs/ufs/ufsmount.h>
      57             : #include <ufs/ufs/inode.h>
      58             : #include <ufs/ufs/dir.h>
      59             : #include <ufs/ufs/ufs_extern.h>
      60             : #include <ufs/ufs/dirhash.h>
      61             : 
      62             : #include <ufs/ffs/fs.h>
      63             : #include <ufs/ffs/ffs_extern.h>
      64             : 
      65             : #include <uvm/uvm_extern.h>
      66             : 
      67             : int ffs_sbupdate(struct ufsmount *, int);
      68             : int ffs_reload_vnode(struct vnode *, void *);
      69             : int ffs_sync_vnode(struct vnode *, void *);
      70             : int ffs_validate(struct fs *);
      71             : 
      72             : void ffs1_compat_read(struct fs *, struct ufsmount *, daddr_t);
      73             : void ffs1_compat_write(struct fs *, struct ufsmount *);
      74             : 
      75             : const struct vfsops ffs_vfsops = {
      76             :         ffs_mount,
      77             :         ufs_start,
      78             :         ffs_unmount,
      79             :         ufs_root,
      80             :         ufs_quotactl,
      81             :         ffs_statfs,
      82             :         ffs_sync,
      83             :         ffs_vget,
      84             :         ffs_fhtovp,
      85             :         ffs_vptofh,
      86             :         ffs_init,
      87             :         ffs_sysctl,
      88             :         ufs_check_export
      89             : };
      90             : 
      91             : struct inode_vtbl ffs_vtbl = {
      92             :         ffs_truncate,
      93             :         ffs_update,
      94             :         ffs_inode_alloc,
      95             :         ffs_inode_free,
      96             :         ffs_balloc,
      97             :         ffs_bufatoff
      98             : };
      99             : 
     100             : int
     101           0 : ffs_checkrange(struct mount *mp, uint32_t ino)
     102             : {
     103           0 :         struct buf *bp;
     104             :         struct cg *cgp;
     105             :         struct fs *fs;
     106             :         struct ufsmount *ump;
     107             :         int cg, error;
     108             : 
     109           0 :         fs = VFSTOUFS(mp)->um_fs;
     110           0 :         if (ino < ROOTINO || ino >= fs->fs_ncg * fs->fs_ipg)
     111           0 :                 return ESTALE;
     112             : 
     113             :         /*
     114             :          * Need to check if inode is initialized because ffsv2 does
     115             :          * lazy initialization and we can get here from nfs_fhtovp
     116             :          */
     117           0 :         if (fs->fs_magic != FS_UFS2_MAGIC)
     118           0 :                 return 0;
     119             : 
     120           0 :         cg = ino_to_cg(fs, ino);
     121             :         ump = VFSTOUFS(mp);
     122             : 
     123           0 :         error = bread(ump->um_devvp, fsbtodb(fs, cgtod(fs, cg)),
     124           0 :             (int)fs->fs_cgsize, &bp);
     125           0 :         if (error)
     126           0 :                 return error;
     127             : 
     128           0 :         cgp = (struct cg *)bp->b_data;
     129           0 :         if (!cg_chkmagic(cgp)) {
     130           0 :                 brelse(bp);
     131           0 :                 return ESTALE;
     132             :         }
     133             : 
     134           0 :         brelse(bp);
     135             : 
     136           0 :         if (cg * fs->fs_ipg + cgp->cg_initediblk < ino)
     137           0 :                 return ESTALE;
     138             : 
     139           0 :         return 0;
     140           0 : }
     141             : 
     142             : /*
     143             :  * Called by main() when ufs is going to be mounted as root.
     144             :  */
     145             : 
     146             : struct pool ffs_ino_pool;
     147             : struct pool ffs_dinode1_pool;
     148             : #ifdef FFS2
     149             : struct pool ffs_dinode2_pool;
     150             : #endif
     151             : 
     152             : int
     153           0 : ffs_mountroot(void)
     154             : {
     155             :         struct fs *fs;
     156           0 :         struct mount *mp;
     157           0 :         struct proc *p = curproc;       /* XXX */
     158             :         struct ufsmount *ump;
     159             :         int error;
     160             : 
     161             :         /*
     162             :          * Get vnodes for swapdev and rootdev.
     163             :          */
     164           0 :         swapdev_vp = NULL;
     165           0 :         if ((error = bdevvp(swapdev, &swapdev_vp)) ||
     166           0 :             (error = bdevvp(rootdev, &rootvp))) {
     167           0 :                 printf("ffs_mountroot: can't setup bdevvp's\n");
     168           0 :                 if (swapdev_vp)
     169           0 :                         vrele(swapdev_vp);
     170           0 :                 return (error);
     171             :         }
     172             : 
     173           0 :         if ((error = vfs_rootmountalloc("ffs", "root_device", &mp)) != 0) {
     174           0 :                 vrele(swapdev_vp);
     175           0 :                 vrele(rootvp);
     176           0 :                 return (error);
     177             :         }
     178             : 
     179           0 :         if ((error = ffs_mountfs(rootvp, mp, p)) != 0) {
     180           0 :                 mp->mnt_vfc->vfc_refcount--;
     181           0 :                 vfs_unbusy(mp);
     182           0 :                 free(mp, M_MOUNT, sizeof(*mp));
     183           0 :                 vrele(swapdev_vp);
     184           0 :                 vrele(rootvp);
     185           0 :                 return (error);
     186             :         }
     187             : 
     188           0 :         TAILQ_INSERT_TAIL(&mountlist, mp, mnt_list);
     189           0 :         ump = VFSTOUFS(mp);
     190           0 :         fs = ump->um_fs;
     191           0 :         strlcpy(fs->fs_fsmnt, mp->mnt_stat.f_mntonname, sizeof(fs->fs_fsmnt));
     192           0 :         (void)ffs_statfs(mp, &mp->mnt_stat, p);
     193           0 :         vfs_unbusy(mp);
     194           0 :         inittodr(fs->fs_time);
     195             : 
     196           0 :         return (0);
     197           0 : }
     198             : 
     199             : /*
     200             :  * VFS Operations.
     201             :  *
     202             :  * mount system call
     203             :  */
     204             : int
     205           0 : ffs_mount(struct mount *mp, const char *path, void *data,
     206             :     struct nameidata *ndp, struct proc *p)
     207             : {
     208             :         struct vnode *devvp;
     209           0 :         struct ufs_args *args = data;
     210             :         struct ufsmount *ump = NULL;
     211             :         struct fs *fs;
     212           0 :         char fname[MNAMELEN];
     213           0 :         char fspec[MNAMELEN];
     214             :         int error = 0, flags;
     215             :         int ronly;
     216             : 
     217             : #ifndef FFS_SOFTUPDATES
     218             :         if (mp->mnt_flag & MNT_SOFTDEP) {
     219             :                 printf("WARNING: soft updates isn't compiled in\n");
     220             :                 mp->mnt_flag &= ~MNT_SOFTDEP;
     221             :         }
     222             : #endif
     223             : 
     224             :         /*
     225             :          * Soft updates is incompatible with "async",
     226             :          * so if we are doing softupdates stop the user
     227             :          * from setting the async flag.
     228             :          */
     229           0 :         if ((mp->mnt_flag & (MNT_SOFTDEP | MNT_ASYNC)) ==
     230             :             (MNT_SOFTDEP | MNT_ASYNC)) {
     231           0 :                 return (EINVAL);
     232             :         }
     233             :         /*
     234             :          * If updating, check whether changing from read-only to
     235             :          * read/write; if there is no device name, that's all we do.
     236             :          */
     237           0 :         if (mp->mnt_flag & MNT_UPDATE) {
     238           0 :                 ump = VFSTOUFS(mp);
     239           0 :                 fs = ump->um_fs;
     240           0 :                 devvp = ump->um_devvp;
     241             :                 error = 0;
     242           0 :                 ronly = fs->fs_ronly;
     243             : 
     244             :                 /*
     245             :                  * Soft updates won't be set if read/write,
     246             :                  * so "async" will be illegal.
     247             :                  */
     248           0 :                 if (ronly == 0 && (mp->mnt_flag & MNT_ASYNC) &&
     249           0 :                     (fs->fs_flags & FS_DOSOFTDEP)) {
     250             :                         error = EINVAL;
     251           0 :                         goto error_1;
     252             :                 }
     253             : 
     254           0 :                 if (ronly == 0 && (mp->mnt_flag & MNT_RDONLY)) {
     255             :                         /* Flush any dirty data */
     256           0 :                         VFS_SYNC(mp, MNT_WAIT, 0, p->p_ucred, p);
     257             : 
     258             :                         /*
     259             :                          * Get rid of files open for writing.
     260             :                          */
     261             :                         flags = WRITECLOSE;
     262           0 :                         if (args == NULL)
     263           0 :                                 flags |= IGNORECLEAN;
     264           0 :                         if (mp->mnt_flag & MNT_FORCE)
     265           0 :                                 flags |= FORCECLOSE;
     266           0 :                         if (fs->fs_flags & FS_DOSOFTDEP) {
     267           0 :                                 error = softdep_flushfiles(mp, flags, p);
     268           0 :                                 mp->mnt_flag &= ~MNT_SOFTDEP;
     269           0 :                         } else
     270           0 :                                 error = ffs_flushfiles(mp, flags, p);
     271           0 :                         mp->mnt_flag |= MNT_RDONLY;
     272             :                         ronly = 1;
     273           0 :                 }
     274             : 
     275             :                 /*
     276             :                  * Flush soft dependencies if disabling it via an update
     277             :                  * mount. This may leave some items to be processed,
     278             :                  * so don't do this yet XXX.
     279             :                  */
     280           0 :                 if ((fs->fs_flags & FS_DOSOFTDEP) &&
     281           0 :                     !(mp->mnt_flag & MNT_SOFTDEP) &&
     282           0 :                     !(mp->mnt_flag & MNT_RDONLY) && fs->fs_ronly == 0) {
     283             : #if 0
     284             :                         flags = WRITECLOSE;
     285             :                         if (mp->mnt_flag & MNT_FORCE)
     286             :                                 flags |= FORCECLOSE;
     287             :                         error = softdep_flushfiles(mp, flags, p);
     288             : #elif FFS_SOFTUPDATES
     289           0 :                         mp->mnt_flag |= MNT_SOFTDEP;
     290             : #endif
     291           0 :                 }
     292             :                 /*
     293             :                  * When upgrading to a softdep mount, we must first flush
     294             :                  * all vnodes. (not done yet -- see above)
     295             :                  */
     296           0 :                 if (!(fs->fs_flags & FS_DOSOFTDEP) &&
     297           0 :                     (mp->mnt_flag & MNT_SOFTDEP) && fs->fs_ronly == 0) {
     298             : #if 0
     299             :                         flags = WRITECLOSE;
     300             :                         if (mp->mnt_flag & MNT_FORCE)
     301             :                                 flags |= FORCECLOSE;
     302             :                         error = ffs_flushfiles(mp, flags, p);
     303             : #else
     304           0 :                         mp->mnt_flag &= ~MNT_SOFTDEP;
     305             : #endif
     306           0 :                 }
     307             : 
     308           0 :                 if (!error && (mp->mnt_flag & MNT_RELOAD))
     309           0 :                         error = ffs_reload(mp, ndp->ni_cnd.cn_cred, p);
     310           0 :                 if (error)
     311             :                         goto error_1;
     312             : 
     313           0 :                 if (ronly && (mp->mnt_flag & MNT_WANTRDWR)) {
     314           0 :                         if (fs->fs_clean == 0) {
     315             : #if 0
     316             :                                 /*
     317             :                                  * It is safe to mount an unclean file system
     318             :                                  * if it was previously mounted with softdep
     319             :                                  * but we may lose space and must
     320             :                                  * sometimes run fsck manually.
     321             :                                  */
     322             :                                 if (fs->fs_flags & FS_DOSOFTDEP)
     323             :                                         printf(
     324             : "WARNING: %s was not properly unmounted\n",
     325             :                                             fs->fs_fsmnt);
     326             :                                 else
     327             : #endif
     328           0 :                                 if (mp->mnt_flag & MNT_FORCE) {
     329           0 :                                         printf(
     330             : "WARNING: %s was not properly unmounted\n",
     331             :                                             fs->fs_fsmnt);
     332             :                                 } else {
     333           0 :                                         printf(
     334             : "WARNING: R/W mount of %s denied.  Filesystem is not clean - run fsck\n",
     335             :                                             fs->fs_fsmnt);
     336             :                                         error = EROFS;
     337           0 :                                         goto error_1;
     338             :                                 }
     339           0 :                         }
     340             : 
     341           0 :                         if ((fs->fs_flags & FS_DOSOFTDEP)) {
     342           0 :                                 error = softdep_mount(devvp, mp, fs,
     343           0 :                                                       p->p_ucred);
     344           0 :                                 if (error)
     345             :                                         goto error_1;
     346             :                         }
     347           0 :                         fs->fs_contigdirs = malloc((u_long)fs->fs_ncg,
     348             :                              M_UFSMNT, M_WAITOK|M_ZERO);
     349             : 
     350             :                         ronly = 0;
     351           0 :                 }
     352           0 :                 if (args == NULL)
     353             :                         goto success;
     354           0 :                 if (args->fspec == NULL) {
     355             :                         /*
     356             :                          * Process export requests.
     357             :                          */
     358           0 :                         error = vfs_export(mp, &ump->um_export, 
     359           0 :                             &args->export_info);
     360           0 :                         if (error)
     361             :                                 goto error_1;
     362             :                         else
     363             :                                 goto success;
     364             :                 }
     365             :         }
     366             : 
     367             :         /*
     368             :          * Not an update, or updating the name: look up the name
     369             :          * and verify that it refers to a sensible block device.
     370             :          */
     371           0 :         error = copyinstr(args->fspec, fspec, sizeof(fspec), NULL);
     372           0 :         if (error)
     373             :                 goto error_1;
     374             : 
     375           0 :         if (disk_map(fspec, fname, MNAMELEN, DM_OPENBLCK) == -1)
     376           0 :                 memcpy(fname, fspec, sizeof(fname));
     377             : 
     378           0 :         NDINIT(ndp, LOOKUP, FOLLOW, UIO_SYSSPACE, fname, p);
     379           0 :         if ((error = namei(ndp)) != 0)
     380             :                 goto error_1;
     381             : 
     382           0 :         devvp = ndp->ni_vp;
     383             : 
     384           0 :         if (devvp->v_type != VBLK) {
     385             :                 error = ENOTBLK;
     386           0 :                 goto error_2;
     387             :         }
     388             : 
     389           0 :         if (major(devvp->v_rdev) >= nblkdev) {
     390             :                 error = ENXIO;
     391           0 :                 goto error_2;
     392             :         }
     393             : 
     394           0 :         if (mp->mnt_flag & MNT_UPDATE) {
     395             :                 /*
     396             :                  * UPDATE
     397             :                  * If it's not the same vnode, or at least the same device
     398             :                  * then it's not correct.
     399             :                  */
     400             : 
     401           0 :                 if (devvp != ump->um_devvp) {
     402           0 :                         if (devvp->v_rdev == ump->um_devvp->v_rdev) {
     403           0 :                                 vrele(devvp);
     404           0 :                         } else {
     405             :                                 error = EINVAL; /* needs translation */
     406             :                         }
     407             :                 } else
     408           0 :                         vrele(devvp);
     409             :                 /*
     410             :                  * Update device name only on success
     411             :                  */
     412           0 :                 if (!error) {
     413             :                         /*
     414             :                          * Save "mounted from" info for mount point (NULL pad)
     415             :                          */
     416           0 :                         memset(mp->mnt_stat.f_mntfromname, 0, MNAMELEN);
     417           0 :                         strlcpy(mp->mnt_stat.f_mntfromname, fname, MNAMELEN);
     418           0 :                         memset(mp->mnt_stat.f_mntfromspec, 0, MNAMELEN);
     419           0 :                         strlcpy(mp->mnt_stat.f_mntfromspec, fspec, MNAMELEN);
     420           0 :                 }
     421             :         } else {
     422             :                 /*
     423             :                  * Since this is a new mount, we want the names for
     424             :                  * the device and the mount point copied in.  If an
     425             :                  * error occurs,  the mountpoint is discarded by the
     426             :                  * upper level code.
     427             :                  */
     428           0 :                 memset(mp->mnt_stat.f_mntonname, 0, MNAMELEN);
     429           0 :                 strlcpy(mp->mnt_stat.f_mntonname, path, MNAMELEN);
     430           0 :                 memset(mp->mnt_stat.f_mntfromname, 0, MNAMELEN);
     431           0 :                 strlcpy(mp->mnt_stat.f_mntfromname, fname, MNAMELEN);
     432           0 :                 memset(mp->mnt_stat.f_mntfromspec, 0, MNAMELEN);
     433           0 :                 strlcpy(mp->mnt_stat.f_mntfromspec, fspec, MNAMELEN);
     434             : 
     435           0 :                 error = ffs_mountfs(devvp, mp, p);
     436             :         }
     437             : 
     438           0 :         if (error)
     439             :                 goto error_2;
     440             : 
     441             :         /*
     442             :          * Initialize FS stat information in mount struct; uses both
     443             :          * mp->mnt_stat.f_mntonname and mp->mnt_stat.f_mntfromname
     444             :          *
     445             :          * This code is common to root and non-root mounts
     446             :          */
     447           0 :         if (args)
     448           0 :                 memcpy(&mp->mnt_stat.mount_info.ufs_args, args, sizeof(*args));
     449           0 :         VFS_STATFS(mp, &mp->mnt_stat, p);
     450             : 
     451             : success:
     452           0 :         if (path && (mp->mnt_flag & MNT_UPDATE)) {
     453             :                 /* Update clean flag after changing read-onlyness. */
     454           0 :                 fs = ump->um_fs;
     455           0 :                 if (ronly != fs->fs_ronly) {
     456           0 :                         fs->fs_ronly = ronly;
     457           0 :                         fs->fs_clean = ronly &&
     458           0 :                             (fs->fs_flags & FS_UNCLEAN) == 0 ? 1 : 0;
     459           0 :                         if (ronly)
     460           0 :                                 free(fs->fs_contigdirs, M_UFSMNT, fs->fs_ncg);
     461             :                 }
     462           0 :                 if (!ronly) {
     463           0 :                         if (mp->mnt_flag & MNT_SOFTDEP)
     464           0 :                                 fs->fs_flags |= FS_DOSOFTDEP;
     465             :                         else
     466           0 :                                 fs->fs_flags &= ~FS_DOSOFTDEP;
     467             :                 }
     468           0 :                 ffs_sbupdate(ump, MNT_WAIT);
     469             : #if 0
     470             :                 if (ronly) {
     471             :                         int force = 0;
     472             : 
     473             :                         /*
     474             :                          * Updating mount to readonly. Try a cache flush.
     475             :                          * Ignore error because the ioctl may not be supported.
     476             :                          */
     477             :                         VOP_IOCTL(ump->um_devvp, DIOCCACHESYNC, &force,
     478             :                             FWRITE, FSCRED, p);
     479             :                }
     480             : #endif
     481           0 :         }
     482           0 :         return (0);
     483             : 
     484             : error_2:        /* error with devvp held */
     485           0 :         vrele (devvp);
     486             : 
     487             : error_1:        /* no state to back out */
     488           0 :         return (error);
     489           0 : }
     490             : 
     491             : struct ffs_reload_args {
     492             :         struct fs *fs;
     493             :         struct proc *p;
     494             :         struct ucred *cred;
     495             :         struct vnode *devvp;
     496             : };
     497             : 
     498             : int
     499           0 : ffs_reload_vnode(struct vnode *vp, void *args) 
     500             : {
     501           0 :         struct ffs_reload_args *fra = args;
     502             :         struct inode *ip;
     503           0 :         struct buf *bp;
     504             :         int error;
     505             : 
     506             :         /*
     507             :          * Step 4: invalidate all inactive vnodes.
     508             :          */
     509           0 :         if (vp->v_usecount == 0) {
     510           0 :                 vgonel(vp, fra->p);
     511           0 :                 return (0);
     512             :         }
     513             : 
     514             :         /*
     515             :          * Step 5: invalidate all cached file data.
     516             :          */
     517           0 :         if (vget(vp, LK_EXCLUSIVE))
     518           0 :                 return (0);
     519             : 
     520           0 :         if (vinvalbuf(vp, 0, fra->cred, fra->p, 0, 0))
     521           0 :                 panic("ffs_reload: dirty2");
     522             : 
     523             :         /*
     524             :          * Step 6: re-read inode data for all active vnodes.
     525             :          */
     526           0 :         ip = VTOI(vp);
     527             : 
     528           0 :         error = bread(fra->devvp, 
     529           0 :             fsbtodb(fra->fs, ino_to_fsba(fra->fs, ip->i_number)),
     530           0 :             (int)fra->fs->fs_bsize, &bp);
     531           0 :         if (error) {
     532           0 :                 brelse(bp);
     533           0 :                 vput(vp);
     534           0 :                 return (error);
     535             :         }
     536             : 
     537           0 :         *ip->i_din1 = *((struct ufs1_dinode *)bp->b_data +
     538           0 :             ino_to_fsbo(fra->fs, ip->i_number));
     539           0 :         ip->i_effnlink = DIP(ip, nlink);
     540           0 :         brelse(bp);
     541           0 :         vput(vp);
     542           0 :         return (0);
     543           0 : }
     544             : 
     545             : /*
     546             :  * Reload all incore data for a filesystem (used after running fsck on
     547             :  * the root filesystem and finding things to fix). The filesystem must
     548             :  * be mounted read-only.
     549             :  *
     550             :  * Things to do to update the mount:
     551             :  *      1) invalidate all cached meta-data.
     552             :  *      2) re-read superblock from disk.
     553             :  *      3) re-read summary information from disk.
     554             :  *      4) invalidate all inactive vnodes.
     555             :  *      5) invalidate all cached file data.
     556             :  *      6) re-read inode data for all active vnodes.
     557             :  */
     558             : int
     559           0 : ffs_reload(struct mount *mountp, struct ucred *cred, struct proc *p)
     560             : {
     561             :         struct vnode *devvp;
     562             :         caddr_t space;
     563             :         struct fs *fs, *newfs;
     564             :         int i, blks, size, error;
     565             :         int32_t *lp;
     566           0 :         struct buf *bp = NULL;
     567           0 :         struct ffs_reload_args fra;
     568             : 
     569           0 :         if ((mountp->mnt_flag & MNT_RDONLY) == 0)
     570           0 :                 return (EINVAL);
     571             :         /*
     572             :          * Step 1: invalidate all cached meta-data.
     573             :          */
     574           0 :         devvp = VFSTOUFS(mountp)->um_devvp;
     575           0 :         vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
     576           0 :         error = vinvalbuf(devvp, 0, cred, p, 0, 0);
     577           0 :         VOP_UNLOCK(devvp);
     578           0 :         if (error)
     579           0 :                 panic("ffs_reload: dirty1");
     580             : 
     581             :         /*
     582             :          * Step 2: re-read superblock from disk.
     583             :          */
     584           0 :         fs = VFSTOUFS(mountp)->um_fs;
     585             : 
     586           0 :         error = bread(devvp, fs->fs_sblockloc / DEV_BSIZE, SBSIZE, &bp);
     587           0 :         if (error) {
     588           0 :                 brelse(bp);
     589           0 :                 return (error);
     590             :         }
     591             : 
     592           0 :         newfs = (struct fs *)bp->b_data;
     593           0 :         if (ffs_validate(newfs) == 0) {
     594           0 :                 brelse(bp);
     595           0 :                 return (EINVAL);
     596             :         }
     597             : 
     598             :         /*
     599             :          * Copy pointer fields back into superblock before copying in   XXX
     600             :          * new superblock. These should really be in the ufsmount.      XXX
     601             :          * Note that important parameters (eg fs_ncg) are unchanged.
     602             :          */
     603           0 :         newfs->fs_csp = fs->fs_csp;
     604           0 :         newfs->fs_maxcluster = fs->fs_maxcluster;
     605           0 :         newfs->fs_ronly = fs->fs_ronly;
     606           0 :         memcpy(fs, newfs, fs->fs_sbsize);
     607           0 :         if (fs->fs_sbsize < SBSIZE)
     608           0 :                 bp->b_flags |= B_INVAL;
     609           0 :         brelse(bp);
     610           0 :         VFSTOUFS(mountp)->um_maxsymlinklen = fs->fs_maxsymlinklen;
     611           0 :         ffs1_compat_read(fs, VFSTOUFS(mountp), fs->fs_sblockloc);
     612           0 :         ffs_oldfscompat(fs);
     613           0 :         (void)ffs_statfs(mountp, &mountp->mnt_stat, p);
     614             :         /*
     615             :          * Step 3: re-read summary information from disk.
     616             :          */
     617           0 :         blks = howmany(fs->fs_cssize, fs->fs_fsize);
     618           0 :         space = (caddr_t)fs->fs_csp;
     619           0 :         for (i = 0; i < blks; i += fs->fs_frag) {
     620           0 :                 size = fs->fs_bsize;
     621           0 :                 if (i + fs->fs_frag > blks)
     622           0 :                         size = (blks - i) * fs->fs_fsize;
     623           0 :                 error = bread(devvp, fsbtodb(fs, fs->fs_csaddr + i), size, &bp);
     624           0 :                 if (error) {
     625           0 :                         brelse(bp);
     626           0 :                         return (error);
     627             :                 }
     628           0 :                 memcpy(space, bp->b_data, size);
     629           0 :                 space += size;
     630           0 :                 brelse(bp);
     631             :         }
     632           0 :         if ((fs->fs_flags & FS_DOSOFTDEP))
     633           0 :                 (void) softdep_mount(devvp, mountp, fs, cred);
     634             :         /*
     635             :          * We no longer know anything about clusters per cylinder group.
     636             :          */
     637           0 :         if (fs->fs_contigsumsize > 0) {
     638           0 :                 lp = fs->fs_maxcluster;
     639           0 :                 for (i = 0; i < fs->fs_ncg; i++)
     640           0 :                         *lp++ = fs->fs_contigsumsize;
     641             :         }
     642             : 
     643           0 :         fra.p = p;
     644           0 :         fra.cred = cred;
     645           0 :         fra.fs = fs;
     646           0 :         fra.devvp = devvp;
     647             : 
     648           0 :         error = vfs_mount_foreach_vnode(mountp, ffs_reload_vnode, &fra);
     649             : 
     650           0 :         return (error);
     651           0 : }
     652             : 
     653             : /*
     654             :  * Checks if a super block is sane enough to be mounted.
     655             :  */
     656             : int
     657           0 : ffs_validate(struct fs *fsp)
     658             : {
     659             : #ifdef FFS2
     660           0 :         if (fsp->fs_magic != FS_UFS2_MAGIC && fsp->fs_magic != FS_UFS1_MAGIC)
     661           0 :                 return (0); /* Invalid magic */
     662             : #else
     663             :         if (fsp->fs_magic != FS_UFS1_MAGIC)
     664             :                 return (0); /* Invalid magic */
     665             : #endif /* FFS2 */
     666             : 
     667           0 :         if ((u_int)fsp->fs_bsize > MAXBSIZE)
     668           0 :                 return (0); /* Invalid block size */
     669             : 
     670           0 :         if ((u_int)fsp->fs_bsize < sizeof(struct fs))
     671           0 :                 return (0); /* Invalid block size */
     672             : 
     673           0 :         if ((u_int)fsp->fs_sbsize > SBSIZE)
     674           0 :                 return (0); /* Invalid super block size */
     675             : 
     676           0 :         if ((u_int)fsp->fs_frag > MAXFRAG || fragtbl[fsp->fs_frag] == NULL)
     677           0 :                 return (0); /* Invalid number of fragments */
     678             : 
     679           0 :         if (fsp->fs_inodefmt == FS_42INODEFMT)
     680           0 :                 fsp->fs_maxsymlinklen = 0;
     681           0 :         else if (fsp->fs_maxsymlinklen < 0)
     682           0 :                 return (0); /* Invalid max size of short symlink */
     683             : 
     684           0 :         return (1); /* Super block is okay */
     685           0 : }
     686             : 
     687             : /*
     688             :  * Possible locations for the super-block.
     689             :  */
     690             : const int sbtry[] = SBLOCKSEARCH;
     691             : 
     692             : /*
     693             :  * Common code for mount and mountroot
     694             :  */
     695             : int
     696           0 : ffs_mountfs(struct vnode *devvp, struct mount *mp, struct proc *p)
     697             : {
     698             :         struct ufsmount *ump;
     699           0 :         struct buf *bp;
     700             :         struct fs *fs;
     701             :         dev_t dev;
     702             :         caddr_t space;
     703             :         daddr_t sbloc;
     704             :         int error, i, blks, size, ronly;
     705             :         int32_t *lp;
     706             :         struct ucred *cred;
     707             :         u_int64_t maxfilesize;                                  /* XXX */
     708             : 
     709           0 :         dev = devvp->v_rdev;
     710           0 :         cred = p ? p->p_ucred : NOCRED;
     711             :         /*
     712             :          * Disallow multiple mounts of the same device.
     713             :          * Disallow mounting of a device that is currently in use
     714             :          * (except for root, which might share swap device for miniroot).
     715             :          * Flush out any old buffers remaining from a previous use.
     716             :          */
     717           0 :         if ((error = vfs_mountedon(devvp)) != 0)
     718           0 :                 return (error);
     719           0 :         if (vcount(devvp) > 1 && devvp != rootvp)
     720           0 :                 return (EBUSY);
     721           0 :         vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
     722           0 :         error = vinvalbuf(devvp, V_SAVE, cred, p, 0, 0);
     723           0 :         VOP_UNLOCK(devvp);
     724           0 :         if (error)
     725           0 :                 return (error);
     726             : 
     727           0 :         ronly = (mp->mnt_flag & MNT_RDONLY) != 0;
     728           0 :         error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, FSCRED, p);
     729           0 :         if (error)
     730           0 :                 return (error);
     731             : 
     732           0 :         bp = NULL;
     733             :         ump = NULL;
     734             : 
     735             :         /*
     736             :          * Try reading the super-block in each of its possible locations.
     737             :          */
     738           0 :         for (i = 0; sbtry[i] != -1; i++) {
     739           0 :                 if (bp != NULL) {
     740           0 :                         bp->b_flags |= B_NOCACHE;
     741           0 :                         brelse(bp);
     742           0 :                         bp = NULL;
     743           0 :                 }
     744             : 
     745           0 :                 error = bread(devvp, sbtry[i] / DEV_BSIZE, SBSIZE, &bp);
     746           0 :                 if (error)
     747             :                         goto out;
     748             : 
     749           0 :                 fs = (struct fs *) bp->b_data;
     750           0 :                 sbloc = sbtry[i];
     751             : 
     752             : #if 0
     753             :                 if (fs->fs_magic == FS_UFS2_MAGIC) {
     754             :                         printf("ffs_mountfs(): Sorry, no UFS2 support (yet)\n");
     755             :                         error = EFTYPE;
     756             :                         goto out;
     757             :                 }
     758             : #endif
     759             : 
     760             :                 /*
     761             :                  * Do not look for an FFS1 file system at SBLOCK_UFS2. Doing so
     762             :                  * will find the wrong super-block for file systems with 64k
     763             :                  * block size.
     764             :                  */
     765           0 :                 if (fs->fs_magic == FS_UFS1_MAGIC && sbloc == SBLOCK_UFS2)
     766             :                         continue;
     767             : 
     768           0 :                 if (ffs_validate(fs))
     769             :                         break; /* Super block validated */
     770             :         }
     771             : 
     772           0 :         if (sbtry[i] == -1) {
     773             :                 error = EINVAL;
     774           0 :                 goto out;
     775             :         }
     776             : 
     777           0 :         fs->fs_fmod = 0;
     778           0 :         fs->fs_flags &= ~FS_UNCLEAN;
     779           0 :         if (fs->fs_clean == 0) {
     780             : #if 0
     781             :                 /*
     782             :                  * It is safe to mount an unclean file system
     783             :                  * if it was previously mounted with softdep
     784             :                  * but we may lose space and must
     785             :                  * sometimes run fsck manually.
     786             :                  */
     787             :                 if (fs->fs_flags & FS_DOSOFTDEP)
     788             :                         printf(
     789             : "WARNING: %s was not properly unmounted\n",
     790             :                             fs->fs_fsmnt);
     791             :                 else
     792             : #endif
     793           0 :                 if (ronly || (mp->mnt_flag & MNT_FORCE)) {
     794           0 :                         printf(
     795             : "WARNING: %s was not properly unmounted\n",
     796           0 :                             fs->fs_fsmnt);
     797             :                 } else {
     798           0 :                         printf(
     799             : "WARNING: R/W mount of %s denied.  Filesystem is not clean - run fsck\n",
     800           0 :                             fs->fs_fsmnt);
     801             :                         error = EROFS;
     802           0 :                         goto out;
     803             :                 }
     804           0 :         }
     805             : 
     806           0 :         if (fs->fs_postblformat == FS_42POSTBLFMT && !ronly) {
     807             : #ifndef SMALL_KERNEL
     808           0 :                 printf("ffs_mountfs(): obsolete rotational table format, "
     809             :                     "please use fsck_ffs(8) -c 1\n");
     810             : #endif
     811             :                 error = EFTYPE;
     812           0 :                 goto out;
     813             :         }
     814             : 
     815           0 :         ump = malloc(sizeof *ump, M_UFSMNT, M_WAITOK|M_ZERO);
     816           0 :         ump->um_fs = malloc((u_long)fs->fs_sbsize, M_UFSMNT,
     817             :             M_WAITOK);
     818             : 
     819           0 :         if (fs->fs_magic == FS_UFS1_MAGIC)
     820           0 :                 ump->um_fstype = UM_UFS1;
     821             : #ifdef FFS2
     822             :         else
     823           0 :                 ump->um_fstype = UM_UFS2;
     824             : #endif
     825             : 
     826           0 :         memcpy(ump->um_fs, bp->b_data, fs->fs_sbsize);
     827           0 :         if (fs->fs_sbsize < SBSIZE)
     828           0 :                 bp->b_flags |= B_INVAL;
     829           0 :         brelse(bp);
     830           0 :         bp = NULL;
     831           0 :         fs = ump->um_fs;
     832             : 
     833           0 :         ffs1_compat_read(fs, ump, sbloc);
     834             : 
     835           0 :         if (fs->fs_clean == 0)
     836           0 :                 fs->fs_flags |= FS_UNCLEAN;
     837           0 :         fs->fs_ronly = ronly;
     838           0 :         size = fs->fs_cssize;
     839           0 :         blks = howmany(size, fs->fs_fsize);
     840           0 :         if (fs->fs_contigsumsize > 0)
     841           0 :                 size += fs->fs_ncg * sizeof(int32_t);
     842           0 :         space = malloc((u_long)size, M_UFSMNT, M_WAITOK);
     843           0 :         fs->fs_csp = (struct csum *)space;
     844           0 :         for (i = 0; i < blks; i += fs->fs_frag) {
     845           0 :                 size = fs->fs_bsize;
     846           0 :                 if (i + fs->fs_frag > blks)
     847           0 :                         size = (blks - i) * fs->fs_fsize;
     848           0 :                 error = bread(devvp, fsbtodb(fs, fs->fs_csaddr + i), size, &bp);
     849           0 :                 if (error) {
     850           0 :                         free(fs->fs_csp, M_UFSMNT, 0);
     851           0 :                         goto out;
     852             :                 }
     853           0 :                 memcpy(space, bp->b_data, size);
     854           0 :                 space += size;
     855           0 :                 brelse(bp);
     856           0 :                 bp = NULL;
     857             :         }
     858           0 :         if (fs->fs_contigsumsize > 0) {
     859           0 :                 fs->fs_maxcluster = lp = (int32_t *)space;
     860           0 :                 for (i = 0; i < fs->fs_ncg; i++)
     861           0 :                         *lp++ = fs->fs_contigsumsize;
     862             :         }
     863           0 :         mp->mnt_data = ump;
     864           0 :         mp->mnt_stat.f_fsid.val[0] = (long)dev;
     865             :         /* Use on-disk fsid if it exists, else fake it */
     866           0 :         if (fs->fs_id[0] != 0 && fs->fs_id[1] != 0)
     867           0 :                 mp->mnt_stat.f_fsid.val[1] = fs->fs_id[1];
     868             :         else
     869           0 :                 mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum;
     870           0 :         mp->mnt_stat.f_namemax = MAXNAMLEN;
     871           0 :         mp->mnt_flag |= MNT_LOCAL;
     872           0 :         ump->um_mountp = mp;
     873           0 :         ump->um_dev = dev;
     874           0 :         ump->um_devvp = devvp;
     875           0 :         ump->um_nindir = fs->fs_nindir;
     876           0 :         ump->um_bptrtodb = fs->fs_fsbtodb;
     877           0 :         ump->um_seqinc = fs->fs_frag;
     878           0 :         ump->um_maxsymlinklen = fs->fs_maxsymlinklen;
     879           0 :         for (i = 0; i < MAXQUOTAS; i++)
     880           0 :                 ump->um_quotas[i] = NULLVP;
     881             : 
     882           0 :         devvp->v_specmountpoint = mp;
     883           0 :         ffs_oldfscompat(fs);
     884             : 
     885           0 :         if (ronly)
     886           0 :                 fs->fs_contigdirs = NULL;
     887             :         else {
     888           0 :                 fs->fs_contigdirs = malloc((u_long)fs->fs_ncg,
     889             :                     M_UFSMNT, M_WAITOK|M_ZERO);
     890             :         }
     891             : 
     892             :         /*
     893             :          * Set FS local "last mounted on" information (NULL pad)
     894             :          */
     895           0 :         memset(fs->fs_fsmnt, 0, sizeof(fs->fs_fsmnt));
     896           0 :         strlcpy(fs->fs_fsmnt, mp->mnt_stat.f_mntonname, sizeof(fs->fs_fsmnt));
     897             : 
     898             : #if 0
     899             :         if( mp->mnt_flag & MNT_ROOTFS) {
     900             :                 /*
     901             :                  * Root mount; update timestamp in mount structure.
     902             :                  * this will be used by the common root mount code
     903             :                  * to update the system clock.
     904             :                  */
     905             :                 mp->mnt_time = fs->fs_time;
     906             :         }
     907             : #endif
     908             : 
     909             :         /*
     910             :          * XXX
     911             :          * Limit max file size.  Even though ffs can handle files up to 16TB,
     912             :          * we do limit the max file to 2^31 pages to prevent overflow of
     913             :          * a 32-bit unsigned int.  The buffer cache has its own checks but
     914             :          * a little added paranoia never hurts.
     915             :          */
     916           0 :         ump->um_savedmaxfilesize = fs->fs_maxfilesize;            /* XXX */
     917           0 :         maxfilesize = FS_KERNMAXFILESIZE(PAGE_SIZE, fs);
     918           0 :         if (fs->fs_maxfilesize > maxfilesize)                     /* XXX */
     919           0 :                 fs->fs_maxfilesize = maxfilesize;            /* XXX */
     920           0 :         if (ronly == 0) {
     921           0 :                 if ((fs->fs_flags & FS_DOSOFTDEP) &&
     922           0 :                     (error = softdep_mount(devvp, mp, fs, cred)) != 0) {
     923           0 :                         free(fs->fs_csp, M_UFSMNT, 0);
     924           0 :                         free(fs->fs_contigdirs, M_UFSMNT, fs->fs_ncg);
     925           0 :                         goto out;
     926             :                 }
     927           0 :                 fs->fs_fmod = 1;
     928           0 :                 fs->fs_clean = 0;
     929           0 :                 if (mp->mnt_flag & MNT_SOFTDEP)
     930           0 :                         fs->fs_flags |= FS_DOSOFTDEP;
     931             :                 else
     932           0 :                         fs->fs_flags &= ~FS_DOSOFTDEP;
     933           0 :                 error = ffs_sbupdate(ump, MNT_WAIT);
     934           0 :                 if (error == EROFS)
     935             :                         goto out;
     936             :         }
     937           0 :         return (0);
     938             : out:
     939           0 :         if (devvp->v_specinfo)
     940           0 :                 devvp->v_specmountpoint = NULL;
     941           0 :         if (bp)
     942           0 :                 brelse(bp);
     943             : 
     944           0 :         vn_lock(devvp, LK_EXCLUSIVE|LK_RETRY);
     945           0 :         (void)VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, cred, p);
     946           0 :         VOP_UNLOCK(devvp);
     947             : 
     948           0 :         if (ump) {
     949           0 :                 free(ump->um_fs, M_UFSMNT, ump->um_fs->fs_sbsize);
     950           0 :                 free(ump, M_UFSMNT, sizeof(*ump));
     951           0 :                 mp->mnt_data = NULL;
     952           0 :         }
     953           0 :         return (error);
     954           0 : }
     955             : 
     956             : /*
     957             :  * Sanity checks for old file systems.
     958             :  */
     959             : int
     960           0 : ffs_oldfscompat(struct fs *fs)
     961             : {
     962             :         int i;
     963             : 
     964           0 :         fs->fs_npsect = max(fs->fs_npsect, fs->fs_nsect);      /* XXX */
     965           0 :         fs->fs_interleave = max(fs->fs_interleave, 1);            /* XXX */
     966           0 :         if (fs->fs_postblformat == FS_42POSTBLFMT)           /* XXX */
     967           0 :                 fs->fs_nrpos = 8;                            /* XXX */
     968           0 :         if (fs->fs_inodefmt < FS_44INODEFMT) {                    /* XXX */
     969           0 :                 u_int64_t sizepb = fs->fs_bsize;             /* XXX */
     970             :                                                                 /* XXX */
     971           0 :                 fs->fs_maxfilesize = fs->fs_bsize * NDADDR - 1;   /* XXX */
     972           0 :                 for (i = 0; i < NIADDR; i++) {                       /* XXX */
     973           0 :                         sizepb *= NINDIR(fs);                   /* XXX */
     974           0 :                         fs->fs_maxfilesize += sizepb;                /* XXX */
     975             :                 }                                               /* XXX */
     976           0 :                 fs->fs_qbmask = ~fs->fs_bmask;                    /* XXX */
     977           0 :                 fs->fs_qfmask = ~fs->fs_fmask;                    /* XXX */
     978           0 :         }                                                       /* XXX */
     979           0 :         if (fs->fs_avgfilesize <= 0)                              /* XXX */
     980           0 :                 fs->fs_avgfilesize = AVFILESIZ;                      /* XXX */
     981           0 :         if (fs->fs_avgfpdir <= 0)                         /* XXX */
     982           0 :                 fs->fs_avgfpdir = AFPDIR;                    /* XXX */
     983           0 :         return (0);
     984             : }
     985             : 
     986             : /*
     987             :  * Auxiliary function for reading FFS1 super blocks.
     988             :  */
     989             : void
     990           0 : ffs1_compat_read(struct fs *fs, struct ufsmount *ump, daddr_t sbloc)
     991             : {
     992           0 :         if (fs->fs_magic == FS_UFS2_MAGIC)
     993             :                 return; /* UFS2 */
     994             : #if 0
     995             :         if (fs->fs_ffs1_flags & FS_FLAGS_UPDATED)
     996             :                 return; /* Already updated */
     997             : #endif
     998           0 :         fs->fs_flags = fs->fs_ffs1_flags;
     999           0 :         fs->fs_sblockloc = sbloc;
    1000           0 :         fs->fs_maxbsize = fs->fs_bsize;
    1001           0 :         fs->fs_time = fs->fs_ffs1_time;
    1002           0 :         fs->fs_size = fs->fs_ffs1_size;
    1003           0 :         fs->fs_dsize = fs->fs_ffs1_dsize;
    1004           0 :         fs->fs_csaddr = fs->fs_ffs1_csaddr;
    1005           0 :         fs->fs_cstotal.cs_ndir = fs->fs_ffs1_cstotal.cs_ndir;
    1006           0 :         fs->fs_cstotal.cs_nbfree = fs->fs_ffs1_cstotal.cs_nbfree;
    1007           0 :         fs->fs_cstotal.cs_nifree = fs->fs_ffs1_cstotal.cs_nifree;
    1008           0 :         fs->fs_cstotal.cs_nffree = fs->fs_ffs1_cstotal.cs_nffree;
    1009           0 :         fs->fs_ffs1_flags |= FS_FLAGS_UPDATED;
    1010           0 : }
    1011             : 
    1012             : /*
    1013             :  * Auxiliary function for writing FFS1 super blocks.
    1014             :  */
    1015             : void
    1016           0 : ffs1_compat_write(struct fs *fs, struct ufsmount *ump)
    1017             : {
    1018           0 :         if (fs->fs_magic != FS_UFS1_MAGIC)
    1019             :                 return; /* UFS2 */
    1020             : 
    1021           0 :         fs->fs_ffs1_time = fs->fs_time;
    1022           0 :         fs->fs_ffs1_cstotal.cs_ndir = fs->fs_cstotal.cs_ndir;
    1023           0 :         fs->fs_ffs1_cstotal.cs_nbfree = fs->fs_cstotal.cs_nbfree;
    1024           0 :         fs->fs_ffs1_cstotal.cs_nifree = fs->fs_cstotal.cs_nifree;
    1025           0 :         fs->fs_ffs1_cstotal.cs_nffree = fs->fs_cstotal.cs_nffree;
    1026           0 : }
    1027             : 
    1028             : /*
    1029             :  * unmount system call
    1030             :  */
    1031             : int
    1032           0 : ffs_unmount(struct mount *mp, int mntflags, struct proc *p)
    1033             : {
    1034             :         struct ufsmount *ump;
    1035             :         struct fs *fs;
    1036             :         int error, flags;
    1037             : 
    1038             :         flags = 0;
    1039           0 :         if (mntflags & MNT_FORCE)
    1040           0 :                 flags |= FORCECLOSE;
    1041             : 
    1042           0 :         ump = VFSTOUFS(mp);
    1043           0 :         fs = ump->um_fs;
    1044           0 :         if (mp->mnt_flag & MNT_SOFTDEP)
    1045           0 :                 error = softdep_flushfiles(mp, flags, p);
    1046             :         else
    1047           0 :                 error = ffs_flushfiles(mp, flags, p);
    1048           0 :         if (error != 0)
    1049           0 :                 return (error);
    1050             : 
    1051           0 :         if (fs->fs_ronly == 0) {
    1052           0 :                 fs->fs_clean = (fs->fs_flags & FS_UNCLEAN) ? 0 : 1;
    1053           0 :                 error = ffs_sbupdate(ump, MNT_WAIT);
    1054             :                 /* ignore write errors if mounted RW on read-only device */
    1055           0 :                 if (error && error != EROFS) {
    1056           0 :                         fs->fs_clean = 0;
    1057           0 :                         return (error);
    1058             :                 }
    1059           0 :                 free(fs->fs_contigdirs, M_UFSMNT, fs->fs_ncg);
    1060           0 :         }
    1061           0 :         ump->um_devvp->v_specmountpoint = NULL;
    1062             : 
    1063           0 :         vn_lock(ump->um_devvp, LK_EXCLUSIVE | LK_RETRY);
    1064           0 :         vinvalbuf(ump->um_devvp, V_SAVE, NOCRED, p, 0, 0);
    1065           0 :         (void)VOP_CLOSE(ump->um_devvp, fs->fs_ronly ? FREAD : FREAD|FWRITE,
    1066             :             NOCRED, p);
    1067           0 :         vput(ump->um_devvp);
    1068           0 :         free(fs->fs_csp, M_UFSMNT, 0);
    1069           0 :         free(fs, M_UFSMNT, fs->fs_sbsize);
    1070           0 :         free(ump, M_UFSMNT, sizeof(*ump));
    1071           0 :         mp->mnt_data = NULL;
    1072           0 :         mp->mnt_flag &= ~MNT_LOCAL;
    1073           0 :         return (0);
    1074           0 : }
    1075             : 
    1076             : /*
    1077             :  * Flush out all the files in a filesystem.
    1078             :  */
    1079             : int
    1080           0 : ffs_flushfiles(struct mount *mp, int flags, struct proc *p)
    1081             : {
    1082             :         struct ufsmount *ump;
    1083             :         int error;
    1084             : 
    1085           0 :         ump = VFSTOUFS(mp);
    1086           0 :         if (mp->mnt_flag & MNT_QUOTA) {
    1087             :                 int i;
    1088           0 :                 if ((error = vflush(mp, NULLVP, SKIPSYSTEM|flags)) != 0)
    1089           0 :                         return (error);
    1090           0 :                 for (i = 0; i < MAXQUOTAS; i++) {
    1091           0 :                         if (ump->um_quotas[i] == NULLVP)
    1092             :                                 continue;
    1093           0 :                         quotaoff(p, mp, i);
    1094           0 :                 }
    1095             :                 /*
    1096             :                  * Here we fall through to vflush again to ensure
    1097             :                  * that we have gotten rid of all the system vnodes.
    1098             :                  */
    1099           0 :         }
    1100             : 
    1101             :         /*
    1102             :          * Flush all the files.
    1103             :          */
    1104           0 :         if ((error = vflush(mp, NULL, flags)) != 0)
    1105           0 :                 return (error);
    1106             :         /*
    1107             :          * Flush filesystem metadata.
    1108             :          */
    1109           0 :         vn_lock(ump->um_devvp, LK_EXCLUSIVE | LK_RETRY);
    1110           0 :         error = VOP_FSYNC(ump->um_devvp, p->p_ucred, MNT_WAIT, p);
    1111           0 :         VOP_UNLOCK(ump->um_devvp);
    1112           0 :         return (error);
    1113           0 : }
    1114             : 
    1115             : /*
    1116             :  * Get file system statistics.
    1117             :  */
    1118             : int
    1119           0 : ffs_statfs(struct mount *mp, struct statfs *sbp, struct proc *p)
    1120             : {
    1121             :         struct ufsmount *ump;
    1122             :         struct fs *fs;
    1123             : 
    1124           0 :         ump = VFSTOUFS(mp);
    1125           0 :         fs = ump->um_fs;
    1126             : 
    1127             : #ifdef FFS2
    1128           0 :         if (fs->fs_magic != FS_MAGIC && fs->fs_magic != FS_UFS2_MAGIC)
    1129           0 :                 panic("ffs_statfs");
    1130             : #else
    1131             :         if (fs->fs_magic != FS_MAGIC)
    1132             :                 panic("ffs_statfs");
    1133             : #endif /* FFS2 */
    1134             : 
    1135           0 :         sbp->f_bsize = fs->fs_fsize;
    1136           0 :         sbp->f_iosize = fs->fs_bsize;
    1137           0 :         sbp->f_blocks = fs->fs_dsize;
    1138           0 :         sbp->f_bfree = fs->fs_cstotal.cs_nbfree * fs->fs_frag +
    1139           0 :             fs->fs_cstotal.cs_nffree;
    1140           0 :         sbp->f_bavail = sbp->f_bfree -
    1141           0 :             ((int64_t)fs->fs_dsize * fs->fs_minfree / 100);
    1142           0 :         sbp->f_files = fs->fs_ncg * fs->fs_ipg - ROOTINO;
    1143           0 :         sbp->f_ffree = fs->fs_cstotal.cs_nifree;
    1144           0 :         sbp->f_favail = sbp->f_ffree;
    1145           0 :         copy_statfs_info(sbp, mp);
    1146             : 
    1147           0 :         return (0);
    1148             : }
    1149             : 
    1150             : struct ffs_sync_args {
    1151             :         int allerror;
    1152             :         struct proc *p;
    1153             :         int waitfor;
    1154             :         int nlink0;
    1155             :         int inflight;
    1156             :         struct ucred *cred;
    1157             : };
    1158             : 
    1159             : int
    1160           0 : ffs_sync_vnode(struct vnode *vp, void *arg)
    1161             : {
    1162           0 :         struct ffs_sync_args *fsa = arg;
    1163             :         struct inode *ip;
    1164             :         int error, nlink0 = 0;
    1165             : 
    1166           0 :         if (vp->v_type == VNON)
    1167           0 :                 return (0);
    1168             : 
    1169           0 :         ip = VTOI(vp);
    1170             : 
    1171           0 :         if (vp->v_inflight && !(vp->v_type == VCHR || vp->v_type == VBLK))
    1172           0 :                 fsa->inflight = MIN(fsa->inflight+1, 65536);
    1173             : 
    1174             :         /*
    1175             :          * If unmounting or converting rw to ro, then stop deferring
    1176             :          * timestamp writes.
    1177             :          */
    1178           0 :         if (fsa->waitfor == MNT_WAIT && (ip->i_flag & IN_LAZYMOD)) {
    1179           0 :                 ip->i_flag |= IN_MODIFIED;
    1180           0 :                 UFS_UPDATE(ip, 1);
    1181           0 :         }
    1182             : 
    1183           0 :         if (ip->i_effnlink == 0)
    1184           0 :                 nlink0 = 1;
    1185             : 
    1186           0 :         if ((ip->i_flag &
    1187           0 :             (IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE)) == 0 &&
    1188           0 :             LIST_EMPTY(&vp->v_dirtyblkhd)) {
    1189             :                 goto end;
    1190             :         }
    1191             : 
    1192           0 :         if (vget(vp, LK_EXCLUSIVE | LK_NOWAIT)) {
    1193             :                 nlink0 = 1;             /* potentially.. */
    1194           0 :                 goto end;
    1195             :         }
    1196             : 
    1197           0 :         if ((error = VOP_FSYNC(vp, fsa->cred, fsa->waitfor, fsa->p)))
    1198           0 :                 fsa->allerror = error;
    1199           0 :         VOP_UNLOCK(vp);
    1200           0 :         vrele(vp);
    1201             : 
    1202             : end:
    1203           0 :         fsa->nlink0 = MIN(fsa->nlink0 + nlink0, 65536);
    1204           0 :         return (0);
    1205           0 : }
    1206             : 
    1207             : /*
    1208             :  * Go through the disk queues to initiate sandbagged IO;
    1209             :  * go through the inodes to write those that have been modified;
    1210             :  * initiate the writing of the super block if it has been modified.
    1211             :  *
    1212             :  * Should always be called with the mount point locked.
    1213             :  */
    1214             : int
    1215           0 : ffs_sync(struct mount *mp, int waitfor, int stall, struct ucred *cred, struct proc *p)
    1216             : {
    1217           0 :         struct ufsmount *ump = VFSTOUFS(mp);
    1218             :         struct fs *fs;
    1219           0 :         int error, allerror = 0, count, clean, fmod;
    1220           0 :         struct ffs_sync_args fsa;
    1221             : 
    1222           0 :         fs = ump->um_fs;
    1223             :         /*
    1224             :          * Write back modified superblock.
    1225             :          * Consistency check that the superblock
    1226             :          * is still in the buffer cache.
    1227             :          */
    1228           0 :         if (fs->fs_fmod != 0 && fs->fs_ronly != 0) {
    1229           0 :                 printf("fs = %s\n", fs->fs_fsmnt);
    1230           0 :                 panic("update: rofs mod");
    1231             :         }
    1232             :  loop:
    1233             :         /*
    1234             :          * Write back each (modified) inode.
    1235             :          */
    1236           0 :         fsa.allerror = 0;
    1237           0 :         fsa.p = p;
    1238           0 :         fsa.cred = cred;
    1239           0 :         fsa.waitfor = waitfor;
    1240           0 :         fsa.nlink0 = 0;
    1241           0 :         fsa.inflight = 0;
    1242             : 
    1243             :         /*
    1244             :          * Don't traverse the vnode list if we want to skip all of them.
    1245             :          */
    1246           0 :         if (waitfor != MNT_LAZY) {
    1247           0 :                 vfs_mount_foreach_vnode(mp, ffs_sync_vnode, &fsa);
    1248           0 :                 allerror = fsa.allerror;
    1249           0 :         }
    1250             : 
    1251             :         /*
    1252             :          * Force stale file system control information to be flushed.
    1253             :          */
    1254           0 :         if ((ump->um_mountp->mnt_flag & MNT_SOFTDEP) && waitfor == MNT_WAIT) {
    1255           0 :                 if ((error = softdep_flushworklist(ump->um_mountp, &count, p)))
    1256           0 :                         allerror = error;
    1257             :                 /* Flushed work items may create new vnodes to clean */
    1258           0 :                 if (count) 
    1259           0 :                         goto loop;
    1260             :         }
    1261           0 :         if (waitfor != MNT_LAZY) {
    1262           0 :                 vn_lock(ump->um_devvp, LK_EXCLUSIVE | LK_RETRY);
    1263           0 :                 if ((error = VOP_FSYNC(ump->um_devvp, cred, waitfor, p)) != 0)
    1264           0 :                         allerror = error;
    1265           0 :                 VOP_UNLOCK(ump->um_devvp);
    1266           0 :         }
    1267           0 :         qsync(mp);
    1268             :         /*
    1269             :          * Write back modified superblock.
    1270             :          */
    1271           0 :         clean = fs->fs_clean;
    1272           0 :         fmod = fs->fs_fmod;
    1273           0 :         if (stall && fs->fs_ronly == 0) {
    1274           0 :                 fs->fs_fmod = 1;
    1275           0 :                 if (allerror == 0 && fsa.nlink0 == 0 && fsa.inflight == 0) {
    1276           0 :                         fs->fs_clean = (fs->fs_flags & FS_UNCLEAN) ? 0 : 1;
    1277             : #if 0
    1278             :                         printf("%s force clean (dangling %d inflight %d)\n",
    1279             :                             mp->mnt_stat.f_mntonname, fsa.nlink0, fsa.inflight);
    1280             : #endif
    1281           0 :                 } else {
    1282           0 :                         fs->fs_clean = 0;
    1283             : #if 0
    1284             :                         printf("%s force dirty (dangling %d inflight %d)\n",
    1285             :                             mp->mnt_stat.f_mntonname, fsa.nlink0, fsa.inflight);
    1286             : #endif
    1287             :                 }
    1288             :         }
    1289           0 :         if (fs->fs_fmod != 0 && (error = ffs_sbupdate(ump, waitfor)) != 0)
    1290           0 :                 allerror = error;
    1291           0 :         fs->fs_clean = clean;
    1292           0 :         fs->fs_fmod = fmod;
    1293             : 
    1294           0 :         return (allerror);
    1295           0 : }
    1296             : 
    1297             : /*
    1298             :  * Look up a FFS dinode number to find its incore vnode, otherwise read it
    1299             :  * in from disk.  If it is in core, wait for the lock bit to clear, then
    1300             :  * return the inode locked.  Detection and handling of mount points must be
    1301             :  * done by the calling routine.
    1302             :  */
    1303             : int
    1304           0 : ffs_vget(struct mount *mp, ino_t ino, struct vnode **vpp)
    1305             : {
    1306             :         struct fs *fs;
    1307             :         struct inode *ip;
    1308             :         struct ufs1_dinode *dp1;
    1309             : #ifdef FFS2
    1310             :         struct ufs2_dinode *dp2;
    1311             : #endif
    1312             :         struct ufsmount *ump;
    1313           0 :         struct buf *bp;
    1314           0 :         struct vnode *vp;
    1315             :         dev_t dev;
    1316             :         int error;
    1317             : 
    1318           0 :         if (ino > (ufsino_t)-1)
    1319           0 :                 panic("ffs_vget: alien ino_t %llu", (unsigned long long)ino);
    1320             : 
    1321           0 :         ump = VFSTOUFS(mp);
    1322           0 :         dev = ump->um_dev;
    1323             : retry:
    1324           0 :         if ((*vpp = ufs_ihashget(dev, ino)) != NULL)
    1325           0 :                 return (0);
    1326             : 
    1327             :         /* Allocate a new vnode/inode. */
    1328           0 :         if ((error = getnewvnode(VT_UFS, mp, &ffs_vops, &vp)) != 0) {
    1329           0 :                 *vpp = NULL;
    1330           0 :                 return (error);
    1331             :         }
    1332             : 
    1333             : #ifdef VFSLCKDEBUG
    1334             :         vp->v_flag |= VLOCKSWORK;
    1335             : #endif
    1336           0 :         ip = pool_get(&ffs_ino_pool, PR_WAITOK|PR_ZERO);
    1337           0 :         rrw_init_flags(&ip->i_lock, "inode", RWL_DUPOK | RWL_IS_VNODE);
    1338           0 :         ip->i_ump = ump;
    1339           0 :         vref(ip->i_devvp);
    1340           0 :         vp->v_data = ip;
    1341           0 :         ip->i_vnode = vp;
    1342           0 :         ip->i_fs = fs = ump->um_fs;
    1343           0 :         ip->i_dev = dev;
    1344           0 :         ip->i_number = ino;
    1345           0 :         ip->i_vtbl = &ffs_vtbl;
    1346             : 
    1347             :         /*
    1348             :          * Put it onto its hash chain and lock it so that other requests for
    1349             :          * this inode will block if they arrive while we are sleeping waiting
    1350             :          * for old data structures to be purged or for the contents of the
    1351             :          * disk portion of this inode to be read.
    1352             :          */
    1353           0 :         error = ufs_ihashins(ip);
    1354             :         
    1355           0 :         if (error) {
    1356             :                 /*
    1357             :                  * VOP_INACTIVE will treat this as a stale file
    1358             :                  * and recycle it quickly
    1359             :                  */
    1360           0 :                 vrele(vp);
    1361             : 
    1362           0 :                 if (error == EEXIST)
    1363           0 :                         goto retry;
    1364             : 
    1365           0 :                 return (error);
    1366             :         }
    1367             : 
    1368             : 
    1369             :         /* Read in the disk contents for the inode, copy into the inode. */
    1370           0 :         error = bread(ump->um_devvp, fsbtodb(fs, ino_to_fsba(fs, ino)),
    1371           0 :             (int)fs->fs_bsize, &bp);
    1372           0 :         if (error) {
    1373             :                 /*
    1374             :                  * The inode does not contain anything useful, so it would
    1375             :                  * be misleading to leave it on its hash chain. With mode
    1376             :                  * still zero, it will be unlinked and returned to the free
    1377             :                  * list by vput().
    1378             :                  */
    1379           0 :                 vput(vp);
    1380           0 :                 brelse(bp);
    1381           0 :                 *vpp = NULL;
    1382           0 :                 return (error);
    1383             :         }
    1384             : 
    1385             : #ifdef FFS2
    1386           0 :         if (ip->i_ump->um_fstype == UM_UFS2) {
    1387           0 :                 ip->i_din2 = pool_get(&ffs_dinode2_pool, PR_WAITOK);
    1388           0 :                 dp2 = (struct ufs2_dinode *) bp->b_data + ino_to_fsbo(fs, ino);
    1389           0 :                 *ip->i_din2 = *dp2;
    1390           0 :         } else
    1391             : #endif
    1392             :         {
    1393           0 :                 ip->i_din1 = pool_get(&ffs_dinode1_pool, PR_WAITOK);
    1394           0 :                 dp1 = (struct ufs1_dinode *) bp->b_data + ino_to_fsbo(fs, ino);
    1395           0 :                 *ip->i_din1 = *dp1;
    1396             :         }
    1397             : 
    1398           0 :         brelse(bp);
    1399             : 
    1400           0 :         if (DOINGSOFTDEP(vp))
    1401           0 :                 softdep_load_inodeblock(ip);
    1402             :         else
    1403           0 :                 ip->i_effnlink = DIP(ip, nlink);
    1404             : 
    1405             :         /*
    1406             :          * Initialize the vnode from the inode, check for aliases.
    1407             :          * Note that the underlying vnode may have changed.
    1408             :          */
    1409           0 :         if ((error = ffs_vinit(mp, &vp)) != 0) {
    1410           0 :                 vput(vp);
    1411           0 :                 *vpp = NULL;
    1412           0 :                 return (error);
    1413             :         }
    1414             : 
    1415             :         /*
    1416             :          * Set up a generation number for this inode if it does not
    1417             :          * already have one. This should only happen on old filesystems.
    1418             :          */
    1419           0 :         if (DIP(ip, gen) == 0) {
    1420           0 :                 DIP_ASSIGN(ip, gen, arc4random() & INT_MAX);
    1421           0 :                 if (DIP(ip, gen) == 0 || DIP(ip, gen) == -1)
    1422           0 :                         DIP_ASSIGN(ip, gen, 1); /* Shouldn't happen */
    1423           0 :                 if ((vp->v_mount->mnt_flag & MNT_RDONLY) == 0)
    1424           0 :                         ip->i_flag |= IN_MODIFIED;
    1425             :         }
    1426             : 
    1427             :         /*
    1428             :          * Ensure that uid and gid are correct. This is a temporary
    1429             :          * fix until fsck has been changed to do the update.
    1430             :          */
    1431           0 :         if (fs->fs_magic == FS_UFS1_MAGIC && fs->fs_inodefmt < FS_44INODEFMT) {
    1432           0 :                 ip->i_ffs1_uid = ip->i_din1->di_ouid;
    1433           0 :                 ip->i_ffs1_gid = ip->i_din1->di_ogid;
    1434           0 :         }
    1435             : 
    1436           0 :         *vpp = vp;
    1437             : 
    1438           0 :         return (0);
    1439           0 : }
    1440             : 
    1441             : /*
    1442             :  * File handle to vnode
    1443             :  *
    1444             :  * Have to be really careful about stale file handles.
    1445             :  */
    1446             : int
    1447           0 : ffs_fhtovp(struct mount *mp, struct fid *fhp, struct vnode **vpp)
    1448             : {
    1449             :         struct ufid *ufhp;
    1450             :         int error;
    1451             : 
    1452           0 :         ufhp = (struct ufid *)fhp;
    1453           0 :         if (ufhp->ufid_len != sizeof(*ufhp))
    1454           0 :                 return EINVAL;
    1455             : 
    1456           0 :         if ((error = ffs_checkrange(mp, ufhp->ufid_ino)) != 0)
    1457           0 :                 return error;
    1458             : 
    1459           0 :         return (ufs_fhtovp(mp, ufhp, vpp));
    1460           0 : }
    1461             : 
    1462             : /*
    1463             :  * Vnode pointer to File handle
    1464             :  */
    1465             : int
    1466           0 : ffs_vptofh(struct vnode *vp, struct fid *fhp)
    1467             : {
    1468             :         struct inode *ip;
    1469             :         struct ufid *ufhp;
    1470             : 
    1471           0 :         ip = VTOI(vp);
    1472           0 :         ufhp = (struct ufid *)fhp;
    1473           0 :         ufhp->ufid_len = sizeof(struct ufid);
    1474           0 :         ufhp->ufid_ino = ip->i_number;
    1475           0 :         ufhp->ufid_gen = DIP(ip, gen);
    1476             : 
    1477           0 :         return (0);
    1478             : }
    1479             : 
    1480             : /*
    1481             :  * Write a superblock and associated information back to disk.
    1482             :  */
    1483             : int
    1484           0 : ffs_sbupdate(struct ufsmount *mp, int waitfor)
    1485             : {
    1486           0 :         struct fs *dfs, *fs = mp->um_fs;
    1487             :         struct buf *bp;
    1488             :         int blks;
    1489             :         caddr_t space;
    1490             :         int i, size, error, allerror = 0;
    1491             : 
    1492             :         /*
    1493             :          * First write back the summary information.
    1494             :          */
    1495           0 :         blks = howmany(fs->fs_cssize, fs->fs_fsize);
    1496           0 :         space = (caddr_t)fs->fs_csp;
    1497           0 :         for (i = 0; i < blks; i += fs->fs_frag) {
    1498           0 :                 size = fs->fs_bsize;
    1499           0 :                 if (i + fs->fs_frag > blks)
    1500           0 :                         size = (blks - i) * fs->fs_fsize;
    1501           0 :                 bp = getblk(mp->um_devvp, fsbtodb(fs, fs->fs_csaddr + i),
    1502             :                             size, 0, 0);
    1503           0 :                 memcpy(bp->b_data, space, size);
    1504           0 :                 space += size;
    1505           0 :                 if (waitfor != MNT_WAIT)
    1506           0 :                         bawrite(bp);
    1507           0 :                 else if ((error = bwrite(bp)))
    1508           0 :                         allerror = error;
    1509             :         }
    1510             : 
    1511             :         /*
    1512             :          * Now write back the superblock itself. If any errors occurred
    1513             :          * up to this point, then fail so that the superblock avoids
    1514             :          * being written out as clean.
    1515             :          */
    1516           0 :         if (allerror) {
    1517           0 :                 return (allerror);
    1518             :         }
    1519             : 
    1520           0 :         bp = getblk(mp->um_devvp,
    1521           0 :             fs->fs_sblockloc >> (fs->fs_fshift - fs->fs_fsbtodb),
    1522           0 :             (int)fs->fs_sbsize, 0, 0);
    1523           0 :         fs->fs_fmod = 0;
    1524           0 :         fs->fs_time = time_second;
    1525           0 :         memcpy(bp->b_data, fs, fs->fs_sbsize);
    1526             :         /* Restore compatibility to old file systems.              XXX */
    1527           0 :         dfs = (struct fs *)bp->b_data;                               /* XXX */
    1528           0 :         if (fs->fs_postblformat == FS_42POSTBLFMT)           /* XXX */
    1529           0 :                 dfs->fs_nrpos = -1;                          /* XXX */
    1530           0 :         if (fs->fs_inodefmt < FS_44INODEFMT) {                    /* XXX */
    1531             :                 int32_t *lp, tmp;                               /* XXX */
    1532             :                                                                 /* XXX */
    1533           0 :                 lp = (int32_t *)&dfs->fs_qbmask;         /* XXX */
    1534           0 :                 tmp = lp[4];                                    /* XXX */
    1535           0 :                 for (i = 4; i > 0; i--)                              /* XXX */
    1536           0 :                         lp[i] = lp[i-1];                        /* XXX */
    1537           0 :                 lp[0] = tmp;                                    /* XXX */
    1538           0 :         }                                                       /* XXX */
    1539           0 :         dfs->fs_maxfilesize = mp->um_savedmaxfilesize;            /* XXX */
    1540             : 
    1541           0 :         ffs1_compat_write(dfs, mp);
    1542             : 
    1543           0 :         if (waitfor != MNT_WAIT)
    1544           0 :                 bawrite(bp);
    1545           0 :         else if ((error = bwrite(bp)))
    1546           0 :                 allerror = error;
    1547             : 
    1548           0 :         return (allerror);
    1549           0 : }
    1550             : 
    1551             : int
    1552           0 : ffs_init(struct vfsconf *vfsp)
    1553             : {
    1554             :         static int done;
    1555             : 
    1556           0 :         if (done)
    1557           0 :                 return (0);
    1558             : 
    1559           0 :         done = 1;
    1560             : 
    1561           0 :         pool_init(&ffs_ino_pool, sizeof(struct inode), 0, IPL_NONE,
    1562             :             PR_WAITOK, "ffsino", NULL);
    1563           0 :         pool_init(&ffs_dinode1_pool, sizeof(struct ufs1_dinode), 0, IPL_NONE,
    1564             :             PR_WAITOK, "dino1pl", NULL);
    1565             : #ifdef FFS2
    1566           0 :         pool_init(&ffs_dinode2_pool, sizeof(struct ufs2_dinode), 0, IPL_NONE,
    1567             :             PR_WAITOK, "dino2pl", NULL);
    1568             : #endif
    1569             : 
    1570           0 :         softdep_initialize();
    1571             : 
    1572           0 :         return (ufs_init(vfsp));
    1573           0 : }
    1574             : 
    1575             : /*
    1576             :  * fast filesystem related variables.
    1577             :  */
    1578             : int
    1579           0 : ffs_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp,
    1580             :     size_t newlen, struct proc *p)
    1581             : {
    1582             : #ifdef FFS_SOFTUPDATES
    1583             :         extern int max_softdeps, tickdelay, stat_worklist_push;
    1584             :         extern int stat_blk_limit_push, stat_ino_limit_push, stat_blk_limit_hit;
    1585             :         extern int stat_ino_limit_hit, stat_sync_limit_hit, stat_indir_blk_ptrs;
    1586             :         extern int stat_inode_bitmap, stat_direct_blk_ptrs, stat_dir_entry;
    1587             : #endif
    1588             : 
    1589             :         /* all sysctl names at this level are terminal */
    1590           0 :         if (namelen != 1)
    1591           0 :                 return (ENOTDIR);               /* overloaded */
    1592             : 
    1593           0 :         switch (name[0]) {
    1594             :         case FFS_CLUSTERREAD:
    1595             :         case FFS_CLUSTERWRITE:
    1596             :         case FFS_REALLOCBLKS:
    1597             :         case FFS_ASYNCFREE:
    1598           0 :                 return (EOPNOTSUPP);
    1599             : #ifdef FFS_SOFTUPDATES
    1600             :         case FFS_MAX_SOFTDEPS:
    1601           0 :                 return (sysctl_int(oldp, oldlenp, newp, newlen, &max_softdeps));
    1602             :         case FFS_SD_TICKDELAY:
    1603           0 :                 return (sysctl_int(oldp, oldlenp, newp, newlen, &tickdelay));
    1604             :         case FFS_SD_WORKLIST_PUSH:
    1605           0 :                 return (sysctl_rdint(oldp, oldlenp, newp, stat_worklist_push));
    1606             :         case FFS_SD_BLK_LIMIT_PUSH:
    1607           0 :                 return (sysctl_rdint(oldp, oldlenp, newp, stat_blk_limit_push));
    1608             :         case FFS_SD_INO_LIMIT_PUSH:
    1609           0 :                 return (sysctl_rdint(oldp, oldlenp, newp, stat_ino_limit_push));
    1610             :         case FFS_SD_BLK_LIMIT_HIT:
    1611           0 :                 return (sysctl_rdint(oldp, oldlenp, newp, stat_blk_limit_hit));
    1612             :         case FFS_SD_INO_LIMIT_HIT:
    1613           0 :                 return (sysctl_rdint(oldp, oldlenp, newp, stat_ino_limit_hit));
    1614             :         case FFS_SD_SYNC_LIMIT_HIT:
    1615           0 :                 return (sysctl_rdint(oldp, oldlenp, newp, stat_sync_limit_hit));
    1616             :         case FFS_SD_INDIR_BLK_PTRS:
    1617           0 :                 return (sysctl_rdint(oldp, oldlenp, newp, stat_indir_blk_ptrs));
    1618             :         case FFS_SD_INODE_BITMAP:
    1619           0 :                 return (sysctl_rdint(oldp, oldlenp, newp, stat_inode_bitmap));
    1620             :         case FFS_SD_DIRECT_BLK_PTRS:
    1621           0 :                 return (sysctl_rdint(oldp, oldlenp, newp, stat_direct_blk_ptrs));
    1622             :         case FFS_SD_DIR_ENTRY:
    1623           0 :                 return (sysctl_rdint(oldp, oldlenp, newp, stat_dir_entry));
    1624             : #endif
    1625             : #ifdef UFS_DIRHASH
    1626             :         case FFS_DIRHASH_DIRSIZE:
    1627           0 :                 return (sysctl_int(oldp, oldlenp, newp, newlen,
    1628             :                     &ufs_mindirhashsize));
    1629             :         case FFS_DIRHASH_MAXMEM:
    1630           0 :                 return (sysctl_int(oldp, oldlenp, newp, newlen,
    1631             :                     &ufs_dirhashmaxmem));
    1632             :         case FFS_DIRHASH_MEM:
    1633           0 :                 return (sysctl_rdint(oldp, oldlenp, newp, ufs_dirhashmem));
    1634             : #endif
    1635             : 
    1636             :         default:
    1637           0 :                 return (EOPNOTSUPP);
    1638             :         }
    1639             :         /* NOTREACHED */
    1640           0 : }

Generated by: LCOV version 1.13