From 45ae0aa1aadb1067c55e7402f2beec4d3ef8dc18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Tue, 23 Oct 2007 16:05:38 +0000 Subject: [PATCH] It's not a good idea to write back large files while keeping the vnode busy. The low memory handler now has two passes which should help there; however, it might also accidently remove recently used vnodes, too. We could mark the clean ones in some way if that turns out to be a problem. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@22678 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/system/kernel/fs/vfs.cpp | 40 +++++++++++++++++++++++++++++++++--- 1 file changed, 37 insertions(+), 3 deletions(-) diff --git a/src/system/kernel/fs/vfs.cpp b/src/system/kernel/fs/vfs.cpp index 5d19405ebd..e215d06bdf 100644 --- a/src/system/kernel/fs/vfs.cpp +++ b/src/system/kernel/fs/vfs.cpp @@ -921,7 +921,7 @@ vnode_low_memory_handler(void */*data*/, int32 level) { TRACE(("vnode_low_memory_handler(level = %ld)\n", level)); - int32 count = 1; + uint32 count = 1; switch (level) { case B_NO_LOW_MEMORY: return; @@ -936,10 +936,44 @@ vnode_low_memory_handler(void */*data*/, int32 level) break; } - for (int32 i = 0; i < count; i++) { + if (count > sUnusedVnodes) + count = sUnusedVnodes; + + // first, write back the modified pages of some unused vnodes + + uint32 freeCount = count; + + for (uint32 i = 0; i < count; i++) { + mutex_lock(&sVnodeMutex); + struct vnode *vnode = (struct vnode *)list_remove_head_item( + &sUnusedVnodeList); + if (vnode == NULL) { + mutex_unlock(&sVnodeMutex); + break; + } + + inc_vnode_ref_count(vnode); + sUnusedVnodes--; + + mutex_unlock(&sVnodeMutex); + + if (vnode->cache != NULL) + vm_cache_write_modified(vnode->cache, false); + + dec_vnode_ref_count(vnode, false); + } + + // and then free them + + for (uint32 i = 0; i < freeCount; i++) { mutex_lock(&sVnodeMutex); - struct vnode *vnode = (struct vnode *)list_remove_head_item(&sUnusedVnodeList); + // We're removing vnodes from the tail of the list - hoping it's + // one of those we have just written back; otherwise we'll write + // back the vnode with the busy flag turned on, and that might + // take some time. + struct vnode *vnode = (struct vnode *)list_remove_tail_item( + &sUnusedVnodeList); if (vnode == NULL) { mutex_unlock(&sVnodeMutex); break;