Source-Changes-HG archive

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

[src/trunk]: src/sys/ufs/lfs Fixed lfs_update (and related functions) so that...



details:   https://anonhg.NetBSD.org/src/rev/c59783d643b2
branches:  trunk
changeset: 473390:c59783d643b2
user:      perseant <perseant%NetBSD.org@localhost>
date:      Tue Jun 01 03:00:40 1999 +0000

description:
Fixed lfs_update (and related functions) so that calls from lfs_fsync
will DTRT with vnodes marked VDIROP.  In particular, the message
"flushing VDIROP" will no longer appear, and the filesystem will remain
stable in the event of a crash.

This was particularly a problem with NFS-exported LFSes, since fsync
was called on every file close.

diffstat:

 sys/ufs/lfs/lfs.h        |   3 +-
 sys/ufs/lfs/lfs_bio.c    |  66 ++++++++++++++++++++++++++---------------------
 sys/ufs/lfs/lfs_extern.h |   3 +-
 sys/ufs/lfs/lfs_inode.c  |  24 +++++++++++++++--
 sys/ufs/lfs/lfs_vfsops.c |   4 +-
 5 files changed, 64 insertions(+), 36 deletions(-)

diffs (218 lines):

diff -r 8c62c0434e4c -r c59783d643b2 sys/ufs/lfs/lfs.h
--- a/sys/ufs/lfs/lfs.h Tue Jun 01 02:39:25 1999 +0000
+++ b/sys/ufs/lfs/lfs.h Tue Jun 01 03:00:40 1999 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: lfs.h,v 1.14 1999/03/25 21:39:18 perseant Exp $        */
+/*     $NetBSD: lfs.h,v 1.15 1999/06/01 03:00:40 perseant Exp $        */
 
 /*-
  * Copyright (c) 1999 The NetBSD Foundation, Inc.
@@ -315,6 +315,7 @@
        daddr_t   lfs_sbactive;         /* disk address of in-progress sb write */
 #endif
        struct vnode *lfs_flushvp;      /* vnode being flushed */
+       u_int32_t lfs_diropwait;        /* # procs waiting on dirop flush */
 };
 
 /*
diff -r 8c62c0434e4c -r c59783d643b2 sys/ufs/lfs/lfs_bio.c
--- a/sys/ufs/lfs/lfs_bio.c     Tue Jun 01 02:39:25 1999 +0000
+++ b/sys/ufs/lfs/lfs_bio.c     Tue Jun 01 03:00:40 1999 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: lfs_bio.c,v 1.10 1999/04/12 00:36:47 perseant Exp $    */
+/*     $NetBSD: lfs_bio.c,v 1.11 1999/06/01 03:00:40 perseant Exp $    */
 
 /*-
  * Copyright (c) 1999 The NetBSD Foundation, Inc.
@@ -267,6 +267,38 @@
        return (0);
 }
 
+void lfs_flush_fs(mp, flags)
+       struct mount *mp;
+       int flags;
+{
+       struct lfs *lfsp;
+
+       lfsp = ((struct ufsmount *)mp->mnt_data)->ufsmount_u.lfs;
+       if((mp->mnt_flag & MNT_RDONLY) == 0 &&
+          lfsp->lfs_dirops==0)
+       {
+               /* disallow dirops during flush */
+               lfsp->lfs_writer++;
+
+               /*
+                * We set the queue to 0 here because we
+                * are about to write all the dirty
+                * buffers we have.  If more come in
+                * while we're writing the segment, they
+                * may not get written, so we want the
+                * count to reflect these new writes
+                * after the segwrite completes.
+                */
+               if(lfs_dostats)
+                       ++lfs_stats.flush_invoked;
+               lfs_segwrite(mp, flags);
+
+               /* XXX KS - allow dirops again */
+               if(--lfsp->lfs_writer==0)
+                       wakeup(&lfsp->lfs_dirops);
+       }
+}
+
 /*
  * XXX
  * This routine flushes buffers out of the B_LOCKED queue when LFS has too
@@ -281,7 +313,6 @@
        int flags;
 {
        register struct mount *mp, *nmp;
-       struct lfs *lfsp;
        
        if(lfs_dostats) 
                ++lfs_stats.write_exceeded;
@@ -296,32 +327,7 @@
                        continue;
                }
                if (strncmp(&mp->mnt_stat.f_fstypename[0], MOUNT_LFS, MFSNAMELEN)==0)
-               {
-                       lfsp = ((struct ufsmount *)mp->mnt_data)->ufsmount_u.lfs;
-                       if((mp->mnt_flag & MNT_RDONLY) == 0 &&
-                          lfsp->lfs_dirops==0)
-                       {
-                               /* disallow dirops during flush */
-                               lfsp->lfs_writer++;
-
-                               /*
-                                * We set the queue to 0 here because we
-                                * are about to write all the dirty
-                                * buffers we have.  If more come in
-                                * while we're writing the segment, they
-                                * may not get written, so we want the
-                                * count to reflect these new writes
-                                * after the segwrite completes.
-                                */
-                               if(lfs_dostats)
-                                       ++lfs_stats.flush_invoked;
-                               lfs_segwrite(mp, flags);
-
-                               /* XXX KS - allow dirops again */
-                               if(--lfsp->lfs_writer==0)
-                                       wakeup(&lfsp->lfs_dirops);
-                       }
-               }
+                       lfs_flush_fs(mp, flags);
                simple_lock(&mountlist_slock);
                nmp = mp->mnt_list.cqe_next;
                vfs_unbusy(mp);
@@ -359,13 +365,15 @@
 
        if (locked_queue_count > LFS_MAX_BUFS
            || locked_queue_bytes > LFS_MAX_BYTES
-           || fs->lfs_dirvcount > LFS_MAXDIROP)
+           || fs->lfs_dirvcount > LFS_MAXDIROP
+           || fs->lfs_diropwait > 0)
        {
                ++fs->lfs_writer;
                lfs_flush(fs, flags);
                if(--fs->lfs_writer==0)
                        wakeup(&fs->lfs_dirops);
        }
+
        while  (locked_queue_count > LFS_WAIT_BUFS
                || locked_queue_bytes > LFS_WAIT_BYTES)
        {
diff -r 8c62c0434e4c -r c59783d643b2 sys/ufs/lfs/lfs_extern.h
--- a/sys/ufs/lfs/lfs_extern.h  Tue Jun 01 02:39:25 1999 +0000
+++ b/sys/ufs/lfs/lfs_extern.h  Tue Jun 01 03:00:40 1999 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: lfs_extern.h,v 1.13 1999/03/10 00:20:00 perseant Exp $ */
+/*     $NetBSD: lfs_extern.h,v 1.14 1999/06/01 03:00:40 perseant Exp $ */
 
 /*-
  * Copyright (c) 1999 The NetBSD Foundation, Inc.
@@ -115,6 +115,7 @@
 
 /* lfs_bio.c */
 int lfs_bwrite_ext __P((struct buf *, int));
+void lfs_flush_fs __P((struct mount *, int));
 void lfs_flush __P((struct lfs *, int));
 int lfs_check __P((struct vnode *, ufs_daddr_t, int));
 void lfs_freebuf __P((struct buf *));
diff -r 8c62c0434e4c -r c59783d643b2 sys/ufs/lfs/lfs_inode.c
--- a/sys/ufs/lfs/lfs_inode.c   Tue Jun 01 02:39:25 1999 +0000
+++ b/sys/ufs/lfs/lfs_inode.c   Tue Jun 01 03:00:40 1999 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: lfs_inode.c,v 1.24 1999/04/12 00:30:08 perseant Exp $  */
+/*     $NetBSD: lfs_inode.c,v 1.25 1999/06/01 03:00:40 perseant Exp $  */
 
 /*-
  * Copyright (c) 1999 The NetBSD Foundation, Inc.
@@ -128,6 +128,7 @@
        struct vnode *vp = ap->a_vp;
        int mod, oflag;
        struct timespec ts;
+       struct lfs *fs = VFSTOUFS(vp->v_mount)->um_lfs;
        
        if (vp->v_mount->mnt_flag & MNT_RDONLY)
                return (0);
@@ -142,7 +143,7 @@
         */
        while((ap->a_waitfor & LFS_SYNC) && WRITEINPROG(vp)) {
 #ifdef DEBUG_LFS
-               printf("lfs_update: sleeping on inode %d\n",ip->i_number);
+               printf("lfs_update: sleeping on inode %d (in-progress)\n",ip->i_number);
 #endif
                tsleep(vp, (PRIBIO+1), "lfs_update", 0);
        }
@@ -159,7 +160,24 @@
        }
        
        /* If sync, push back the vnode and any dirty blocks it may have. */
-       return (ap->a_waitfor & LFS_SYNC ? lfs_vflush(vp) : 0);
+       if(ap->a_waitfor & LFS_SYNC) {
+               /* Avoid flushing VDIROP. */
+               ++fs->lfs_diropwait;
+               while(vp->v_flag & VDIROP) {
+#ifdef DEBUG_LFS
+                       printf("lfs_update: sleeping on inode %d (dirops)\n",ip->i_number);
+#endif
+                       if(fs->lfs_dirops==0)
+                               lfs_flush_fs(vp->v_mount,0);
+                       else
+                               tsleep(&fs->lfs_writer, PRIBIO+1, "lfs_fsync", 0);
+                       /* XXX KS - by falling out here, are we writing the vn
+                       twice? */
+               }
+               --fs->lfs_diropwait;
+               return lfs_vflush(vp);
+        }
+       return 0;
 }
 
 /* Update segment usage information when removing a block. */
diff -r 8c62c0434e4c -r c59783d643b2 sys/ufs/lfs/lfs_vfsops.c
--- a/sys/ufs/lfs/lfs_vfsops.c  Tue Jun 01 02:39:25 1999 +0000
+++ b/sys/ufs/lfs/lfs_vfsops.c  Tue Jun 01 03:00:40 1999 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: lfs_vfsops.c,v 1.33 1999/05/04 00:35:37 scottr Exp $   */
+/*     $NetBSD: lfs_vfsops.c,v 1.34 1999/06/01 03:00:40 perseant Exp $ */
 
 /*-
  * Copyright (c) 1999 The NetBSD Foundation, Inc.
@@ -71,7 +71,6 @@
  */
 
 #if defined(_KERNEL) && !defined(_LKM)
-#include "opt_ddb.h"
 #include "opt_quota.h"
 #endif
 
@@ -395,6 +394,7 @@
        /* Set up the I/O information */
        fs->lfs_iocount = 0;
        fs->lfs_dirvcount = 0;
+       fs->lfs_diropwait = 0;
        fs->lfs_activesb = 0;
 #ifdef LFS_CANNOT_ROLLFW
        fs->lfs_sbactive = NULL;



Home | Main Index | Thread Index | Old Index