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:
+5
-2
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user