summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormickey <mickey@openbsd.org>2006-06-28 14:17:07 +0000
committermickey <mickey@openbsd.org>2006-06-28 14:17:07 +0000
commit0f4e54cee0196abe6da03cd36fcf6ee48027ef43 (patch)
tree47570c1246d1c950632f32368ad05e66aa307873
parentdocument lists, prodded by david@ (diff)
downloadwireguard-openbsd-0f4e54cee0196abe6da03cd36fcf6ee48027ef43.tar.xz
wireguard-openbsd-0f4e54cee0196abe6da03cd36fcf6ee48027ef43.zip
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
-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);
}