summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/kern/vfs_bio.c17
1 files changed, 15 insertions, 2 deletions
diff --git a/sys/kern/vfs_bio.c b/sys/kern/vfs_bio.c
index 1dbb1b68fd1f..501febb833a2 100644
--- a/sys/kern/vfs_bio.c
+++ b/sys/kern/vfs_bio.c
@@ -1053,9 +1053,13 @@ trytofreespace:
* Certain layered filesystems can recursively re-enter the vfs_bio
* code, due to delayed writes. This helps keep the system from
* deadlocking.
+ * This hack to avoid premature panic is courtesy of alfred
+ * (alfred@freebsd.org)
*/
if (writerecursion > 0) {
if (writerecursion > 5) {
+ int loop = 0;
+norecurse:
bp = TAILQ_FIRST(&bufqueues[QUEUE_AGE]);
while (bp) {
if ((bp->b_flags & B_DELWRI) == 0)
@@ -1070,8 +1074,17 @@ trytofreespace:
bp = TAILQ_NEXT(bp, b_freelist);
}
}
- if (bp == NULL)
- panic("getnewbuf: cannot get buffer, infinite recursion failure");
+ if (bp == NULL) {
+ needsbuffer |= VFS_BIO_NEED_ANY;
+ if (tsleep(&needsbuffer,
+ (PRIBIO + 4) | slpflag,
+ "nbufhack", slptimeo+1))
+ return (NULL);
+ if (loop++ < 5)
+ goto norecurse;
+ else
+ goto start;
+ }
} else {
bremfree(bp);
bp->b_flags |= B_BUSY | B_AGE | B_ASYNC;