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


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

FreeBSD/Linux Kernel Cross Reference
sys/ufs/ffs/ffs_vfsops.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: ffs_vfsops.c,v 1.140.2.3 2004/05/29 09:03:56 tron Exp $        */
    2 
    3 /*
    4  * Copyright (c) 1989, 1991, 1993, 1994
    5  *      The Regents of the University of California.  All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  * 3. Neither the name of the University nor the names of its contributors
   16  *    may be used to endorse or promote products derived from this software
   17  *    without specific prior written permission.
   18  *
   19  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   29  * SUCH DAMAGE.
   30  *
   31  *      @(#)ffs_vfsops.c        8.31 (Berkeley) 5/20/95
   32  */
   33 
   34 #include <sys/cdefs.h>
   35 __KERNEL_RCSID(0, "$NetBSD: ffs_vfsops.c,v 1.140.2.3 2004/05/29 09:03:56 tron Exp $");
   36 
   37 #if defined(_KERNEL_OPT)
   38 #include "opt_ffs.h"
   39 #include "opt_quota.h"
   40 #include "opt_compat_netbsd.h"
   41 #include "opt_softdep.h"
   42 #endif
   43 
   44 #include <sys/param.h>
   45 #include <sys/systm.h>
   46 #include <sys/namei.h>
   47 #include <sys/proc.h>
   48 #include <sys/kernel.h>
   49 #include <sys/vnode.h>
   50 #include <sys/socket.h>
   51 #include <sys/mount.h>
   52 #include <sys/buf.h>
   53 #include <sys/device.h>
   54 #include <sys/mbuf.h>
   55 #include <sys/file.h>
   56 #include <sys/disklabel.h>
   57 #include <sys/ioctl.h>
   58 #include <sys/errno.h>
   59 #include <sys/malloc.h>
   60 #include <sys/pool.h>
   61 #include <sys/lock.h>
   62 #include <sys/sysctl.h>
   63 #include <sys/conf.h>
   64 
   65 #include <miscfs/specfs/specdev.h>
   66 
   67 #include <ufs/ufs/quota.h>
   68 #include <ufs/ufs/ufsmount.h>
   69 #include <ufs/ufs/inode.h>
   70 #include <ufs/ufs/dir.h>
   71 #include <ufs/ufs/ufs_extern.h>
   72 #include <ufs/ufs/ufs_bswap.h>
   73 
   74 #include <ufs/ffs/fs.h>
   75 #include <ufs/ffs/ffs_extern.h>
   76 
   77 /* how many times ffs_init() was called */
   78 int ffs_initcount = 0;
   79 
   80 extern struct lock ufs_hashlock;
   81 
   82 extern const struct vnodeopv_desc ffs_vnodeop_opv_desc;
   83 extern const struct vnodeopv_desc ffs_specop_opv_desc;
   84 extern const struct vnodeopv_desc ffs_fifoop_opv_desc;
   85 
   86 const struct vnodeopv_desc * const ffs_vnodeopv_descs[] = {
   87         &ffs_vnodeop_opv_desc,
   88         &ffs_specop_opv_desc,
   89         &ffs_fifoop_opv_desc,
   90         NULL,
   91 };
   92 
   93 struct vfsops ffs_vfsops = {
   94         MOUNT_FFS,
   95         ffs_mount,
   96         ufs_start,
   97         ffs_unmount,
   98         ufs_root,
   99         ufs_quotactl,
  100         ffs_statfs,
  101         ffs_sync,
  102         ffs_vget,
  103         ffs_fhtovp,
  104         ffs_vptofh,
  105         ffs_init,
  106         ffs_reinit,
  107         ffs_done,
  108         NULL,
  109         ffs_mountroot,
  110         ufs_check_export,
  111         ffs_vnodeopv_descs,
  112 };
  113 
  114 struct genfs_ops ffs_genfsops = {
  115         ffs_gop_size,
  116         ufs_gop_alloc,
  117         genfs_gop_write,
  118 };
  119 
  120 struct pool ffs_inode_pool;
  121 struct pool ffs_dinode1_pool;
  122 struct pool ffs_dinode2_pool;
  123 
  124 static void ffs_oldfscompat_read(struct fs *, struct ufsmount *,
  125                                    daddr_t);
  126 static void ffs_oldfscompat_write(struct fs *, struct ufsmount *);
  127 
  128 /*
  129  * Called by main() when ffs is going to be mounted as root.
  130  */
  131 
  132 int
  133 ffs_mountroot()
  134 {
  135         struct fs *fs;
  136         struct mount *mp;
  137         struct proc *p = curproc;       /* XXX */
  138         struct ufsmount *ump;
  139         int error;
  140 
  141         if (root_device->dv_class != DV_DISK)
  142                 return (ENODEV);
  143 
  144         /*
  145          * Get vnodes for rootdev.
  146          */
  147         if (bdevvp(rootdev, &rootvp))
  148                 panic("ffs_mountroot: can't setup bdevvp's");
  149 
  150         if ((error = vfs_rootmountalloc(MOUNT_FFS, "root_device", &mp))) {
  151                 vrele(rootvp);
  152                 return (error);
  153         }
  154         if ((error = ffs_mountfs(rootvp, mp, p)) != 0) {
  155                 mp->mnt_op->vfs_refcount--;
  156                 vfs_unbusy(mp);
  157                 free(mp, M_MOUNT);
  158                 vrele(rootvp);
  159                 return (error);
  160         }
  161         simple_lock(&mountlist_slock);
  162         CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list);
  163         simple_unlock(&mountlist_slock);
  164         ump = VFSTOUFS(mp);
  165         fs = ump->um_fs;
  166         memset(fs->fs_fsmnt, 0, sizeof(fs->fs_fsmnt));
  167         (void)copystr(mp->mnt_stat.f_mntonname, fs->fs_fsmnt, MNAMELEN - 1, 0);
  168         (void)ffs_statfs(mp, &mp->mnt_stat, p);
  169         vfs_unbusy(mp);
  170         inittodr(fs->fs_time);
  171         return (0);
  172 }
  173 
  174 /*
  175  * VFS Operations.
  176  *
  177  * mount system call
  178  */
  179 int
  180 ffs_mount(mp, path, data, ndp, p)
  181         struct mount *mp;
  182         const char *path;
  183         void *data;
  184         struct nameidata *ndp;
  185         struct proc *p;
  186 {
  187         struct vnode *devvp = NULL;
  188         struct ufs_args args;
  189         struct ufsmount *ump = NULL;
  190         struct fs *fs;
  191         int error, flags, update;
  192         mode_t accessmode;
  193 
  194         if (mp->mnt_flag & MNT_GETARGS) {
  195                 ump = VFSTOUFS(mp);
  196                 if (ump == NULL)
  197                         return EIO;
  198                 args.fspec = NULL;
  199                 vfs_showexport(mp, &args.export, &ump->um_export);
  200                 return copyout(&args, data, sizeof(args));
  201         }
  202         error = copyin(data, &args, sizeof (struct ufs_args));
  203         if (error)
  204                 return (error);
  205 
  206 #if !defined(SOFTDEP)
  207         mp->mnt_flag &= ~MNT_SOFTDEP;
  208 #endif
  209 
  210         update = mp->mnt_flag & MNT_UPDATE;
  211 
  212         /* Check arguments */
  213         if (update) {
  214                 /* Use the extant mount */
  215                 ump = VFSTOUFS(mp);
  216                 devvp = ump->um_devvp;
  217                 if (args.fspec == NULL)
  218                         vref(devvp);
  219         } else {
  220                 /* New mounts must have a filename for the device */
  221                 if (args.fspec == NULL)
  222                         return (EINVAL);
  223         }
  224 
  225         if (args.fspec != NULL) {
  226                 /*
  227                  * Look up the name and verify that it's sane.
  228                  */
  229                 NDINIT(ndp, LOOKUP, FOLLOW, UIO_USERSPACE, args.fspec, p);
  230                 if ((error = namei(ndp)) != 0)
  231                         return (error);
  232                 devvp = ndp->ni_vp;
  233 
  234                 if (!update) {
  235                         /*
  236                          * Be sure this is a valid block device
  237                          */
  238                         if (devvp->v_type != VBLK)
  239                                 error = ENOTBLK;
  240                         else if (bdevsw_lookup(devvp->v_rdev) == NULL)
  241                                 error = ENXIO;
  242                 } else {
  243                         /*
  244                          * Be sure we're still naming the same device
  245                          * used for our initial mount
  246                          */
  247                         if (devvp != ump->um_devvp)
  248                                 error = EINVAL;
  249                 }
  250         }
  251 
  252         /*
  253          * If mount by non-root, then verify that user has necessary
  254          * permissions on the device.
  255          */
  256         if (error == 0 && p->p_ucred->cr_uid != 0) {
  257                 accessmode = VREAD;
  258                 if (update ?
  259                     (mp->mnt_iflag & IMNT_WANTRDWR) != 0 :
  260                     (mp->mnt_flag & MNT_RDONLY) == 0)
  261                         accessmode |= VWRITE;
  262                 vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
  263                 error = VOP_ACCESS(devvp, accessmode, p->p_ucred, p);
  264                 VOP_UNLOCK(devvp, 0);
  265         }
  266 
  267         if (error) {
  268                 vrele(devvp);
  269                 return (error);
  270         }
  271 
  272         if (!update) {
  273                 error = ffs_mountfs(devvp, mp, p);
  274                 if (error) {
  275                         vrele(devvp);
  276                         return (error);
  277                 }
  278 
  279                 ump = VFSTOUFS(mp);
  280                 fs = ump->um_fs;
  281                 if ((mp->mnt_flag & (MNT_SOFTDEP | MNT_ASYNC)) ==
  282                     (MNT_SOFTDEP | MNT_ASYNC)) {
  283                         printf("%s fs uses soft updates, "
  284                             "ignoring async mode\n",
  285                             fs->fs_fsmnt);
  286                         mp->mnt_flag &= ~MNT_ASYNC;
  287                 }
  288         } else {
  289                 /*
  290                  * Update the mount.
  291                  */
  292 
  293                 /*
  294                  * The initial mount got a reference on this
  295                  * device, so drop the one obtained via
  296                  * namei(), above.
  297                  */
  298                 vrele(devvp);
  299 
  300                 fs = ump->um_fs;
  301                 if (fs->fs_ronly == 0 && (mp->mnt_flag & MNT_RDONLY)) {
  302                         /*
  303                          * Changing from r/w to r/o
  304                          */
  305                         vn_start_write(NULL, &mp, V_WAIT);
  306                         flags = WRITECLOSE;
  307                         if (mp->mnt_flag & MNT_FORCE)
  308                                 flags |= FORCECLOSE;
  309                         if (mp->mnt_flag & MNT_SOFTDEP)
  310                                 error = softdep_flushfiles(mp, flags, p);
  311                         else
  312                                 error = ffs_flushfiles(mp, flags, p);
  313                         if (fs->fs_pendingblocks != 0 ||
  314                             fs->fs_pendinginodes != 0) {
  315                                 printf("%s: update error: blocks %" PRId64
  316                                        " files %d\n",
  317                                     fs->fs_fsmnt, fs->fs_pendingblocks,
  318                                     fs->fs_pendinginodes);
  319                                 fs->fs_pendingblocks = 0;
  320                                 fs->fs_pendinginodes = 0;
  321                         }
  322                         if (error == 0 &&
  323                             ffs_cgupdate(ump, MNT_WAIT) == 0 &&
  324                             fs->fs_clean & FS_WASCLEAN) {
  325                                 if (mp->mnt_flag & MNT_SOFTDEP)
  326                                         fs->fs_flags &= ~FS_DOSOFTDEP;
  327                                 fs->fs_clean = FS_ISCLEAN;
  328                                 (void) ffs_sbupdate(ump, MNT_WAIT);
  329                         }
  330                         vn_finished_write(mp, 0);
  331                         if (error)
  332                                 return (error);
  333                         fs->fs_ronly = 1;
  334                         fs->fs_fmod = 0;
  335                 }
  336 
  337                 /*
  338                  * Flush soft dependencies if disabling it via an update
  339                  * mount. This may leave some items to be processed,
  340                  * so don't do this yet XXX.
  341                  */
  342                 if ((fs->fs_flags & FS_DOSOFTDEP) &&
  343                     !(mp->mnt_flag & MNT_SOFTDEP) && fs->fs_ronly == 0) {
  344 #ifdef notyet
  345                         vn_start_write(NULL, &mp, V_WAIT);
  346                         flags = WRITECLOSE;
  347                         if (mp->mnt_flag & MNT_FORCE)
  348                                 flags |= FORCECLOSE;
  349                         error = softdep_flushfiles(mp, flags, p);
  350                         if (error == 0 && ffs_cgupdate(ump, MNT_WAIT) == 0)
  351                                 fs->fs_flags &= ~FS_DOSOFTDEP;
  352                                 (void) ffs_sbupdate(ump, MNT_WAIT);
  353                         vn_finished_write(mp);
  354 #elif defined(SOFTDEP)
  355                         mp->mnt_flag |= MNT_SOFTDEP;
  356 #endif
  357                 }
  358 
  359                 /*
  360                  * When upgrading to a softdep mount, we must first flush
  361                  * all vnodes. (not done yet -- see above)
  362                  */
  363                 if (!(fs->fs_flags & FS_DOSOFTDEP) &&
  364                     (mp->mnt_flag & MNT_SOFTDEP) && fs->fs_ronly == 0) {
  365 #ifdef notyet
  366                         vn_start_write(NULL, &mp, V_WAIT);
  367                         flags = WRITECLOSE;
  368                         if (mp->mnt_flag & MNT_FORCE)
  369                                 flags |= FORCECLOSE;
  370                         error = ffs_flushfiles(mp, flags, p);
  371                         vn_finished_write(mp);
  372 #else
  373                         mp->mnt_flag &= ~MNT_SOFTDEP;
  374 #endif
  375                 }
  376 
  377                 if (mp->mnt_flag & MNT_RELOAD) {
  378                         error = ffs_reload(mp, p->p_ucred, p);
  379                         if (error)
  380                                 return (error);
  381                 }
  382 
  383                 if (fs->fs_ronly && (mp->mnt_iflag & IMNT_WANTRDWR)) {
  384                         /*
  385                          * Changing from read-only to read/write
  386                          */
  387                         fs->fs_ronly = 0;
  388                         fs->fs_clean <<= 1;
  389                         fs->fs_fmod = 1;
  390                         if ((fs->fs_flags & FS_DOSOFTDEP)) {
  391                                 error = softdep_mount(devvp, mp, fs,
  392                                     p->p_ucred);
  393                                 if (error)
  394                                         return (error);
  395                         }
  396                 }
  397                 if (args.fspec == 0) {
  398                         /*
  399                          * Process export requests.
  400                          */
  401                         return (vfs_export(mp, &ump->um_export, &args.export));
  402                 }
  403                 if ((mp->mnt_flag & (MNT_SOFTDEP | MNT_ASYNC)) ==
  404                     (MNT_SOFTDEP | MNT_ASYNC)) {
  405                         printf("%s fs uses soft updates, ignoring async mode\n",
  406                             fs->fs_fsmnt);
  407                         mp->mnt_flag &= ~MNT_ASYNC;
  408                 }
  409         }
  410 
  411         error = set_statfs_info(path, UIO_USERSPACE, args.fspec,
  412             UIO_USERSPACE, mp, p);
  413         if (error == 0)
  414                 (void)strncpy(fs->fs_fsmnt, mp->mnt_stat.f_mntonname,
  415                     sizeof(fs->fs_fsmnt));
  416         if (mp->mnt_flag & MNT_SOFTDEP)
  417                 fs->fs_flags |= FS_DOSOFTDEP;
  418         else
  419                 fs->fs_flags &= ~FS_DOSOFTDEP;
  420         if (fs->fs_fmod != 0) { /* XXX */
  421                 fs->fs_fmod = 0;
  422                 if (fs->fs_clean & FS_WASCLEAN)
  423                         fs->fs_time = time.tv_sec;
  424                 else {
  425                         printf("%s: file system not clean (fs_clean=%x); please fsck(8)\n",
  426                             mp->mnt_stat.f_mntfromname, fs->fs_clean);
  427                         printf("%s: lost blocks %" PRId64 " files %d\n",
  428                             mp->mnt_stat.f_mntfromname, fs->fs_pendingblocks,
  429                             fs->fs_pendinginodes);
  430                 }
  431                 (void) ffs_cgupdate(ump, MNT_WAIT);
  432         }
  433         return error;
  434 }
  435 
  436 /*
  437  * Reload all incore data for a filesystem (used after running fsck on
  438  * the root filesystem and finding things to fix). The filesystem must
  439  * be mounted read-only.
  440  *
  441  * Things to do to update the mount:
  442  *      1) invalidate all cached meta-data.
  443  *      2) re-read superblock from disk.
  444  *      3) re-read summary information from disk.
  445  *      4) invalidate all inactive vnodes.
  446  *      5) invalidate all cached file data.
  447  *      6) re-read inode data for all active vnodes.
  448  */
  449 int
  450 ffs_reload(mountp, cred, p)
  451         struct mount *mountp;
  452         struct ucred *cred;
  453         struct proc *p;
  454 {
  455         struct vnode *vp, *nvp, *devvp;
  456         struct inode *ip;
  457         void *space;
  458         struct buf *bp;
  459         struct fs *fs, *newfs;
  460         struct partinfo dpart;
  461         int i, blks, size, error;
  462         int32_t *lp;
  463         struct ufsmount *ump;
  464         daddr_t sblockloc;
  465 
  466         if ((mountp->mnt_flag & MNT_RDONLY) == 0)
  467                 return (EINVAL);
  468 
  469         ump = VFSTOUFS(mountp);
  470         /*
  471          * Step 1: invalidate all cached meta-data.
  472          */
  473         devvp = ump->um_devvp;
  474         vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
  475         error = vinvalbuf(devvp, 0, cred, p, 0, 0);
  476         VOP_UNLOCK(devvp, 0);
  477         if (error)
  478                 panic("ffs_reload: dirty1");
  479         /*
  480          * Step 2: re-read superblock from disk.
  481          */
  482         fs = ump->um_fs;
  483         if (VOP_IOCTL(devvp, DIOCGPART, &dpart, FREAD, NOCRED, p) != 0)
  484                 size = DEV_BSIZE;
  485         else
  486                 size = dpart.disklab->d_secsize;
  487         /* XXX we don't handle possibility that superblock moved. */
  488         error = bread(devvp, fs->fs_sblockloc / size, fs->fs_sbsize,
  489                       NOCRED, &bp);
  490         if (error) {
  491                 brelse(bp);
  492                 return (error);
  493         }
  494         newfs = malloc(fs->fs_sbsize, M_UFSMNT, M_WAITOK);
  495         memcpy(newfs, bp->b_data, fs->fs_sbsize);
  496 #ifdef FFS_EI
  497         if (ump->um_flags & UFS_NEEDSWAP) {
  498                 ffs_sb_swap((struct fs*)bp->b_data, newfs);
  499                 fs->fs_flags |= FS_SWAPPED;
  500         } else
  501 #endif
  502                 fs->fs_flags &= ~FS_SWAPPED;
  503         if ((newfs->fs_magic != FS_UFS1_MAGIC &&        
  504              newfs->fs_magic != FS_UFS2_MAGIC)||
  505              newfs->fs_bsize > MAXBSIZE ||
  506              newfs->fs_bsize < sizeof(struct fs)) {
  507                 brelse(bp);
  508                 free(newfs, M_UFSMNT);
  509                 return (EIO);           /* XXX needs translation */
  510         }
  511         /* Store off old fs_sblockloc for fs_oldfscompat_read. */
  512         sblockloc = fs->fs_sblockloc;
  513         /* 
  514          * Copy pointer fields back into superblock before copying in   XXX
  515          * new superblock. These should really be in the ufsmount.      XXX
  516          * Note that important parameters (eg fs_ncg) are unchanged.
  517          */
  518         newfs->fs_csp = fs->fs_csp;
  519         newfs->fs_maxcluster = fs->fs_maxcluster;
  520         newfs->fs_contigdirs = fs->fs_contigdirs;
  521         newfs->fs_ronly = fs->fs_ronly;
  522         newfs->fs_active = fs->fs_active;
  523         memcpy(fs, newfs, (u_int)fs->fs_sbsize);
  524         brelse(bp);
  525         free(newfs, M_UFSMNT);
  526 
  527         /* Recheck for apple UFS filesystem */
  528         VFSTOUFS(mountp)->um_flags &= ~UFS_ISAPPLEUFS;
  529         /* First check to see if this is tagged as an Apple UFS filesystem
  530          * in the disklabel
  531          */
  532         if ((VOP_IOCTL(devvp, DIOCGPART, &dpart, FREAD, cred, p) == 0) &&
  533                 (dpart.part->p_fstype == FS_APPLEUFS)) {
  534                 VFSTOUFS(mountp)->um_flags |= UFS_ISAPPLEUFS;
  535         }
  536 #ifdef APPLE_UFS
  537         else {
  538                 /* Manually look for an apple ufs label, and if a valid one
  539                  * is found, then treat it like an Apple UFS filesystem anyway
  540                  */
  541                 error = bread(devvp, (daddr_t)(APPLEUFS_LABEL_OFFSET / size),
  542                         APPLEUFS_LABEL_SIZE, cred, &bp);
  543                 if (error) {
  544                         brelse(bp);
  545                         return (error);
  546                 }
  547                 error = ffs_appleufs_validate(fs->fs_fsmnt,
  548                         (struct appleufslabel *)bp->b_data,NULL);
  549                 if (error == 0) {
  550                         VFSTOUFS(mountp)->um_flags |= UFS_ISAPPLEUFS;
  551                 }
  552                 brelse(bp);
  553                 bp = NULL;
  554         }
  555 #else
  556         if (VFSTOUFS(mountp)->um_flags & UFS_ISAPPLEUFS)
  557                 return (EIO);
  558 #endif
  559 
  560         mountp->mnt_maxsymlinklen = fs->fs_maxsymlinklen;
  561         if (UFS_MPISAPPLEUFS(mountp)) {
  562                 /* see comment about NeXT below */
  563                 mountp->mnt_maxsymlinklen = APPLEUFS_MAXSYMLINKLEN;
  564         }
  565         ffs_oldfscompat_read(fs, VFSTOUFS(mountp), sblockloc);
  566         if (fs->fs_pendingblocks != 0 || fs->fs_pendinginodes != 0) {
  567                 fs->fs_pendingblocks = 0;
  568                 fs->fs_pendinginodes = 0;
  569         }
  570 
  571         ffs_statfs(mountp, &mountp->mnt_stat, p);
  572         /*
  573          * Step 3: re-read summary information from disk.
  574          */
  575         blks = howmany(fs->fs_cssize, fs->fs_fsize);
  576         space = fs->fs_csp;
  577         for (i = 0; i < blks; i += fs->fs_frag) {
  578                 size = fs->fs_bsize;
  579                 if (i + fs->fs_frag > blks)
  580                         size = (blks - i) * fs->fs_fsize;
  581                 error = bread(devvp, fsbtodb(fs, fs->fs_csaddr + i), size,
  582                               NOCRED, &bp);
  583                 if (error) {
  584                         brelse(bp);
  585                         return (error);
  586                 }
  587 #ifdef FFS_EI
  588                 if (UFS_FSNEEDSWAP(fs))
  589                         ffs_csum_swap((struct csum *)bp->b_data,
  590                             (struct csum *)space, size);
  591                 else
  592 #endif
  593                         memcpy(space, bp->b_data, (size_t)size);
  594                 space = (char *)space + size;
  595                 brelse(bp);
  596         }
  597         if ((fs->fs_flags & FS_DOSOFTDEP))
  598                 softdep_mount(devvp, mountp, fs, cred);
  599         /*
  600          * We no longer know anything about clusters per cylinder group.
  601          */
  602         if (fs->fs_contigsumsize > 0) {
  603                 lp = fs->fs_maxcluster;
  604                 for (i = 0; i < fs->fs_ncg; i++)
  605                         *lp++ = fs->fs_contigsumsize;
  606         }
  607 
  608 loop:
  609         simple_lock(&mntvnode_slock);
  610         for (vp = mountp->mnt_vnodelist.lh_first; vp != NULL; vp = nvp) {
  611                 if (vp->v_mount != mountp) {
  612                         simple_unlock(&mntvnode_slock);
  613                         goto loop;
  614                 }
  615                 nvp = vp->v_mntvnodes.le_next;
  616                 /*
  617                  * Step 4: invalidate all inactive vnodes.
  618                  */
  619                 if (vrecycle(vp, &mntvnode_slock, p))
  620                         goto loop;
  621                 /*
  622                  * Step 5: invalidate all cached file data.
  623                  */
  624                 simple_lock(&vp->v_interlock);
  625                 simple_unlock(&mntvnode_slock);
  626                 if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK))
  627                         goto loop;
  628                 if (vinvalbuf(vp, 0, cred, p, 0, 0))
  629                         panic("ffs_reload: dirty2");
  630                 /*
  631                  * Step 6: re-read inode data for all active vnodes.
  632                  */
  633                 ip = VTOI(vp);
  634                 error = bread(devvp, fsbtodb(fs, ino_to_fsba(fs, ip->i_number)),
  635                               (int)fs->fs_bsize, NOCRED, &bp);
  636                 if (error) {
  637                         brelse(bp);
  638                         vput(vp);
  639                         return (error);
  640                 }
  641                 ffs_load_inode(bp, ip, fs, ip->i_number);
  642                 ip->i_ffs_effnlink = ip->i_nlink;
  643                 brelse(bp);
  644                 vput(vp);
  645                 simple_lock(&mntvnode_slock);
  646         }
  647         simple_unlock(&mntvnode_slock);
  648         return (0);
  649 }
  650 
  651 /*
  652  * Possible superblock locations ordered from most to least likely.
  653  */
  654 static const int sblock_try[] = SBLOCKSEARCH;
  655 
  656 /*
  657  * Common code for mount and mountroot
  658  */
  659 int
  660 ffs_mountfs(devvp, mp, p)
  661         struct vnode *devvp;
  662         struct mount *mp;
  663         struct proc *p;
  664 {
  665         struct ufsmount *ump;
  666         struct buf *bp;
  667         struct fs *fs;
  668         dev_t dev;
  669         struct partinfo dpart;
  670         void *space;
  671         daddr_t sblockloc, fsblockloc;
  672         int blks, fstype;
  673         int error, i, size, ronly;
  674 #ifdef FFS_EI
  675         int needswap = 0;               /* keep gcc happy */
  676 #endif
  677         int32_t *lp;
  678         struct ucred *cred;
  679         u_int32_t sbsize = 8192;        /* keep gcc happy*/
  680 
  681         dev = devvp->v_rdev;
  682         cred = p ? p->p_ucred : NOCRED;
  683         /*
  684          * Disallow multiple mounts of the same device.
  685          * Disallow mounting of a device that is currently in use
  686          * (except for root, which might share swap device for miniroot).
  687          * Flush out any old buffers remaining from a previous use.
  688          */
  689         if ((error = vfs_mountedon(devvp)) != 0)
  690                 return (error);
  691         if (vcount(devvp) > 1 && devvp != rootvp)
  692                 return (EBUSY);
  693         vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
  694         error = vinvalbuf(devvp, V_SAVE, cred, p, 0, 0);
  695         VOP_UNLOCK(devvp, 0);
  696         if (error)
  697                 return (error);
  698 
  699         ronly = (mp->mnt_flag & MNT_RDONLY) != 0;
  700         error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, FSCRED, p);
  701         if (error)
  702                 return (error);
  703         if (VOP_IOCTL(devvp, DIOCGPART, &dpart, FREAD, cred, p) != 0)
  704                 size = DEV_BSIZE;
  705         else
  706                 size = dpart.disklab->d_secsize;
  707 
  708         bp = NULL;
  709         ump = NULL;
  710         fs = NULL;
  711         sblockloc = 0;
  712         fstype = 0;
  713 
  714         /*
  715          * Try reading the superblock in each of its possible locations.                 */
  716         for (i = 0; ; i++) {
  717                 if (bp != NULL) {
  718                         bp->b_flags |= B_NOCACHE;
  719                         brelse(bp);
  720                         bp = NULL;
  721                 }
  722                 if (sblock_try[i] == -1) {
  723                         error = EINVAL;
  724                         fs = NULL;
  725                         goto out;
  726                 }
  727                 error = bread(devvp, sblock_try[i] / size, SBLOCKSIZE, cred,
  728                               &bp);
  729                 if (error)
  730                         goto out;
  731                 fs = (struct fs*)bp->b_data;
  732                 fsblockloc = sblockloc = sblock_try[i];
  733                 if (fs->fs_magic == FS_UFS1_MAGIC) {
  734                         sbsize = fs->fs_sbsize;
  735                         fstype = UFS1;
  736 #ifdef FFS_EI
  737                         needswap = 0;
  738                 } else if (fs->fs_magic == bswap32(FS_UFS1_MAGIC)) {
  739                         sbsize = bswap32(fs->fs_sbsize);
  740                         fstype = UFS1;
  741                         needswap = 1;
  742 #endif
  743                 } else if (fs->fs_magic == FS_UFS2_MAGIC) {
  744                         sbsize = fs->fs_sbsize;
  745                         fstype = UFS2;
  746 #ifdef FFS_EI
  747                         needswap = 0;
  748                 } else if (fs->fs_magic == bswap32(FS_UFS2_MAGIC)) {
  749                         sbsize = bswap32(fs->fs_sbsize);
  750                         fstype = UFS2;
  751                         needswap = 1;
  752 #endif
  753                 } else
  754                         continue;
  755 
  756 
  757                 /* fs->fs_sblockloc isn't defined for old filesystems */
  758                 if (fstype == UFS1 && !(fs->fs_old_flags & FS_FLAGS_UPDATED)) {
  759                         if (sblockloc == SBLOCK_UFS2)
  760                                 /*
  761                                  * This is likely to be the first alternate
  762                                  * in a filesystem with 64k blocks.
  763                                  * Don't use it.
  764                                  */
  765                                 continue;
  766                         fsblockloc = sblockloc;
  767                 } else {
  768                         fsblockloc = fs->fs_sblockloc;
  769 #ifdef FFS_EI
  770                         if (needswap)
  771                                 fsblockloc = bswap64(fsblockloc);
  772 #endif
  773                 }
  774 
  775                 /* Check we haven't found an alternate superblock */
  776                 if (fsblockloc != sblockloc)
  777                         continue;
  778 
  779                 /* Validate size of superblock */
  780                 if (sbsize > MAXBSIZE || sbsize < sizeof(struct fs))
  781                         continue;
  782 
  783                 /* Ok seems to be a good superblock */
  784                 break;
  785         }
  786 
  787         fs = malloc((u_long)sbsize, M_UFSMNT, M_WAITOK);
  788         memcpy(fs, bp->b_data, sbsize);
  789 
  790         ump = malloc(sizeof *ump, M_UFSMNT, M_WAITOK);
  791         memset(ump, 0, sizeof *ump);
  792         ump->um_fs = fs;
  793 
  794 #ifdef FFS_EI
  795         if (needswap) {
  796                 ffs_sb_swap((struct fs*)bp->b_data, fs);
  797                 fs->fs_flags |= FS_SWAPPED;
  798         } else
  799 #endif
  800                 fs->fs_flags &= ~FS_SWAPPED;
  801 
  802         ffs_oldfscompat_read(fs, ump, sblockloc);
  803 
  804         if (fs->fs_pendingblocks != 0 || fs->fs_pendinginodes != 0) {
  805                 fs->fs_pendingblocks = 0;
  806                 fs->fs_pendinginodes = 0;
  807         }
  808 
  809         ump->um_fstype = fstype;
  810         if (fs->fs_sbsize < SBLOCKSIZE)
  811                 bp->b_flags |= B_INVAL;
  812         brelse(bp);
  813         bp = NULL;
  814 
  815         /* First check to see if this is tagged as an Apple UFS filesystem
  816          * in the disklabel
  817          */
  818         if ((VOP_IOCTL(devvp, DIOCGPART, &dpart, FREAD, cred, p) == 0) &&
  819                 (dpart.part->p_fstype == FS_APPLEUFS)) {
  820                 ump->um_flags |= UFS_ISAPPLEUFS;
  821         }
  822 #ifdef APPLE_UFS
  823         else {
  824                 /* Manually look for an apple ufs label, and if a valid one
  825                  * is found, then treat it like an Apple UFS filesystem anyway
  826                  */
  827                 error = bread(devvp, (daddr_t)(APPLEUFS_LABEL_OFFSET / size),
  828                         APPLEUFS_LABEL_SIZE, cred, &bp);
  829                 if (error)
  830                         goto out;
  831                 error = ffs_appleufs_validate(fs->fs_fsmnt,
  832                         (struct appleufslabel *)bp->b_data,NULL);
  833                 if (error == 0) {
  834                         ump->um_flags |= UFS_ISAPPLEUFS;
  835                 }
  836                 brelse(bp);
  837                 bp = NULL;
  838         }
  839 #else
  840         if (ump->um_flags & UFS_ISAPPLEUFS) {
  841                 error = EINVAL;
  842                 goto out;
  843         }
  844 #endif
  845 
  846         /*
  847          * verify that we can access the last block in the fs
  848          * if we're mounting read/write.
  849          */
  850 
  851         if (!ronly) {
  852                 error = bread(devvp, fsbtodb(fs, fs->fs_size - 1), fs->fs_fsize,
  853                     cred, &bp);
  854                 if (bp->b_bcount != fs->fs_fsize)
  855                         error = EINVAL;
  856                 bp->b_flags |= B_INVAL;
  857                 if (error)
  858                         goto out;
  859                 brelse(bp);
  860                 bp = NULL;
  861         }
  862 
  863         fs->fs_ronly = ronly;
  864         if (ronly == 0) {
  865                 fs->fs_clean <<= 1;
  866                 fs->fs_fmod = 1;
  867         }
  868         size = fs->fs_cssize;
  869         blks = howmany(size, fs->fs_fsize);
  870         if (fs->fs_contigsumsize > 0)
  871                 size += fs->fs_ncg * sizeof(int32_t);
  872         size += fs->fs_ncg * sizeof(*fs->fs_contigdirs);
  873         space = malloc((u_long)size, M_UFSMNT, M_WAITOK);
  874         fs->fs_csp = space;
  875         for (i = 0; i < blks; i += fs->fs_frag) {
  876                 size = fs->fs_bsize;
  877                 if (i + fs->fs_frag > blks)
  878                         size = (blks - i) * fs->fs_fsize;
  879                 error = bread(devvp, fsbtodb(fs, fs->fs_csaddr + i), size,
  880                               cred, &bp);
  881                 if (error) {
  882                         free(fs->fs_csp, M_UFSMNT);
  883                         goto out;
  884                 }
  885 #ifdef FFS_EI
  886                 if (needswap)
  887                         ffs_csum_swap((struct csum *)bp->b_data,
  888                                 (struct csum *)space, size);
  889                 else
  890 #endif
  891                         memcpy(space, bp->b_data, (u_int)size);
  892                         
  893                 space = (char *)space + size;
  894                 brelse(bp);
  895                 bp = NULL;
  896         }
  897         if (fs->fs_contigsumsize > 0) {
  898                 fs->fs_maxcluster = lp = space;
  899                 for (i = 0; i < fs->fs_ncg; i++)
  900                         *lp++ = fs->fs_contigsumsize;
  901                 space = lp;
  902         }
  903         size = fs->fs_ncg * sizeof(*fs->fs_contigdirs);
  904         fs->fs_contigdirs = space;
  905         space = (char *)space + size;
  906         memset(fs->fs_contigdirs, 0, size);
  907                 /* Compatibility for old filesystems - XXX */
  908         if (fs->fs_avgfilesize <= 0)
  909                 fs->fs_avgfilesize = AVFILESIZ;
  910         if (fs->fs_avgfpdir <= 0)
  911                 fs->fs_avgfpdir = AFPDIR;
  912         mp->mnt_data = ump;
  913         mp->mnt_stat.f_fsid.val[0] = (long)dev;
  914         mp->mnt_stat.f_fsid.val[1] = makefstype(MOUNT_FFS);
  915         mp->mnt_maxsymlinklen = fs->fs_maxsymlinklen;
  916         if (UFS_MPISAPPLEUFS(mp)) {
  917                 /* NeXT used to keep short symlinks in the inode even
  918                  * when using FS_42INODEFMT.  In that case fs->fs_maxsymlinklen
  919                  * is probably -1, but we still need to be able to identify
  920                  * short symlinks.
  921                  */
  922                 mp->mnt_maxsymlinklen = APPLEUFS_MAXSYMLINKLEN;
  923         }
  924         mp->mnt_fs_bshift = fs->fs_bshift;
  925         mp->mnt_dev_bshift = DEV_BSHIFT;        /* XXX */
  926         mp->mnt_flag |= MNT_LOCAL;
  927 #ifdef FFS_EI
  928         if (needswap)
  929                 ump->um_flags |= UFS_NEEDSWAP;
  930 #endif
  931         ump->um_mountp = mp;
  932         ump->um_dev = dev;
  933         ump->um_devvp = devvp;
  934         ump->um_nindir = fs->fs_nindir;
  935         ump->um_lognindir = ffs(fs->fs_nindir) - 1;
  936         ump->um_bptrtodb = fs->fs_fsbtodb;
  937         ump->um_seqinc = fs->fs_frag;
  938         for (i = 0; i < MAXQUOTAS; i++)
  939                 ump->um_quotas[i] = NULLVP;
  940         devvp->v_specmountpoint = mp;
  941         if (ronly == 0 && (fs->fs_flags & FS_DOSOFTDEP)) {
  942                 error = softdep_mount(devvp, mp, fs, cred);
  943                 if (error) {
  944                         free(fs->fs_csp, M_UFSMNT);
  945                         goto out;
  946                 }
  947         }
  948         return (0);
  949 out:
  950         if (fs)
  951                 free(fs, M_UFSMNT);
  952         devvp->v_specmountpoint = NULL;
  953         if (bp)
  954                 brelse(bp);
  955         vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
  956         (void)VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, cred, p);
  957         VOP_UNLOCK(devvp, 0);
  958         if (ump) {
  959                 if (ump->um_oldfscompat)
  960                         free(ump->um_oldfscompat, M_UFSMNT);
  961                 free(ump, M_UFSMNT);
  962                 mp->mnt_data = NULL;
  963         }
  964         return (error);
  965 }
  966 
  967 /*
  968  * Sanity checks for loading old filesystem superblocks.
  969  * See ffs_oldfscompat_write below for unwound actions.
  970  *
  971  * XXX - Parts get retired eventually.
  972  * Unfortunately new bits get added.
  973  */
  974 static void
  975 ffs_oldfscompat_read(fs, ump, sblockloc)
  976         struct fs *fs;
  977         struct ufsmount *ump;
  978         daddr_t sblockloc;
  979 {
  980         off_t maxfilesize;
  981         int32_t *extrasave;
  982 
  983         if ((fs->fs_magic != FS_UFS1_MAGIC) ||
  984             (fs->fs_old_flags & FS_FLAGS_UPDATED))
  985                 return;
  986 
  987         if (!ump->um_oldfscompat)
  988                 ump->um_oldfscompat = malloc(512 + 3*sizeof(int32_t),
  989                     M_UFSMNT, M_WAITOK);
  990 
  991         memcpy(ump->um_oldfscompat, &fs->fs_old_postbl_start, 512);
  992         extrasave = ump->um_oldfscompat;
  993         extrasave += 512/sizeof(int32_t);
  994         extrasave[0] = fs->fs_old_npsect;
  995         extrasave[1] = fs->fs_old_interleave;
  996         extrasave[2] = fs->fs_old_trackskew;
  997 
  998         /* These fields will be overwritten by their
  999          * original values in fs_oldfscompat_write, so it is harmless
 1000          * to modify them here.
 1001          */
 1002         fs->fs_cstotal.cs_ndir = fs->fs_old_cstotal.cs_ndir;
 1003         fs->fs_cstotal.cs_nbfree = fs->fs_old_cstotal.cs_nbfree;
 1004         fs->fs_cstotal.cs_nifree = fs->fs_old_cstotal.cs_nifree;
 1005         fs->fs_cstotal.cs_nffree = fs->fs_old_cstotal.cs_nffree;
 1006 
 1007         fs->fs_maxbsize = fs->fs_bsize;
 1008         fs->fs_time = fs->fs_old_time;
 1009         fs->fs_size = fs->fs_old_size;
 1010         fs->fs_dsize = fs->fs_old_dsize;
 1011         fs->fs_csaddr = fs->fs_old_csaddr;
 1012         fs->fs_sblockloc = sblockloc;
 1013 
 1014         fs->fs_flags = fs->fs_old_flags;
 1015 
 1016         if (fs->fs_old_postblformat == FS_42POSTBLFMT) {
 1017                 fs->fs_old_nrpos = 8;
 1018                 fs->fs_old_npsect = fs->fs_old_nsect;
 1019                 fs->fs_old_interleave = 1;
 1020                 fs->fs_old_trackskew = 0;
 1021         }
 1022 
 1023         if (fs->fs_old_inodefmt < FS_44INODEFMT) {
 1024                 fs->fs_maxfilesize = (u_quad_t) 1LL << 39;
 1025                 fs->fs_qbmask = ~fs->fs_bmask;
 1026                 fs->fs_qfmask = ~fs->fs_fmask;
 1027         }
 1028 
 1029         maxfilesize = (u_int64_t)0x80000000 * fs->fs_bsize - 1;
 1030         if (fs->fs_maxfilesize > maxfilesize)
 1031                 fs->fs_maxfilesize = maxfilesize;
 1032 
 1033         /* Compatibility for old filesystems */
 1034         if (fs->fs_avgfilesize <= 0)
 1035                 fs->fs_avgfilesize = AVFILESIZ;
 1036         if (fs->fs_avgfpdir <= 0)
 1037                 fs->fs_avgfpdir = AFPDIR;
 1038 
 1039 #if 0
 1040         if (bigcgs) {
 1041                 fs->fs_save_cgsize = fs->fs_cgsize;
 1042                 fs->fs_cgsize = fs->fs_bsize;
 1043         }
 1044 #endif
 1045 }
 1046 
 1047 /*
 1048  * Unwinding superblock updates for old filesystems.
 1049  * See ffs_oldfscompat_read above for details.
 1050  *
 1051  * XXX - Parts get retired eventually.
 1052  * Unfortunately new bits get added.
 1053  */
 1054 static void
 1055 ffs_oldfscompat_write(fs, ump)
 1056         struct fs *fs;
 1057         struct ufsmount *ump;
 1058 {
 1059         int32_t *extrasave;
 1060 
 1061         if ((fs->fs_magic != FS_UFS1_MAGIC) ||
 1062             (fs->fs_old_flags & FS_FLAGS_UPDATED))
 1063                 return;
 1064 
 1065         fs->fs_old_time = fs->fs_time;
 1066         fs->fs_old_cstotal.cs_ndir = fs->fs_cstotal.cs_ndir;
 1067         fs->fs_old_cstotal.cs_nbfree = fs->fs_cstotal.cs_nbfree;
 1068         fs->fs_old_cstotal.cs_nifree = fs->fs_cstotal.cs_nifree;
 1069         fs->fs_old_cstotal.cs_nffree = fs->fs_cstotal.cs_nffree;
 1070         fs->fs_old_flags = fs->fs_flags;
 1071 
 1072 #if 0
 1073         if (bigcgs) {
 1074                 fs->fs_cgsize = fs->fs_save_cgsize;
 1075         }
 1076 #endif
 1077 
 1078         memcpy(&fs->fs_old_postbl_start, ump->um_oldfscompat, 512);
 1079         extrasave = ump->um_oldfscompat;
 1080         extrasave += 512/sizeof(int32_t);
 1081         fs->fs_old_npsect = extrasave[0];
 1082         fs->fs_old_interleave = extrasave[1];
 1083         fs->fs_old_trackskew = extrasave[2];
 1084 
 1085 }
 1086 
 1087 /*
 1088  * unmount system call
 1089  */
 1090 int
 1091 ffs_unmount(mp, mntflags, p)
 1092         struct mount *mp;
 1093         int mntflags;
 1094         struct proc *p;
 1095 {
 1096         struct ufsmount *ump;
 1097         struct fs *fs;
 1098         int error, flags, penderr;
 1099 
 1100         penderr = 0;
 1101         flags = 0;
 1102         if (mntflags & MNT_FORCE)
 1103                 flags |= FORCECLOSE;
 1104         if (mp->mnt_flag & MNT_SOFTDEP) {
 1105                 if ((error = softdep_flushfiles(mp, flags, p)) != 0)
 1106                         return (error);
 1107         } else {
 1108                 if ((error = ffs_flushfiles(mp, flags, p)) != 0)
 1109                         return (error);
 1110         }
 1111         ump = VFSTOUFS(mp);
 1112         fs = ump->um_fs;
 1113         if (fs->fs_pendingblocks != 0 || fs->fs_pendinginodes != 0) {
 1114                 printf("%s: unmount pending error: blocks %" PRId64
 1115                        " files %d\n",
 1116                     fs->fs_fsmnt, fs->fs_pendingblocks, fs->fs_pendinginodes);
 1117                 fs->fs_pendingblocks = 0;
 1118                 fs->fs_pendinginodes = 0;
 1119                 penderr = 1;
 1120         }
 1121         if (fs->fs_ronly == 0 &&
 1122             ffs_cgupdate(ump, MNT_WAIT) == 0 &&
 1123             fs->fs_clean & FS_WASCLEAN) {
 1124                 /*
 1125                  * XXXX don't mark fs clean in the case of softdep
 1126                  * pending block errors, until they are fixed.
 1127                  */
 1128                 if (penderr == 0) {
 1129                         if (mp->mnt_flag & MNT_SOFTDEP)
 1130                                 fs->fs_flags &= ~FS_DOSOFTDEP;
 1131                         fs->fs_clean = FS_ISCLEAN;
 1132                 }
 1133                 fs->fs_fmod = 0;
 1134                 (void) ffs_sbupdate(ump, MNT_WAIT);
 1135         }
 1136         if (ump->um_devvp->v_type != VBAD)
 1137                 ump->um_devvp->v_specmountpoint = NULL;
 1138         vn_lock(ump->um_devvp, LK_EXCLUSIVE | LK_RETRY);
 1139         (void)VOP_CLOSE(ump->um_devvp, fs->fs_ronly ? FREAD : FREAD|FWRITE,
 1140                 NOCRED, p);
 1141         vput(ump->um_devvp);
 1142         free(fs->fs_csp, M_UFSMNT);
 1143         free(fs, M_UFSMNT);
 1144         if (ump->um_oldfscompat != NULL)
 1145                 free(ump->um_oldfscompat, M_UFSMNT);
 1146         free(ump, M_UFSMNT);
 1147         mp->mnt_data = NULL;
 1148         mp->mnt_flag &= ~MNT_LOCAL;
 1149         return (0);
 1150 }
 1151 
 1152 /*
 1153  * Flush out all the files in a filesystem.
 1154  */
 1155 int
 1156 ffs_flushfiles(mp, flags, p)
 1157         struct mount *mp;
 1158         int flags;
 1159         struct proc *p;
 1160 {
 1161         extern int doforce;
 1162         struct ufsmount *ump;
 1163         int error;
 1164 
 1165         if (!doforce)
 1166                 flags &= ~FORCECLOSE;
 1167         ump = VFSTOUFS(mp);
 1168 #ifdef QUOTA
 1169         if (mp->mnt_flag & MNT_QUOTA) {
 1170                 int i;
 1171                 if ((error = vflush(mp, NULLVP, SKIPSYSTEM|flags)) != 0)
 1172                         return (error);
 1173                 for (i = 0; i < MAXQUOTAS; i++) {
 1174                         if (ump->um_quotas[i] == NULLVP)
 1175                                 continue;
 1176                         quotaoff(p, mp, i);
 1177                 }
 1178                 /*
 1179                  * Here we fall through to vflush again to ensure
 1180                  * that we have gotten rid of all the system vnodes.
 1181                  */
 1182         }
 1183 #endif
 1184         /*
 1185          * Flush all the files.
 1186          */
 1187         error = vflush(mp, NULLVP, flags);
 1188         if (error)
 1189                 return (error);
 1190         /*
 1191          * Flush filesystem metadata.
 1192          */
 1193         vn_lock(ump->um_devvp, LK_EXCLUSIVE | LK_RETRY);
 1194         error = VOP_FSYNC(ump->um_devvp, p->p_ucred, FSYNC_WAIT, 0, 0, p);
 1195         VOP_UNLOCK(ump->um_devvp, 0);
 1196         return (error);
 1197 }
 1198 
 1199 /*
 1200  * Get file system statistics.
 1201  */
 1202 int
 1203 ffs_statfs(mp, sbp, p)
 1204         struct mount *mp;
 1205         struct statfs *sbp;
 1206         struct proc *p;
 1207 {
 1208         struct ufsmount *ump;
 1209         struct fs *fs;
 1210 
 1211         ump = VFSTOUFS(mp);
 1212         fs = ump->um_fs;
 1213 #ifdef COMPAT_09
 1214         sbp->f_type = 1;
 1215 #else
 1216         sbp->f_type = 0;
 1217 #endif
 1218         sbp->f_bsize = fs->fs_fsize;
 1219         sbp->f_iosize = fs->fs_bsize;
 1220         sbp->f_blocks = fs->fs_dsize;
 1221         sbp->f_bfree = blkstofrags(fs, fs->fs_cstotal.cs_nbfree) +
 1222                 fs->fs_cstotal.cs_nffree + dbtofsb(fs, fs->fs_pendingblocks);
 1223         sbp->f_bavail = (long) (((u_int64_t) fs->fs_dsize * (u_int64_t)
 1224             (100 - fs->fs_minfree) / (u_int64_t) 100) -
 1225             (u_int64_t) (fs->fs_dsize - sbp->f_bfree));
 1226         sbp->f_files =  fs->fs_ncg * fs->fs_ipg - ROOTINO;
 1227         sbp->f_ffree = fs->fs_cstotal.cs_nifree + fs->fs_pendinginodes;
 1228         copy_statfs_info(sbp, mp);
 1229         return (0);
 1230 }
 1231 
 1232 /*
 1233  * Go through the disk queues to initiate sandbagged IO;
 1234  * go through the inodes to write those that have been modified;
 1235  * initiate the writing of the super block if it has been modified.
 1236  *
 1237  * Note: we are always called with the filesystem marked `MPBUSY'.
 1238  */
 1239 int
 1240 ffs_sync(mp, waitfor, cred, p)
 1241         struct mount *mp;
 1242         int waitfor;
 1243         struct ucred *cred;
 1244         struct proc *p;
 1245 {
 1246         struct vnode *vp, *nvp;
 1247         struct inode *ip;
 1248         struct ufsmount *ump = VFSTOUFS(mp);
 1249         struct fs *fs;
 1250         int error, count, allerror = 0;
 1251 
 1252         fs = ump->um_fs;
 1253         if (fs->fs_fmod != 0 && fs->fs_ronly != 0) {            /* XXX */
 1254                 printf("fs = %s\n", fs->fs_fsmnt);
 1255                 panic("update: rofs mod");
 1256         }
 1257         /*
 1258          * Write back each (modified) inode.
 1259          */
 1260         simple_lock(&mntvnode_slock);
 1261 loop:
 1262         for (vp = LIST_FIRST(&mp->mnt_vnodelist); vp != NULL; vp = nvp) {
 1263                 /*
 1264                  * If the vnode that we are about to sync is no longer
 1265                  * associated with this mount point, start over.
 1266                  */
 1267                 if (vp->v_mount != mp)
 1268                         goto loop;
 1269                 simple_lock(&vp->v_interlock);
 1270                 nvp = LIST_NEXT(vp, v_mntvnodes);
 1271                 ip = VTOI(vp);
 1272                 if (vp->v_type == VNON ||
 1273                     ((ip->i_flag &
 1274                       (IN_ACCESS | IN_CHANGE | IN_UPDATE | IN_MODIFIED | IN_ACCESSED)) == 0 &&
 1275                      LIST_EMPTY(&vp->v_dirtyblkhd) &&
 1276                      vp->v_uobj.uo_npages == 0))
 1277                 {
 1278                         simple_unlock(&vp->v_interlock);
 1279                         continue;
 1280                 }
 1281                 simple_unlock(&mntvnode_slock);
 1282                 error = vget(vp, LK_EXCLUSIVE | LK_NOWAIT | LK_INTERLOCK);
 1283                 if (error) {
 1284                         simple_lock(&mntvnode_slock);
 1285                         if (error == ENOENT)
 1286                                 goto loop;
 1287                         continue;
 1288                 }
 1289                 if ((error = VOP_FSYNC(vp, cred,
 1290                     waitfor == MNT_WAIT ? FSYNC_WAIT : 0, 0, 0, p)) != 0)
 1291                         allerror = error;
 1292                 vput(vp);
 1293                 simple_lock(&mntvnode_slock);
 1294         }
 1295         simple_unlock(&mntvnode_slock);
 1296         /*
 1297          * Force stale file system control information to be flushed.
 1298          */
 1299         if (waitfor == MNT_WAIT && (ump->um_mountp->mnt_flag & MNT_SOFTDEP)) {
 1300                 if ((error = softdep_flushworklist(ump->um_mountp, &count, p)))
 1301                         allerror = error;
 1302                 /* Flushed work items may create new vnodes to clean */
 1303                 if (allerror == 0 && count) {
 1304                         simple_lock(&mntvnode_slock);
 1305                         goto loop;
 1306                 }
 1307         }
 1308         if (waitfor != MNT_LAZY && (ump->um_devvp->v_numoutput > 0 ||
 1309             !LIST_EMPTY(&ump->um_devvp->v_dirtyblkhd))) {
 1310                 vn_lock(ump->um_devvp, LK_EXCLUSIVE | LK_RETRY);
 1311                 if ((error = VOP_FSYNC(ump->um_devvp, cred,
 1312                     waitfor == MNT_WAIT ? FSYNC_WAIT : 0, 0, 0, p)) != 0)
 1313                         allerror = error;
 1314                 VOP_UNLOCK(ump->um_devvp, 0);
 1315                 if (allerror == 0 && waitfor == MNT_WAIT) {
 1316                         simple_lock(&mntvnode_slock);
 1317                         goto loop;
 1318                 }
 1319         }
 1320 #ifdef QUOTA
 1321         qsync(mp);
 1322 #endif
 1323         /*
 1324          * Write back modified superblock.
 1325          */
 1326         if (fs->fs_fmod != 0) {
 1327                 fs->fs_fmod = 0;
 1328                 fs->fs_time = time.tv_sec;
 1329                 if ((error = ffs_cgupdate(ump, waitfor)))
 1330                         allerror = error;
 1331         }
 1332         return (allerror);
 1333 }
 1334 
 1335 /*
 1336  * Look up a FFS dinode number to find its incore vnode, otherwise read it
 1337  * in from disk.  If it is in core, wait for the lock bit to clear, then
 1338  * return the inode locked.  Detection and handling of mount points must be
 1339  * done by the calling routine.
 1340  */
 1341 int
 1342 ffs_vget(mp, ino, vpp)
 1343         struct mount *mp;
 1344         ino_t ino;
 1345         struct vnode **vpp;
 1346 {
 1347         struct fs *fs;
 1348         struct inode *ip;
 1349         struct ufsmount *ump;
 1350         struct buf *bp;
 1351         struct vnode *vp;
 1352         dev_t dev;
 1353         int error;
 1354 
 1355         ump = VFSTOUFS(mp);
 1356         dev = ump->um_dev;
 1357 
 1358         if ((*vpp = ufs_ihashget(dev, ino, LK_EXCLUSIVE)) != NULL)
 1359                 return (0);
 1360 
 1361         /* Allocate a new vnode/inode. */
 1362         if ((error = getnewvnode(VT_UFS, mp, ffs_vnodeop_p, &vp)) != 0) {
 1363                 *vpp = NULL;
 1364                 return (error);
 1365         }
 1366 
 1367         /*
 1368          * If someone beat us to it while sleeping in getnewvnode(),
 1369          * push back the freshly allocated vnode we don't need, and return.
 1370          */
 1371 
 1372         do {
 1373                 if ((*vpp = ufs_ihashget(dev, ino, LK_EXCLUSIVE)) != NULL) {
 1374                         ungetnewvnode(vp);
 1375                         return (0);
 1376                 }
 1377         } while (lockmgr(&ufs_hashlock, LK_EXCLUSIVE|LK_SLEEPFAIL, 0));
 1378 
 1379         /*
 1380          * XXX MFS ends up here, too, to allocate an inode.  Should we
 1381          * XXX create another pool for MFS inodes?
 1382          */
 1383 
 1384         ip = pool_get(&ffs_inode_pool, PR_WAITOK);
 1385         memset(ip, 0, sizeof(struct inode));
 1386         vp->v_data = ip;
 1387         ip->i_vnode = vp;
 1388         ip->i_ump = ump;
 1389         ip->i_fs = fs = ump->um_fs;
 1390         ip->i_dev = dev;
 1391         ip->i_number = ino;
 1392         LIST_INIT(&ip->i_pcbufhd);
 1393 #ifdef QUOTA
 1394         {
 1395                 int i;
 1396 
 1397                 for (i = 0; i < MAXQUOTAS; i++)
 1398                         ip->i_dquot[i] = NODQUOT;
 1399         }
 1400 #endif
 1401 
 1402         /*
 1403          * Put it onto its hash chain and lock it so that other requests for
 1404          * this inode will block if they arrive while we are sleeping waiting
 1405          * for old data structures to be purged or for the contents of the
 1406          * disk portion of this inode to be read.
 1407          */
 1408 
 1409         ufs_ihashins(ip);
 1410         lockmgr(&ufs_hashlock, LK_RELEASE, 0);
 1411 
 1412         /* Read in the disk contents for the inode, copy into the inode. */
 1413         error = bread(ump->um_devvp, fsbtodb(fs, ino_to_fsba(fs, ino)),
 1414                       (int)fs->fs_bsize, NOCRED, &bp);
 1415         if (error) {
 1416 
 1417                 /*
 1418                  * The inode does not contain anything useful, so it would
 1419                  * be misleading to leave it on its hash chain. With mode
 1420                  * still zero, it will be unlinked and returned to the free
 1421                  * list by vput().
 1422                  */
 1423 
 1424                 vput(vp);
 1425                 brelse(bp);
 1426                 *vpp = NULL;
 1427                 return (error);
 1428         }
 1429         if (ip->i_ump->um_fstype == UFS1)
 1430                 ip->i_din.ffs1_din = pool_get(&ffs_dinode1_pool, PR_WAITOK);
 1431         else
 1432                 ip->i_din.ffs2_din = pool_get(&ffs_dinode2_pool, PR_WAITOK);
 1433         ffs_load_inode(bp, ip, fs, ino);
 1434         if (DOINGSOFTDEP(vp))
 1435                 softdep_load_inodeblock(ip);
 1436         else
 1437                 ip->i_ffs_effnlink = ip->i_nlink;
 1438         brelse(bp);
 1439 
 1440         /*
 1441          * Initialize the vnode from the inode, check for aliases.
 1442          * Note that the underlying vnode may have changed.
 1443          */
 1444 
 1445         ufs_vinit(mp, ffs_specop_p, ffs_fifoop_p, &vp);
 1446 
 1447         /*
 1448          * Finish inode initialization now that aliasing has been resolved.
 1449          */
 1450 
 1451         genfs_node_init(vp, &ffs_genfsops);
 1452         ip->i_devvp = ump->um_devvp;
 1453         VREF(ip->i_devvp);
 1454 
 1455         /*
 1456          * Ensure that uid and gid are correct. This is a temporary
 1457          * fix until fsck has been changed to do the update.
 1458          */
 1459 
 1460         if (fs->fs_old_inodefmt < FS_44INODEFMT) {              /* XXX */
 1461                 ip->i_uid = ip->i_ffs1_ouid;                    /* XXX */
 1462                 ip->i_gid = ip->i_ffs1_ogid;                    /* XXX */
 1463         }                                                       /* XXX */
 1464         uvm_vnp_setsize(vp, ip->i_size);
 1465         *vpp = vp;
 1466         return (0);
 1467 }
 1468 
 1469 /*
 1470  * File handle to vnode
 1471  *
 1472  * Have to be really careful about stale file handles:
 1473  * - check that the inode number is valid
 1474  * - call ffs_vget() to get the locked inode
 1475  * - check for an unallocated inode (i_mode == 0)
 1476  * - check that the given client host has export rights and return
 1477  *   those rights via. exflagsp and credanonp
 1478  */
 1479 int
 1480 ffs_fhtovp(mp, fhp, vpp)
 1481         struct mount *mp;
 1482         struct fid *fhp;
 1483         struct vnode **vpp;
 1484 {
 1485         struct ufid *ufhp;
 1486         struct fs *fs;
 1487 
 1488         ufhp = (struct ufid *)fhp;
 1489         fs = VFSTOUFS(mp)->um_fs;
 1490         if (ufhp->ufid_ino < ROOTINO ||
 1491             ufhp->ufid_ino >= fs->fs_ncg * fs->fs_ipg)
 1492                 return (ESTALE);
 1493         return (ufs_fhtovp(mp, ufhp, vpp));
 1494 }
 1495 
 1496 /*
 1497  * Vnode pointer to File handle
 1498  */
 1499 /* ARGSUSED */
 1500 int
 1501 ffs_vptofh(vp, fhp)
 1502         struct vnode *vp;
 1503         struct fid *fhp;
 1504 {
 1505         struct inode *ip;
 1506         struct ufid *ufhp;
 1507 
 1508         ip = VTOI(vp);
 1509         ufhp = (struct ufid *)fhp;
 1510         ufhp->ufid_len = sizeof(struct ufid);
 1511         ufhp->ufid_ino = ip->i_number;
 1512         ufhp->ufid_gen = ip->i_gen;
 1513         return (0);
 1514 }
 1515 
 1516 void
 1517 ffs_init()
 1518 {
 1519         if (ffs_initcount++ > 0)
 1520                 return;
 1521 
 1522         softdep_initialize();
 1523         ufs_init();
 1524 
 1525         pool_init(&ffs_inode_pool, sizeof(struct inode), 0, 0, 0, "ffsinopl",
 1526             &pool_allocator_nointr);
 1527         pool_init(&ffs_dinode1_pool, sizeof(struct ufs1_dinode), 0, 0, 0,
 1528             "dino1pl", &pool_allocator_nointr);
 1529         pool_init(&ffs_dinode2_pool, sizeof(struct ufs2_dinode), 0, 0, 0,
 1530             "dino2pl", &pool_allocator_nointr);
 1531 }
 1532 
 1533 void
 1534 ffs_reinit()
 1535 {
 1536         softdep_reinitialize();
 1537         ufs_reinit();
 1538 }
 1539 
 1540 void
 1541 ffs_done()
 1542 {
 1543         if (--ffs_initcount > 0)
 1544                 return;
 1545 
 1546         /* XXX softdep cleanup ? */
 1547         ufs_done();
 1548         pool_destroy(&ffs_inode_pool);
 1549 }
 1550 
 1551 SYSCTL_SETUP(sysctl_vfs_ffs_setup, "sysctl vfs.ffs subtree setup")
 1552 {
 1553         extern int doasyncfree;
 1554         extern int ffs_log_changeopt;
 1555 
 1556         sysctl_createv(clog, 0, NULL, NULL,
 1557                        CTLFLAG_PERMANENT,
 1558                        CTLTYPE_NODE, "vfs", NULL,
 1559                        NULL, 0, NULL, 0,
 1560                        CTL_VFS, CTL_EOL);
 1561         sysctl_createv(clog, 0, NULL, NULL,
 1562                        CTLFLAG_PERMANENT,
 1563                        CTLTYPE_NODE, "ffs",
 1564                        SYSCTL_DESCR("Berkeley Fast File System"),
 1565                        NULL, 0, NULL, 0,
 1566                        CTL_VFS, 1, CTL_EOL);
 1567 
 1568         /*
 1569          * @@@ should we even bother with these first three?
 1570          */
 1571         sysctl_createv(clog, 0, NULL, NULL,
 1572                        CTLFLAG_PERMANENT,
 1573                        CTLTYPE_INT, "doclusterread", NULL,
 1574                        sysctl_notavail, 0, NULL, 0,
 1575                        CTL_VFS, 1, FFS_CLUSTERREAD, CTL_EOL);
 1576         sysctl_createv(clog, 0, NULL, NULL,
 1577                        CTLFLAG_PERMANENT,
 1578                        CTLTYPE_INT, "doclusterwrite", NULL,
 1579                        sysctl_notavail, 0, NULL, 0,
 1580                        CTL_VFS, 1, FFS_CLUSTERWRITE, CTL_EOL);
 1581         sysctl_createv(clog, 0, NULL, NULL,
 1582                        CTLFLAG_PERMANENT,
 1583                        CTLTYPE_INT, "doreallocblks", NULL,
 1584                        sysctl_notavail, 0, NULL, 0,
 1585                        CTL_VFS, 1, FFS_REALLOCBLKS, CTL_EOL);
 1586         sysctl_createv(clog, 0, NULL, NULL,
 1587                        CTLFLAG_PERMANENT,
 1588                        CTLTYPE_INT, "doasyncfree",
 1589                        SYSCTL_DESCR("Release dirty blocks asynchronously"),
 1590                        NULL, 0, &doasyncfree, 0,
 1591                        CTL_VFS, 1, FFS_ASYNCFREE, CTL_EOL);
 1592         sysctl_createv(clog, 0, NULL, NULL,
 1593                        CTLFLAG_PERMANENT,
 1594                        CTLTYPE_INT, "log_changeopt",
 1595                        SYSCTL_DESCR("Log changes in optimization strategy"),
 1596                        NULL, 0, &ffs_log_changeopt, 0,
 1597                        CTL_VFS, 1, FFS_LOG_CHANGEOPT, CTL_EOL);
 1598 }
 1599 
 1600 /*
 1601  * Write a superblock and associated information back to disk.
 1602  */
 1603 int
 1604 ffs_sbupdate(mp, waitfor)
 1605         struct ufsmount *mp;
 1606         int waitfor;
 1607 {
 1608         struct fs *fs = mp->um_fs;
 1609         struct buf *bp;
 1610         int error = 0;
 1611         u_int32_t saveflag;
 1612 
 1613         bp = getblk(mp->um_devvp,
 1614             fs->fs_sblockloc >> (fs->fs_fshift - fs->fs_fsbtodb),
 1615             (int)fs->fs_sbsize, 0, 0);
 1616         saveflag = fs->fs_flags & FS_INTERNAL;
 1617         fs->fs_flags &= ~FS_INTERNAL;
 1618         
 1619         memcpy(bp->b_data, fs, fs->fs_sbsize);
 1620 
 1621         ffs_oldfscompat_write((struct fs *)bp->b_data, mp);
 1622 #ifdef FFS_EI
 1623         if (mp->um_flags & UFS_NEEDSWAP)
 1624                 ffs_sb_swap((struct fs *)bp->b_data, (struct fs *)bp->b_data);
 1625 #endif
 1626         fs->fs_flags |= saveflag;
 1627 
 1628         if (waitfor == MNT_WAIT)
 1629                 error = bwrite(bp);
 1630         else
 1631                 bawrite(bp);
 1632         return (error);
 1633 }
 1634 
 1635 int
 1636 ffs_cgupdate(mp, waitfor)
 1637         struct ufsmount *mp;
 1638         int waitfor;
 1639 {
 1640         struct fs *fs = mp->um_fs;
 1641         struct buf *bp;
 1642         int blks;
 1643         void *space;
 1644         int i, size, error = 0, allerror = 0;
 1645 
 1646         allerror = ffs_sbupdate(mp, waitfor);
 1647         blks = howmany(fs->fs_cssize, fs->fs_fsize);
 1648         space = fs->fs_csp;
 1649         for (i = 0; i < blks; i += fs->fs_frag) {
 1650                 size = fs->fs_bsize;
 1651                 if (i + fs->fs_frag > blks)
 1652                         size = (blks - i) * fs->fs_fsize;
 1653                 bp = getblk(mp->um_devvp, fsbtodb(fs, fs->fs_csaddr + i),
 1654                     size, 0, 0);
 1655 #ifdef FFS_EI
 1656                 if (mp->um_flags & UFS_NEEDSWAP)
 1657                         ffs_csum_swap((struct csum*)space,
 1658                             (struct csum*)bp->b_data, size);
 1659                 else
 1660 #endif
 1661                         memcpy(bp->b_data, space, (u_int)size);
 1662                 space = (char *)space + size;
 1663                 if (waitfor == MNT_WAIT)
 1664                         error = bwrite(bp);
 1665                 else
 1666                         bawrite(bp);
 1667         }
 1668         if (!allerror && error)
 1669                 allerror = error;
 1670         return (allerror);
 1671 }

Cache object: 83773d90f58bf2a620971b8a953eb404


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


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