Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/ufs Prevent dirops from getting around lfs_check and wed...
details: https://anonhg.NetBSD.org/src/rev/f2dc1a284345
branches: trunk
changeset: 486626:f2dc1a284345
user: perseant <perseant%NetBSD.org@localhost>
date: Sat May 27 00:19:52 2000 +0000
description:
Prevent dirops from getting around lfs_check and wedging the buffer cache.
All the dirop vnops now mark the inodes with a new flag, IN_ADIROP, which
is removed as soon as the dirop is done (as opposed to VDIROP which stays
until the file is written). To address one issue raised in PR#9357.
diffstat:
sys/ufs/lfs/lfs.h | 3 +-
sys/ufs/lfs/lfs_alloc.c | 6 +-
sys/ufs/lfs/lfs_bio.c | 39 ++++++++++----
sys/ufs/lfs/lfs_segment.c | 10 +---
sys/ufs/lfs/lfs_vfsops.c | 3 +-
sys/ufs/lfs/lfs_vnops.c | 115 ++++++++++++++++++++++++++++---------------
sys/ufs/ufs/inode.h | 3 +-
sys/ufs/ufs/ufs_readwrite.c | 9 +++-
8 files changed, 122 insertions(+), 66 deletions(-)
diffs (truncated from 474 to 300 lines):
diff -r f8e8643874ed -r f2dc1a284345 sys/ufs/lfs/lfs.h
--- a/sys/ufs/lfs/lfs.h Sat May 27 00:11:12 2000 +0000
+++ b/sys/ufs/lfs/lfs.h Sat May 27 00:19:52 2000 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: lfs.h,v 1.22 2000/05/13 23:43:14 perseant Exp $ */
+/* $NetBSD: lfs.h,v 1.23 2000/05/27 00:19:52 perseant Exp $ */
/*-
* Copyright (c) 1999 The NetBSD Foundation, Inc.
@@ -300,6 +300,7 @@
struct vnode *lfs_unlockvp; /* being inactivated in lfs_segunlock */
u_int32_t lfs_diropwait; /* # procs waiting on dirop flush */
struct lock lfs_freelock;
+ int lfs_nadirop; /* number of active dirop nodes */
};
/*
diff -r f8e8643874ed -r f2dc1a284345 sys/ufs/lfs/lfs_alloc.c
--- a/sys/ufs/lfs/lfs_alloc.c Sat May 27 00:11:12 2000 +0000
+++ b/sys/ufs/lfs/lfs_alloc.c Sat May 27 00:19:52 2000 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: lfs_alloc.c,v 1.31 2000/01/19 00:03:04 perseant Exp $ */
+/* $NetBSD: lfs_alloc.c,v 1.32 2000/05/27 00:19:52 perseant Exp $ */
/*-
* Copyright (c) 1999 The NetBSD Foundation, Inc.
@@ -230,6 +230,10 @@
vp->v_flag |= VDIROP;
VREF(ip->i_devvp);
+ if(!(ip->i_flag & IN_ADIROP))
+ ++fs->lfs_nadirop;
+ ip->i_flag |= IN_ADIROP;
+
/* Set superblock modified bit and increment file count. */
fs->lfs_fmod = 1;
++fs->lfs_nfiles;
diff -r f8e8643874ed -r f2dc1a284345 sys/ufs/lfs/lfs_bio.c
--- a/sys/ufs/lfs/lfs_bio.c Sat May 27 00:11:12 2000 +0000
+++ b/sys/ufs/lfs/lfs_bio.c Sat May 27 00:19:52 2000 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: lfs_bio.c,v 1.19 2000/05/19 04:34:44 thorpej Exp $ */
+/* $NetBSD: lfs_bio.c,v 1.20 2000/05/27 00:19:52 perseant Exp $ */
/*-
* Copyright (c) 1999 The NetBSD Foundation, Inc.
@@ -358,24 +358,39 @@
{
int error;
struct lfs *fs;
+ struct inode *ip;
extern int lfs_dirvcount;
error = 0;
+ ip = VTOI(vp);
/* If out of buffers, wait on writer */
/* XXX KS - if it's the Ifile, we're probably the cleaner! */
- if (VTOI(vp)->i_number == LFS_IFILE_INUM)
+ if (ip->i_number == LFS_IFILE_INUM)
+ return 0;
+ /* If we're being called from inside a dirop, don't sleep */
+ if (ip->i_flag & IN_ADIROP)
return 0;
- /* If dirops are active, can't flush. Wait for SET_ENDOP */
- fs = VTOI(vp)->i_lfs;
- if (fs->lfs_dirops)
- return 0;
+ fs = ip->i_lfs;
- if (locked_queue_count > LFS_MAX_BUFS
- || locked_queue_bytes > LFS_MAX_BYTES
- || lfs_dirvcount > LFS_MAXDIROP
- || fs->lfs_diropwait > 0)
+ /*
+ * If we would flush below, but dirops are active, sleep.
+ * Note that a dirop cannot ever reach this code!
+ */
+ while (fs->lfs_dirops > 0 &&
+ (locked_queue_count > LFS_MAX_BUFS ||
+ locked_queue_bytes > LFS_MAX_BYTES ||
+ lfs_dirvcount > LFS_MAXDIROP || fs->lfs_diropwait > 0))
+ {
+ ++fs->lfs_diropwait;
+ tsleep(&fs->lfs_writer, PRIBIO+1, "bufdirop", 0);
+ --fs->lfs_diropwait;
+ }
+
+ if (locked_queue_count > LFS_MAX_BUFS ||
+ locked_queue_bytes > LFS_MAX_BYTES ||
+ lfs_dirvcount > LFS_MAXDIROP || fs->lfs_diropwait > 0)
{
++fs->lfs_writer;
lfs_flush(fs, flags);
@@ -399,8 +414,8 @@
* inodes were locked. Try flushing again to keep us from
* blocking indefinitely.
*/
- if (locked_queue_count > LFS_MAX_BUFS
- || locked_queue_bytes > LFS_MAX_BYTES)
+ if (locked_queue_count > LFS_MAX_BUFS ||
+ locked_queue_bytes > LFS_MAX_BYTES)
{
++fs->lfs_writer;
lfs_flush(fs, flags);
diff -r f8e8643874ed -r f2dc1a284345 sys/ufs/lfs/lfs_segment.c
--- a/sys/ufs/lfs/lfs_segment.c Sat May 27 00:11:12 2000 +0000
+++ b/sys/ufs/lfs/lfs_segment.c Sat May 27 00:19:52 2000 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: lfs_segment.c,v 1.45 2000/05/19 04:34:44 thorpej Exp $ */
+/* $NetBSD: lfs_segment.c,v 1.46 2000/05/27 00:19:53 perseant Exp $ */
/*-
* Copyright (c) 1999 The NetBSD Foundation, Inc.
@@ -419,7 +419,7 @@
lfs_vunref(vp);
continue;
}
- } else {
+ } else if (vp != fs->lfs_ivnode) {
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
needs_unlock = 1;
}
@@ -1025,8 +1025,6 @@
if(vp != fs->lfs_ivnode && (ooff == 0 || ooff == UNASSIGNED)) {
#ifdef DEBUG_LFS
printf("lfs_updatemeta[1]: warning: writing ino %d lbn %d at 0x%x, was 0x%x\n", ip->i_number, lbn, off, ooff);
-#else
- ;
#endif
} else
ip->i_ffs_db[lbn] = off;
@@ -1036,8 +1034,6 @@
if(vp != fs->lfs_ivnode && (ooff == 0 || ooff == UNASSIGNED)) {
#ifdef DEBUG_LFS
printf("lfs_updatemeta[2]: warning: writing ino %d lbn %d at 0x%x, was 0x%x\n", ip->i_number, lbn, off, ooff);
-#else
- ;
#endif
} else
ip->i_ffs_ib[a[0].in_off] = off;
@@ -1082,8 +1078,6 @@
if(vp != fs->lfs_ivnode && (ooff == 0 || ooff == UNASSIGNED)) {
#ifdef DEBUG_LFS
printf("lfs_updatemeta[3]: warning: writing ino %d lbn %d at 0x%x, was 0x%x\n", ip->i_number, lbn, off, ooff);
-#else
- ;
#endif
brelse(bp);
} else {
diff -r f8e8643874ed -r f2dc1a284345 sys/ufs/lfs/lfs_vfsops.c
--- a/sys/ufs/lfs/lfs_vfsops.c Sat May 27 00:11:12 2000 +0000
+++ b/sys/ufs/lfs/lfs_vfsops.c Sat May 27 00:19:52 2000 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: lfs_vfsops.c,v 1.51 2000/05/19 04:34:45 thorpej Exp $ */
+/* $NetBSD: lfs_vfsops.c,v 1.52 2000/05/27 00:19:53 perseant Exp $ */
/*-
* Copyright (c) 1999 The NetBSD Foundation, Inc.
@@ -434,6 +434,7 @@
fs->lfs_doifile = 0;
fs->lfs_writer = 0;
fs->lfs_dirops = 0;
+ fs->lfs_nadirop = 0;
fs->lfs_seglock = 0;
lockinit(&fs->lfs_freelock, PINOD, "lfs_freelock", 0, 0);
diff -r f8e8643874ed -r f2dc1a284345 sys/ufs/lfs/lfs_vnops.c
--- a/sys/ufs/lfs/lfs_vnops.c Sat May 27 00:11:12 2000 +0000
+++ b/sys/ufs/lfs/lfs_vnops.c Sat May 27 00:19:52 2000 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: lfs_vnops.c,v 1.36 2000/05/13 23:43:15 perseant Exp $ */
+/* $NetBSD: lfs_vnops.c,v 1.37 2000/05/27 00:19:54 perseant Exp $ */
/*-
* Copyright (c) 1999 The NetBSD Foundation, Inc.
@@ -277,7 +277,7 @@
} */ *ap = v;
return (VOP_UPDATE(ap->a_vp, NULL, NULL,
- (ap->a_flags & FSYNC_WAIT) != 0 ? UPDATE_WAIT : 0)); /* XXX */
+ (ap->a_flags & FSYNC_WAIT) != 0 ? UPDATE_WAIT : 0));
}
/*
@@ -315,7 +315,7 @@
#ifdef DEBUG_LFS
printf("lfs_set_dirop: sleeping with dirops=%d, dirvcount=%d\n",fs->lfs_dirops,lfs_dirvcount);
#endif
- if((error=tsleep(&lfs_dirvcount, PCATCH|PUSER, "lfs_maxdirop", 0))!=0)
+ if((error = tsleep(&lfs_dirvcount, PCATCH|PUSER, "lfs_maxdirop", 0)) !=0)
return error;
}
}
@@ -328,17 +328,30 @@
#define SET_ENDOP(fs,vp,str) { \
--(fs)->lfs_dirops; \
if (!(fs)->lfs_dirops) { \
+ if ((fs)->lfs_nadirop) \
+ panic("no dirops but nadirop=%d\n", (fs)->lfs_nadirop);\
wakeup(&(fs)->lfs_writer); \
lfs_check((vp),LFS_UNUSED_LBN,0); \
} \
}
#define MARK_VNODE(dvp) do { \
- if(!((dvp)->v_flag & VDIROP)) { \
+ if (!((dvp)->v_flag & VDIROP)) { \
lfs_vref(dvp); \
++lfs_dirvcount; \
} \
(dvp)->v_flag |= VDIROP; \
+ if (!(VTOI(dvp)->i_flag & IN_ADIROP)) { \
+ ++VTOI(dvp)->i_lfs->lfs_nadirop; \
+ } \
+ VTOI(dvp)->i_flag |= IN_ADIROP; \
+} while(0)
+
+#define UNMARK_VNODE(vp) do { \
+ if (VTOI(vp)->i_flag & IN_ADIROP) { \
+ --VTOI(vp)->i_lfs->lfs_nadirop; \
+ } \
+ VTOI(vp)->i_flag &= ~IN_ADIROP; \
} while(0)
int
@@ -352,16 +365,19 @@
struct vattr *a_vap;
char *a_target;
} */ *ap = v;
- int ret;
+ int error;
- if((ret=SET_DIROP(VTOI(ap->a_dvp)->i_lfs))!=0) {
+ if ((error = SET_DIROP(VTOI(ap->a_dvp)->i_lfs)) != 0) {
vput(ap->a_dvp);
- return ret;
+ return error;
}
MARK_VNODE(ap->a_dvp);
- ret = ufs_symlink(ap);
- SET_ENDOP(VTOI(ap->a_dvp)->i_lfs,ap->a_dvp,"symilnk");
- return (ret);
+ error = ufs_symlink(ap);
+ UNMARK_VNODE(ap->a_dvp);
+ if (error == 0)
+ UNMARK_VNODE(*(ap->a_vpp));
+ SET_ENDOP(VTOI(ap->a_dvp)->i_lfs,ap->a_dvp,"symlink");
+ return (error);
}
int
@@ -379,13 +395,16 @@
struct inode *ip;
int error;
- if((error=SET_DIROP(VTOI(ap->a_dvp)->i_lfs))!=0) {
+ if ((error = SET_DIROP(VTOI(ap->a_dvp)->i_lfs)) != 0) {
vput(ap->a_dvp);
return error;
}
MARK_VNODE(ap->a_dvp);
error = ufs_makeinode(MAKEIMODE(vap->va_type, vap->va_mode),
ap->a_dvp, vpp, ap->a_cnp);
+ UNMARK_VNODE(ap->a_dvp);
+ if (error == 0)
+ UNMARK_VNODE(*(ap->a_vpp));
/* Either way we're done with the dirop at this point */
SET_ENDOP(VTOI(ap->a_dvp)->i_lfs,ap->a_dvp,"mknod");
@@ -441,16 +460,19 @@
struct componentname *a_cnp;
struct vattr *a_vap;
} */ *ap = v;
- int ret;
+ int error;
- if((ret=SET_DIROP(VTOI(ap->a_dvp)->i_lfs))!=0) {
+ if((error = SET_DIROP(VTOI(ap->a_dvp)->i_lfs)) != 0) {
vput(ap->a_dvp);
- return ret;
+ return error;
}
MARK_VNODE(ap->a_dvp);
- ret = ufs_create(ap);
+ error = ufs_create(ap);
+ UNMARK_VNODE(ap->a_dvp);
+ if (error == 0)
+ UNMARK_VNODE(*(ap->a_vpp));
SET_ENDOP(VTOI(ap->a_dvp)->i_lfs,ap->a_dvp,"create");
- return (ret);
+ return (error);
}
int
@@ -462,15 +484,16 @@
struct componentname *a_cnp;
int a_flags;
} */ *ap = v;
Home |
Main Index |
Thread Index |
Old Index