Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/ufs/ffs Cleanup ffs fsync and make devices on wapbl enab...



details:   https://anonhg.NetBSD.org/src/rev/be2202b6ee36
branches:  trunk
changeset: 764553:be2202b6ee36
user:      hannken <hannken%NetBSD.org@localhost>
date:      Wed Apr 27 07:24:52 2011 +0000

description:
Cleanup ffs fsync and make devices on wapbl enabled file systems work here:

- Replace the ugly sync loop in ffs_full_fsync() and ffs_vfs_fsync() with
  vflushbuf().  This loop is a relic of softdeps and not needed anymore.

- Add ffs_spec_fsync() for device nodes on ffs file systems that calls
  spec_fsync() like all other file systems do and then updates the ctime.

Discussed on tech-kern.

Should fix PRs:
PR #41192 wapbl diagnostic panic during cgdconfig
PR #41977 kernel diagnostic assertion "rw_lock_held(&wl->wl_rwlock)" failed
PR #42149 wapbl locking panic if watching DVD
PR #42551 Lockdebug assert in wapbl when running zpool

diffstat:

 sys/ufs/ffs/ffs_extern.h |    3 +-
 sys/ufs/ffs/ffs_vfsops.c |   85 +----------------------
 sys/ufs/ffs/ffs_vnops.c  |  166 +++++++++++++++++++---------------------------
 3 files changed, 77 insertions(+), 177 deletions(-)

diffs (truncated from 373 to 300 lines):

diff -r 0b50cf82ce42 -r be2202b6ee36 sys/ufs/ffs/ffs_extern.h
--- a/sys/ufs/ffs/ffs_extern.h  Wed Apr 27 06:22:11 2011 +0000
+++ b/sys/ufs/ffs/ffs_extern.h  Wed Apr 27 07:24:52 2011 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: ffs_extern.h,v 1.76 2011/03/06 17:08:38 bouyer Exp $   */
+/*     $NetBSD: ffs_extern.h,v 1.77 2011/04/27 07:24:52 hannken Exp $  */
 
 /*-
  * Copyright (c) 1991, 1993, 1994
@@ -125,6 +125,7 @@
 int    ffs_read(void *);
 int    ffs_write(void *);
 int    ffs_fsync(void *);
+int    ffs_spec_fsync(void *);
 int    ffs_reclaim(void *);
 int    ffs_getpages(void *);
 void   ffs_gop_size(struct vnode *, off_t, off_t *, int);
diff -r 0b50cf82ce42 -r be2202b6ee36 sys/ufs/ffs/ffs_vfsops.c
--- a/sys/ufs/ffs/ffs_vfsops.c  Wed Apr 27 06:22:11 2011 +0000
+++ b/sys/ufs/ffs/ffs_vfsops.c  Wed Apr 27 07:24:52 2011 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: ffs_vfsops.c,v 1.265 2011/03/27 08:04:50 mlelstv Exp $ */
+/*     $NetBSD: ffs_vfsops.c,v 1.266 2011/04/27 07:24:53 hannken Exp $ */
 
 /*-
  * Copyright (c) 2008, 2009 The NetBSD Foundation, Inc.
@@ -61,7 +61,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ffs_vfsops.c,v 1.265 2011/03/27 08:04:50 mlelstv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ffs_vfsops.c,v 1.266 2011/04/27 07:24:53 hannken Exp $");
 
 #if defined(_KERNEL_OPT)
 #include "opt_ffs.h"
@@ -2071,14 +2071,12 @@
 }
 
 /*
- * Synch vnode for a mounted file system.  This is called for foreign
- * vnodes, i.e. non-ffs.
+ * Synch vnode for a mounted file system.
  */
 static int
 ffs_vfs_fsync(vnode_t *vp, int flags)
 {
-       int error, passes, skipmeta, i, pflags;
-       buf_t *bp, *nbp;
+       int error, i, pflags;
 #ifdef WAPBL
        struct mount *mp;
 #endif
@@ -2130,80 +2128,9 @@
        }
 #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
-               }
-       }
-
+       error = vflushbuf(vp, (flags & FSYNC_WAIT) != 0);
        if (error == 0 && (flags & FSYNC_CACHE) != 0) {
+               i = 1;
                (void)VOP_IOCTL(vp, DIOCCACHESYNC, &i, FWRITE,
                    kauth_cred_get());
        }
diff -r 0b50cf82ce42 -r be2202b6ee36 sys/ufs/ffs/ffs_vnops.c
--- a/sys/ufs/ffs/ffs_vnops.c   Wed Apr 27 06:22:11 2011 +0000
+++ b/sys/ufs/ffs/ffs_vnops.c   Wed Apr 27 07:24:52 2011 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: ffs_vnops.c,v 1.117 2011/04/15 15:54:11 hannken Exp $  */
+/*     $NetBSD: ffs_vnops.c,v 1.118 2011/04/27 07:24:53 hannken Exp $  */
 
 /*-
  * Copyright (c) 2008, 2009 The NetBSD Foundation, Inc.
@@ -61,7 +61,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ffs_vnops.c,v 1.117 2011/04/15 15:54:11 hannken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ffs_vnops.c,v 1.118 2011/04/27 07:24:53 hannken Exp $");
 
 #if defined(_KERNEL_OPT)
 #include "opt_ffs.h"
@@ -175,7 +175,7 @@
        { &vop_kqfilter_desc, spec_kqfilter },          /* kqfilter */
        { &vop_revoke_desc, spec_revoke },              /* revoke */
        { &vop_mmap_desc, spec_mmap },                  /* mmap */
-       { &vop_fsync_desc, ffs_fsync },                 /* fsync */
+       { &vop_fsync_desc, ffs_spec_fsync },            /* fsync */
        { &vop_seek_desc, spec_seek },                  /* seek */
        { &vop_remove_desc, spec_remove },              /* remove */
        { &vop_link_desc, spec_link },                  /* link */
@@ -266,6 +266,61 @@
 #include <ufs/ufs/ufs_readwrite.c>
 
 int
+ffs_spec_fsync(void *v)
+{
+       struct vop_fsync_args /* {
+               struct vnode *a_vp;
+               kauth_cred_t a_cred;
+               int a_flags;
+               off_t a_offlo;
+               off_t a_offhi;
+               struct lwp *a_l;
+       } */ *ap = v;
+       int error, flags, uflags;
+       struct vnode *vp;
+       struct mount *mp;
+
+       flags = ap->a_flags;
+       uflags = UPDATE_CLOSE | ((flags & FSYNC_WAIT) ? UPDATE_WAIT : 0);
+       vp = ap->a_vp;
+       mp = vp->v_mount;
+
+       fstrans_start(mp, FSTRANS_LAZY);
+
+       error = spec_fsync(v);
+       if (error)
+               goto out;
+
+#ifdef WAPBL
+       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)) != 0)
+                       goto out;
+               if ((VTOI(vp)->i_flag & (IN_ACCESS | IN_CHANGE | IN_UPDATE
+                   | IN_MODIFY | IN_MODIFIED | IN_ACCESSED)) != 0) {
+                       error = UFS_WAPBL_BEGIN(mp);
+                       if (error != 0)
+                               goto out;
+                       error = ffs_update(vp, NULL, NULL, uflags);
+                       UFS_WAPBL_END(mp);
+               }
+               goto out;
+       }
+#endif /* WAPBL */
+
+       error = ffs_update(vp, NULL, NULL, uflags);
+
+out:
+       fstrans_done(mp);
+       return error;
+}
+
+int
 ffs_fsync(void *v)
 {
        struct vop_fsync_args /* {
@@ -399,32 +454,27 @@
 int
 ffs_full_fsync(struct vnode *vp, int flags)
 {
-       struct buf *bp, *nbp;
-       int error, passes, skipmeta, waitfor, i;
+       int error, i, uflags;
        struct mount *mp;
 
+       KASSERT(vp->v_tag == VT_UFS);
        KASSERT(VTOI(vp) != NULL);
-       KASSERT(vp->v_tag == VT_UFS);
+       KASSERT(vp->v_type != VCHR && vp->v_type != VBLK);
 
        error = 0;
+       uflags = UPDATE_CLOSE | ((flags & FSYNC_WAIT) ? UPDATE_WAIT : 0);
 
        mp = vp->v_mount;
-       if (vp->v_type == VBLK && vp->v_specmountpoint != NULL) {
-               mp = vp->v_specmountpoint;
-       } else {
-               mp = vp->v_mount;
-       }
 
        /*
         * Flush all dirty data associated with the vnode.
         */
-       if (vp->v_type == VREG || vp->v_type == VBLK) {
+       if (vp->v_type == VREG) {
                int pflags = PGO_ALLPAGES | PGO_CLEANIT;
 
                if ((flags & FSYNC_WAIT))
                        pflags |= PGO_SYNCIO;
-               if (vp->v_type == VREG &&
-                   fstrans_getstate(mp) == FSTRANS_SUSPENDING)
+               if (fstrans_getstate(mp) == FSTRANS_SUSPENDING)
                        pflags |= PGO_FREE;
                mutex_enter(&vp->v_interlock);
                error = VOP_PUTPAGES(vp, 0, 0, pflags);
@@ -433,7 +483,6 @@
        }
 
 #ifdef WAPBL
-       mp = wapbl_vptomp(vp);
        if (mp && mp->mnt_wapbl) {
                /*
                 * Don't bother writing out metadata if the syncer is
@@ -449,8 +498,7 @@
                        error = UFS_WAPBL_BEGIN(mp);
                        if (error)
                                return error;
-                       error = ffs_update(vp, NULL, NULL, UPDATE_CLOSE |
-                           ((flags & FSYNC_WAIT) ? UPDATE_WAIT : 0));
+                       error = ffs_update(vp, NULL, NULL, uflags);
                        UFS_WAPBL_END(mp);
                }
                if (error || (flags & FSYNC_NOLOG) != 0)
@@ -477,87 +525,11 @@
        }
 #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) {



Home | Main Index | Thread Index | Old Index