[BACK]Return to ffs_vfsops.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / ufs / ffs

Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.

Diff for /src/sys/ufs/ffs/ffs_vfsops.c between version 1.223.4.1 and 1.223.4.2

version 1.223.4.1, 2008/05/16 02:26:00 version 1.223.4.2, 2009/05/04 08:14:37
Line 1 
Line 1 
 /*      $NetBSD$        */  /*      $NetBSD$        */
   
   /*-
    * Copyright (c) 2008, 2009 The NetBSD Foundation, Inc.
    * All rights reserved.
    *
    * This code is derived from software contributed to The NetBSD Foundation
    * by Wasabi Systems, Inc, and by Andrew Doran.
    *
    * Redistribution and use in source and binary forms, with or without
    * modification, are permitted provided that the following conditions
    * are met:
    * 1. Redistributions of source code must retain the above copyright
    *    notice, this list of conditions and the following disclaimer.
    * 2. Redistributions in binary form must reproduce the above copyright
    *    notice, this list of conditions and the following disclaimer in the
    *    documentation and/or other materials provided with the distribution.
    *
    * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
    * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
    * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
    * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
    * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
    * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
    * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
    * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
    * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
    * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
    * POSSIBILITY OF SUCH DAMAGE.
    */
   
 /*  /*
  * Copyright (c) 1989, 1991, 1993, 1994   * Copyright (c) 1989, 1991, 1993, 1994
  *      The Regents of the University of California.  All rights reserved.   *      The Regents of the University of California.  All rights reserved.
Line 37  __KERNEL_RCSID(0, "$NetBSD$");
Line 66  __KERNEL_RCSID(0, "$NetBSD$");
 #if defined(_KERNEL_OPT)  #if defined(_KERNEL_OPT)
 #include "opt_ffs.h"  #include "opt_ffs.h"
 #include "opt_quota.h"  #include "opt_quota.h"
 #include "opt_softdep.h"  #include "opt_wapbl.h"
 #endif  #endif
   
 #include <sys/param.h>  #include <sys/param.h>
Line 61  __KERNEL_RCSID(0, "$NetBSD$");
Line 90  __KERNEL_RCSID(0, "$NetBSD$");
 #include <sys/sysctl.h>  #include <sys/sysctl.h>
 #include <sys/conf.h>  #include <sys/conf.h>
 #include <sys/kauth.h>  #include <sys/kauth.h>
   #include <sys/wapbl.h>
 #include <sys/fstrans.h>  #include <sys/fstrans.h>
 #include <sys/module.h>  #include <sys/module.h>
   
Line 73  __KERNEL_RCSID(0, "$NetBSD$");
Line 103  __KERNEL_RCSID(0, "$NetBSD$");
 #include <ufs/ufs/dir.h>  #include <ufs/ufs/dir.h>
 #include <ufs/ufs/ufs_extern.h>  #include <ufs/ufs/ufs_extern.h>
 #include <ufs/ufs/ufs_bswap.h>  #include <ufs/ufs/ufs_bswap.h>
   #include <ufs/ufs/ufs_wapbl.h>
   
 #include <ufs/ffs/fs.h>  #include <ufs/ffs/fs.h>
 #include <ufs/ffs/ffs_extern.h>  #include <ufs/ffs/ffs_extern.h>
   
 MODULE(MODULE_CLASS_VFS, ffs, NULL);  MODULE(MODULE_CLASS_VFS, ffs, NULL);
   
   static int      ffs_vfs_fsync(vnode_t *, int);
   
   static struct sysctllog *ffs_sysctl_log;
   
 /* how many times ffs_init() was called */  /* how many times ffs_init() was called */
 int ffs_initcount = 0;  int ffs_initcount = 0;
   
Line 117  struct vfsops ffs_vfsops = {
Line 152  struct vfsops ffs_vfsops = {
         ffs_suspendctl,          ffs_suspendctl,
         genfs_renamelock_enter,          genfs_renamelock_enter,
         genfs_renamelock_exit,          genfs_renamelock_exit,
         ffs_full_fsync,          ffs_vfs_fsync,
         ffs_vnodeopv_descs,          ffs_vnodeopv_descs,
         0,          0,
         { NULL, NULL },          { NULL, NULL },
Line 137  static const struct ufs_ops ffs_ufsops =
Line 172  static const struct ufs_ops ffs_ufsops =
         .uo_valloc = ffs_valloc,          .uo_valloc = ffs_valloc,
         .uo_vfree = ffs_vfree,          .uo_vfree = ffs_vfree,
         .uo_balloc = ffs_balloc,          .uo_balloc = ffs_balloc,
           .uo_unmark_vnode = (void (*)(vnode_t *))nullop,
 };  };
   
 static int  static int
 ffs_modcmd(modcmd_t cmd, void *arg)  ffs_modcmd(modcmd_t cmd, void *arg)
 {  {
           int error;
   
   #if 0
           extern int doasyncfree;
   #endif
           extern int ffs_log_changeopt;
   
         switch (cmd) {          switch (cmd) {
         case MODULE_CMD_INIT:          case MODULE_CMD_INIT:
                 return vfs_attach(&ffs_vfsops);                  error = vfs_attach(&ffs_vfsops);
                   if (error != 0)
                           break;
   
                   sysctl_createv(&ffs_sysctl_log, 0, NULL, NULL,
                                  CTLFLAG_PERMANENT,
                                  CTLTYPE_NODE, "vfs", NULL,
                                  NULL, 0, NULL, 0,
                                  CTL_VFS, CTL_EOL);
                   sysctl_createv(&ffs_sysctl_log, 0, NULL, NULL,
                                  CTLFLAG_PERMANENT,
                                  CTLTYPE_NODE, "ffs",
                                  SYSCTL_DESCR("Berkeley Fast File System"),
                                  NULL, 0, NULL, 0,
                                  CTL_VFS, 1, CTL_EOL);
   
                   /*
                    * @@@ should we even bother with these first three?
                    */
                   sysctl_createv(&ffs_sysctl_log, 0, NULL, NULL,
                                  CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
                                  CTLTYPE_INT, "doclusterread", NULL,
                                  sysctl_notavail, 0, NULL, 0,
                                  CTL_VFS, 1, FFS_CLUSTERREAD, CTL_EOL);
                   sysctl_createv(&ffs_sysctl_log, 0, NULL, NULL,
                                  CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
                                  CTLTYPE_INT, "doclusterwrite", NULL,
                                  sysctl_notavail, 0, NULL, 0,
                                  CTL_VFS, 1, FFS_CLUSTERWRITE, CTL_EOL);
                   sysctl_createv(&ffs_sysctl_log, 0, NULL, NULL,
                                  CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
                                  CTLTYPE_INT, "doreallocblks", NULL,
                                  sysctl_notavail, 0, NULL, 0,
                                  CTL_VFS, 1, FFS_REALLOCBLKS, CTL_EOL);
   #if 0
                   sysctl_createv(&ffs_sysctl_log, 0, NULL, NULL,
                                  CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
                                  CTLTYPE_INT, "doasyncfree",
                                  SYSCTL_DESCR("Release dirty blocks asynchronously"),
                                  NULL, 0, &doasyncfree, 0,
                                  CTL_VFS, 1, FFS_ASYNCFREE, CTL_EOL);
   #endif
                   sysctl_createv(&ffs_sysctl_log, 0, NULL, NULL,
                                  CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
                                  CTLTYPE_INT, "log_changeopt",
                                  SYSCTL_DESCR("Log changes in optimization strategy"),
                                  NULL, 0, &ffs_log_changeopt, 0,
                                  CTL_VFS, 1, FFS_LOG_CHANGEOPT, CTL_EOL);
                   break;
         case MODULE_CMD_FINI:          case MODULE_CMD_FINI:
                 return vfs_detach(&ffs_vfsops);                  error = vfs_detach(&ffs_vfsops);
                   if (error != 0)
                           break;
                   sysctl_teardown(&ffs_sysctl_log);
                   break;
         default:          default:
                 return ENOTTY;                  error = ENOTTY;
                   break;
         }          }
   
           return (error);
 }  }
   
 pool_cache_t ffs_inode_cache;  pool_cache_t ffs_inode_cache;
Line 180  ffs_mountroot(void)
Line 277  ffs_mountroot(void)
                 vrele(rootvp);                  vrele(rootvp);
                 return (error);                  return (error);
         }          }
   
           /*
            * We always need to be able to mount the root file system.
            */
           mp->mnt_flag |= MNT_FORCE;
         if ((error = ffs_mountfs(rootvp, mp, l)) != 0) {          if ((error = ffs_mountfs(rootvp, mp, l)) != 0) {
                 vfs_unbusy(mp, false, NULL);                  vfs_unbusy(mp, false, NULL);
                 vfs_destroy(mp);                  vfs_destroy(mp);
                 return (error);                  return (error);
         }          }
           mp->mnt_flag &= ~MNT_FORCE;
         mutex_enter(&mountlist_lock);          mutex_enter(&mountlist_lock);
         CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list);          CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list);
         mutex_exit(&mountlist_lock);          mutex_exit(&mountlist_lock);
Line 208  ffs_mount(struct mount *mp, const char *
Line 311  ffs_mount(struct mount *mp, const char *
 {  {
         struct lwp *l = curlwp;          struct lwp *l = curlwp;
         struct nameidata nd;          struct nameidata nd;
         struct vnode *vp, *devvp = NULL;          struct vnode *devvp = NULL;
         struct ufs_args *args = data;          struct ufs_args *args = data;
         struct ufsmount *ump = NULL;          struct ufsmount *ump = NULL;
         struct fs *fs;          struct fs *fs;
Line 227  ffs_mount(struct mount *mp, const char *
Line 330  ffs_mount(struct mount *mp, const char *
                 return 0;                  return 0;
         }          }
   
 #if !defined(SOFTDEP)  
         mp->mnt_flag &= ~MNT_SOFTDEP;  
 #endif  
   
         update = mp->mnt_flag & MNT_UPDATE;          update = mp->mnt_flag & MNT_UPDATE;
   
         /* Check arguments */          /* Check arguments */
Line 280  ffs_mount(struct mount *mp, const char *
Line 379  ffs_mount(struct mount *mp, const char *
         }          }
   
         /*          /*
          * Mark the device and any existing vnodes as involved in  
          * softdep processing.  
          */  
         if ((mp->mnt_flag & MNT_SOFTDEP) != 0) {  
                 devvp->v_uflag |= VU_SOFTDEP;  
                 mutex_enter(&mntvnode_lock);  
                 TAILQ_FOREACH(vp, &mp->mnt_vnodelist, v_mntvnodes) {  
                         if (vp->v_mount != mp || vismarker(vp))  
                                 continue;  
                         vp->v_uflag |= VU_SOFTDEP;  
                 }  
                 mutex_exit(&mntvnode_lock);  
         }  
   
         /*  
          * If mount by non-root, then verify that user has necessary           * If mount by non-root, then verify that user has necessary
          * permissions on the device.           * permissions on the device.
          */           *
         if (error == 0 && kauth_authorize_generic(l->l_cred,           * Permission to update a mount is checked higher, so here we presume
             KAUTH_GENERIC_ISSUSER, NULL) != 0) {           * updating the mount is okay (for example, as far as securelevel goes)
                 accessmode = VREAD;           * which leaves us with the normal check.
                 if (update ?           */
                     (mp->mnt_iflag & IMNT_WANTRDWR) != 0 :          accessmode = VREAD;
                     (mp->mnt_flag & MNT_RDONLY) == 0)          if (update ?
                         accessmode |= VWRITE;              (mp->mnt_iflag & IMNT_WANTRDWR) != 0 :
                 vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);              (mp->mnt_flag & MNT_RDONLY) == 0)
                 error = VOP_ACCESS(devvp, accessmode, l->l_cred);                  accessmode |= VWRITE;
                 VOP_UNLOCK(devvp, 0);          vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
         }          error = genfs_can_mount(devvp, accessmode, l->l_cred);
           VOP_UNLOCK(devvp, 0);
   
         if (error) {          if (error) {
                 vrele(devvp);                  vrele(devvp);
                 return (error);                  return (error);
         }          }
   
   #ifdef WAPBL
           /* WAPBL can only be enabled on a r/w mount. */
           if ((mp->mnt_flag & MNT_RDONLY) && !(mp->mnt_iflag & IMNT_WANTRDWR)) {
                   mp->mnt_flag &= ~MNT_LOG;
           }
   #else /* !WAPBL */
           mp->mnt_flag &= ~MNT_LOG;
   #endif /* !WAPBL */
   
         if (!update) {          if (!update) {
                 int xflags;                  int xflags;
   
                 if (mp->mnt_flag & MNT_RDONLY)                  if (mp->mnt_flag & MNT_RDONLY)
                         xflags = FREAD;                          xflags = FREAD;
                 else                  else
                         xflags = FREAD|FWRITE;                          xflags = FREAD | FWRITE;
                 error = VOP_OPEN(devvp, xflags, FSCRED);                  error = VOP_OPEN(devvp, xflags, FSCRED);
                 if (error)                  if (error)
                         goto fail;                          goto fail;
Line 335  ffs_mount(struct mount *mp, const char *
Line 429  ffs_mount(struct mount *mp, const char *
   
                 ump = VFSTOUFS(mp);                  ump = VFSTOUFS(mp);
                 fs = ump->um_fs;                  fs = ump->um_fs;
                 if ((mp->mnt_flag & (MNT_SOFTDEP | MNT_ASYNC)) ==  
                     (MNT_SOFTDEP | MNT_ASYNC)) {  
                         printf("%s fs uses soft updates, "  
                             "ignoring async mode\n",  
                             fs->fs_fsmnt);  
                         mp->mnt_flag &= ~MNT_ASYNC;  
                 }  
         } else {          } else {
                 /*                  /*
                  * Update the mount.                   * Update the mount.
Line 363  ffs_mount(struct mount *mp, const char *
Line 450  ffs_mount(struct mount *mp, const char *
                         flags = WRITECLOSE;                          flags = WRITECLOSE;
                         if (mp->mnt_flag & MNT_FORCE)                          if (mp->mnt_flag & MNT_FORCE)
                                 flags |= FORCECLOSE;                                  flags |= FORCECLOSE;
                         if (mp->mnt_flag & MNT_SOFTDEP)                          error = ffs_flushfiles(mp, flags, l);
                                 error = softdep_flushfiles(mp, flags, l);                          if (error == 0)
                         else                                  error = UFS_WAPBL_BEGIN(mp);
                                 error = ffs_flushfiles(mp, flags, l);  
                         if (fs->fs_pendingblocks != 0 ||  
                             fs->fs_pendinginodes != 0) {  
                                 printf("%s: update error: blocks %" PRId64  
                                        " files %d\n",  
                                     fs->fs_fsmnt, fs->fs_pendingblocks,  
                                     fs->fs_pendinginodes);  
                                 fs->fs_pendingblocks = 0;  
                                 fs->fs_pendinginodes = 0;  
                         }  
                         if (error == 0 &&                          if (error == 0 &&
                             ffs_cgupdate(ump, MNT_WAIT) == 0 &&                              ffs_cgupdate(ump, MNT_WAIT) == 0 &&
                             fs->fs_clean & FS_WASCLEAN) {                              fs->fs_clean & FS_WASCLEAN) {
Line 384  ffs_mount(struct mount *mp, const char *
Line 461  ffs_mount(struct mount *mp, const char *
                                 fs->fs_clean = FS_ISCLEAN;                                  fs->fs_clean = FS_ISCLEAN;
                                 (void) ffs_sbupdate(ump, MNT_WAIT);                                  (void) ffs_sbupdate(ump, MNT_WAIT);
                         }                          }
                           if (error == 0)
                                   UFS_WAPBL_END(mp);
                         if (error)                          if (error)
                                 return (error);                                  return (error);
                         fs->fs_ronly = 1;  
                         fs->fs_fmod = 0;  
                 }                  }
   
                 /*  #ifdef WAPBL
                  * Flush soft dependencies if disabling it via an update                  if ((mp->mnt_flag & MNT_LOG) == 0) {
                  * mount. This may leave some items to be processed,                          error = ffs_wapbl_stop(mp, mp->mnt_flag & MNT_FORCE);
                  * so don't do this yet XXX.                          if (error)
                  */                                  return error;
                 if ((fs->fs_flags & FS_DOSOFTDEP) &&  
                     !(mp->mnt_flag & MNT_SOFTDEP) && fs->fs_ronly == 0) {  
 #ifdef notyet  
                         flags = WRITECLOSE;  
                         if (mp->mnt_flag & MNT_FORCE)  
                                 flags |= FORCECLOSE;  
                         error = softdep_flushfiles(mp, flags, l);  
                         if (error == 0 && ffs_cgupdate(ump, MNT_WAIT) == 0)  
                                 fs->fs_flags &= ~FS_DOSOFTDEP;  
                                 (void) ffs_sbupdate(ump, MNT_WAIT);  
 #elif defined(SOFTDEP)  
                         mp->mnt_flag |= MNT_SOFTDEP;  
 #endif  
                 }                  }
   #endif /* WAPBL */
   
                 /*                  if (fs->fs_ronly == 0 && (mp->mnt_flag & MNT_RDONLY)) {
                  * When upgrading to a softdep mount, we must first flush                          /*
                  * all vnodes. (not done yet -- see above)                           * Finish change from r/w to r/o
                  */                           */
                 if (!(fs->fs_flags & FS_DOSOFTDEP) &&                          fs->fs_ronly = 1;
                     (mp->mnt_flag & MNT_SOFTDEP) && fs->fs_ronly == 0) {                          fs->fs_fmod = 0;
 #ifdef notyet  
                         flags = WRITECLOSE;  
                         if (mp->mnt_flag & MNT_FORCE)  
                                 flags |= FORCECLOSE;  
                         error = ffs_flushfiles(mp, flags, l);  
 #else  
                         mp->mnt_flag &= ~MNT_SOFTDEP;  
 #endif  
                 }                  }
   
                 if (mp->mnt_flag & MNT_RELOAD) {                  if (mp->mnt_flag & MNT_RELOAD) {
Line 439  ffs_mount(struct mount *mp, const char *
Line 496  ffs_mount(struct mount *mp, const char *
                         fs->fs_ronly = 0;                          fs->fs_ronly = 0;
                         fs->fs_clean <<= 1;                          fs->fs_clean <<= 1;
                         fs->fs_fmod = 1;                          fs->fs_fmod = 1;
                         if ((fs->fs_flags & FS_DOSOFTDEP)) {  #ifdef WAPBL
                                 error = softdep_mount(devvp, mp, fs,                          if (fs->fs_flags & FS_DOWAPBL) {
                                     l->l_cred);                                  printf("%s: replaying log to disk\n",
                                 if (error)                                      fs->fs_fsmnt);
                                         return (error);                                  KDASSERT(mp->mnt_wapbl_replay);
                                   error = wapbl_replay_write(mp->mnt_wapbl_replay,
                                                              devvp);
                                   if (error) {
                                           return error;
                                   }
                                   wapbl_replay_stop(mp->mnt_wapbl_replay);
                                   fs->fs_clean = FS_WASCLEAN;
                         }                          }
   #endif /* WAPBL */
                         if (fs->fs_snapinum[0] != 0)                          if (fs->fs_snapinum[0] != 0)
                                 ffs_snapshot_mount(mp);                                  ffs_snapshot_mount(mp);
                 }                  }
   
   #ifdef WAPBL
                   error = ffs_wapbl_start(mp);
                   if (error)
                           return error;
   #endif /* WAPBL */
   
                 if (args->fspec == NULL)                  if (args->fspec == NULL)
                         return EINVAL;                          return EINVAL;
                 if ((mp->mnt_flag & (MNT_SOFTDEP | MNT_ASYNC)) ==  
                     (MNT_SOFTDEP | MNT_ASYNC)) {  
                         printf("%s fs uses soft updates, ignoring async mode\n",  
                             fs->fs_fsmnt);  
                         mp->mnt_flag &= ~MNT_ASYNC;  
                 }  
         }          }
   
         error = set_statvfs_info(path, UIO_USERSPACE, args->fspec,          error = set_statvfs_info(path, UIO_USERSPACE, args->fspec,
Line 463  ffs_mount(struct mount *mp, const char *
Line 529  ffs_mount(struct mount *mp, const char *
         if (error == 0)          if (error == 0)
                 (void)strncpy(fs->fs_fsmnt, mp->mnt_stat.f_mntonname,                  (void)strncpy(fs->fs_fsmnt, mp->mnt_stat.f_mntonname,
                     sizeof(fs->fs_fsmnt));                      sizeof(fs->fs_fsmnt));
         if (mp->mnt_flag & MNT_SOFTDEP)          fs->fs_flags &= ~FS_DOSOFTDEP;
                 fs->fs_flags |= FS_DOSOFTDEP;  
         else  
                 fs->fs_flags &= ~FS_DOSOFTDEP;  
         if (fs->fs_fmod != 0) { /* XXX */          if (fs->fs_fmod != 0) { /* XXX */
                   int err;
   
                 fs->fs_fmod = 0;                  fs->fs_fmod = 0;
                 if (fs->fs_clean & FS_WASCLEAN)                  if (fs->fs_clean & FS_WASCLEAN)
                         fs->fs_time = time_second;                          fs->fs_time = time_second;
                 else {                  else {
                         printf("%s: file system not clean (fs_clean=%x); please fsck(8)\n",                          printf("%s: file system not clean (fs_clean=%#x); "
                             mp->mnt_stat.f_mntfromname, fs->fs_clean);                              "please fsck(8)\n", mp->mnt_stat.f_mntfromname,
                               fs->fs_clean);
                         printf("%s: lost blocks %" PRId64 " files %d\n",                          printf("%s: lost blocks %" PRId64 " files %d\n",
                             mp->mnt_stat.f_mntfromname, fs->fs_pendingblocks,                              mp->mnt_stat.f_mntfromname, fs->fs_pendingblocks,
                             fs->fs_pendinginodes);                              fs->fs_pendinginodes);
                 }                  }
                 (void) ffs_cgupdate(ump, MNT_WAIT);                  err = UFS_WAPBL_BEGIN(mp);
                   if (err == 0) {
                           (void) ffs_cgupdate(ump, MNT_WAIT);
                           UFS_WAPBL_END(mp);
                   }
         }          }
           if ((mp->mnt_flag & MNT_SOFTDEP) != 0) {
                   printf("%s: `-o softdep' is no longer supported, "
                       "consider `-o log'\n", mp->mnt_stat.f_mntfromname);
                   mp->mnt_flag &= ~MNT_SOFTDEP;
           }
   
         return (error);          return (error);
   
 fail:  fail:
Line 537  ffs_reload(struct mount *mp, kauth_cred_
Line 613  ffs_reload(struct mount *mp, kauth_cred_
                 size = dpart.disklab->d_secsize;                  size = dpart.disklab->d_secsize;
         /* XXX we don't handle possibility that superblock moved. */          /* XXX we don't handle possibility that superblock moved. */
         error = bread(devvp, fs->fs_sblockloc / size, fs->fs_sbsize,          error = bread(devvp, fs->fs_sblockloc / size, fs->fs_sbsize,
                       NOCRED, &bp);                        NOCRED, 0, &bp);
         if (error) {          if (error) {
                 brelse(bp, 0);                  brelse(bp, 0);
                 return (error);                  return (error);
Line 590  ffs_reload(struct mount *mp, kauth_cred_
Line 666  ffs_reload(struct mount *mp, kauth_cred_
                  * is found, then treat it like an Apple UFS filesystem anyway                   * is found, then treat it like an Apple UFS filesystem anyway
                  */                   */
                 error = bread(devvp, (daddr_t)(APPLEUFS_LABEL_OFFSET / size),                  error = bread(devvp, (daddr_t)(APPLEUFS_LABEL_OFFSET / size),
                         APPLEUFS_LABEL_SIZE, cred, &bp);                          APPLEUFS_LABEL_SIZE, cred, 0, &bp);
                 if (error) {                  if (error) {
                         brelse(bp, 0);                          brelse(bp, 0);
                         return (error);                          return (error);
                 }                  }
                 error = ffs_appleufs_validate(fs->fs_fsmnt,                  error = ffs_appleufs_validate(fs->fs_fsmnt,
                         (struct appleufslabel *)bp->b_data,NULL);                          (struct appleufslabel *)bp->b_data, NULL);
                 if (error == 0)                  if (error == 0)
                         ump->um_flags |= UFS_ISAPPLEUFS;                          ump->um_flags |= UFS_ISAPPLEUFS;
                 brelse(bp, 0);                  brelse(bp, 0);
Line 621  ffs_reload(struct mount *mp, kauth_cred_
Line 697  ffs_reload(struct mount *mp, kauth_cred_
                         mp->mnt_iflag &= ~IMNT_DTYPE;                          mp->mnt_iflag &= ~IMNT_DTYPE;
         }          }
         ffs_oldfscompat_read(fs, ump, sblockloc);          ffs_oldfscompat_read(fs, ump, sblockloc);
   
         mutex_enter(&ump->um_lock);          mutex_enter(&ump->um_lock);
         ump->um_maxfilesize = fs->fs_maxfilesize;          ump->um_maxfilesize = fs->fs_maxfilesize;
           if (fs->fs_flags & ~(FS_KNOWN_FLAGS | FS_INTERNAL)) {
                   uprintf("%s: unknown ufs flags: 0x%08"PRIx32"%s\n",
                       mp->mnt_stat.f_mntonname, fs->fs_flags,
                       (mp->mnt_flag & MNT_FORCE) ? "" : ", not mounting");
                   if ((mp->mnt_flag & MNT_FORCE) == 0) {
                           mutex_exit(&ump->um_lock);
                           return (EINVAL);
                   }
           }
         if (fs->fs_pendingblocks != 0 || fs->fs_pendinginodes != 0) {          if (fs->fs_pendingblocks != 0 || fs->fs_pendinginodes != 0) {
                 fs->fs_pendingblocks = 0;                  fs->fs_pendingblocks = 0;
                 fs->fs_pendinginodes = 0;                  fs->fs_pendinginodes = 0;
Line 640  ffs_reload(struct mount *mp, kauth_cred_
Line 726  ffs_reload(struct mount *mp, kauth_cred_
                 if (i + fs->fs_frag > blks)                  if (i + fs->fs_frag > blks)
                         size = (blks - i) * fs->fs_fsize;                          size = (blks - i) * fs->fs_fsize;
                 error = bread(devvp, fsbtodb(fs, fs->fs_csaddr + i), size,                  error = bread(devvp, fsbtodb(fs, fs->fs_csaddr + i), size,
                               NOCRED, &bp);                                NOCRED, 0, &bp);
                 if (error) {                  if (error) {
                         brelse(bp, 0);                          brelse(bp, 0);
                         return (error);                          return (error);
Line 655  ffs_reload(struct mount *mp, kauth_cred_
Line 741  ffs_reload(struct mount *mp, kauth_cred_
                 space = (char *)space + size;                  space = (char *)space + size;
                 brelse(bp, 0);                  brelse(bp, 0);
         }          }
         if ((fs->fs_flags & FS_DOSOFTDEP))  
                 softdep_mount(devvp, mp, fs, cred);  
         if (fs->fs_snapinum[0] != 0)          if (fs->fs_snapinum[0] != 0)
                 ffs_snapshot_mount(mp);                  ffs_snapshot_mount(mp);
         /*          /*
Line 705  ffs_reload(struct mount *mp, kauth_cred_
Line 789  ffs_reload(struct mount *mp, kauth_cred_
                  */                   */
                 ip = VTOI(vp);                  ip = VTOI(vp);
                 error = bread(devvp, fsbtodb(fs, ino_to_fsba(fs, ip->i_number)),                  error = bread(devvp, fsbtodb(fs, ino_to_fsba(fs, ip->i_number)),
                               (int)fs->fs_bsize, NOCRED, &bp);                                (int)fs->fs_bsize, NOCRED, 0, &bp);
                 if (error) {                  if (error) {
                         brelse(bp, 0);                          brelse(bp, 0);
                         vput(vp);                          vput(vp);
Line 713  ffs_reload(struct mount *mp, kauth_cred_
Line 797  ffs_reload(struct mount *mp, kauth_cred_
                         break;                          break;
                 }                  }
                 ffs_load_inode(bp, ip, fs, ip->i_number);                  ffs_load_inode(bp, ip, fs, ip->i_number);
                 ip->i_ffs_effnlink = ip->i_nlink;  
                 brelse(bp, 0);                  brelse(bp, 0);
                 vput(vp);                  vput(vp);
                 mutex_enter(&mntvnode_lock);                  mutex_enter(&mntvnode_lock);
Line 776  ffs_mountfs(struct vnode *devvp, struct 
Line 859  ffs_mountfs(struct vnode *devvp, struct 
         if (error)          if (error)
                 return error;                  return error;
   
           ump = malloc(sizeof *ump, M_UFSMNT, M_WAITOK);
           memset(ump, 0, sizeof *ump);
           mutex_init(&ump->um_lock, MUTEX_DEFAULT, IPL_NONE);
           error = ffs_snapshot_init(ump);
           if (error)
                   goto out;
           ump->um_ops = &ffs_ufsops;
   
   #ifdef WAPBL
    sbagain:
   #endif
         /*          /*
          * Try reading the superblock in each of its possible locations.           * Try reading the superblock in each of its possible locations.
          */           */
Line 790  ffs_mountfs(struct vnode *devvp, struct 
Line 884  ffs_mountfs(struct vnode *devvp, struct 
                         goto out;                          goto out;
                 }                  }
                 error = bread(devvp, sblock_try[i] / size, SBLOCKSIZE, cred,                  error = bread(devvp, sblock_try[i] / size, SBLOCKSIZE, cred,
                               &bp);                                0, &bp);
                 if (error) {                  if (error) {
                         fs = NULL;                          fs = NULL;
                         goto out;                          goto out;
Line 853  ffs_mountfs(struct vnode *devvp, struct 
Line 947  ffs_mountfs(struct vnode *devvp, struct 
   
         fs = malloc((u_long)sbsize, M_UFSMNT, M_WAITOK);          fs = malloc((u_long)sbsize, M_UFSMNT, M_WAITOK);
         memcpy(fs, bp->b_data, sbsize);          memcpy(fs, bp->b_data, sbsize);
   
         ump = malloc(sizeof *ump, M_UFSMNT, M_WAITOK);  
         memset(ump, 0, sizeof *ump);  
         mutex_init(&ump->um_lock, MUTEX_DEFAULT, IPL_NONE);  
         error = ffs_snapshot_init(ump);  
         if (error)  
                 goto out;  
         ump->um_fs = fs;          ump->um_fs = fs;
         ump->um_ops = &ffs_ufsops;  
   
 #ifdef FFS_EI  #ifdef FFS_EI
         if (needswap) {          if (needswap) {
Line 871  ffs_mountfs(struct vnode *devvp, struct 
Line 957  ffs_mountfs(struct vnode *devvp, struct 
 #endif  #endif
                 fs->fs_flags &= ~FS_SWAPPED;                  fs->fs_flags &= ~FS_SWAPPED;
   
   #ifdef WAPBL
           if ((mp->mnt_wapbl_replay == 0) && (fs->fs_flags & FS_DOWAPBL)) {
                   error = ffs_wapbl_replay_start(mp, fs, devvp);
                   if (error)
                           goto out;
   
                   if (!ronly) {
                           /* XXX fsmnt may be stale. */
                           printf("%s: replaying log to disk\n", fs->fs_fsmnt);
                           error = wapbl_replay_write(mp->mnt_wapbl_replay, devvp);
                           if (error)
                                   goto out;
                           wapbl_replay_stop(mp->mnt_wapbl_replay);
                           fs->fs_clean = FS_WASCLEAN;
                   } else {
                           /* XXX fsmnt may be stale */
                           printf("%s: replaying log to memory\n", fs->fs_fsmnt);
                   }
   
                   /* Force a re-read of the superblock */
                   brelse(bp, BC_INVAL);
                   bp = NULL;
                   free(fs, M_UFSMNT);
                   fs = NULL;
                   goto sbagain;
           }
   #else /* !WAPBL */
           if ((fs->fs_flags & FS_DOWAPBL) && (mp->mnt_flag & MNT_FORCE) == 0) {
                   error = EPERM;
                   goto out;
           }
   #endif /* !WAPBL */
   
         ffs_oldfscompat_read(fs, ump, sblockloc);          ffs_oldfscompat_read(fs, ump, sblockloc);
         ump->um_maxfilesize = fs->fs_maxfilesize;          ump->um_maxfilesize = fs->fs_maxfilesize;
   
           if (fs->fs_flags & ~(FS_KNOWN_FLAGS | FS_INTERNAL)) {
                   uprintf("%s: unknown ufs flags: 0x%08"PRIx32"%s\n",
                       mp->mnt_stat.f_mntonname, fs->fs_flags,
                       (mp->mnt_flag & MNT_FORCE) ? "" : ", not mounting");
                   if ((mp->mnt_flag & MNT_FORCE) == 0) {
                           error = EINVAL;
                           goto out;
                   }
           }
   
         if (fs->fs_pendingblocks != 0 || fs->fs_pendinginodes != 0) {          if (fs->fs_pendingblocks != 0 || fs->fs_pendinginodes != 0) {
                 fs->fs_pendingblocks = 0;                  fs->fs_pendingblocks = 0;
                 fs->fs_pendinginodes = 0;                  fs->fs_pendinginodes = 0;
Line 899  ffs_mountfs(struct vnode *devvp, struct 
Line 1028  ffs_mountfs(struct vnode *devvp, struct 
                  * is found, then treat it like an Apple UFS filesystem anyway                   * is found, then treat it like an Apple UFS filesystem anyway
                  */                   */
                 error = bread(devvp, (daddr_t)(APPLEUFS_LABEL_OFFSET / size),                  error = bread(devvp, (daddr_t)(APPLEUFS_LABEL_OFFSET / size),
                         APPLEUFS_LABEL_SIZE, cred, &bp);                          APPLEUFS_LABEL_SIZE, cred, 0, &bp);
                 if (error)                  if (error)
                         goto out;                          goto out;
                 error = ffs_appleufs_validate(fs->fs_fsmnt,                  error = ffs_appleufs_validate(fs->fs_fsmnt,
                         (struct appleufslabel *)bp->b_data,NULL);                          (struct appleufslabel *)bp->b_data, NULL);
                 if (error == 0) {                  if (error == 0) {
                         ump->um_flags |= UFS_ISAPPLEUFS;                          ump->um_flags |= UFS_ISAPPLEUFS;
                 }                  }
Line 917  ffs_mountfs(struct vnode *devvp, struct 
Line 1046  ffs_mountfs(struct vnode *devvp, struct 
         }          }
 #endif  #endif
   
   #if 0
   /*
    * XXX This code changes the behaviour of mounting dirty filesystems, to
    * XXX require "mount -f ..." to mount them.  This doesn't match what
    * XXX mount(8) describes and is disabled for now.
    */
           /*
            * If the file system is not clean, don't allow it to be mounted
            * unless MNT_FORCE is specified.  (Note: MNT_FORCE is always set
            * for the root file system.)
            */
           if (fs->fs_flags & FS_DOWAPBL) {
                   /*
                    * wapbl normally expects to be FS_WASCLEAN when the FS_DOWAPBL
                    * bit is set, although there's a window in unmount where it
                    * could be FS_ISCLEAN
                    */
                   if ((mp->mnt_flag & MNT_FORCE) == 0 &&
                       (fs->fs_clean & (FS_WASCLEAN | FS_ISCLEAN)) == 0) {
                           error = EPERM;
                           goto out;
                   }
           } else
                   if ((fs->fs_clean & FS_ISCLEAN) == 0 &&
                       (mp->mnt_flag & MNT_FORCE) == 0) {
                           error = EPERM;
                           goto out;
                   }
   #endif
   
         /*          /*
          * verify that we can access the last block in the fs           * verify that we can access the last block in the fs
          * if we're mounting read/write.           * if we're mounting read/write.
Line 924  ffs_mountfs(struct vnode *devvp, struct 
Line 1083  ffs_mountfs(struct vnode *devvp, struct 
   
         if (!ronly) {          if (!ronly) {
                 error = bread(devvp, fsbtodb(fs, fs->fs_size - 1), fs->fs_fsize,                  error = bread(devvp, fsbtodb(fs, fs->fs_size - 1), fs->fs_fsize,
                     cred, &bp);                      cred, 0, &bp);
                 if (bp->b_bcount != fs->fs_fsize)                  if (bp->b_bcount != fs->fs_fsize)
                         error = EINVAL;                          error = EINVAL;
                 if (error) {                  if (error) {
Line 936  ffs_mountfs(struct vnode *devvp, struct 
Line 1095  ffs_mountfs(struct vnode *devvp, struct 
         }          }
   
         fs->fs_ronly = ronly;          fs->fs_ronly = ronly;
         if (ronly == 0) {          /* Don't bump fs_clean if we're replaying journal */
                 fs->fs_clean <<= 1;          if (!((fs->fs_flags & FS_DOWAPBL) && (fs->fs_clean & FS_WASCLEAN)))
                 fs->fs_fmod = 1;                  if (ronly == 0) {
         }                          fs->fs_clean <<= 1;
                           fs->fs_fmod = 1;
                   }
         size = fs->fs_cssize;          size = fs->fs_cssize;
         blks = howmany(size, fs->fs_fsize);          blks = howmany(size, fs->fs_fsize);
         if (fs->fs_contigsumsize > 0)          if (fs->fs_contigsumsize > 0)
Line 952  ffs_mountfs(struct vnode *devvp, struct 
Line 1113  ffs_mountfs(struct vnode *devvp, struct 
                 if (i + fs->fs_frag > blks)                  if (i + fs->fs_frag > blks)
                         size = (blks - i) * fs->fs_fsize;                          size = (blks - i) * fs->fs_fsize;
                 error = bread(devvp, fsbtodb(fs, fs->fs_csaddr + i), size,                  error = bread(devvp, fsbtodb(fs, fs->fs_csaddr + i), size,
                               cred, &bp);                                cred, 0, &bp);
                 if (error) {                  if (error) {
                         free(fs->fs_csp, M_UFSMNT);                          free(fs->fs_csp, M_UFSMNT);
                         goto out;                          goto out;
Line 1025  ffs_mountfs(struct vnode *devvp, struct 
Line 1186  ffs_mountfs(struct vnode *devvp, struct 
         for (i = 0; i < MAXQUOTAS; i++)          for (i = 0; i < MAXQUOTAS; i++)
                 ump->um_quotas[i] = NULLVP;                  ump->um_quotas[i] = NULLVP;
         devvp->v_specmountpoint = mp;          devvp->v_specmountpoint = mp;
         if (ronly == 0 && (fs->fs_flags & FS_DOSOFTDEP)) {          if (ronly == 0 && fs->fs_snapinum[0] != 0)
                 error = softdep_mount(devvp, mp, fs, cred);                  ffs_snapshot_mount(mp);
   
   #ifdef WAPBL
           if (!ronly) {
                   KDASSERT(fs->fs_ronly == 0);
                   /*
                    * ffs_wapbl_start() needs mp->mnt_stat initialised if it
                    * needs to create a new log file in-filesystem.
                    */
                   ffs_statvfs(mp, &mp->mnt_stat);
   
                   error = ffs_wapbl_start(mp);
                 if (error) {                  if (error) {
                         free(fs->fs_csp, M_UFSMNT);                          free(fs->fs_csp, M_UFSMNT);
                         goto out;                          goto out;
                 }                  }
         }          }
         if (ronly == 0 && fs->fs_snapinum[0] != 0)  #endif /* WAPBL */
                 ffs_snapshot_mount(mp);  
 #ifdef UFS_EXTATTR  #ifdef UFS_EXTATTR
         /*          /*
          * Initialize file-backed extended attributes on UFS1 file           * Initialize file-backed extended attributes on UFS1 file
Line 1052  ffs_mountfs(struct vnode *devvp, struct 
Line 1223  ffs_mountfs(struct vnode *devvp, struct 
 #endif /* UFS_EXTATTR */  #endif /* UFS_EXTATTR */
         return (0);          return (0);
 out:  out:
   #ifdef WAPBL
           if (mp->mnt_wapbl_replay) {
                   wapbl_replay_stop(mp->mnt_wapbl_replay);
                   wapbl_replay_free(mp->mnt_wapbl_replay);
                   mp->mnt_wapbl_replay = 0;
           }
   #endif
   
         fstrans_unmount(mp);          fstrans_unmount(mp);
         if (fs)          if (fs)
                 free(fs, M_UFSMNT);                  free(fs, M_UFSMNT);
Line 1112  ffs_oldfscompat_read(struct fs *fs, stru
Line 1291  ffs_oldfscompat_read(struct fs *fs, stru
         fs->fs_csaddr = fs->fs_old_csaddr;          fs->fs_csaddr = fs->fs_old_csaddr;
         fs->fs_sblockloc = sblockloc;          fs->fs_sblockloc = sblockloc;
   
         fs->fs_flags = fs->fs_old_flags | (fs->fs_flags & FS_INTERNAL);          fs->fs_flags = fs->fs_old_flags | (fs->fs_flags & FS_INTERNAL);
   
         if (fs->fs_old_postblformat == FS_42POSTBLFMT) {          if (fs->fs_old_postblformat == FS_42POSTBLFMT) {
                 fs->fs_old_nrpos = 8;                  fs->fs_old_nrpos = 8;
Line 1192  ffs_unmount(struct mount *mp, int mntfla
Line 1371  ffs_unmount(struct mount *mp, int mntfla
         struct lwp *l = curlwp;          struct lwp *l = curlwp;
         struct ufsmount *ump = VFSTOUFS(mp);          struct ufsmount *ump = VFSTOUFS(mp);
         struct fs *fs = ump->um_fs;          struct fs *fs = ump->um_fs;
         int error, flags, penderr;          int error, flags;
   #ifdef WAPBL
           extern int doforce;
   #endif
   
         penderr = 0;  
         flags = 0;          flags = 0;
         if (mntflags & MNT_FORCE)          if (mntflags & MNT_FORCE)
                 flags |= FORCECLOSE;                  flags |= FORCECLOSE;
Line 1204  ffs_unmount(struct mount *mp, int mntfla
Line 1385  ffs_unmount(struct mount *mp, int mntfla
                 ufs_extattr_uepm_destroy(&ump->um_extattr);                  ufs_extattr_uepm_destroy(&ump->um_extattr);
         }          }
 #endif /* UFS_EXTATTR */  #endif /* UFS_EXTATTR */
         if (mp->mnt_flag & MNT_SOFTDEP) {          if ((error = ffs_flushfiles(mp, flags, l)) != 0)
                 if ((error = softdep_flushfiles(mp, flags, l)) != 0)                  return (error);
                         return (error);          error = UFS_WAPBL_BEGIN(mp);
         } else {          if (error == 0)
                 if ((error = ffs_flushfiles(mp, flags, l)) != 0)                  if (fs->fs_ronly == 0 &&
                         return (error);                      ffs_cgupdate(ump, MNT_WAIT) == 0 &&
         }                      fs->fs_clean & FS_WASCLEAN) {
         mutex_enter(&ump->um_lock);  
         if (fs->fs_pendingblocks != 0 || fs->fs_pendinginodes != 0) {  
                 printf("%s: unmount pending error: blocks %" PRId64  
                        " files %d\n",  
                     fs->fs_fsmnt, fs->fs_pendingblocks, fs->fs_pendinginodes);  
                 fs->fs_pendingblocks = 0;  
                 fs->fs_pendinginodes = 0;  
                 penderr = 1;  
         }  
         mutex_exit(&ump->um_lock);  
         if (fs->fs_ronly == 0 &&  
             ffs_cgupdate(ump, MNT_WAIT) == 0 &&  
             fs->fs_clean & FS_WASCLEAN) {  
                 /*  
                  * XXXX don't mark fs clean in the case of softdep  
                  * pending block errors, until they are fixed.  
                  */  
                 if (penderr == 0) {  
                         if (mp->mnt_flag & MNT_SOFTDEP)  
                                 fs->fs_flags &= ~FS_DOSOFTDEP;  
                         fs->fs_clean = FS_ISCLEAN;                          fs->fs_clean = FS_ISCLEAN;
                           fs->fs_fmod = 0;
                           (void) ffs_sbupdate(ump, MNT_WAIT);
                 }                  }
                 fs->fs_fmod = 0;          if (error == 0)
                 (void) ffs_sbupdate(ump, MNT_WAIT);                  UFS_WAPBL_END(mp);
   #ifdef WAPBL
           KASSERT(!(mp->mnt_wapbl_replay && mp->mnt_wapbl));
           if (mp->mnt_wapbl_replay) {
                   KDASSERT(fs->fs_ronly);
                   wapbl_replay_stop(mp->mnt_wapbl_replay);
                   wapbl_replay_free(mp->mnt_wapbl_replay);
                   mp->mnt_wapbl_replay = 0;
         }          }
           error = ffs_wapbl_stop(mp, doforce && (mntflags & MNT_FORCE));
           if (error) {
                   return error;
           }
   #endif /* WAPBL */
         if (ump->um_devvp->v_type != VBAD)          if (ump->um_devvp->v_type != VBAD)
                 ump->um_devvp->v_specmountpoint = NULL;                  ump->um_devvp->v_specmountpoint = NULL;
         vn_lock(ump->um_devvp, LK_EXCLUSIVE | LK_RETRY);          vn_lock(ump->um_devvp, LK_EXCLUSIVE | LK_RETRY);
         (void)VOP_CLOSE(ump->um_devvp, fs->fs_ronly ? FREAD : FREAD|FWRITE,          (void)VOP_CLOSE(ump->um_devvp, fs->fs_ronly ? FREAD : FREAD | FWRITE,
                 NOCRED);                  NOCRED);
         vput(ump->um_devvp);          vput(ump->um_devvp);
         free(fs->fs_csp, M_UFSMNT);          free(fs->fs_csp, M_UFSMNT);
         free(fs, M_UFSMNT);          free(fs, M_UFSMNT);
         if (ump->um_oldfscompat != NULL)          if (ump->um_oldfscompat != NULL)
                 free(ump->um_oldfscompat, M_UFSMNT);                  free(ump->um_oldfscompat, M_UFSMNT);
         softdep_unmount(mp);  
         mutex_destroy(&ump->um_lock);          mutex_destroy(&ump->um_lock);
         ffs_snapshot_fini(ump);          ffs_snapshot_fini(ump);
         free(ump, M_UFSMNT);          free(ump, M_UFSMNT);
Line 1272  ffs_flushfiles(struct mount *mp, int fla
Line 1446  ffs_flushfiles(struct mount *mp, int fla
 #ifdef QUOTA  #ifdef QUOTA
         if (mp->mnt_flag & MNT_QUOTA) {          if (mp->mnt_flag & MNT_QUOTA) {
                 int i;                  int i;
                 if ((error = vflush(mp, NULLVP, SKIPSYSTEM|flags)) != 0)                  if ((error = vflush(mp, NULLVP, SKIPSYSTEM | flags)) != 0)
                         return (error);                          return (error);
                 for (i = 0; i < MAXQUOTAS; i++) {                  for (i = 0; i < MAXQUOTAS; i++) {
                         if (ump->um_quotas[i] == NULLVP)                          if (ump->um_quotas[i] == NULLVP)
Line 1300  ffs_flushfiles(struct mount *mp, int fla
Line 1474  ffs_flushfiles(struct mount *mp, int fla
         vn_lock(ump->um_devvp, LK_EXCLUSIVE | LK_RETRY);          vn_lock(ump->um_devvp, LK_EXCLUSIVE | LK_RETRY);
         error = VOP_FSYNC(ump->um_devvp, l->l_cred, FSYNC_WAIT, 0, 0);          error = VOP_FSYNC(ump->um_devvp, l->l_cred, FSYNC_WAIT, 0, 0);
         VOP_UNLOCK(ump->um_devvp, 0);          VOP_UNLOCK(ump->um_devvp, 0);
           if (flags & FORCECLOSE) /* XXXDBJ */
                   error = 0;
   
   #ifdef WAPBL
           if (error)
                   return error;
           if (mp->mnt_wapbl) {
                   error = wapbl_flush(mp->mnt_wapbl, 1);
                   if (flags & FORCECLOSE)
                           error = 0;
           }
   #endif
   
         return (error);          return (error);
 }  }
   
Line 1320  ffs_statvfs(struct mount *mp, struct sta
Line 1507  ffs_statvfs(struct mount *mp, struct sta
         sbp->f_iosize = fs->fs_bsize;          sbp->f_iosize = fs->fs_bsize;
         sbp->f_blocks = fs->fs_dsize;          sbp->f_blocks = fs->fs_dsize;
         sbp->f_bfree = blkstofrags(fs, fs->fs_cstotal.cs_nbfree) +          sbp->f_bfree = blkstofrags(fs, fs->fs_cstotal.cs_nbfree) +
                 fs->fs_cstotal.cs_nffree + dbtofsb(fs, fs->fs_pendingblocks);              fs->fs_cstotal.cs_nffree + dbtofsb(fs, fs->fs_pendingblocks);
         sbp->f_bresvd = ((u_int64_t) fs->fs_dsize * (u_int64_t)          sbp->f_bresvd = ((u_int64_t) fs->fs_dsize * (u_int64_t)
             fs->fs_minfree) / (u_int64_t) 100;              fs->fs_minfree) / (u_int64_t) 100;
         if (sbp->f_bfree > sbp->f_bresvd)          if (sbp->f_bfree > sbp->f_bresvd)
Line 1347  ffs_statvfs(struct mount *mp, struct sta
Line 1534  ffs_statvfs(struct mount *mp, struct sta
 int  int
 ffs_sync(struct mount *mp, int waitfor, kauth_cred_t cred)  ffs_sync(struct mount *mp, int waitfor, kauth_cred_t cred)
 {  {
         struct lwp *l = curlwp;          struct vnode *vp, *mvp, *nvp;
         struct vnode *vp, *mvp;  
         struct inode *ip;          struct inode *ip;
         struct ufsmount *ump = VFSTOUFS(mp);          struct ufsmount *ump = VFSTOUFS(mp);
         struct fs *fs;          struct fs *fs;
         int error, count, allerror = 0;          int error, allerror = 0;
   
         fs = ump->um_fs;          fs = ump->um_fs;
         if (fs->fs_fmod != 0 && fs->fs_ronly != 0) {            /* XXX */          if (fs->fs_fmod != 0 && fs->fs_ronly != 0) {            /* XXX */
Line 1374  loop:
Line 1560  loop:
          * NOTE: not using the TAILQ_FOREACH here since in this loop vgone()           * NOTE: not using the TAILQ_FOREACH here since in this loop vgone()
          * and vclean() can be called indirectly           * and vclean() can be called indirectly
          */           */
         for (vp = TAILQ_FIRST(&mp->mnt_vnodelist); vp; vp = vunmark(mvp)) {          for (vp = TAILQ_FIRST(&mp->mnt_vnodelist); vp; vp = nvp) {
                 vmark(mvp, vp);                  nvp = TAILQ_NEXT(vp, v_mntvnodes);
                 /*                  /*
                  * If the vnode that we are about to sync is no longer                   * If the vnode that we are about to sync is no longer
                  * associated with this mount point, start over.                   * associated with this mount point, start over.
                  */                   */
                 if (vp->v_mount != mp || vismarker(vp))                  if (vp->v_mount != mp)
                           goto loop;
                   /*
                    * Don't interfere with concurrent scans of this FS.
                    */
                   if (vismarker(vp))
                         continue;                          continue;
                 mutex_enter(&vp->v_interlock);                  mutex_enter(&vp->v_interlock);
                 ip = VTOI(vp);                  ip = VTOI(vp);
                 if (ip == NULL || (vp->v_iflag & (VI_XLOCK|VI_CLEAN)) != 0 ||  
                     vp->v_type == VNON || ((ip->i_flag &                  /*
                     (IN_CHANGE | IN_UPDATE | IN_MODIFIED)) == 0 &&                   * Skip the vnode/inode if inaccessible.
                     LIST_EMPTY(&vp->v_dirtyblkhd) &&                   */
                     UVM_OBJ_IS_CLEAN(&vp->v_uobj)))                  if (ip == NULL || (vp->v_iflag & (VI_XLOCK | VI_CLEAN)) != 0 ||
                 {                      vp->v_type == VNON) {
                           mutex_exit(&vp->v_interlock);
                           continue;
                   }
   
                   /*
                    * We deliberately update inode times here.  This will
                    * prevent a massive queue of updates accumulating, only
                    * to be handled by a call to unmount.
                    *
                    * XXX It would be better to have the syncer trickle these
                    * out.  Adjustment needed to allow registering vnodes for
                    * sync when the vnode is clean, but the inode dirty.  Or
                    * have ufs itself trickle out inode updates.
                    *
                    * If doing a lazy sync, we don't care about metadata or
                    * data updates, because they are handled by each vnode's
                    * synclist entry.  In this case we are only interested in
                    * writing back modified inodes.
                    */
                   if ((ip->i_flag & (IN_ACCESS | IN_CHANGE | IN_UPDATE |
                       IN_MODIFY | IN_MODIFIED | IN_ACCESSED)) == 0 &&
                       (waitfor == MNT_LAZY || (LIST_EMPTY(&vp->v_dirtyblkhd) &&
                       UVM_OBJ_IS_CLEAN(&vp->v_uobj)))) {
                         mutex_exit(&vp->v_interlock);                          mutex_exit(&vp->v_interlock);
                         continue;                          continue;
                 }                  }
Line 1398  loop:
Line 1612  loop:
                         mutex_exit(&vp->v_interlock);                          mutex_exit(&vp->v_interlock);
                         continue;                          continue;
                 }                  }
                   vmark(mvp, vp);
                 mutex_exit(&mntvnode_lock);                  mutex_exit(&mntvnode_lock);
                 error = vget(vp, LK_EXCLUSIVE | LK_NOWAIT | LK_INTERLOCK);                  error = vget(vp, LK_EXCLUSIVE | LK_NOWAIT | LK_INTERLOCK);
                 if (error) {                  if (error) {
                         mutex_enter(&mntvnode_lock);                          mutex_enter(&mntvnode_lock);
                           nvp = vunmark(mvp);
                         if (error == ENOENT) {                          if (error == ENOENT) {
                                 (void)vunmark(mvp);  
                                 goto loop;                                  goto loop;
                         }                          }
                         continue;                          continue;
                 }                  }
                 if (vp->v_type == VREG && waitfor == MNT_LAZY)                  if (waitfor == MNT_LAZY) {
                         error = ffs_update(vp, NULL, NULL, 0);                          error = UFS_WAPBL_BEGIN(vp->v_mount);
                 else                          if (!error) {
                         error = VOP_FSYNC(vp, cred,                                  error = ffs_update(vp, NULL, NULL,
                             waitfor == MNT_WAIT ? FSYNC_WAIT : 0, 0, 0);                                      UPDATE_CLOSE);
                                   UFS_WAPBL_END(vp->v_mount);
                           }
                   } else {
                           error = VOP_FSYNC(vp, cred, FSYNC_NOLOG |
                               (waitfor == MNT_WAIT ? FSYNC_WAIT : 0), 0, 0);
                   }
                 if (error)                  if (error)
                         allerror = error;                          allerror = error;
                 vput(vp);                  vput(vp);
                 mutex_enter(&mntvnode_lock);                  mutex_enter(&mntvnode_lock);
                   nvp = vunmark(mvp);
         }          }
         mutex_exit(&mntvnode_lock);          mutex_exit(&mntvnode_lock);
         /*          /*
          * Force stale file system control information to be flushed.           * Force stale file system control information to be flushed.
          */           */
         if (waitfor == MNT_WAIT && (ump->um_mountp->mnt_flag & MNT_SOFTDEP)) {  
                 if ((error = softdep_flushworklist(ump->um_mountp, &count, l)))  
                         allerror = error;  
                 /* Flushed work items may create new vnodes to clean */  
                 if (allerror == 0 && count) {  
                         mutex_enter(&mntvnode_lock);  
                         goto loop;  
                 }  
         }  
         if (waitfor != MNT_LAZY && (ump->um_devvp->v_numoutput > 0 ||          if (waitfor != MNT_LAZY && (ump->um_devvp->v_numoutput > 0 ||
             !LIST_EMPTY(&ump->um_devvp->v_dirtyblkhd))) {              !LIST_EMPTY(&ump->um_devvp->v_dirtyblkhd))) {
                 vn_lock(ump->um_devvp, LK_EXCLUSIVE | LK_RETRY);                  vn_lock(ump->um_devvp, LK_EXCLUSIVE | LK_RETRY);
                 if ((error = VOP_FSYNC(ump->um_devvp, cred,                  if ((error = VOP_FSYNC(ump->um_devvp, cred,
                     waitfor == MNT_WAIT ? FSYNC_WAIT : 0, 0, 0)) != 0)                      (waitfor == MNT_WAIT ? FSYNC_WAIT : 0) | FSYNC_NOLOG,
                       0, 0)) != 0)
                         allerror = error;                          allerror = error;
                 VOP_UNLOCK(ump->um_devvp, 0);                  VOP_UNLOCK(ump->um_devvp, 0);
                 if (allerror == 0 && waitfor == MNT_WAIT) {                  if (allerror == 0 && waitfor == MNT_WAIT && !mp->mnt_wapbl) {
                         mutex_enter(&mntvnode_lock);                          mutex_enter(&mntvnode_lock);
                         goto loop;                          goto loop;
                 }                  }
Line 1452  loop:
Line 1666  loop:
         if (fs->fs_fmod != 0) {          if (fs->fs_fmod != 0) {
                 fs->fs_fmod = 0;                  fs->fs_fmod = 0;
                 fs->fs_time = time_second;                  fs->fs_time = time_second;
                 if ((error = ffs_cgupdate(ump, waitfor)))                  error = UFS_WAPBL_BEGIN(mp);
                   if (error)
                           allerror = error;
                   else {
                           if ((error = ffs_cgupdate(ump, waitfor)))
                                   allerror = error;
                           UFS_WAPBL_END(mp);
                   }
           }
   
   #ifdef WAPBL
           if (mp->mnt_wapbl) {
                   error = wapbl_flush(mp->mnt_wapbl, 0);
                   if (error)
                         allerror = error;                          allerror = error;
         }          }
   #endif
   
         fstrans_done(mp);          fstrans_done(mp);
         vnfree(mvp);          vnfree(mvp);
         return (allerror);          return (allerror);
Line 1504  ffs_vget(struct mount *mp, ino_t ino, st
Line 1733  ffs_vget(struct mount *mp, ino_t ino, st
         }          }
   
         vp->v_vflag |= VV_LOCKSWORK;          vp->v_vflag |= VV_LOCKSWORK;
         if ((mp->mnt_flag & MNT_SOFTDEP) != 0)  
                 vp->v_uflag |= VU_SOFTDEP;  
   
         /*          /*
          * XXX MFS ends up here, too, to allocate an inode.  Should we           * XXX MFS ends up here, too, to allocate an inode.  Should we
Line 1519  ffs_vget(struct mount *mp, ino_t ino, st
Line 1746  ffs_vget(struct mount *mp, ino_t ino, st
         ip->i_fs = fs = ump->um_fs;          ip->i_fs = fs = ump->um_fs;
         ip->i_dev = dev;          ip->i_dev = dev;
         ip->i_number = ino;          ip->i_number = ino;
         LIST_INIT(&ip->i_pcbufhd);  
 #ifdef QUOTA  #ifdef QUOTA
         ufsquota_init(ip);          ufsquota_init(ip);
 #endif  #endif
Line 1542  ffs_vget(struct mount *mp, ino_t ino, st
Line 1768  ffs_vget(struct mount *mp, ino_t ino, st
   
         /* Read in the disk contents for the inode, copy into the inode. */          /* Read in the disk contents for the inode, copy into the inode. */
         error = bread(ump->um_devvp, fsbtodb(fs, ino_to_fsba(fs, ino)),          error = bread(ump->um_devvp, fsbtodb(fs, ino_to_fsba(fs, ino)),
                       (int)fs->fs_bsize, NOCRED, &bp);                        (int)fs->fs_bsize, NOCRED, 0, &bp);
         if (error) {          if (error) {
   
                 /*                  /*
Line 1564  ffs_vget(struct mount *mp, ino_t ino, st
Line 1790  ffs_vget(struct mount *mp, ino_t ino, st
                 ip->i_din.ffs2_din = pool_cache_get(ffs_dinode2_cache,                  ip->i_din.ffs2_din = pool_cache_get(ffs_dinode2_cache,
                     PR_WAITOK);                      PR_WAITOK);
         ffs_load_inode(bp, ip, fs, ino);          ffs_load_inode(bp, ip, fs, ino);
         if (DOINGSOFTDEP(vp))  
                 softdep_load_inodeblock(ip);  
         else  
                 ip->i_ffs_effnlink = ip->i_nlink;  
         brelse(bp, 0);          brelse(bp, 0);
   
         /*          /*
Line 1661  ffs_init(void)
Line 1883  ffs_init(void)
             "ffsdino1", NULL, IPL_NONE, NULL, NULL, NULL);              "ffsdino1", NULL, IPL_NONE, NULL, NULL, NULL);
         ffs_dinode2_cache = pool_cache_init(sizeof(struct ufs2_dinode), 0, 0, 0,          ffs_dinode2_cache = pool_cache_init(sizeof(struct ufs2_dinode), 0, 0, 0,
             "ffsdino2", NULL, IPL_NONE, NULL, NULL, NULL);              "ffsdino2", NULL, IPL_NONE, NULL, NULL, NULL);
         softdep_initialize();  
         ufs_init();          ufs_init();
 }  }
   
 void  void
 ffs_reinit(void)  ffs_reinit(void)
 {  {
         softdep_reinitialize();  
         ufs_reinit();          ufs_reinit();
 }  }
   
Line 1678  ffs_done(void)
Line 1899  ffs_done(void)
         if (--ffs_initcount > 0)          if (--ffs_initcount > 0)
                 return;                  return;
   
         /* XXX softdep cleanup ? */  
         ufs_done();          ufs_done();
         pool_cache_destroy(ffs_dinode2_cache);          pool_cache_destroy(ffs_dinode2_cache);
         pool_cache_destroy(ffs_dinode1_cache);          pool_cache_destroy(ffs_dinode1_cache);
         pool_cache_destroy(ffs_inode_cache);          pool_cache_destroy(ffs_inode_cache);
 }  }
   
 SYSCTL_SETUP(sysctl_vfs_ffs_setup, "sysctl vfs.ffs subtree setup")  
 {  
 #if 0  
         extern int doasyncfree;  
 #endif  
         extern int ffs_log_changeopt;  
   
         sysctl_createv(clog, 0, NULL, NULL,  
                        CTLFLAG_PERMANENT,  
                        CTLTYPE_NODE, "vfs", NULL,  
                        NULL, 0, NULL, 0,  
                        CTL_VFS, CTL_EOL);  
         sysctl_createv(clog, 0, NULL, NULL,  
                        CTLFLAG_PERMANENT,  
                        CTLTYPE_NODE, "ffs",  
                        SYSCTL_DESCR("Berkeley Fast File System"),  
                        NULL, 0, NULL, 0,  
                        CTL_VFS, 1, CTL_EOL);  
   
         /*  
          * @@@ should we even bother with these first three?  
          */  
         sysctl_createv(clog, 0, NULL, NULL,  
                        CTLFLAG_PERMANENT|CTLFLAG_READWRITE,  
                        CTLTYPE_INT, "doclusterread", NULL,  
                        sysctl_notavail, 0, NULL, 0,  
                        CTL_VFS, 1, FFS_CLUSTERREAD, CTL_EOL);  
         sysctl_createv(clog, 0, NULL, NULL,  
                        CTLFLAG_PERMANENT|CTLFLAG_READWRITE,  
                        CTLTYPE_INT, "doclusterwrite", NULL,  
                        sysctl_notavail, 0, NULL, 0,  
                        CTL_VFS, 1, FFS_CLUSTERWRITE, CTL_EOL);  
         sysctl_createv(clog, 0, NULL, NULL,  
                        CTLFLAG_PERMANENT|CTLFLAG_READWRITE,  
                        CTLTYPE_INT, "doreallocblks", NULL,  
                        sysctl_notavail, 0, NULL, 0,  
                        CTL_VFS, 1, FFS_REALLOCBLKS, CTL_EOL);  
 #if 0  
         sysctl_createv(clog, 0, NULL, NULL,  
                        CTLFLAG_PERMANENT|CTLFLAG_READWRITE,  
                        CTLTYPE_INT, "doasyncfree",  
                        SYSCTL_DESCR("Release dirty blocks asynchronously"),  
                        NULL, 0, &doasyncfree, 0,  
                        CTL_VFS, 1, FFS_ASYNCFREE, CTL_EOL);  
 #endif  
         sysctl_createv(clog, 0, NULL, NULL,  
                        CTLFLAG_PERMANENT|CTLFLAG_READWRITE,  
                        CTLTYPE_INT, "log_changeopt",  
                        SYSCTL_DESCR("Log changes in optimization strategy"),  
                        NULL, 0, &ffs_log_changeopt, 0,  
                        CTL_VFS, 1, FFS_LOG_CHANGEOPT, CTL_EOL);  
 }  
   
 /*  /*
  * Write a superblock and associated information back to disk.   * Write a superblock and associated information back to disk.
  */   */
Line 1749  ffs_sbupdate(struct ufsmount *mp, int wa
Line 1916  ffs_sbupdate(struct ufsmount *mp, int wa
         int error = 0;          int error = 0;
         u_int32_t saveflag;          u_int32_t saveflag;
   
         bp = getblk(mp->um_devvp,          error = ffs_getblk(mp->um_devvp,
             fs->fs_sblockloc >> (fs->fs_fshift - fs->fs_fsbtodb),              fs->fs_sblockloc >> (fs->fs_fshift - fs->fs_fsbtodb), FFS_NOBLK,
             (int)fs->fs_sbsize, 0, 0);              fs->fs_sbsize, false, &bp);
           if (error)
                   return error;
         saveflag = fs->fs_flags & FS_INTERNAL;          saveflag = fs->fs_flags & FS_INTERNAL;
         fs->fs_flags &= ~FS_INTERNAL;          fs->fs_flags &= ~FS_INTERNAL;
   
Line 1787  ffs_cgupdate(struct ufsmount *mp, int wa
Line 1956  ffs_cgupdate(struct ufsmount *mp, int wa
                 size = fs->fs_bsize;                  size = fs->fs_bsize;
                 if (i + fs->fs_frag > blks)                  if (i + fs->fs_frag > blks)
                         size = (blks - i) * fs->fs_fsize;                          size = (blks - i) * fs->fs_fsize;
                 bp = getblk(mp->um_devvp, fsbtodb(fs, fs->fs_csaddr + i),                  error = ffs_getblk(mp->um_devvp, fsbtodb(fs, fs->fs_csaddr + i),
                     size, 0, 0);                      FFS_NOBLK, size, false, &bp);
                   if (error)
                           break;
 #ifdef FFS_EI  #ifdef FFS_EI
                 if (mp->um_flags & UFS_NEEDSWAP)                  if (mp->um_flags & UFS_NEEDSWAP)
                         ffs_csum_swap((struct csum*)space,                          ffs_csum_swap((struct csum*)space,
Line 1835  ffs_suspendctl(struct mount *mp, int cmd
Line 2006  ffs_suspendctl(struct mount *mp, int cmd
                 error = ffs_sync(mp, MNT_WAIT, l->l_proc->p_cred);                  error = ffs_sync(mp, MNT_WAIT, l->l_proc->p_cred);
                 if (error == 0)                  if (error == 0)
                         error = fstrans_setstate(mp, FSTRANS_SUSPENDED);                          error = fstrans_setstate(mp, FSTRANS_SUSPENDED);
   #ifdef WAPBL
                   if (error == 0 && mp->mnt_wapbl)
                           error = wapbl_flush(mp->mnt_wapbl, 1);
   #endif
                 if (error != 0) {                  if (error != 0) {
                         (void) fstrans_setstate(mp, FSTRANS_NORMAL);                          (void) fstrans_setstate(mp, FSTRANS_NORMAL);
                         return error;                          return error;
Line 1848  ffs_suspendctl(struct mount *mp, int cmd
Line 2023  ffs_suspendctl(struct mount *mp, int cmd
                 return EINVAL;                  return EINVAL;
         }          }
 }  }
   
   /*
    * Synch vnode for a mounted file system.  This is called for foreign
    * vnodes, i.e. non-ffs.
    */
   static int
   ffs_vfs_fsync(vnode_t *vp, int flags)
   {
           int error, passes, skipmeta, i, pflags;
           buf_t *bp, *nbp;
   #ifdef WAPBL
           struct mount *mp;
   #endif
   
           KASSERT(vp->v_type == VBLK);
           KASSERT(vp->v_specmountpoint != NULL);
   
           /*
            * Flush all dirty data associated with the vnode.
            */
           pflags = PGO_ALLPAGES | PGO_CLEANIT;
           if ((flags & FSYNC_WAIT) != 0)
                   pflags |= PGO_SYNCIO;
           mutex_enter(&vp->v_interlock);
           error = VOP_PUTPAGES(vp, 0, 0, pflags);
           if (error)
                   return error;
   
   #ifdef WAPBL
           mp = vp->v_specmountpoint;
           if (mp && mp->mnt_wapbl) {
                   /*
                    * Don't bother writing out metadata if the syncer is
                    * making the request.  We will let the sync vnode
                    * write it out in a single burst through a call to
                    * VFS_SYNC().
                    */
                   if ((flags & (FSYNC_DATAONLY | FSYNC_LAZY | FSYNC_NOLOG)) != 0)
                           return 0;
   
                   /*
                    * Don't flush the log if the vnode being flushed
                    * contains no dirty buffers that could be in the log.
                    */
                   if (!LIST_EMPTY(&vp->v_dirtyblkhd)) {
                           error = wapbl_flush(mp->mnt_wapbl, 0);
                           if (error)
                                   return error;
                   }
   
                   if ((flags & FSYNC_WAIT) != 0) {
                           mutex_enter(&vp->v_interlock);
                           while (vp->v_numoutput)
                                   cv_wait(&vp->v_cv, &vp->v_interlock);
                           mutex_exit(&vp->v_interlock);
                   }
   
                   return 0;
           }
   #endif /* WAPBL */
   
           /*
            * Write out metadata for non-logging file systems. XXX This block
            * should be simplified now that softdep is gone.
            */
           passes = NIADDR + 1;
           skipmeta = 0;
           if (flags & FSYNC_WAIT)
                   skipmeta = 1;
   
   loop:
           mutex_enter(&bufcache_lock);
           LIST_FOREACH(bp, &vp->v_dirtyblkhd, b_vnbufs) {
                   bp->b_cflags &= ~BC_SCANNED;
           }
           for (bp = LIST_FIRST(&vp->v_dirtyblkhd); bp; bp = nbp) {
                   nbp = LIST_NEXT(bp, b_vnbufs);
                   if (bp->b_cflags & (BC_BUSY | BC_SCANNED))
                           continue;
                   if ((bp->b_oflags & BO_DELWRI) == 0)
                           panic("ffs_fsync: not dirty");
                   if (skipmeta && bp->b_lblkno < 0)
                           continue;
                   bp->b_cflags |= BC_BUSY | BC_VFLUSH | BC_SCANNED;
                   mutex_exit(&bufcache_lock);
                   /*
                    * On our final pass through, do all I/O synchronously
                    * so that we can find out if our flush is failing
                    * because of write errors.
                    */
                   if (passes > 0 || !(flags & FSYNC_WAIT))
                           (void) bawrite(bp);
                   else if ((error = bwrite(bp)) != 0)
                           return (error);
                   /*
                    * Since we unlocked during the I/O, we need
                    * to start from a known point.
                    */
                   mutex_enter(&bufcache_lock);
                   nbp = LIST_FIRST(&vp->v_dirtyblkhd);
           }
           mutex_exit(&bufcache_lock);
           if (skipmeta) {
                   skipmeta = 0;
                   goto loop;
           }
   
           if ((flags & FSYNC_WAIT) != 0) {
                   mutex_enter(&vp->v_interlock);
                   while (vp->v_numoutput) {
                           cv_wait(&vp->v_cv, &vp->v_interlock);
                   }
                   mutex_exit(&vp->v_interlock);
   
                   if (!LIST_EMPTY(&vp->v_dirtyblkhd)) {
                           /*
                           * Block devices associated with filesystems may
                           * have new I/O requests posted for them even if
                           * the vnode is locked, so no amount of trying will
                           * get them clean. Thus we give block devices a
                           * good effort, then just give up. For all other file
                           * types, go around and try again until it is clean.
                           */
                           if (passes > 0) {
                                   passes--;
                                   goto loop;
                           }
   #ifdef DIAGNOSTIC
                           if (vp->v_type != VBLK)
                                   vprint("ffs_fsync: dirty", vp);
   #endif
                   }
           }
   
           if (error == 0 && (flags & FSYNC_CACHE) != 0) {
                   (void)VOP_IOCTL(vp, DIOCCACHESYNC, &i, FWRITE,
                       kauth_cred_get());
           }
   
           return error;
   }

Legend:
Removed from v.1.223.4.1  
changed lines
  Added in v.1.223.4.2

CVSweb <webmaster@jp.NetBSD.org>