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