Source-Changes-HG archive

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

[src/trunk]: src Pass t_renamerace and t_rmdirrace tests.



details:   https://anonhg.NetBSD.org/src/rev/36b88e91e7c0
branches:  trunk
changeset: 777356:36b88e91e7c0
user:      perseant <perseant%NetBSD.org@localhost>
date:      Thu Feb 16 02:47:54 2012 +0000

description:
Pass t_renamerace and t_rmdirrace tests.

Adapt dholland@'s fix to ufs_rename to fix PR kern/43582.  Address several
other MP locking issues discovered during the course of investigating the
same problem.

Removed extraneous vn_lock() calls on the Ifile, since the Ifile writes
are controlled by the segment lock.

Fix PR kern/45982 by deemphasizing the estimate of how much metadata
will fill the empty space on disk when the disk is nearly empty
(t_renamerace crates a lot of inode blocks on a tiny empty disk).

diffstat:

 sbin/newfs_lfs/make_lfs.c   |    6 +-
 sys/ufs/lfs/lfs.h           |   22 +-
 sys/ufs/lfs/lfs_alloc.c     |    9 +-
 sys/ufs/lfs/lfs_bio.c       |   63 +--
 sys/ufs/lfs/lfs_segment.c   |   10 +-
 sys/ufs/lfs/lfs_vfsops.c    |    6 +-
 sys/ufs/lfs/lfs_vnops.c     |  847 +++++++++++++++++++++++++++++++++++++++++--
 tests/fs/vfs/t_renamerace.c |   16 +-
 tests/fs/vfs/t_rmdirrace.c  |   12 +-
 9 files changed, 856 insertions(+), 135 deletions(-)

diffs (truncated from 1384 to 300 lines):

diff -r 20427ce603c6 -r 36b88e91e7c0 sbin/newfs_lfs/make_lfs.c
--- a/sbin/newfs_lfs/make_lfs.c Thu Feb 16 02:37:43 2012 +0000
+++ b/sbin/newfs_lfs/make_lfs.c Thu Feb 16 02:47:54 2012 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: make_lfs.c,v 1.18 2012/02/02 03:50:32 perseant Exp $   */
+/*     $NetBSD: make_lfs.c,v 1.19 2012/02/16 02:47:54 perseant Exp $   */
 
 /*-
  * Copyright (c) 2003 The NetBSD Foundation, Inc.
@@ -62,7 +62,7 @@
 #if 0
 static char sccsid[] = "@(#)lfs.c      8.5 (Berkeley) 5/24/95";
 #else
-__RCSID("$NetBSD: make_lfs.c,v 1.18 2012/02/02 03:50:32 perseant Exp $");
+__RCSID("$NetBSD: make_lfs.c,v 1.19 2012/02/16 02:47:54 perseant Exp $");
 #endif
 #endif /* not lint */
 
@@ -496,7 +496,7 @@
        if (fs->lfs_resvseg < MIN_RESV_SEGS)
                fs->lfs_resvseg = MIN_RESV_SEGS;
 
-       if(fs->lfs_nseg < (3 * CM_MAG_NUM * fs->lfs_minfreeseg) / CM_MAG_DEN + 1
+       if(fs->lfs_nseg < (4 * fs->lfs_minfreeseg)
           || fs->lfs_nseg < LFS_MIN_SBINTERVAL + 1)
        {
                if(seg_size == 0 && ssize > (bsize<<1)) {
diff -r 20427ce603c6 -r 36b88e91e7c0 sys/ufs/lfs/lfs.h
--- a/sys/ufs/lfs/lfs.h Thu Feb 16 02:37:43 2012 +0000
+++ b/sys/ufs/lfs/lfs.h Thu Feb 16 02:47:54 2012 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: lfs.h,v 1.135 2012/01/02 22:10:44 perseant Exp $       */
+/*     $NetBSD: lfs.h,v 1.136 2012/02/16 02:47:55 perseant Exp $       */
 
 /*-
  * Copyright (c) 1999, 2000, 2001, 2002, 2003 The NetBSD Foundation, Inc.
@@ -1027,13 +1027,23 @@
 /*
  * Estimate number of clean blocks not available for writing because
  * they will contain metadata or overhead.  This is calculated as
- * (dmeta / # dirty segments) * (# clean segments).
+ *
+ *             E = ((C * M / D) * D + (0) * (T - D)) / T
+ * or more simply
+ *             E = (C * M) / T
+ *
+ * where
+ * C is the clean space,
+ * D is the dirty space,
+ * M is the dirty metadata, and
+ * T = C + D is the total space on disk.
+ *
+ * This approximates the old formula of E = C * M / D when D is close to T,
+ * but avoids falsely reporting "disk full" when the sample size (D) is small.
  */
-#define CM_MAG_NUM 3
-#define CM_MAG_DEN 2
 #define LFS_EST_CMETA(F) (int32_t)((                                   \
-                                   (CM_MAG_NUM * ((F)->lfs_dmeta * (int64_t)(F)->lfs_nclean)) / \
-                                   (CM_MAG_DEN * ((F)->lfs_nseg - (F)->lfs_nclean))))
+       ((F)->lfs_dmeta * (int64_t)(F)->lfs_nclean) /                   \
+       ((F)->lfs_nseg)))
 
 /* Estimate total size of the disk not including metadata */
 #define LFS_EST_NONMETA(F) ((F)->lfs_dsize - (F)->lfs_dmeta - LFS_EST_CMETA(F))
diff -r 20427ce603c6 -r 36b88e91e7c0 sys/ufs/lfs/lfs_alloc.c
--- a/sys/ufs/lfs/lfs_alloc.c   Thu Feb 16 02:37:43 2012 +0000
+++ b/sys/ufs/lfs/lfs_alloc.c   Thu Feb 16 02:47:54 2012 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: lfs_alloc.c,v 1.111 2011/06/12 03:36:01 rmind Exp $    */
+/*     $NetBSD: lfs_alloc.c,v 1.112 2012/02/16 02:47:55 perseant Exp $ */
 
 /*-
  * Copyright (c) 1999, 2000, 2001, 2002, 2003, 2007 The NetBSD Foundation, Inc.
@@ -60,7 +60,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: lfs_alloc.c,v 1.111 2011/06/12 03:36:01 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: lfs_alloc.c,v 1.112 2012/02/16 02:47:55 perseant Exp $");
 
 #if defined(_KERNEL_OPT)
 #include "opt_quota.h"
@@ -207,7 +207,6 @@
        ASSERT_NO_SEGLOCK(fs);
 
        lfs_seglock(fs, SEGM_PROT);
-       vn_lock(fs->lfs_ivnode, LK_EXCLUSIVE);
 
        /* Get the head of the freelist. */
        LFS_GET_HEADFREE(fs, cip, cbp, &new_ino);
@@ -236,7 +235,6 @@
        if (fs->lfs_freehd == LFS_UNUSED_INUM) {
                if ((error = lfs_extend_ifile(fs, cred)) != 0) {
                        LFS_PUT_HEADFREE(fs, cip, cbp, new_ino);
-                       VOP_UNLOCK(fs->lfs_ivnode);
                        lfs_segunlock(fs);
                        return error;
                }
@@ -252,7 +250,6 @@
        mutex_exit(&lfs_lock);
        ++fs->lfs_nfiles;
 
-       VOP_UNLOCK(fs->lfs_ivnode);
        lfs_segunlock(fs);
 
        return lfs_ialloc(fs, pvp, new_ino, new_gen, vpp);
@@ -440,7 +437,6 @@
        mutex_exit(vp->v_interlock);
 
        lfs_seglock(fs, SEGM_PROT);
-       vn_lock(fs->lfs_ivnode, LK_EXCLUSIVE);
 
        lfs_unmark_vnode(vp);
        mutex_enter(&lfs_lock);
@@ -575,7 +571,6 @@
        mutex_exit(&lfs_lock);
        --fs->lfs_nfiles;
 
-       VOP_UNLOCK(fs->lfs_ivnode);
        lfs_segunlock(fs);
 
        return (0);
diff -r 20427ce603c6 -r 36b88e91e7c0 sys/ufs/lfs/lfs_bio.c
--- a/sys/ufs/lfs/lfs_bio.c     Thu Feb 16 02:37:43 2012 +0000
+++ b/sys/ufs/lfs/lfs_bio.c     Thu Feb 16 02:47:54 2012 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: lfs_bio.c,v 1.121 2012/01/02 22:10:44 perseant Exp $   */
+/*     $NetBSD: lfs_bio.c,v 1.122 2012/02/16 02:47:55 perseant Exp $   */
 
 /*-
  * Copyright (c) 1999, 2000, 2001, 2002, 2003, 2008 The NetBSD Foundation, Inc.
@@ -60,7 +60,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: lfs_bio.c,v 1.121 2012/01/02 22:10:44 perseant Exp $");
+__KERNEL_RCSID(0, "$NetBSD: lfs_bio.c,v 1.122 2012/02/16 02:47:55 perseant Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -151,12 +151,15 @@
 lfs_reservebuf(struct lfs *fs, struct vnode *vp,
     struct vnode *vp2, int n, int bytes)
 {
+       int cantwait;
+
        ASSERT_MAYBE_SEGLOCK(fs);
        KASSERT(locked_queue_rcount >= 0);
        KASSERT(locked_queue_rbytes >= 0);
 
+       cantwait = (VTOI(vp)->i_flag & IN_ADIROP) || fs->lfs_unlockvp == vp;
        mutex_enter(&lfs_lock);
-       while (n > 0 && !lfs_fits_buf(fs, n, bytes)) {
+       while (!cantwait && n > 0 && !lfs_fits_buf(fs, n, bytes)) {
                int error;
 
                lfs_flush(fs, 0, 0);
@@ -213,28 +216,15 @@
        CLEANERINFO *cip;
        struct buf *bp;
        int error, slept;
+       int cantwait;
 
        ASSERT_MAYBE_SEGLOCK(fs);
        slept = 0;
        mutex_enter(&lfs_lock);
-       while (fsb > 0 && !lfs_fits(fs, fsb + fs->lfs_ravail + fs->lfs_favail)) {
+       cantwait = (VTOI(vp)->i_flag & IN_ADIROP) || fs->lfs_unlockvp == vp;
+       while (!cantwait && fsb > 0 &&
+              !lfs_fits(fs, fsb + fs->lfs_ravail + fs->lfs_favail)) {
                mutex_exit(&lfs_lock);
-#if 0
-               /*
-                * XXX ideally, we should unlock vnodes here
-                * because we might sleep very long time.
-                */
-               VOP_UNLOCK(vp);
-               if (vp2 != NULL) {
-                       VOP_UNLOCK(vp2);
-               }
-#else
-               /*
-                * XXX since we'll sleep for cleaner with vnode lock holding,
-                * deadlock will occur if cleaner tries to lock the vnode.
-                * (eg. lfs_markv -> lfs_fastvget -> getnewvnode -> vclean)
-                */
-#endif
 
                if (!slept) {
                        DLOG((DLOG_AVAIL, "lfs_reserve: waiting for %ld (bfree = %d,"
@@ -256,10 +246,6 @@
 
                error = mtsleep(&fs->lfs_avail, PCATCH | PUSER, "lfs_reserve",
                                0, &lfs_lock);
-#if 0
-               vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); /* XXX use lockstatus */
-               vn_lock(vp2, LK_EXCLUSIVE | LK_RETRY); /* XXX use lockstatus */
-#endif
                if (error) {
                        mutex_exit(&lfs_lock);
                        return error;
@@ -285,7 +271,6 @@
 lfs_reserve(struct lfs *fs, struct vnode *vp, struct vnode *vp2, int fsb)
 {
        int error;
-       int cantwait;
 
        ASSERT_MAYBE_SEGLOCK(fs);
        if (vp2) {
@@ -300,30 +285,18 @@
 
        KASSERT(fsb < 0 || VOP_ISLOCKED(vp));
        KASSERT(vp2 == NULL || fsb < 0 || VOP_ISLOCKED(vp2));
-       KASSERT(vp2 == NULL || !(VTOI(vp2)->i_flag & IN_ADIROP));
        KASSERT(vp2 == NULL || vp2 != fs->lfs_unlockvp);
 
-       cantwait = (VTOI(vp)->i_flag & IN_ADIROP) || fs->lfs_unlockvp == vp;
 #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");
-       }
+       mutex_enter(&lfs_lock);
+       if (fsb > 0)
+               lfs_rescount++;
+       else if (fsb < 0)
+               lfs_rescount--;
+       if (lfs_rescount < 0)
+               panic("lfs_rescount");
+       mutex_exit(&lfs_lock);
 #endif
-       if (cantwait)
-               return 0;
 
        /*
         * XXX
diff -r 20427ce603c6 -r 36b88e91e7c0 sys/ufs/lfs/lfs_segment.c
--- a/sys/ufs/lfs/lfs_segment.c Thu Feb 16 02:37:43 2012 +0000
+++ b/sys/ufs/lfs/lfs_segment.c Thu Feb 16 02:47:54 2012 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: lfs_segment.c,v 1.223 2012/01/02 22:10:44 perseant Exp $       */
+/*     $NetBSD: lfs_segment.c,v 1.224 2012/02/16 02:47:55 perseant Exp $       */
 
 /*-
  * Copyright (c) 1999, 2000, 2001, 2002, 2003 The NetBSD Foundation, Inc.
@@ -60,7 +60,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: lfs_segment.c,v 1.223 2012/01/02 22:10:44 perseant Exp $");
+__KERNEL_RCSID(0, "$NetBSD: lfs_segment.c,v 1.224 2012/02/16 02:47:55 perseant Exp $");
 
 #ifdef DEBUG
 # define vndebug(vp, str) do {                                         \
@@ -734,7 +734,6 @@
        did_ckp = 0;
        if (do_ckp || fs->lfs_doifile) {
                vp = fs->lfs_ivnode;
-               vn_lock(vp, LK_EXCLUSIVE);
                loopcount = 0;
                do {
 #ifdef DEBUG
@@ -807,7 +806,6 @@
                }
 #endif
                mutex_exit(vp->v_interlock);
-               VOP_UNLOCK(vp);
        } else {
                (void) lfs_writeseg(fs, sp);
        }
@@ -2603,8 +2601,8 @@
                 * XXX KS - Shouldn't we set *both* if both types
                 * of blocks are present (traverse the dirty list?)
                 */
+               mutex_enter(vp->v_interlock);
                mutex_enter(&lfs_lock);
-               mutex_enter(vp->v_interlock);
                if (vp != devvp && vp->v_numoutput == 0 &&
                    (fbp = LIST_FIRST(&vp->v_dirtyblkhd)) != NULL) {
                        ip = VTOI(vp);
@@ -2616,8 +2614,8 @@
                                LFS_SET_UINO(ip, IN_MODIFIED);
                }
                cv_broadcast(&vp->v_cv);
+               mutex_exit(&lfs_lock);
                mutex_exit(vp->v_interlock);
-               mutex_exit(&lfs_lock);



Home | Main Index | Thread Index | Old Index