Source-Changes-HG archive

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

[src/trunk]: src/sys/ufs - in lfs_reserve, reserve locked buffer count as well.



details:   https://anonhg.NetBSD.org/src/rev/933593a61530
branches:  trunk
changeset: 540849:933593a61530
user:      yamt <yamt%NetBSD.org@localhost>
date:      Thu Dec 26 13:37:18 2002 +0000

description:
- in lfs_reserve, reserve locked buffer count as well.
- don't wait for locking buf in lfs_bwrite_ext to avoid deadlocks.
- skip lfs_reserve when we're doing dirop.
  reserve more (for lfs_truncate) in set_dirop instead.

this mostly solves PR 18972. (and hopefully PR 19196)

diffstat:

 sys/ufs/lfs/lfs_bio.c       |  135 +++++++++++++++++++++++++++++++++++++------
 sys/ufs/lfs/lfs_vnops.c     |   18 +++-
 sys/ufs/ufs/ufs_readwrite.c |   28 +++++++-
 3 files changed, 148 insertions(+), 33 deletions(-)

diffs (truncated from 326 to 300 lines):

diff -r 6423c1550e83 -r 933593a61530 sys/ufs/lfs/lfs_bio.c
--- a/sys/ufs/lfs/lfs_bio.c     Thu Dec 26 13:20:44 2002 +0000
+++ b/sys/ufs/lfs/lfs_bio.c     Thu Dec 26 13:37:18 2002 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: lfs_bio.c,v 1.50 2002/12/22 17:31:52 yamt Exp $        */
+/*     $NetBSD: lfs_bio.c,v 1.51 2002/12/26 13:37:18 yamt Exp $        */
 
 /*-
  * Copyright (c) 1999, 2000 The NetBSD Foundation, Inc.
@@ -71,7 +71,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: lfs_bio.c,v 1.50 2002/12/22 17:31:52 yamt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: lfs_bio.c,v 1.51 2002/12/26 13:37:18 yamt Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -109,6 +109,69 @@
 extern int lfs_dostats;
 
 /*
+ * reserved number/bytes of locked buffers
+ */
+int locked_queue_rcount = 0;
+long locked_queue_rbytes = 0L;
+
+int lfs_fits_buf(struct lfs *, int, int);
+int lfs_reservebuf(struct lfs *, int, int);
+int lfs_reserveavail(struct lfs *, struct vnode *, int);
+
+int
+lfs_fits_buf(struct lfs *fs, int n, int bytes)
+{
+       int count_fit =
+           (locked_queue_count + locked_queue_rcount + n < LFS_WAIT_BUFS);
+       int bytes_fit =
+           (locked_queue_bytes + locked_queue_rbytes + bytes < LFS_WAIT_BYTES);
+
+#ifdef DEBUG_LFS
+       if (!count_fit) {
+               printf("lfs_fits_buf: no fit count: %d + %d + %d >= %d\n",
+                       locked_queue_count, locked_queue_rcount,
+                       n, LFS_WAIT_BUFS);
+       }
+       if (!bytes_fit) {
+               printf("lfs_fits_buf: no fit bytes: %ld + %ld + %d >= %d\n",
+                       locked_queue_bytes, locked_queue_rbytes,
+                       bytes, LFS_WAIT_BYTES);
+       }
+#endif /* DEBUG_LFS */
+
+       return (count_fit && bytes_fit);
+}
+
+int
+lfs_reservebuf(struct lfs *fs, int n, int bytes)
+{
+       KASSERT(locked_queue_rcount >= 0);
+       KASSERT(locked_queue_rbytes >= 0);
+
+       while (n > 0 && !lfs_fits_buf(fs, n, bytes)) {
+               int error;
+
+               ++fs->lfs_writer;
+               lfs_flush(fs, 0);
+               if (--fs->lfs_writer == 0)
+                       wakeup(&fs->lfs_dirops);
+
+               error = tsleep(&locked_queue_count, PCATCH | PUSER,
+                   "lfsresbuf", hz * LFS_BUFWAIT);
+               if (error && error != EWOULDBLOCK)
+                       return error;
+       }
+
+       locked_queue_rcount += n;
+       locked_queue_rbytes += bytes;
+
+       KASSERT(locked_queue_rcount >= 0);
+       KASSERT(locked_queue_rbytes >= 0);
+
+       return 0;
+}
+
+/*
  * Try to reserve some blocks, prior to performing a sensitive operation that
  * requires the vnode lock to be honored.  If there is not enough space, give
  * up the vnode lock temporarily and wait for the space to become available.
@@ -126,7 +189,7 @@
  * is going to be removed as well.
  */
 int
-lfs_reserve(struct lfs *fs, struct vnode *vp, int fsb)
+lfs_reserveavail(struct lfs *fs, struct vnode *vp, int fsb)
 {
        CLEANERINFO *cip;
        struct buf *bp;
@@ -179,20 +242,56 @@
                printf("lfs_reserve: woke up\n");
 #endif
        fs->lfs_ravail += fsb;
+
        return 0;
 }
 
-/*
- *
- * XXX we don't let meta-data writes run out of space because they can
- * come from the segment writer.  We need to make sure that there is
- * enough space reserved so that there's room to write meta-data
- * blocks.
- *
- * Also, we don't let blocks that have come to us from the cleaner
- * run out of space.
- */
-#define CANT_WAIT(BP,F) (IS_IFILE((BP)) || (BP)->b_lblkno < 0 || ((F) & BW_CLEAN))
+#ifdef DIAGNOSTIC
+int lfs_rescount;
+int lfs_rescountdirop;
+#endif
+
+int
+lfs_reserve(struct lfs *fs, struct vnode *vp, int fsb)
+{
+       int error;
+       int cantwait;
+
+       cantwait = (VTOI(vp)->i_flag & IN_ADIROP);
+#ifdef DIAGNOSTIC
+       if (cantwait) {
+               if (fsb > 0)
+                       lfs_rescountdirop++;
+               else if (fsb < 0)
+                       lfs_rescountdirop--;
+               if (lfs_rescountdirop < 0)
+                       panic("lfs_rescountdirop");
+       }
+       else {
+               if (fsb > 0)
+                       lfs_rescount++;
+               else if (fsb < 0)
+                       lfs_rescount--;
+               if (lfs_rescount < 0)
+                       panic("lfs_rescount");
+       }
+#endif
+       if (cantwait)
+               return 0;
+
+       error = lfs_reserveavail(fs, vp, fsb);
+       if (error)
+               return error;
+
+       /*
+        * XXX just a guess. should be more precise.
+        */
+       error = lfs_reservebuf(fs, fragstoblks(fs, fsb), fsbtob(fs, fsb));
+       if (error)
+               lfs_reserveavail(fs, vp, -fsb);
+
+       return error;
+}
 
 int
 lfs_bwrite(void *v)
@@ -274,7 +373,7 @@
 {
        struct lfs *fs;
        struct inode *ip;
-       int fsb, error, s;
+       int fsb, s;
 
        KASSERT(bp->b_flags & B_BUSY);
        KASSERT(flags & BW_CLEAN || !(bp->b_flags & B_CALL));
@@ -310,12 +409,6 @@
        if (!(bp->b_flags & B_LOCKED)) {
                fs = VFSTOUFS(bp->b_vp->v_mount)->um_lfs;
                fsb = fragstofsb(fs, numfrags(fs, bp->b_bcount));
-               if (!CANT_WAIT(bp, flags)) {
-                       if ((error = lfs_availwait(fs, fsb)) != 0) {
-                               brelse(bp);
-                               return error;
-                       }
-               }
                
                ip = VTOI(bp->b_vp);
                if (flags & BW_CLEAN) {
diff -r 6423c1550e83 -r 933593a61530 sys/ufs/lfs/lfs_vnops.c
--- a/sys/ufs/lfs/lfs_vnops.c   Thu Dec 26 13:20:44 2002 +0000
+++ b/sys/ufs/lfs/lfs_vnops.c   Thu Dec 26 13:37:18 2002 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: lfs_vnops.c,v 1.69 2002/11/24 08:23:41 yamt Exp $      */
+/*     $NetBSD: lfs_vnops.c,v 1.70 2002/12/26 13:37:19 yamt Exp $      */
 
 /*-
  * Copyright (c) 1999, 2000 The NetBSD Foundation, Inc.
@@ -71,7 +71,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: lfs_vnops.c,v 1.69 2002/11/24 08:23:41 yamt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: lfs_vnops.c,v 1.70 2002/12/26 13:37:19 yamt Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -361,6 +361,8 @@
 static int lfs_set_dirop(struct vnode *);
 extern int lfs_dirvcount;
 
+#define        NRESERVE(fs)    (btofsb(fs, (NIADDR + 3 + (2 * NIADDR + 3)) << fs->lfs_bshift))
+
 static int
 lfs_set_dirop(struct vnode *vp)
 {
@@ -372,8 +374,9 @@
         * We might need one directory block plus supporting indirect blocks,
         * plus an inode block and ifile page for the new vnode.
         */
-       if ((error = lfs_reserve(fs, vp, btofsb(fs, (NIADDR + 3) << fs->lfs_bshift))) != 0)
+       if ((error = lfs_reserve(fs, vp, NRESERVE(fs))) != 0)
                return (error);
+
        if (fs->lfs_dirops == 0)
                lfs_check(vp, LFS_UNUSED_LBN, 0);
        while (fs->lfs_writer || lfs_dirvcount > LFS_MAXDIROP) {
@@ -394,8 +397,7 @@
 #endif
                        if ((error = tsleep(&lfs_dirvcount, PCATCH|PUSER,
                                           "lfs_maxdirop", 0)) != 0) {
-                               lfs_reserve(fs, vp, -btofsb(fs, (NIADDR + 3) << fs->lfs_bshift));
-                               return error;
+                               goto unreserve;
                        }
                }                                                       
        }                                                               
@@ -406,6 +408,10 @@
        lfs_vref(vp);
 
        return 0;
+
+unreserve:
+       lfs_reserve(fs, vp, -NRESERVE(fs));
+       return error;
 }
 
 #define        SET_ENDOP(fs,vp,str) {                                          \
@@ -418,7 +424,7 @@
                wakeup(&(fs)->lfs_writer);                              \
                lfs_check((vp),LFS_UNUSED_LBN,0);                       \
        }                                                               \
-       lfs_reserve((fs), vp, -btofsb((fs), (NIADDR + 3) << (fs)->lfs_bshift)); /* XXX */       \
+       lfs_reserve((fs), vp, -NRESERVE(fs)); /* XXX */                 \
        lfs_vunref(vp);                                                 \
 }
 
diff -r 6423c1550e83 -r 933593a61530 sys/ufs/ufs/ufs_readwrite.c
--- a/sys/ufs/ufs/ufs_readwrite.c       Thu Dec 26 13:20:44 2002 +0000
+++ b/sys/ufs/ufs/ufs_readwrite.c       Thu Dec 26 13:37:18 2002 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: ufs_readwrite.c,v 1.44 2002/10/23 09:15:08 jdolecek Exp $      */
+/*     $NetBSD: ufs_readwrite.c,v 1.45 2002/12/26 13:37:21 yamt Exp $  */
 
 /*-
  * Copyright (c) 1993
@@ -36,7 +36,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(1, "$NetBSD: ufs_readwrite.c,v 1.44 2002/10/23 09:15:08 jdolecek Exp $");
+__KERNEL_RCSID(1, "$NetBSD: ufs_readwrite.c,v 1.45 2002/12/26 13:37:21 yamt Exp $");
 
 #ifdef LFS_READWRITE
 #define        BLKSIZE(a, b, c)        blksize(a, b, c)
@@ -211,6 +211,9 @@
        vsize_t bytelen;
        boolean_t async;
        boolean_t usepc = FALSE;
+#ifdef LFS_READWRITE
+       boolean_t need_unreserve = FALSE;
+#endif
 
        cred = ap->a_cred;
        ioflag = ap->a_ioflag;
@@ -415,6 +418,13 @@
                else
                        flags &= ~B_CLRBUF;
 
+#ifdef LFS_READWRITE
+               error = lfs_reserve(fs, vp,
+                   btofsb(fs, (NIADDR + 1) << fs->lfs_bshift));
+               if (error)
+                       break;
+               need_unreserve = TRUE;
+#endif
                error = VOP_BALLOC(vp, uio->uio_offset, xfersize,
                    ap->a_cred, flags, &bp);
 
@@ -442,11 +452,10 @@
                        break;
                }



Home | Main Index | Thread Index | Old Index