From aa0150ba7da7399b3e4017978cece102dd3eedbc Mon Sep 17 00:00:00 2001 From: Matthew Dillon Date: Fri, 8 Sep 2017 08:44:13 -0700 Subject: [PATCH] kernel - vfsync() use synchronous bwrite() in low-memory situations * For now, make vfsync() use a synchronous bwrite() in low-memory situations and do not call vm_wait_nominal(). This could wind up being a chicken-or-egg issue unfortunately. * Addresses issues where the pageout daemon gets indirectly deadlocked when other unrelated kernel threads (aka H2 support threads) are flushing buffers. --- sys/kern/vfs_subr.c | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c index 47148c5155..f8369de5f4 100644 --- a/sys/kern/vfs_subr.c +++ b/sys/kern/vfs_subr.c @@ -83,6 +83,7 @@ #include #include #include +#include #include @@ -869,21 +870,32 @@ vfsync_bp(struct buf *bp, void *data) if (info->synchronous) { /* - * Synchronous flushing. An error may be returned. + * Synchronous flush. An error may be returned and will + * stop the scan. */ bremfree(bp); error = bwrite(bp); - } else { + } else { /* - * Asynchronous flushing. A negative return value simply - * stops the scan and is not considered an error. We use - * this to support limited MNT_LAZY flushes. + * Asynchronous flush. We use the error return to support + * MNT_LAZY flushes. + * + * In low-memory situations we revert to synchronous + * operation. This should theoretically prevent the I/O + * path from exhausting memory in a non-recoverable way. */ vp->v_lazyw = bp->b_loffset; bremfree(bp); - info->lazycount += cluster_awrite(bp); - waitrunningbufspace(); - vm_wait_nominal(); + if (vm_page_count_min(0)) { + /* low memory */ + info->lazycount += bp->b_bufsize; + bwrite(bp); + } else { + /* normal */ + info->lazycount += cluster_awrite(bp); + waitrunningbufspace(); + /*vm_wait_nominal();*/ + } if (info->lazylimit && info->lazycount >= info->lazylimit) error = 1; else -- 2.11.4.GIT