aboutsummaryrefslogtreecommitdiff
path: root/sys/gnu/fs
diff options
context:
space:
mode:
authorKonstantin Belousov <kib@FreeBSD.org>2009-03-16 15:39:46 +0000
committerKonstantin Belousov <kib@FreeBSD.org>2009-03-16 15:39:46 +0000
commitc1d8b5e82c32e14be2d82bde39e4c601563eb2a1 (patch)
tree8fce6f1bbebd9a85755ca938fe7cc8371fe71a22 /sys/gnu/fs
parentef39bc9f180616b0bd5ce1680513bcb87afe70a2 (diff)
downloadsrc-c1d8b5e82c32e14be2d82bde39e4c601563eb2a1.tar.gz
src-c1d8b5e82c32e14be2d82bde39e4c601563eb2a1.zip
Fix two issues with bufdaemon, often causing the processes to hang in
the "nbufkv" sleep. First, ffs background cg group block write requests a new buffer for the shadow copy. When ffs_bufwrite() is called from the bufdaemon due to buffers shortage, requesting the buffer deadlock bufdaemon. Introduce a new flag for getnewbuf(), GB_NOWAIT_BD, to request getblk to not block while allocating the buffer, and return failure instead. Add a flag argument to the geteblk to allow to pass the flags to getblk(). Do not repeat the getnewbuf() call from geteblk if buffer allocation failed and either GB_NOWAIT_BD is specified, or geteblk() is called from bufdaemon (or its helper, see below). In ffs_bufwrite(), fall back to synchronous cg block write if shadow block allocation failed. Since r107847, buffer write assumes that vnode owning the buffer is locked. The second problem is that buffer cache may accumulate many buffers belonging to limited number of vnodes. With such workload, quite often threads that own the mentioned vnodes locks are trying to read another block from the vnodes, and, due to buffer cache exhaustion, are asking bufdaemon for help. Bufdaemon is unable to make any substantial progress because the vnodes are locked. Allow the threads owning vnode locks to help the bufdaemon by doing the flush pass over the buffer cache before getnewbuf() is going to uninterruptible sleep. Move the flushing code from buf_daemon() to new helper function buf_do_flush(), that is called from getnewbuf(). The number of buffers flushed by single call to buf_do_flush() from getnewbuf() is limited by new sysctl vfs.flushbufqtarget. Prevent recursive calls to buf_do_flush() by marking the bufdaemon and threads that temporarily help bufdaemon by TDP_BUFNEED flag. In collaboration with: pho Reviewed by: tegge (previous version) Tested by: glebius, yandex ... MFC after: 3 weeks
Notes
Notes: svn path=/head/; revision=189878
Diffstat (limited to 'sys/gnu/fs')
-rw-r--r--sys/gnu/fs/xfs/FreeBSD/xfs_buf.c4
1 files changed, 2 insertions, 2 deletions
diff --git a/sys/gnu/fs/xfs/FreeBSD/xfs_buf.c b/sys/gnu/fs/xfs/FreeBSD/xfs_buf.c
index 9759d5aacc12..ff06865e1ac0 100644
--- a/sys/gnu/fs/xfs/FreeBSD/xfs_buf.c
+++ b/sys/gnu/fs/xfs/FreeBSD/xfs_buf.c
@@ -81,7 +81,7 @@ xfs_buf_get_empty(size_t size, xfs_buftarg_t *target)
{
struct buf *bp;
- bp = geteblk(0);
+ bp = geteblk(0, 0);
if (bp != NULL) {
bp->b_bufsize = size;
bp->b_bcount = size;
@@ -100,7 +100,7 @@ xfs_buf_get_noaddr(size_t len, xfs_buftarg_t *target)
if (len >= MAXPHYS)
return (NULL);
- bp = geteblk(len);
+ bp = geteblk(len, 0);
if (bp != NULL) {
BUF_ASSERT_HELD(bp);