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.
This commit is contained in:
Augustin Cavalier
2025-06-30 15:06:45 -04:00
parent 7415ce0639
commit 9b0788bdc8
+5 -2
View File
@@ -138,7 +138,7 @@ PrecacheIO::~PrecacheIO()
delete[] fPages; delete[] fPages;
delete[] fVecs; delete[] fVecs;
fCache->ReleaseStoreRef(); fCache->ReleaseStoreRef();
fCache->ReleaseRefLocked(); fCache->ReleaseRef();
} }
@@ -191,7 +191,7 @@ void
PrecacheIO::IOFinished(status_t status, bool partialTransfer, PrecacheIO::IOFinished(status_t status, bool partialTransfer,
generic_size_t bytesTransferred) generic_size_t bytesTransferred)
{ {
AutoLocker<VMCache> locker(fCache); fCache->Lock();
// Make successfully loaded pages accessible again (partially // Make successfully loaded pages accessible again (partially
// transferred pages are considered failed) // transferred pages are considered failed)
@@ -227,6 +227,7 @@ PrecacheIO::IOFinished(status_t status, bool partialTransfer,
vm_page_free(fCache, fPages[i]); vm_page_free(fCache, fPages[i]);
} }
fCache->Unlock();
delete this; 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, PrecacheIO* io = new(std::nothrow) PrecacheIO(ref, lastOffset,
bytesToRead); bytesToRead);
if (io == NULL || io->Prepare(&reservation) != B_OK) { if (io == NULL || io->Prepare(&reservation) != B_OK) {
cache->Unlock();
delete io; delete io;
cache->Lock();
break; break;
} }