summaryrefslogtreecommitdiffstats
path: root/sys/ufs
diff options
context:
space:
mode:
authordas <das@FreeBSD.org>2005-03-25 17:30:31 +0000
committerdas <das@FreeBSD.org>2005-03-25 17:30:31 +0000
commit3b88b0f403c14a37086d6bc0f64e2727d63455e0 (patch)
treee7de0cbd9c448a0e41a872102dc8e0d123f49608 /sys/ufs
parentea5af1c34abf6a5a5427daad4842337cfc7392b9 (diff)
downloadFreeBSD-src-3b88b0f403c14a37086d6bc0f64e2727d63455e0.zip
FreeBSD-src-3b88b0f403c14a37086d6bc0f64e2727d63455e0.tar.gz
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. Tested by: kris Reviewed by: mckusick
Diffstat (limited to 'sys/ufs')
-rw-r--r--sys/ufs/ffs/ffs_softdep.c7
1 files changed, 5 insertions, 2 deletions
diff --git a/sys/ufs/ffs/ffs_softdep.c b/sys/ufs/ffs/ffs_softdep.c
index 3169475..1d0cd15 100644
--- a/sys/ufs/ffs/ffs_softdep.c
+++ b/sys/ufs/ffs/ffs_softdep.c
@@ -5528,18 +5528,21 @@ request_cleanup(resource)
/*
* We never hold up the filesystem syncer process.
*/
- if (td == filesys_syncer)
+ if (td == filesys_syncer || (td->td_pflags & TDP_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 TDP_SOFTDEP
+ * to avoid recursively processing the worklist.
*/
if (num_on_worklist > max_softdeps / 10) {
+ td->td_pflags |= TDP_SOFTDEP;
process_worklist_item(NULL, LK_NOWAIT);
process_worklist_item(NULL, LK_NOWAIT);
+ td->td_pflags &= ~TDP_SOFTDEP;
stat_worklist_push += 2;
return(1);
}
OpenPOWER on IntegriCloud