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 an lfs_strategy() that checks to make sure w...



details:   https://anonhg.NetBSD.org/src/rev/fc6580cc2dcc
branches:  trunk
changeset: 544000:fc6580cc2dcc
user:      perseant <perseant%NetBSD.org@localhost>
date:      Sat Mar 08 02:55:47 2003 +0000

description:
Add an lfs_strategy() that checks to make sure we're not trying to read
where the cleaner is trying to write, instead of tying up the "live"
buffers (or pages).

Fix a bug in the LFS_UBC case where oversized buffers would not be
checksummed correctly, causing uncleanable segments.

Make sure that wakeup(fs->lfs_iocount) is done if fs->lfs_iocount is 1
as well as 0, since we wait in some places for it to drop to 1.

Activate all pages that make it into lfs_gop_write without the segment
lock held, since they must have been dirtied very recently, even if
PG_DELWRI is not set.

diffstat:

 sys/ufs/lfs/lfs.h          |   7 ++-
 sys/ufs/lfs/lfs_extern.h   |   3 +-
 sys/ufs/lfs/lfs_segment.c  |  23 ++++++++--
 sys/ufs/lfs/lfs_subr.c     |  19 ++++++--
 sys/ufs/lfs/lfs_syscalls.c |  42 ++-----------------
 sys/ufs/lfs/lfs_vfsops.c   |  20 ++++++---
 sys/ufs/lfs/lfs_vnops.c    |  97 ++++++++++++++++++++++++++++++++++++++++++++-
 7 files changed, 151 insertions(+), 60 deletions(-)

diffs (truncated from 430 to 300 lines):

diff -r 55c5a03a6a28 -r fc6580cc2dcc sys/ufs/lfs/lfs.h
--- a/sys/ufs/lfs/lfs.h Sat Mar 08 01:20:21 2003 +0000
+++ b/sys/ufs/lfs/lfs.h Sat Mar 08 02:55:47 2003 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: lfs.h,v 1.54 2003/03/02 04:34:30 perseant Exp $        */
+/*     $NetBSD: lfs.h,v 1.55 2003/03/08 02:55:47 perseant Exp $        */
 
 /*-
  * Copyright (c) 1999, 2000, 2001, 2002, 2003 The NetBSD Foundation, Inc.
@@ -154,7 +154,7 @@
      (((uvmexp.active + uvmexp.inactive + uvmexp.free) * uvmexp.filemax) >> 8)
 
 #define LFS_IS_MALLOC_BUF(bp) (((bp)->b_flags & B_CALL) &&             \
-     ((bp)->b_iodone == lfs_callback || (bp)->b_iodone == lfs_fakebuf_iodone))
+     (bp)->b_iodone == lfs_callback)
 
 #define LFS_LOCK_BUF(bp) do {                                          \
        if (((bp)->b_flags & (B_LOCKED | B_CALL)) == 0) {               \
@@ -534,6 +534,9 @@
        struct pool lfs_bpppool;        /* Pool for bpp */
        struct pool lfs_segpool;        /* Pool for struct segment */
 #endif /* KERNEL */
+#define LFS_MAX_CLEANIND 64
+       int32_t  lfs_cleanint[LFS_MAX_CLEANIND]; /* Active cleaning intervals */
+       int      lfs_cleanind;  /* Index into intervals */
 };
 
 /*
diff -r 55c5a03a6a28 -r fc6580cc2dcc sys/ufs/lfs/lfs_extern.h
--- a/sys/ufs/lfs/lfs_extern.h  Sat Mar 08 01:20:21 2003 +0000
+++ b/sys/ufs/lfs/lfs_extern.h  Sat Mar 08 02:55:47 2003 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: lfs_extern.h,v 1.44 2003/02/25 23:12:07 perseant Exp $ */
+/*     $NetBSD: lfs_extern.h,v 1.45 2003/03/08 02:55:48 perseant Exp $ */
 
 /*-
  * Copyright (c) 1999, 2000, 2001, 2002, 2003 The NetBSD Foundation, Inc.
@@ -248,6 +248,7 @@
 int lfs_fcntl   (void *);
 int lfs_inactive (void *);
 int lfs_reclaim         (void *);
+int lfs_strategy (void *);
 int lfs_write   (void *);
 int lfs_getpages (void *);
 int lfs_putpages (void *);
diff -r 55c5a03a6a28 -r fc6580cc2dcc sys/ufs/lfs/lfs_segment.c
--- a/sys/ufs/lfs/lfs_segment.c Sat Mar 08 01:20:21 2003 +0000
+++ b/sys/ufs/lfs/lfs_segment.c Sat Mar 08 02:55:47 2003 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: lfs_segment.c,v 1.106 2003/03/04 19:19:43 perseant Exp $       */
+/*     $NetBSD: lfs_segment.c,v 1.107 2003/03/08 02:55:48 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.106 2003/03/04 19:19:43 perseant Exp $");
+__KERNEL_RCSID(0, "$NetBSD: lfs_segment.c,v 1.107 2003/03/08 02:55:48 perseant Exp $");
 
 #define ivndebug(vp,str) printf("ino %d: %s\n",VTOI(vp)->i_number,(str))
 
@@ -1459,6 +1459,7 @@
        sp = fs->lfs_sp;
 
        repeat = 0;
+
        /* Advance to the next segment. */
        if (!LFS_PARTIAL_FITS(fs)) {
                /* lfs_avail eats the remaining space */
@@ -1497,6 +1498,18 @@
        }
        fs->lfs_lastpseg = fs->lfs_offset;
        
+       /* Record first address of this partial segment */
+       if (sp->seg_flags & SEGM_CLEAN) {
+               fs->lfs_cleanint[fs->lfs_cleanind] = fs->lfs_offset;
+               if (++fs->lfs_cleanind >= LFS_MAX_CLEANIND) {
+                       /* "1" is the artificial inc in lfs_seglock */
+                       while (fs->lfs_iocount > 1) {
+                               tsleep(&fs->lfs_iocount, PRIBIO + 1, "lfs_initseg", 0);
+                       }
+                       fs->lfs_cleanind = 0;
+               }
+       }
+
        sp->fs = fs;
        sp->ibp = NULL;
        sp->idp = NULL;
@@ -1952,7 +1965,7 @@
        /* Set the summary block busy too */
        (*(sp->bpp))->b_flags |= B_BUSY;
 #endif
-       ssp->ss_datasum = cksum(datap, (nblocks - 1) * el_size);
+       ssp->ss_datasum = cksum(datap, dp - datap);
        ssp->ss_sumsum =
            cksum(&ssp->ss_datasum, fs->lfs_sumsize - sizeof(ssp->ss_sumsum));
        pool_put(&fs->lfs_bpppool, datap);
@@ -2311,7 +2324,7 @@
        fs = (struct lfs *)bp->b_saveaddr;
        fs->lfs_sbactive = 0;
        wakeup(&fs->lfs_sbactive);
-       if (--fs->lfs_iocount == 0)
+       if (--fs->lfs_iocount <= 1)
                wakeup(&fs->lfs_iocount);
        lfs_freebuf(fs, bp);
 }
@@ -2451,7 +2464,7 @@
        if (fs->lfs_iocount == 0)
                panic("lfs_cluster_aiodone: zero iocount");
 #endif
-       if (--fs->lfs_iocount == 0)
+       if (--fs->lfs_iocount <= 1)
                wakeup(&fs->lfs_iocount);
 
        pool_put(&fs->lfs_bpppool, cl->bpp);
diff -r 55c5a03a6a28 -r fc6580cc2dcc sys/ufs/lfs/lfs_subr.c
--- a/sys/ufs/lfs/lfs_subr.c    Sat Mar 08 01:20:21 2003 +0000
+++ b/sys/ufs/lfs/lfs_subr.c    Sat Mar 08 02:55:47 2003 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: lfs_subr.c,v 1.35 2003/03/04 19:15:26 perseant Exp $   */
+/*     $NetBSD: lfs_subr.c,v 1.36 2003/03/08 02:55:49 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_subr.c,v 1.35 2003/03/04 19:15:26 perseant Exp $");
+__KERNEL_RCSID(0, "$NetBSD: lfs_subr.c,v 1.36 2003/03/08 02:55:49 perseant Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -333,7 +333,8 @@
        
        fs->lfs_seglock = 1;
        fs->lfs_lockpid = curproc->p_pid;
-       
+       fs->lfs_cleanind = 0;
+
        /* Drain fragment size changes out */
        lockmgr(&fs->lfs_fraglock, LK_EXCLUSIVE, 0);
 
@@ -455,7 +456,13 @@
 
                pool_put(&fs->lfs_bpppool, sp->bpp);
                sp->bpp = NULL;
-               /* The sync case holds a reference in `sp' to be freed below */
+
+               /*
+                * If we're not sync, we're done with sp, get rid of it.
+                * Otherwise, we keep a local copy around but free
+                * fs->lfs_sp so another process can use it (we have to
+                * wait but they don't have to wait for us).
+                */
                if (!sync)
                        pool_put(&fs->lfs_segpool, sp);
                fs->lfs_sp = NULL;
@@ -469,8 +476,9 @@
                        lfs_countlocked(&locked_queue_count,
                                        &locked_queue_bytes, "lfs_segunlock");
                        wakeup(&locked_queue_count);
+               }
+               if (fs->lfs_iocount <= 1)
                        wakeup(&fs->lfs_iocount);
-               }
                /*
                 * If we're not checkpointing, we don't have to block
                 * other processes to wait for a synchronous write
@@ -498,6 +506,7 @@
                }
                if (sync)
                        pool_put(&fs->lfs_segpool, sp);
+
                if (ckp) {
                        fs->lfs_nactive = 0;
                        /* If we *know* everything's on disk, write both sbs */
diff -r 55c5a03a6a28 -r fc6580cc2dcc sys/ufs/lfs/lfs_syscalls.c
--- a/sys/ufs/lfs/lfs_syscalls.c        Sat Mar 08 01:20:21 2003 +0000
+++ b/sys/ufs/lfs/lfs_syscalls.c        Sat Mar 08 02:55:47 2003 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: lfs_syscalls.c,v 1.84 2003/02/24 08:42:49 perseant Exp $       */
+/*     $NetBSD: lfs_syscalls.c,v 1.85 2003/03/08 02:55:49 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_syscalls.c,v 1.84 2003/02/24 08:42:49 perseant Exp $");
+__KERNEL_RCSID(0, "$NetBSD: lfs_syscalls.c,v 1.85 2003/03/08 02:55:49 perseant Exp $");
 
 #define LFS            /* for prototypes in syscallargs.h */
 
@@ -1224,57 +1224,25 @@
        return (0);
 }
 
-void
-lfs_fakebuf_iodone(struct buf *bp)
-{
-       struct buf *obp = bp->b_saveaddr;
-
-       if (!(obp->b_flags & (B_DELWRI | B_DONE)))
-               obp->b_flags |= B_INVAL;
-       bp->b_saveaddr = (caddr_t)(VTOI(obp->b_vp)->i_lfs);
-       brelse(obp);
-       lfs_callback(bp);
-}
-
+/*
+ * Make up a "fake" cleaner buffer, copy the data from userland into it.
+ */
 struct buf *
 lfs_fakebuf(struct lfs *fs, struct vnode *vp, int lbn, size_t size, caddr_t uaddr)
 {
        struct buf *bp;
        int error;
-       
-       struct buf *obp;
 
        KASSERT(VTOI(vp)->i_number != LFS_IFILE_INUM);
 
-       /*
-        * make corresponding buffer busy to avoid
-        * reading blocks that isn't written yet.
-        * it's needed because we'll update metadatas in lfs_updatemeta
-        * before data pointed by them is actually written to disk.
-        *
-        * XXX no need to allocbuf.
-        *
-        * XXX this can cause buf starvation.
-        */
-       obp = getblk(vp, lbn, size, 0, 0);
-       if (obp == NULL)
-               panic("lfs_fakebuf: getblk failed");
-
        bp = lfs_newbuf(VTOI(vp)->i_lfs, vp, lbn, size, LFS_NB_CLEAN);
        error = copyin(uaddr, bp->b_data, size);
        if (error) {
                lfs_freebuf(fs, bp);
                return NULL;
        }
-       bp->b_saveaddr = obp;
        KDASSERT(bp->b_iodone == lfs_callback);
-       bp->b_iodone = lfs_fakebuf_iodone;
 
-#ifdef DIAGNOSTIC
-       if (obp->b_flags & B_GATHERED)
-               panic("lfs_fakebuf: gathered bp: %p, ino=%u, lbn=%d",
-                   bp, VTOI(vp)->i_number, lbn);
-#endif
 #if 0
        bp->b_saveaddr = (caddr_t)fs;
        ++fs->lfs_iocount;
diff -r 55c5a03a6a28 -r fc6580cc2dcc sys/ufs/lfs/lfs_vfsops.c
--- a/sys/ufs/lfs/lfs_vfsops.c  Sat Mar 08 01:20:21 2003 +0000
+++ b/sys/ufs/lfs/lfs_vfsops.c  Sat Mar 08 02:55:47 2003 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: lfs_vfsops.c,v 1.102 2003/03/02 04:34:31 perseant Exp $        */
+/*     $NetBSD: lfs_vfsops.c,v 1.103 2003/03/08 02:55:49 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_vfsops.c,v 1.102 2003/03/02 04:34:31 perseant Exp $");
+__KERNEL_RCSID(0, "$NetBSD: lfs_vfsops.c,v 1.103 2003/03/08 02:55:49 perseant Exp $");
 
 #if defined(_KERNEL_OPT)
 #include "opt_quota.h"
@@ -1811,17 +1811,23 @@
                for (i = 0; i < npages; i++) {
                        pg = pgs[i];
 
-                       if (pg->flags & PG_WANTED)
-                               wakeup(pg);
                        if (pg->flags & PG_PAGEOUT)
                                uvmexp.paging--;
                        if (pg->flags & PG_DELWRI) {
                                uvm_pageunwire(pg);
-                               uvm_pageactivate(pg);
                        }
-                       pg->flags &= ~(PG_BUSY|PG_CLEAN|PG_WANTED|PG_DELWRI|PG_PAGEOUT|PG_RELEASED);
-                       UVM_PAGE_OWN(pg, NULL);
+                       uvm_pageactivate(pg);
+                       pg->flags &= ~(PG_CLEAN|PG_DELWRI|PG_PAGEOUT|PG_RELEASED);
+#ifdef DEBUG_LFS
+                       printf("pg[%d]->flags = %x\n", i, pg->flags);
+                       printf("pg[%d]->pqflags = %x\n", i, pg->pqflags);
+                       printf("pg[%d]->uanon = %p\n", i, pg->uanon);
+                       printf("pg[%d]->uobject = %p\n", i, pg->uobject);
+                       printf("pg[%d]->wire_count = %d\n", i, pg->wire_count);
+                       printf("pg[%d]->loan_count = %d\n", i, pg->loan_count);
+#endif



Home | Main Index | Thread Index | Old Index