summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorMichael Shalayeff <mickey@cvs.openbsd.org>2006-06-28 14:17:08 +0000
committerMichael Shalayeff <mickey@cvs.openbsd.org>2006-06-28 14:17:08 +0000
commitfe06797d105825b636b610f3c40802dce5e4d1b4 (patch)
treec63d5da660a5d0ea863dda548e3bad0b8f0d5323 /sys
parent4ee19b36365f9c5c15df8aef3f6fded0fdf6c9d8 (diff)
from freebsd 1.179:
When the softupdates worklist gets too long, threads that attempt to add more work are forced to process two worklist items first. However, processing an item may generate additional work, causing the unlucky thread to recursively process the worklist. Add a per-thread flag to detect this situation and avoid the recursion. This should fix the stack overflows that could occur while removing large directory trees. pedro@ tedu@ ok
Diffstat (limited to 'sys')
-rw-r--r--sys/sys/proc.h5
-rw-r--r--sys/ufs/ffs/ffs_softdep.c10
2 files changed, 9 insertions, 6 deletions
diff --git a/sys/sys/proc.h b/sys/sys/proc.h
index 212853116c3..507c48ce3e7 100644
--- a/sys/sys/proc.h
+++ b/sys/sys/proc.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: proc.h,v 1.87 2006/06/15 20:08:02 miod Exp $ */
+/* $OpenBSD: proc.h,v 1.88 2006/06/28 14:17:07 mickey Exp $ */
/* $NetBSD: proc.h,v 1.44 1996/04/22 01:23:21 christos Exp $ */
/*-
@@ -289,13 +289,14 @@ struct proc {
#define P_BIGLOCK 0x2000000 /* Process needs kernel "big lock" to run */
#define P_THREAD 0x4000000 /* Only a thread, not a real process */
#define P_IGNEXITRV 0x8000000 /* For thread kills */
+#define P_SOFTDEP 0x10000000 /* Stuck processing softdep worklist */
#define P_BITS \
("\20\01ADVLOCK\02CTTY\03INMEM\04NOCLDSTOP\05PPWAIT\06PROFIL\07SELECT" \
"\010SINTR\011SUGID\012SYSTEM\013TIMEOUT\014TRACED\015WAITED\016WEXIT" \
"\017EXEC\020PWEUPC\022SSTEP\023SUGIDEXEC\024NOCLDWAIT" \
"\025NOZOMBIE\026INEXEC\027SYSTRACE\030CONTINUED\031SWAPIN\032BIGLOCK" \
- "\033THREAD\034IGNEXITRV")
+ "\033THREAD\034IGNEXITRV\035SOFTDEP")
/* Macro to compute the exit signal to be delivered. */
#define P_EXITSIG(p) \
diff --git a/sys/ufs/ffs/ffs_softdep.c b/sys/ufs/ffs/ffs_softdep.c
index ef56c480cb7..66108fa5935 100644
--- a/sys/ufs/ffs/ffs_softdep.c
+++ b/sys/ufs/ffs/ffs_softdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ffs_softdep.c,v 1.70 2006/06/21 10:01:10 mickey Exp $ */
+/* $OpenBSD: ffs_softdep.c,v 1.71 2006/06/28 14:17:07 mickey Exp $ */
/*
* Copyright 1998, 2000 Marshall Kirk McKusick. All Rights Reserved.
@@ -5233,20 +5233,23 @@ request_cleanup(resource, islocked)
/*
* We never hold up the filesystem syncer process.
*/
- if (p == filesys_syncer)
+ if (p == filesys_syncer || (p->p_flag & P_SOFTDEP))
return (0);
/*
* First check to see if the work list has gotten backlogged.
* If it has, co-opt this process to help clean up two entries.
* Because this process may hold inodes locked, we cannot
* handle any remove requests that might block on a locked
- * inode as that could lead to deadlock.
+ * inode as that could lead to deadlock. We set P_SOFTDEP
+ * to avoid recursively processing the worklist.
*/
if (num_on_worklist > max_softdeps / 10) {
+ p->p_flag |= P_SOFTDEP;
if (islocked)
FREE_LOCK(&lk);
process_worklist_item(NULL, LK_NOWAIT);
process_worklist_item(NULL, LK_NOWAIT);
+ p->p_flag &= ~P_SOFTDEP;
stat_worklist_push += 2;
if (islocked)
ACQUIRE_LOCK(&lk);
@@ -5453,7 +5456,6 @@ clear_inodedeps(p)
vn_finished_write(mp);
#endif
ACQUIRE_LOCK(&lk);
- drain_output(vp, 1);
}
FREE_LOCK(&lk);
}