From 0956fd050249f260f664b13e5fea8c3cbf45a9a1 Mon Sep 17 00:00:00 2001 From: Ingo Weinhold Date: Mon, 24 Mar 2008 05:15:42 +0000 Subject: [PATCH] Applied change proposed in #1917 after encountering the bug the third time. Releasing the cache's store reference while holding the cache lock could reverse the usual locking order -- the VFS could potentially call the remove_vnode() or put_vnode() FS hook, which in turn could use the file cache, thus resulting in a deadlock. Now we release the store ref before locking the cache. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@24548 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/system/kernel/vm/vm_cache.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/system/kernel/vm/vm_cache.cpp b/src/system/kernel/vm/vm_cache.cpp index 66ba8b5183..f8aeb55187 100644 --- a/src/system/kernel/vm/vm_cache.cpp +++ b/src/system/kernel/vm/vm_cache.cpp @@ -545,14 +545,17 @@ vm_cache_remove_consumer(vm_cache *cache, vm_cache *consumer) TRACE(("remove consumer vm cache %p from cache %p\n", consumer, cache)); ASSERT_LOCKED_MUTEX(&consumer->lock); + // Remove the store ref before locking the cache. Otherwise we'd call into + // the VFS while holding the cache lock, which would reverse the usual + // locking order. + if (cache->store->ops->release_ref) + cache->store->ops->release_ref(cache->store); + // remove the consumer from the cache, but keep its reference until later mutex_lock(&cache->lock); list_remove_item(&cache->consumers, consumer); consumer->source = NULL; - if (cache->store->ops->release_ref) - cache->store->ops->release_ref(cache->store); - if (cache->areas == NULL && cache->source != NULL && !list_is_empty(&cache->consumers) && cache->consumers.link.next == cache->consumers.link.prev) {