Source-Changes-HG archive

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

[src/trunk]: src/sys/ufs/lfs Add simple_lock protection for lfs_seglock and l...



details:   https://anonhg.NetBSD.org/src/rev/28baad81c008
branches:  trunk
changeset: 544234:28baad81c008
user:      perseant <perseant%NetBSD.org@localhost>
date:      Sat Mar 15 06:58:49 2003 +0000

description:
Add simple_lock protection for lfs_seglock and lfs_subsys_pages; these will
be expanded to cover other per-fs and subsystem-wide data as well.

Fix a case of IN_MODIFIED being set without updating lfs_uinodes, resulting
in a "lfs_uinodes < 0" panic.

Fix a deadlock in lfs_putpages arising from the need to busy all pages in a
block; unbusy any that had already been busied before starting over.

diffstat:

 sys/ufs/lfs/lfs.h          |   7 ++++++-
 sys/ufs/lfs/lfs_alloc.c    |  12 +++++++-----
 sys/ufs/lfs/lfs_balloc.c   |   6 ++----
 sys/ufs/lfs/lfs_bio.c      |  30 ++++++++++++++++++++++++------
 sys/ufs/lfs/lfs_segment.c  |  37 +++++++------------------------------
 sys/ufs/lfs/lfs_subr.c     |  24 ++++++++++++++++++------
 sys/ufs/lfs/lfs_syscalls.c |   7 ++-----
 sys/ufs/lfs/lfs_vfsops.c   |   5 +++--
 sys/ufs/lfs/lfs_vnops.c    |  24 +++++++++++++++++-------
 9 files changed, 86 insertions(+), 66 deletions(-)

diffs (truncated from 549 to 300 lines):

diff -r 7f6fdad9f815 -r 28baad81c008 sys/ufs/lfs/lfs.h
--- a/sys/ufs/lfs/lfs.h Sat Mar 15 04:51:13 2003 +0000
+++ b/sys/ufs/lfs/lfs.h Sat Mar 15 06:58:49 2003 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: lfs.h,v 1.57 2003/03/11 02:47:39 perseant Exp $        */
+/*     $NetBSD: lfs.h,v 1.58 2003/03/15 06:58:49 perseant Exp $        */
 
 /*-
  * Copyright (c) 1999, 2000, 2001, 2002, 2003 The NetBSD Foundation, Inc.
@@ -187,6 +187,7 @@
 #define IN_ALLMOD (IN_MODIFIED|IN_ACCESS|IN_CHANGE|IN_UPDATE|IN_ACCESSED|IN_CLEANING)
 
 #define LFS_SET_UINO(ip, flags) do {                                   \
+       simple_lock(&(ip)->i_lfs->lfs_interlock);                       \
        if (((flags) & IN_ACCESSED) && !((ip)->i_flag & IN_ACCESSED))   \
                ++(ip)->i_lfs->lfs_uinodes;                             \
        if (((flags) & IN_CLEANING) && !((ip)->i_flag & IN_CLEANING))   \
@@ -194,9 +195,11 @@
        if (((flags) & IN_MODIFIED) && !((ip)->i_flag & IN_MODIFIED))   \
                ++(ip)->i_lfs->lfs_uinodes;                             \
        (ip)->i_flag |= (flags);                                        \
+       simple_unlock(&(ip)->i_lfs->lfs_interlock);                     \
 } while (0)
 
 #define LFS_CLR_UINO(ip, flags) do {                                   \
+       simple_lock(&(ip)->i_lfs->lfs_interlock);                       \
        if (((flags) & IN_ACCESSED) && ((ip)->i_flag & IN_ACCESSED))    \
                --(ip)->i_lfs->lfs_uinodes;                             \
        if (((flags) & IN_CLEANING) && ((ip)->i_flag & IN_CLEANING))    \
@@ -207,6 +210,7 @@
        if ((ip)->i_lfs->lfs_uinodes < 0) {                             \
                panic("lfs_uinodes < 0");                               \
        }                                                               \
+       simple_unlock(&(ip)->i_lfs->lfs_interlock);                     \
 } while (0)
 
 #ifdef DEBUG
@@ -527,6 +531,7 @@
 #define LFS_MAX_CLEANIND 64
        int32_t  lfs_cleanint[LFS_MAX_CLEANIND]; /* Active cleaning intervals */
        int      lfs_cleanind;  /* Index into intervals */
+       struct simplelock lfs_interlock;  /* lock for lfs_seglock */
 };
 
 /*
diff -r 7f6fdad9f815 -r 28baad81c008 sys/ufs/lfs/lfs_alloc.c
--- a/sys/ufs/lfs/lfs_alloc.c   Sat Mar 15 04:51:13 2003 +0000
+++ b/sys/ufs/lfs/lfs_alloc.c   Sat Mar 15 06:58:49 2003 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: lfs_alloc.c,v 1.64 2003/02/20 04:27:23 perseant Exp $  */
+/*     $NetBSD: lfs_alloc.c,v 1.65 2003/03/15 06:58:50 perseant Exp $  */
 
 /*-
  * Copyright (c) 1999, 2000, 2001, 2002, 2003 The NetBSD Foundation, Inc.
@@ -71,7 +71,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: lfs_alloc.c,v 1.64 2003/02/20 04:27:23 perseant Exp $");
+__KERNEL_RCSID(0, "$NetBSD: lfs_alloc.c,v 1.65 2003/03/15 06:58:50 perseant Exp $");
 
 #if defined(_KERNEL_OPT)
 #include "opt_quota.h"
@@ -98,8 +98,6 @@
 
 extern int lfs_dirvcount;
 extern struct lock ufs_hashlock;
-extern struct simplelock lfs_subsys_lock;
-extern int lfs_subsys_pages;
 
 static int extend_ifile(struct lfs *, struct ucred *);
 static int lfs_ialloc(struct lfs *, struct vnode *, ino_t, int, struct vnode **);
@@ -217,7 +215,8 @@
 }
 
 /*
- * Called with the Ifile inode locked. 
+ * Add a new block to the Ifile, to accommodate future file creations.
+ * Called with the segment lock held.
  */
 static int
 extend_ifile(struct lfs *fs, struct ucred *cred)
@@ -350,6 +349,9 @@
        return lfs_ialloc(fs, ap->a_pvp, new_ino, new_gen, ap->a_vpp);
 }
 
+/*
+ * Finish allocating a new inode, given an inode and generation number.
+ */
 static int
 lfs_ialloc(struct lfs *fs, struct vnode *pvp, ino_t new_ino, int new_gen,
           struct vnode **vpp)
diff -r 7f6fdad9f815 -r 28baad81c008 sys/ufs/lfs/lfs_balloc.c
--- a/sys/ufs/lfs/lfs_balloc.c  Sat Mar 15 04:51:13 2003 +0000
+++ b/sys/ufs/lfs/lfs_balloc.c  Sat Mar 15 06:58:49 2003 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: lfs_balloc.c,v 1.38 2003/02/28 07:36:32 perseant Exp $ */
+/*     $NetBSD: lfs_balloc.c,v 1.39 2003/03/15 06:58:50 perseant Exp $ */
 
 /*-
  * Copyright (c) 1999, 2000, 2001, 2002, 2003 The NetBSD Foundation, Inc.
@@ -71,7 +71,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: lfs_balloc.c,v 1.38 2003/02/28 07:36:32 perseant Exp $");
+__KERNEL_RCSID(0, "$NetBSD: lfs_balloc.c,v 1.39 2003/03/15 06:58:50 perseant Exp $");
 
 #if defined(_KERNEL_OPT)
 #include "opt_quota.h"
@@ -98,8 +98,6 @@
 
 #include <uvm/uvm.h>
 
-extern int lfs_subsys_pages;
-
 int lfs_fragextend(struct vnode *, int, int, daddr_t, struct buf **, struct ucred *);
 
 /*
diff -r 7f6fdad9f815 -r 28baad81c008 sys/ufs/lfs/lfs_bio.c
--- a/sys/ufs/lfs/lfs_bio.c     Sat Mar 15 04:51:13 2003 +0000
+++ b/sys/ufs/lfs/lfs_bio.c     Sat Mar 15 06:58:49 2003 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: lfs_bio.c,v 1.63 2003/03/02 04:34:31 perseant Exp $    */
+/*     $NetBSD: lfs_bio.c,v 1.64 2003/03/15 06:58:50 perseant Exp $    */
 
 /*-
  * Copyright (c) 1999, 2000, 2001, 2002, 2003 The NetBSD Foundation, Inc.
@@ -71,7 +71,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: lfs_bio.c,v 1.63 2003/03/02 04:34:31 perseant Exp $");
+__KERNEL_RCSID(0, "$NetBSD: lfs_bio.c,v 1.64 2003/03/15 06:58:50 perseant Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -108,7 +108,9 @@
 int    lfs_subsys_pages     = 0L;      /* Total number LFS-written pages */
 int    lfs_writing          = 0;       /* Set if already kicked off a writer
                                           because of buffer space */
-struct simplelock lfs_subsys_lock;     /* Lock on subsys_pages */
+/* Lock for lfs_subsys_pages */
+struct simplelock lfs_subsys_lock = SIMPLELOCK_INITIALIZER;
+
 extern int lfs_dostats;
 extern int lfs_do_flush;
 
@@ -373,10 +375,14 @@
        struct buf *cbp;
 
        /* Push cleaner blocks through regardless */
+       simple_lock(&fs->lfs_interlock);
        if (fs->lfs_seglock &&
            fs->lfs_lockpid == curproc->p_pid &&
-           fs->lfs_sp->seg_flags & (SEGM_CLEAN | SEGM_FORCE_CKP))
+           fs->lfs_sp->seg_flags & (SEGM_CLEAN | SEGM_FORCE_CKP)) {
+               simple_unlock(&fs->lfs_interlock);
                return 0;
+       }
+       simple_unlock(&fs->lfs_interlock);
 
        while (!lfs_fits(fs, fsb)) {
                /*
@@ -523,7 +529,9 @@
                ltsleep(&lfs_writing, PRIBIO + 1, "lfsflush", 0, 0);
        lfs_writing = 1;
        
+       simple_lock(&lfs_subsys_lock);
        lfs_subsys_pages = 0; /* XXXUBC need a better way to count this */
+       simple_unlock(&lfs_subsys_lock);
        wakeup(&lfs_subsys_pages);
 
        simple_lock(&mountlist_slock);
@@ -573,6 +581,7 @@
         * If we would flush below, but dirops are active, sleep.
         * Note that a dirop cannot ever reach this code!
         */
+       simple_lock(&lfs_subsys_lock);
        while (fs->lfs_dirops > 0 &&
               (locked_queue_count + INOCOUNT(fs) > LFS_MAX_BUFS ||
                locked_queue_bytes + INOBYTES(fs) > LFS_MAX_BYTES ||
@@ -580,7 +589,8 @@
                lfs_dirvcount > LFS_MAX_DIROP || fs->lfs_diropwait > 0))
        {
                ++fs->lfs_diropwait;
-               tsleep(&fs->lfs_writer, PRIBIO+1, "bufdirop", 0);
+               ltsleep(&fs->lfs_writer, PRIBIO+1, "bufdirop", 0,
+                       &lfs_subsys_lock);
                --fs->lfs_diropwait;
        }
 
@@ -598,12 +608,15 @@
        if (fs->lfs_diropwait > 0)
                printf("ldvw = %d\n", fs->lfs_diropwait);
 #endif
+
        if (locked_queue_count + INOCOUNT(fs) > LFS_MAX_BUFS ||
            locked_queue_bytes + INOBYTES(fs) > LFS_MAX_BYTES ||
            lfs_subsys_pages > LFS_MAX_PAGES ||
            lfs_dirvcount > LFS_MAX_DIROP || fs->lfs_diropwait > 0)
        {
+               simple_unlock(&lfs_subsys_lock);
                lfs_flush(fs, flags);
+               simple_lock(&lfs_subsys_lock);
        }
 
        while (locked_queue_count + INOCOUNT(fs) > LFS_WAIT_BUFS ||
@@ -611,6 +624,7 @@
                lfs_subsys_pages > LFS_WAIT_PAGES ||
                lfs_dirvcount > LFS_MAX_DIROP)
        {
+               simple_unlock(&lfs_subsys_lock);
                if (lfs_dostats)
                        ++lfs_stats.wait_exceeded;
 #ifdef DEBUG_LFS
@@ -619,8 +633,10 @@
 #endif
                error = tsleep(&locked_queue_count, PCATCH | PUSER,
                               "buffers", hz * LFS_BUFWAIT);
-               if (error != EWOULDBLOCK)
+               if (error != EWOULDBLOCK) {
+                       simple_lock(&lfs_subsys_lock);
                        break;
+               }
                /*
                 * lfs_flush might not flush all the buffers, if some of the
                 * inodes were locked or if most of them were Ifile blocks
@@ -632,7 +648,9 @@
                {
                        lfs_flush(fs, flags | SEGM_CKP);
                }
+               simple_lock(&lfs_subsys_lock);
        }
+       simple_unlock(&lfs_subsys_lock);
        return (error);
 }
 
diff -r 7f6fdad9f815 -r 28baad81c008 sys/ufs/lfs/lfs_segment.c
--- a/sys/ufs/lfs/lfs_segment.c Sat Mar 15 04:51:13 2003 +0000
+++ b/sys/ufs/lfs/lfs_segment.c Sat Mar 15 06:58:49 2003 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: lfs_segment.c,v 1.110 2003/03/15 02:27:18 kristerw Exp $       */
+/*     $NetBSD: lfs_segment.c,v 1.111 2003/03/15 06:58:50 perseant Exp $       */
 
 /*-
  * Copyright (c) 1999, 2000, 2001, 2002, 2003 The NetBSD Foundation, Inc.
@@ -71,7 +71,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: lfs_segment.c,v 1.110 2003/03/15 02:27:18 kristerw Exp $");
+__KERNEL_RCSID(0, "$NetBSD: lfs_segment.c,v 1.111 2003/03/15 06:58:50 perseant Exp $");
 
 #define ivndebug(vp,str) printf("ino %d: %s\n",VTOI(vp)->i_number,(str))
 
@@ -109,7 +109,6 @@
 
 extern int count_lock_queue(void);
 extern struct simplelock vnode_free_list_slock;                /* XXX */
-extern int lfs_subsys_pages; 
 
 static void lfs_generic_callback(struct buf *, void (*)(struct buf *));
 static void lfs_super_aiodone(struct buf *);
@@ -405,11 +404,15 @@
         * We compare the iocount against 1, not 0, because it is
         * artificially incremented by lfs_seglock().
         */
+       simple_lock(&fs->lfs_interlock);
        if (fs->lfs_seglock > 1) {
+               simple_unlock(&fs->lfs_interlock);
                while (fs->lfs_iocount > 1)
                        (void)tsleep(&fs->lfs_iocount, PRIBIO + 1,
                                     "lfs_vflush", 0);
-       }
+       } else
+               simple_unlock(&fs->lfs_interlock);
+
        lfs_segunlock(fs);
 
        CLR_FLUSHING(fs,vp);
@@ -543,31 +546,6 @@
 
        lfs_imtime(fs);
 
-       /* printf("lfs_segwrite: ifile flags are 0x%lx\n",
-              (long)(VTOI(fs->lfs_ivnode)->i_flag)); */
-
-#if 0  
-       /*
-        * If we are not the cleaner, and there is no space available,
-        * wait until cleaner writes.
-        */
-       if (!(flags & SEGM_CLEAN) && !(fs->lfs_seglock && fs->lfs_sp &&
-                                     (fs->lfs_sp->seg_flags & SEGM_CLEAN)))
-       {
-               while (fs->lfs_avail <= 0) {
-                       LFS_CLEANERINFO(cip, fs, bp);
-                       LFS_SYNC_CLEANERINFO(cip, fs, bp, 0);
-       



Home | Main Index | Thread Index | Old Index