diff options
author | Michael Shalayeff <mickey@cvs.openbsd.org> | 2006-06-28 14:17:08 +0000 |
---|---|---|
committer | Michael Shalayeff <mickey@cvs.openbsd.org> | 2006-06-28 14:17:08 +0000 |
commit | fe06797d105825b636b610f3c40802dce5e4d1b4 (patch) | |
tree | c63d5da660a5d0ea863dda548e3bad0b8f0d5323 /sys | |
parent | 4ee19b36365f9c5c15df8aef3f6fded0fdf6c9d8 (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.h | 5 | ||||
-rw-r--r-- | sys/ufs/ffs/ffs_softdep.c | 10 |
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); } |