summaryrefslogtreecommitdiff
path: root/sys/ufs
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/ufs
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/ufs')
-rw-r--r--sys/ufs/ffs/ffs_softdep.c10
1 files changed, 6 insertions, 4 deletions
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);
}