From 9b0788bdc85ff07aa2b610e0ff1a7a0bb4049819 Mon Sep 17 00:00:00 2001 From: Augustin Cavalier Date: Mon, 30 Jun 2025 15:06:45 -0400 Subject: [PATCH] kernel/file_cache: Invoke VMCache::ReleaseStoreRef without a lock held. Otherwise we might get lock-order inversion in the VFS (see comment in VMCache::RemoveArea) and deadlock the system, which indeed I observed while testing some things today. --- src/system/kernel/cache/file_cache.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/system/kernel/cache/file_cache.cpp b/src/system/kernel/cache/file_cache.cpp index 4ddd0497b9..907f532c07 100644 --- a/src/system/kernel/cache/file_cache.cpp +++ b/src/system/kernel/cache/file_cache.cpp @@ -138,7 +138,7 @@ PrecacheIO::~PrecacheIO() delete[] fPages; delete[] fVecs; fCache->ReleaseStoreRef(); - fCache->ReleaseRefLocked(); + fCache->ReleaseRef(); } @@ -191,7 +191,7 @@ void PrecacheIO::IOFinished(status_t status, bool partialTransfer, generic_size_t bytesTransferred) { - AutoLocker locker(fCache); + fCache->Lock(); // Make successfully loaded pages accessible again (partially // transferred pages are considered failed) @@ -227,6 +227,7 @@ PrecacheIO::IOFinished(status_t status, bool partialTransfer, vm_page_free(fCache, fPages[i]); } + fCache->Unlock(); delete this; } @@ -1064,7 +1065,9 @@ cache_prefetch_vnode(struct vnode* vnode, off_t offset, size_t size) PrecacheIO* io = new(std::nothrow) PrecacheIO(ref, lastOffset, bytesToRead); if (io == NULL || io->Prepare(&reservation) != B_OK) { + cache->Unlock(); delete io; + cache->Lock(); break; }