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