diff options
author | das <das@FreeBSD.org> | 2005-03-25 17:30:31 +0000 |
---|---|---|
committer | das <das@FreeBSD.org> | 2005-03-25 17:30:31 +0000 |
commit | 3b88b0f403c14a37086d6bc0f64e2727d63455e0 (patch) | |
tree | e7de0cbd9c448a0e41a872102dc8e0d123f49608 | |
parent | ea5af1c34abf6a5a5427daad4842337cfc7392b9 (diff) | |
download | FreeBSD-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
-rw-r--r-- | sys/sys/proc.h | 1 | ||||
-rw-r--r-- | sys/ufs/ffs/ffs_softdep.c | 7 |
2 files changed, 6 insertions, 2 deletions
diff --git a/sys/sys/proc.h b/sys/sys/proc.h index e6875e1..5f95865 100644 --- a/sys/sys/proc.h +++ b/sys/sys/proc.h @@ -375,6 +375,7 @@ struct thread { #define TDP_SCHED3 0x00004000 /* Reserved for scheduler private use */ #define TDP_SCHED4 0x00008000 /* Reserved for scheduler private use */ #define TDP_GEOM 0x00010000 /* Settle GEOM before finishing syscall */ +#define TDP_SOFTDEP 0x00020000 /* Stuck processing softdep worklist */ /* * Reasons that the current thread can not be run yet. 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); } |